From 3f2d3a72abe9a2913095e800f820c85c66f66fe3 Mon Sep 17 00:00:00 2001 From: Curtis Conard Date: Sun, 14 Jan 2024 10:11:44 -0500 Subject: [PATCH 1/2] ITIL template field twig ui --- CHANGELOG.md | 1 + src/ITILTemplateField.php | 165 ++++++++++++++++- src/ITILTemplateHiddenField.php | 111 +----------- src/ITILTemplateMandatoryField.php | 132 -------------- src/ITILTemplatePredefinedField.php | 169 ------------------ src/ITILTemplateReadonlyField.php | 101 ----------- templates/components/form/add_field.html.twig | 55 ------ 7 files changed, 167 insertions(+), 567 deletions(-) delete mode 100644 templates/components/form/add_field.html.twig diff --git a/CHANGELOG.md b/CHANGELOG.md index f079d89e98c..09f69304ded 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -110,6 +110,7 @@ The present file will list all changes made to the project; according to the - `kanban:filter` JS event now includes the columns in the event data. Filtering must set the `_filtered_out` property of cards to hide them instead of changing the elements in the DOM. - `CommonITILActor::getActors()` signature changed. The `$items_id` parameter must strictly be an integer. - The `date_mod` property for historical entries returned by `Log::getHistoryData` is no longer formatted based on the user's preferences. +- `ITILTemplateField::showForITILTemplate()` method is no longer abstract. #### Deprecated - Usage of `GLPI_USE_CSRF_CHECK` constant. diff --git a/src/ITILTemplateField.php b/src/ITILTemplateField.php index c2551bdc82d..185347455c9 100644 --- a/src/ITILTemplateField.php +++ b/src/ITILTemplateField.php @@ -33,6 +33,9 @@ * --------------------------------------------------------------------- */ +use Glpi\Application\View\TemplateRenderer; +use Glpi\Search\SearchOption; + /** * ITILTemplateMandatoryField Class * @@ -117,7 +120,167 @@ abstract public static function getExcludedFields(); * * @return void **/ - abstract public static function showForITILTemplate(ITILTemplate $tt, $withtemplate = 0); + public static function showForITILTemplate(ITILTemplate $tt, $withtemplate = 0) + { + /** + * @var \DBmysql $DB + * @var array $CFG_GLPI + */ + global $DB, $CFG_GLPI; + + $ID = $tt->fields['id']; + + if (!$tt->getFromDB($ID) || !$tt->can($ID, READ)) { + return false; + } + $canedit = $tt->canEdit($ID); + $fields = $tt->getAllowedFieldsNames(false); + $fields = array_diff_key($fields, static::getExcludedFields()); + $simplified_fields = $tt->getSimplifiedInterfaceFields(); + $both_interfaces_label = sprintf(__('%1$s + %2$s'), __('Simplified interface'), __('Standard interface')); + $display_options = [ + 'relative_dates' => true, + 'comments' => true, + 'html' => true + ]; + $itil_class = static::$itiltype; + $searchOption = SearchOption::getOptionsForItemtype($itil_class); + $itil_object = new $itil_class(); + $rand = mt_rand(); + + $crtiteria = [ + 'SELECT' => ['id', 'num'], + 'FROM' => static::getTable(), + 'WHERE' => [static::$items_id => $ID] + ]; + if (is_subclass_of(static::class, ITILTemplatePredefinedField::class)) { + $crtiteria['SELECT'][] = 'value'; + } + $iterator = $DB->request($crtiteria); + $entries = []; + + $numrows = count($iterator); + + $used = []; + foreach ($iterator as $data) { + $interface_label = in_array($data['num'], $simplified_fields, false) ? $both_interfaces_label : __('Standard interface'); + $entry = [ + 'itemtype' => static::class, + 'id' => $data['id'], + 'name' => $fields[$data['num']], + 'interface' => $interface_label, + ]; + if (is_subclass_of(static::class, ITILTemplatePredefinedField::class)) { + $display_datas[$searchOption[$data['num']]['field']] = $data['value']; + $value_label = $itil_object->getValueToDisplay( + $searchOption[$data['num']], + $display_datas, + $display_options + ); + $entry['value'] = $value_label; + } + $entries[] = $entry; + $used[$data['num']] = $data['num']; + } + + $fields_dropdown_values = []; + foreach ($fields as $k => $field) { + $is_simple_field = in_array($k, $simplified_fields, false); + $label = sprintf(__('%1$s (%2$s)'), $field, $is_simple_field ? $both_interfaces_label : __('Standard interface')); + $fields_dropdown_values[$k] = $label; + } + + if (is_subclass_of(static::class, ITILTemplatePredefinedField::class)) { + $fields_dropdown_values = array_replace([ + -1 => Dropdown::EMPTY_VALUE + ], $fields_dropdown_values); + } + + if ($canedit) { + $extra_form_html = ''; + if (is_subclass_of(static::class, ITILTemplatePredefinedField::class)) { + $embedded_ma_params = [ + 'id_field' => '__VALUE__', + 'itemtype' => static::$itiltype, + 'inline' => true, + 'submitname' => _sx('button', 'Add'), + 'options' => [ + 'relative_dates' => 1, + 'with_time' => 1, + 'with_days' => 0, + 'with_specific_date' => 0, + 'itemlink_as_string' => 1, + 'entity' => $tt->getEntityID() + ] + ]; + $extra_form_html = Ajax::updateItemOnSelectEvent( + "dropdown_num{$rand}", + "show_massiveaction_field", + $CFG_GLPI["root_doc"] . "/ajax/dropdownMassiveActionField.php", + $embedded_ma_params, + false + ); + $extra_form_html .= "
"; + } + + $twig_params = [ + 'form_url' => static::getFormURL(), + 'items_id_field' => static::$items_id, + 'itemtype_name' => static::getTypeName(), + 'used' => $used, + 'id' => $ID, + 'fields' => $fields_dropdown_values, + 'extra_form_html' => $extra_form_html, + 'rand' => $rand, + 'show_submit' => !is_subclass_of(static::class, ITILTemplatePredefinedField::class) + ]; + echo TemplateRenderer::getInstance()->renderFromStringTemplate(<< +
+ {{ inputs.hidden('_glpi_csrf_token', csrf_token()) }} + {{ inputs.hidden(items_id_field, id) }} +
+ {{ fields.dropdownArrayField('num', 0, fields, null, { + no_label: true, + used: used, + add_field_attribs: { + 'aria-label': itemtype_name + }, + rand: rand + }) }} + {{ extra_form_html|raw }} + {% if show_submit %} +
{{ inputs.submit('add', _x('button', 'Add')) }}
+ {% endif %} +
+
+ +TWIG, $twig_params); + } + + $columns = [ + 'name' => __('Name'), + 'interface' => __("Profile's interface") + ]; + if (is_subclass_of(static::class, ITILTemplatePredefinedField::class)) { + $columns['value'] = __('Value'); + } + TemplateRenderer::getInstance()->display('components/datatable.html.twig', [ + 'is_tab' => true, + 'nofilter' => true, + 'columns' => $columns, + 'entries' => $entries, + 'total_number' => count($entries), + 'filtered_number' => count($entries), + 'showmassiveactions' => $canedit, + 'massiveactionparams' => [ + 'num_displayed' => min($_SESSION['glpilist_limit'], $numrows), + 'container' => 'mass' . static::class . $rand + ], + ]); + } /** diff --git a/src/ITILTemplateHiddenField.php b/src/ITILTemplateHiddenField.php index 5bfd5bf2f3a..b8f1be74fe3 100644 --- a/src/ITILTemplateHiddenField.php +++ b/src/ITILTemplateHiddenField.php @@ -33,6 +33,8 @@ * --------------------------------------------------------------------- */ +use Glpi\Application\View\TemplateRenderer; + /** * ITILTemplateHiddenField Class * @@ -148,113 +150,4 @@ public static function getExcludedFields() 175 => 175, // ticket's tasks (template) ]; } - - - /** - * Print the hidden fields - * - * @since 0.83 - * - * @param ITILTemplate $tt ITIL Template - * @param integer $withtemplate Template or basic item (default 0) - * - * @return void - **/ - public static function showForITILTemplate(ITILTemplate $tt, $withtemplate = 0) - { - /** @var \DBmysql $DB */ - global $DB; - - $ID = $tt->fields['id']; - - if (!$tt->getFromDB($ID) || !$tt->can($ID, READ)) { - return false; - } - $canedit = $tt->canEdit($ID); - $ttm = new static(); - $fields = $tt->getAllowedFieldsNames(false); - $fields = array_diff_key($fields, self::getExcludedFields()); - $rand = mt_rand(); - - $iterator = $DB->request([ - 'FROM' => static::getTable(), - 'WHERE' => [static::$items_id => $ID] - ]); - - $numrows = count($iterator); - - $hiddenfields = []; - $used = []; - foreach ($iterator as $data) { - $hiddenfields[$data['id']] = $data; - $used[$data['num']] = $data['num']; - } - - if ($canedit) { - echo "
"; - echo "
"; - - echo ""; - echo ""; - echo ""; - echo "
" . __('Add a hidden field') . "
"; - echo ""; - Dropdown::showFromArray('num', $fields, ['used' => $used]); - echo ""; - echo " "; - echo "
"; - Html::closeForm(); - echo "
"; - } - - echo "
"; - if ($canedit && $numrows) { - Html::openMassiveActionsForm('mass' . $ttm->getType() . $rand); - $massiveactionparams = ['num_displayed' => min($_SESSION['glpilist_limit'], $numrows), - 'container' => 'mass' . $ttm->getType() . $rand - ]; - Html::showMassiveActions($massiveactionparams); - } - echo ""; - echo ""; - if ($numrows) { - $header_begin = ""; - $header_top = ''; - $header_bottom = ''; - $header_end = ''; - if ($canedit) { - $header_top .= ""; - $header_bottom .= ""; - } - $header_end .= ""; - $header_end .= ""; - echo $header_begin . $header_top . $header_end; - - foreach ($hiddenfields as $data) { - echo ""; - if ($canedit) { - echo ""; - } - echo ""; - echo ""; - } - echo $header_begin . $header_bottom . $header_end; - } else { - echo ""; - } - - echo "
"; - echo static::getTypeName(count($iterator)); - echo "
"; - $header_top .= Html::getCheckAllAsCheckbox('mass' . $ttm->getType() . $rand) . ""; - $header_bottom .= Html::getCheckAllAsCheckbox('mass' . $ttm->getType() . $rand) . "" . __('Name') . "
" . Html::getMassiveActionCheckBox($ttm->getType(), $data["id"]) . "" . $fields[$data['num']] . "
" . __('No item found') . "
"; - if ($canedit && $numrows) { - $massiveactionparams['ontop'] = false; - Html::showMassiveActions($massiveactionparams); - Html::closeForm(); - } - echo "
"; - } } diff --git a/src/ITILTemplateMandatoryField.php b/src/ITILTemplateMandatoryField.php index c5f8b41760a..dd770e76aec 100644 --- a/src/ITILTemplateMandatoryField.php +++ b/src/ITILTemplateMandatoryField.php @@ -149,136 +149,4 @@ public static function getExcludedFields() 175 => 175, // ticket's tasks ]; } - - /** - * Print the mandatory fields - * - * @since 0.83 - * - * @param ITILTemplate $tt ITIL Template - * @param integer $withtemplate Template or basic item (default 0) - * - * @return void - **/ - public static function showForITILTemplate(ITILTemplate $tt, $withtemplate = 0) - { - /** @var \DBmysql $DB */ - global $DB; - - $ID = $tt->fields['id']; - - if (!$tt->getFromDB($ID) || !$tt->can($ID, READ)) { - return false; - } - $canedit = $tt->canEdit($ID); - $ttm = new static(); - $fields = $ttm->getAllFields($tt); - $simplified_fields = $tt->getSimplifiedInterfaceFields(); - $both_interfaces = sprintf(__('%1$s + %2$s'), __('Simplified interface'), __('Standard interface')); - - $rand = mt_rand(); - - $iterator = $DB->request([ - 'FROM' => static::getTable(), - 'WHERE' => [static::$items_id => $ID] - ]); - - $numrows = count($iterator); - - $mandatoryfields = []; - $used = []; - foreach ($iterator as $data) { - $mandatoryfields[$data['id']] = $data; - $used[$data['num']] = $data['num']; - } - - if ($canedit) { - echo "
"; - echo ""; - - echo ""; - echo ""; - echo ""; - echo "
" . __('Add a mandatory field') . "
"; - echo ""; - - $select_fields = $fields; - foreach ($select_fields as $key => $val) { - if (static::$itiltype == Ticket::getType()) { - if (in_array($key, $simplified_fields)) { - $select_fields[$key] = sprintf(__('%1$s (%2$s)'), $val, $both_interfaces); - } else { - $select_fields[$key] = sprintf(__('%1$s (%2$s)'), $val, __('Standard interface')); - } - } else { - $select_fields[$key] = $val; - } - } - - Dropdown::showFromArray('num', $select_fields, ['used' => $used]); - echo ""; - echo " "; - echo "
"; - Html::closeForm(); - echo "
"; - } - - echo "
"; - if ($canedit && $numrows) { - Html::openMassiveActionsForm('mass' . $ttm->getType() . $rand); - $massiveactionparams = ['num_displayed' => min($_SESSION['glpilist_limit'], $numrows), - 'container' => 'mass' . $ttm->getType() . $rand - ]; - Html::showMassiveActions($massiveactionparams); - } - echo ""; - echo ""; - if ($numrows) { - $header_begin = ""; - $header_top = ''; - $header_bottom = ''; - $header_end = ''; - if ($canedit) { - $header_top .= ""; - $header_bottom .= ""; - } - $header_end .= ""; - $header_end .= ""; - $header_end .= ""; - echo $header_begin . $header_top . $header_end; - - foreach ($mandatoryfields as $data) { - echo ""; - if ($canedit) { - echo ""; - } - echo ""; - echo ""; - echo ""; - } - echo $header_begin . $header_bottom . $header_end; - } else { - echo ""; - } - - echo "
"; - echo static::getTypeName(count($iterator)); - echo "
"; - $header_top .= Html::getCheckAllAsCheckbox('mass' . $ttm->getType() . $rand) . ""; - $header_bottom .= Html::getCheckAllAsCheckbox('mass' . $ttm->getType() . $rand) . "" . __('Name') . "" . __("Profile's interface") . "
" . Html::getMassiveActionCheckBox($ttm->getType(), $data["id"]) . "" . $fields[$data['num']] . ""; - if (in_array($data['num'], $simplified_fields)) { - echo $both_interfaces; - } else { - echo __('Standard interface'); - } - echo "
" . __('No item found') . "
"; - if ($canedit && $numrows) { - $massiveactionparams['ontop'] = false; - Html::showMassiveActions($massiveactionparams); - Html::closeForm(); - } - echo "
"; - } } diff --git a/src/ITILTemplatePredefinedField.php b/src/ITILTemplatePredefinedField.php index fd672b4ac75..54918b96fe0 100644 --- a/src/ITILTemplatePredefinedField.php +++ b/src/ITILTemplatePredefinedField.php @@ -248,173 +248,4 @@ public static function getExcludedFields() 142 => 142, // documents ]; } - - - /** - * Print the predefined fields - * - * @since 0.83 - * - * @param ITILTemplate $tt ITIL Template - * @param integer $withtemplate Template or basic item (default 0) - * - * @return void - **/ - public static function showForITILTemplate(ITILTemplate $tt, $withtemplate = 0) - { - /** - * @var array $CFG_GLPI - * @var \DBmysql $DB - */ - global $CFG_GLPI, $DB; - - $ID = $tt->fields['id']; - - if (!$tt->getFromDB($ID) || !$tt->can($ID, READ)) { - return false; - } - - $canedit = $tt->canEdit($ID); - - $fields = $tt->getAllowedFieldsNames(true, true); - $fields = array_diff_key($fields, self::getExcludedFields()); - - $itil_class = static::$itiltype; - $searchOption = SearchOption::getOptionsForItemtype($itil_class); - $itil_object = new $itil_class(); - $rand = mt_rand(); - - $iterator = $DB->request([ - 'FROM' => static::getTable(), - 'WHERE' => [static::$items_id => $ID], - 'ORDER' => 'id' - ]); - - $display_options = [ - 'relative_dates' => true, - 'comments' => true, - 'html' => true - ]; - - $predeffields = []; - $used = []; - $numrows = count($iterator); - foreach ($iterator as $data) { - $predeffields[$data['id']] = $data; - $used[$data['num']] = $data['num']; - } - - if ($canedit) { - echo "
"; - echo ""; - - echo ""; - echo ""; - echo ""; - echo "
" . __('Add a predefined field') . "
"; - echo ""; - $display_fields[-1] = Dropdown::EMPTY_VALUE; - $display_fields += $fields; - - // Unset multiple items - $multiple = self::getMultiplePredefinedValues(); - foreach ($multiple as $val) { - if (isset($used[$val])) { - unset($used[$val]); - } - } - - $rand_dp = Dropdown::showFromArray('num', $display_fields, ['used' => $used, - 'toadd' - ]); - echo ""; - $paramsmassaction = ['id_field' => '__VALUE__', - 'itemtype' => static::$itiltype, - 'inline' => true, - 'submitname' => _sx('button', 'Add'), - 'options' => ['relative_dates' => 1, - 'with_time' => 1, - 'with_days' => 0, - 'with_specific_date' => 0, - 'itemlink_as_string' => 1, - 'entity' => $tt->getEntityID() - ] - ]; - - Ajax::updateItemOnSelectEvent( - "dropdown_num" . $rand_dp, - "show_massiveaction_field", - $CFG_GLPI["root_doc"] . "/ajax/dropdownMassiveActionField.php", - $paramsmassaction - ); - echo ""; - echo " \n"; - echo "
"; - Html::closeForm(); - echo "
"; - } - - echo "
"; - if ($canedit && $numrows) { - Html::openMassiveActionsForm('mass' . static::getType() . $rand); - $massiveactionparams = ['num_displayed' => min($_SESSION['glpilist_limit'], $numrows), - 'container' => 'mass' . static::getType() . $rand - ]; - Html::showMassiveActions($massiveactionparams); - } - echo ""; - echo ""; - if ($numrows) { - $header_begin = ""; - $header_top = ''; - $header_bottom = ''; - $header_end = ''; - if ($canedit) { - $header_top .= ""; - $header_bottom .= ""; - } - $header_end .= ""; - $header_end .= ""; - $header_end .= ""; - echo $header_begin . $header_top . $header_end; - - foreach ($predeffields as $data) { - if (!isset($fields[$data['num']])) { - // could happen when itemtype removed and items_id present - continue; - } - echo ""; - if ($canedit) { - echo ""; - } - echo ""; - - echo ""; - echo ""; - } - echo $header_begin . $header_bottom . $header_end; - } else { - echo ""; - } - - echo "
"; - echo self::getTypeName($numrows); - echo "
"; - $header_top .= Html::getCheckAllAsCheckbox('mass' . static::getType() . $rand) . ""; - $header_bottom .= Html::getCheckAllAsCheckbox('mass' . static::getType() . $rand) . "" . __('Name') . "" . __('Value') . "
" . Html::getMassiveActionCheckBox(static::getType(), $data["id"]) . "" . $fields[$data['num']] . ""; - $display_datas[$searchOption[$data['num']]['field']] = $data['value']; - echo $itil_object->getValueToDisplay( - $searchOption[$data['num']], - $display_datas, - $display_options - ); - echo "
" . __('No item found') . "
"; - if ($canedit && $numrows) { - $massiveactionparams['ontop'] = false; - Html::showMassiveActions($massiveactionparams); - Html::closeForm(); - } - echo "
"; - } } diff --git a/src/ITILTemplateReadonlyField.php b/src/ITILTemplateReadonlyField.php index ea144759388..4fc79bbdd28 100644 --- a/src/ITILTemplateReadonlyField.php +++ b/src/ITILTemplateReadonlyField.php @@ -160,105 +160,4 @@ public static function getExcludedFields() 193 => 193, // Contract ]; } - - - /** - * Print the readonly fields - * - * @param ITILTemplate $tt ITIL Template - * @param boolean $withtemplate Template or basic item (default 0) - * - * @return void - **/ - public static function showForITILTemplate(ITILTemplate $tt, $withtemplate = 0) - { - /** @var \DBmysql $DB */ - global $DB; - - $ID = $tt->fields['id']; - - if (!$tt->getFromDB($ID) || !$tt->can($ID, READ)) { - return false; - } - $canedit = $tt->canEdit($ID); - $ttr = new static(); - $fields = $tt->getAllowedFieldsNames(false); - $fields = array_diff_key($fields, self::getExcludedFields()); - $rand = mt_rand(); - - $iterator = $DB->request([ - 'FROM' => static::getTable(), - 'WHERE' => [static::$items_id => $ID] - ]); - - $numrows = count($iterator); - - $readonlyfields = []; - $used = []; - foreach ($iterator as $data) { - $readonlyfields[$data['id']] = $data; - $used[$data['num']] = $data['num']; - } - - if ($canedit) { - echo TemplateRenderer::getInstance()->render('components/form/add_field.html.twig', [ - 'rand' => $rand, - 'form_url' => $ttr->getFormURL(), - 'form_title' => __('Add a read only field'), - 'itemtype' => __CLASS__, - 'items_name' => static::$items_id, - 'items_id' => $ID, - 'readonlyfields' => $fields, - 'used' => $used, - ]); - } - - echo "
"; - if ($canedit && $numrows) { - Html::openMassiveActionsForm('mass' . $ttr->getType() . $rand); - $massiveactionparams = ['num_displayed' => min($_SESSION['glpilist_limit'], $numrows), - 'container' => 'mass' . $ttr->getType() . $rand - ]; - Html::showMassiveActions($massiveactionparams); - } - echo ""; - echo ""; - if ($numrows) { - $header_begin = ""; - $header_top = ''; - $header_bottom = ''; - $header_end = ''; - if ($canedit) { - $header_top .= ""; - $header_bottom .= ""; - } - $header_end .= ""; - $header_end .= ""; - echo $header_begin . $header_top . $header_end; - - foreach ($readonlyfields as $data) { - echo ""; - if ($canedit) { - echo ""; - } - echo ""; - echo ""; - } - echo $header_begin . $header_bottom . $header_end; - } else { - echo ""; - } - - echo "
"; - echo static::getTypeName(count($iterator)); - echo "
"; - $header_top .= Html::getCheckAllAsCheckbox('mass' . $ttr->getType() . $rand) . ""; - $header_bottom .= Html::getCheckAllAsCheckbox('mass' . $ttr->getType() . $rand) . "" . __('Name') . "
" . Html::getMassiveActionCheckBox($ttr->getType(), $data["id"]) . "" . $fields[$data['num']] . "
" . __('No item found') . "
"; - if ($canedit && $numrows) { - $massiveactionparams['ontop'] = false; - Html::showMassiveActions($massiveactionparams); - Html::closeForm(); - } - echo "
"; - } } diff --git a/templates/components/form/add_field.html.twig b/templates/components/form/add_field.html.twig deleted file mode 100644 index 2c8630c0835..00000000000 --- a/templates/components/form/add_field.html.twig +++ /dev/null @@ -1,55 +0,0 @@ -{# - # --------------------------------------------------------------------- - # - # GLPI - Gestionnaire Libre de Parc Informatique - # - # http://glpi-project.org - # - # @copyright 2015-2024 Teclib' and contributors. - # @copyright 2003-2014 by the INDEPNET Development Team. - # @licence https://www.gnu.org/licenses/gpl-3.0.html - # - # --------------------------------------------------------------------- - # - # LICENSE - # - # This file is part of GLPI. - # - # This program is free software: you can redistribute it and/or modify - # it under the terms of the GNU General Public License as published by - # the Free Software Foundation, either version 3 of the License, or - # (at your option) any later version. - # - # This program is distributed in the hope that it will be useful, - # but WITHOUT ANY WARRANTY; without even the implied warranty of - # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - # GNU General Public License for more details. - # - # You should have received a copy of the GNU General Public License - # along with this program. If not, see . - # - # --------------------------------------------------------------------- - #} - -{% import 'components/form/fields_macros.html.twig' as fields %} - -{% set rand = rand|default(random()) %} -
- - - - - - - - - -
{{ form_title }}
- - {{ fields.dropdownArrayField('num', readonlyfields|first, readonlyfields, '', {'used': used}) }} - -   -
- {{ fields.hiddenField('_glpi_csrf_token', csrf_token()) }} - -
From 5e9b7adfaabaa8a09ed95616cb41607586425891 Mon Sep 17 00:00:00 2001 From: Curtis Conard Date: Mon, 15 Jan 2024 20:31:12 -0500 Subject: [PATCH 2/2] ignore unavailable fields --- src/ITILTemplateField.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ITILTemplateField.php b/src/ITILTemplateField.php index 185347455c9..f30dd0af079 100644 --- a/src/ITILTemplateField.php +++ b/src/ITILTemplateField.php @@ -163,6 +163,10 @@ public static function showForITILTemplate(ITILTemplate $tt, $withtemplate = 0) $used = []; foreach ($iterator as $data) { + if (!array_key_exists($data['num'], $fields)) { + // Ignore deleted/unavailable fields + continue; + } $interface_label = in_array($data['num'], $simplified_fields, false) ? $both_interfaces_label : __('Standard interface'); $entry = [ 'itemtype' => static::class,