From 024f2536267af1c23c7071fa8ff15e6ae5d3829b Mon Sep 17 00:00:00 2001 From: Yoan Bozhilov Date: Thu, 14 May 2026 12:03:19 +0300 Subject: [PATCH 1/3] Add safety guards in Generate item flow for invalid references and non-existent classes The Generate item massive action threw fatal errors on GLPI 11 / PHP 8.3 under two scenarios: 1. PluginOrderReference::getReferenceItemID() (reference.class.php) - getItemForItemtype() returns false in HTTP context for some dynamically-generated classes (e.g. Glpi\CustomAsset\* in GLPI 11), causing "Call to a member function getFromDB() on false". - Existing references migrated from older itemtypes may have templates_id = 0, which makes getFromDB() fail silently and the subsequent getField() calls operate on a half-initialised object. 2. PluginOrderLink::generateItem() (link.class.php) - Toolbox::hasTrait() internally calls class_uses(). On PHP 8.3 with the Safe library wrapper, class_uses() on a non-existent class throws Safe\Exceptions\SplException instead of emitting a warning. - This is triggered by stale itemtype values in glpi_plugin_order_orders_items that reference classes from uninstalled plugins (e.g. PluginGenericobjectOther after migrating to native custom assets). Both call sites are now guarded: - reference.class.php: bail out early with return 0 when the item cannot be instantiated or templates_id is empty. - link.class.php: prefix both Toolbox::hasTrait() calls with class_exists() so non-existent classes are skipped cleanly. Tested on GLPI 11.0.7, PHP 8.3, Order plugin 2.12.6: - Order with valid native itemtypes (Computer, Monitor, etc.): unchanged. - Order containing custom asset references (Glpi\CustomAsset\otherAsset): Generate item form now renders fully and submits successfully. - Order containing stale itemtypes from uninstalled plugins (PluginGenericobjectOther): items are skipped without fatal error, remaining items render correctly. --- CHANGELOG.md | 1 + inc/link.class.php | 5 +++-- inc/reference.class.php | 9 ++++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 233952fe40..8cdce0d51e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Fix generate associated item massive action +- Add safety guards in Generate item flow for invalid references and non-existent classes (GLPI 11 / PHP 8.3) - Update locales diff --git a/inc/link.class.php b/inc/link.class.php index 8af76df2a8..9af3c3015a 100644 --- a/inc/link.class.php +++ b/inc/link.class.php @@ -148,7 +148,8 @@ public function showItemGenerationForm($params) $row['template_name'] = ""; } - if (Toolbox::hasTrait($itemtype, AssignableItem::class)) { + // GLPI 11 safety: skip non-existent classes (e.g. uninstalled plugins like GenericObject) + if (class_exists($itemtype) && Toolbox::hasTrait($itemtype, AssignableItem::class)) { $row['assignableitem'] = true; if (!is_array($row['groups_id'])) { $row['groups_id'] = $row['groups_id'] > 0 ? [$row['groups_id']] : []; @@ -174,7 +175,7 @@ public function showItemGenerationForm($params) 'active_entities' => $_SESSION['glpiactiveentities'] ?? [], 'item_rows' => $item_rows, 'order_web_dir' => $order_web_dir, - 'assignableitem' => Toolbox::hasTrait($itemtype, AssignableItem::class), + 'assignableitem' => class_exists($itemtype) && Toolbox::hasTrait($itemtype, AssignableItem::class), ]); return null; } diff --git a/inc/reference.class.php b/inc/reference.class.php index a54866540b..e7e5fb8c73 100644 --- a/inc/reference.class.php +++ b/inc/reference.class.php @@ -471,7 +471,14 @@ public function checkIfTemplateExistsInEntity($detailID, $itemtype, $entity) } else { $row = $result->current(); $item = getItemForItemtype($itemtype); - $item->getFromDB($row["templates_id"]); + // GLPI 11 safety: custom asset classes may fail to resolve in HTTP context + // and templates_id may be 0 for entries created before plugin migration. + if ($item === false || empty($row["templates_id"])) { + return 0; + } + if (!$item->getFromDB($row["templates_id"])) { + return 0; + } if ($item->getField('entities_id') == $entity || ($item->maybeRecursive() && $item->fields['is_recursive'] From 0d12da7a545b741358dea5963cb7b697348337ab Mon Sep 17 00:00:00 2001 From: Yoan Bozhilov Date: Thu, 21 May 2026 10:22:04 +0300 Subject: [PATCH 2/3] Collapse safety guards in checkIfTemplateExistsInEntity Apply review feedback from @Rom1-B: merge the two consecutive early-return guards into a single if block, and use (int) cast for templates_id check instead of empty(). This also satisfies the Rector codeQuality ruleset enforced in CI. --- inc/reference.class.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/inc/reference.class.php b/inc/reference.class.php index e7e5fb8c73..36e101151d 100644 --- a/inc/reference.class.php +++ b/inc/reference.class.php @@ -471,14 +471,14 @@ public function checkIfTemplateExistsInEntity($detailID, $itemtype, $entity) } else { $row = $result->current(); $item = getItemForItemtype($itemtype); - // GLPI 11 safety: custom asset classes may fail to resolve in HTTP context - // and templates_id may be 0 for entries created before plugin migration. - if ($item === false || empty($row["templates_id"])) { - return 0; - } - if (!$item->getFromDB($row["templates_id"])) { + if ( + $item === false + || (int) $row["templates_id"] === 0 + || !$item->getFromDB($row["templates_id"]) + ) { return 0; } + if ($item->getField('entities_id') == $entity || ($item->maybeRecursive() && $item->fields['is_recursive'] From dabdbba39a3c73a6d770dfae2a709dae186b745a Mon Sep 17 00:00:00 2001 From: Yoan Bozhilov Date: Thu, 21 May 2026 10:41:44 +0300 Subject: [PATCH 3/3] Apply review suggestion on CHANGELOG entry Per @stonebuzz review suggestion: use a shorter, action-oriented phrasing for the changelog entry and drop the version-specific suffix. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cdce0d51e..79f1d5dea3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Fix generate associated item massive action -- Add safety guards in Generate item flow for invalid references and non-existent classes (GLPI 11 / PHP 8.3) +- Prevent invalid references and non-existent classes during generate item flow. - Update locales