Skip to content

Add safety guards in Generate item flow for invalid references and non-existent classes#578

Open
bygadd wants to merge 1 commit into
pluginsGLPI:mainfrom
bygadd:fix/glpi11-safety-guards-reference-and-link
Open

Add safety guards in Generate item flow for invalid references and non-existent classes#578
bygadd wants to merge 1 commit into
pluginsGLPI:mainfrom
bygadd:fix/glpi11-safety-guards-reference-and-link

Conversation

@bygadd
Copy link
Copy Markdown

@bygadd bygadd commented May 14, 2026

Summary

The Generate item massive action throws fatal errors on GLPI 11 / PHP 8.3 under two scenarios that have become common after the GLPI 10 → 11 migration:

  1. Invalid item references in PluginOrderReference::getReferenceItemID()getItemForItemtype() returns false in HTTP context for some dynamically-generated classes (notably Glpi\CustomAsset\* in GLPI 11), causing Call to a member function getFromDB() on false. Existing references migrated from older itemtypes may also have templates_id = 0, which makes getFromDB() fail silently and downstream getField() calls operate on a half-initialised object.

  2. Non-existent classes in PluginOrderLink::generateItem()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 via the GenericObject 3.0.0 EOL migration tool).

Implementation

Both call sites are now guarded:

  • inc/reference.class.php — bail out early with return 0 when the item cannot be instantiated or templates_id is empty.
  • inc/link.class.php — prefix both Toolbox::hasTrait() calls with class_exists() so non-existent classes are skipped cleanly, both in the iteration loop (where $row['assignableitem'] is set) and in the final TemplateRenderer::display() call.

The changes are defensive and minimal — they preserve all existing behaviour for valid native itemtypes, and only short-circuit when the underlying data cannot be resolved to a working class.

Testing

Tested on GLPI 11.0.7, PHP 8.3, Order plugin 2.12.6:

Scenario Result
Order with valid native itemtypes (Computer, Monitor, etc.) — unchanged behaviour
Order containing custom asset references (Glpi\CustomAsset\otherAsset) — form now renders fully and submits
Order containing stale itemtypes from uninstalled plugins (PluginGenericobjectOther) — items skipped without fatal error, remaining items render
Generate item massive action end-to-end (form → submit → items created)

Tested on a production instance with ~21,000 order line items and ~1,300 references, including a mix of native itemtypes, custom asset references, and stale references from a deinstalled plugin.

Checklist

  • I have performed a self-review of my code.
  • I have added tests (when available) that prove my fix is effective or that my feature works.
  • I have updated the CHANGELOG with a short functional description of the fix or new feature.
  • This change requires a documentation update.

…n-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.
@bygadd
Copy link
Copy Markdown
Author

bygadd commented May 14, 2026

Related: opened pluginsGLPI/room#64 today documenting similar GLPI 11 compatibility issues in the room plugin — including null-safety patterns analogous to the ones in this PR (guard before object instantiation, guard before trait checks).

The room patch set is in production use on the same instance where this PR's guards were developed (GLPI 11.0.7, ~700K warnings/day → 0).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant