diff --git a/CHANGELOG.md b/CHANGELOG.md index 233952fe40..279f830d69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [unreleased] +### Added +- Add an `Orderable` capacity for GLPI 11 custom asset definitions, allowing each definition to opt-in to being used as a Product reference itemtype. Asset classes are filtered by per-user read permission. Disabling the capacity on a definition cleans up its order line items and product references. + ### Fixed - Fix generate associated item massive action diff --git a/inc/orderablecapacity.class.php b/inc/orderablecapacity.class.php new file mode 100644 index 0000000000..47c4578da1 --- /dev/null +++ b/inc/orderablecapacity.class.php @@ -0,0 +1,73 @@ + + * Asset definitions -> {your asset} -> Capacities), the corresponding + * generated asset class is appended to $ORDER_TYPES and becomes selectable + * as an Item type when creating a Product reference. + */ +class PluginOrderOrderableCapacity extends \Glpi\Asset\Capacity\AbstractCapacity +{ + public function getLabel(): string + { + return __('Orderable', 'order'); + } + + public function getIcon(): string + { + return 'ti ti-shopping-cart'; + } + + public function getDescription(): string + { + return __( + 'Allow this asset to be referenced as a Product reference and ' + . 'generated from the Generate item massive action.', + 'order' + ); + } + + public function getCapacityUsageDescription(string $classname): string + { + $count = 0; + if (class_exists('PluginOrderReference')) { + $count = countElementsInTable( + \PluginOrderReference::getTable(), + ['itemtype' => $classname] + ); + } + return sprintf( + _n('Used by %d order reference', 'Used by %d order references', $count, 'order'), + $count + ); + } + + /** + * Clean up plugin data linked to the asset class when the capacity is + * disabled on its definition: remove Product references targeting the + * class and order line items that link orders to instances of the class. + * Free-form references are intentionally left untouched, as they are + * standalone records that do not reference any itemtype. + */ + public function onCapacityDisabled(string $classname, \Glpi\Asset\CapacityConfig $config): void + { + // Delete order line items first: PluginOrderReference::pre_deleteItem() + // refuses deletion while references are still in use by orders_items, + // so child records must be removed before parent references. + if (class_exists('PluginOrderOrder_Item')) { + (new \PluginOrderOrder_Item())->deleteByCriteria( + ['itemtype' => $classname], + force: true, + history: false + ); + } + if (class_exists('PluginOrderReference')) { + (new \PluginOrderReference())->deleteByCriteria( + ['itemtype' => $classname], + force: true, + history: false + ); + } + } +} diff --git a/setup.php b/setup.php index 7cd7cfd6b0..d59fdfcc4f 100644 --- a/setup.php +++ b/setup.php @@ -125,6 +125,29 @@ function plugin_init_order() 'Pdu', ]; + + // Register the Orderable capacity for GLPI 11 custom assets and append + // any custom asset class that has it enabled to $ORDER_TYPES, provided + // the current user is allowed to view it. + if (class_exists(\Glpi\Asset\AssetDefinitionManager::class)) { + $asset_manager = \Glpi\Asset\AssetDefinitionManager::getInstance(); + $orderable_capacity = new PluginOrderOrderableCapacity(); + $asset_manager->registerCapacity($orderable_capacity); + $asset_manager->bootDefinitions(); + foreach ($asset_manager->getDefinitions(true) as $definition) { + if (!$definition->hasCapacityEnabled($orderable_capacity)) { + continue; + } + $custom_asset_class = $definition->getAssetClassName(); + if ( + !in_array($custom_asset_class, $ORDER_TYPES, true) + && $custom_asset_class::canView() + ) { + $ORDER_TYPES[] = $custom_asset_class; + } + } + } + $CFG_GLPI['plugin_order_types'] = $ORDER_TYPES; $PLUGIN_HOOKS['pre_item_purge']['order'] = [