From 7cd5e2591311926a4ea77a08bc599d1d10da30bf Mon Sep 17 00:00:00 2001 From: Thetsmr Date: Thu, 7 May 2026 14:52:45 +0200 Subject: [PATCH 01/20] Permit to Inject GlpiAsset --- inc/commoninjectionlib.class.php | 16 +++++ inc/injectiontype.class.php | 6 +- setup.php | 109 ++++++++++++++++++++++++++++++- 3 files changed, 129 insertions(+), 2 deletions(-) diff --git a/inc/commoninjectionlib.class.php b/inc/commoninjectionlib.class.php index 1ee5679c..acbb40ec 100644 --- a/inc/commoninjectionlib.class.php +++ b/inc/commoninjectionlib.class.php @@ -27,6 +27,7 @@ * @link https://github.com/pluginsGLPI/datainjection * ------------------------------------------------------------------------- */ +use Glpi\Asset\Asset; use Glpi\Exception\Http\HttpException; use Glpi\Features\AssignableItem; @@ -334,6 +335,9 @@ public static function getItemtypeByInjection($injectionClassName) public static function getItemtypeByInjectionClass($injectionClass) { + if (is_a($injectionClass, Asset::class, true)) { + return Toolbox::ucfirst(getItemTypeForTable($injectionClass->getVirtualTable())); + } return Toolbox::ucfirst(getItemTypeForTable($injectionClass->getTable())); } @@ -355,6 +359,11 @@ public static function getInjectionClassInstance($itemtype) $injectionClass = ucfirst($itemtype) . 'Injection'; } + if (!class_exists($injectionClass)) { + plugin_datainjection_creationInjectableAssets(); + } + + if (!is_a($injectionClass, PluginDatainjectionInjectionInterface::class, true)) { throw new HttpException(500, 'Class ' . $injectionClass . ' is not a valid class'); } @@ -1994,6 +2003,13 @@ private function dataAlreadyInDB($injectionClass, $itemtype) } } + if (is_a($injectionClass, Asset::class, true)) { + if (method_exists($injectionClass, 'getAssetDefinitionID')) { + $assets_assetdefinitions_id = $injectionClass->getAssetDefinitionID(); + $where .= " AND `assets_assetdefinitions_id` = '" . $assets_assetdefinitions_id . "'"; + } + } + //Add additional parameters specific to this itemtype (or function checkPresent exists) if (method_exists($injectionClass, 'checkPresent')) { $where .= $injectionClass->checkPresent($this->values, $options); diff --git a/inc/injectiontype.class.php b/inc/injectiontype.class.php index 9cfb291d..d74aa3cf 100644 --- a/inc/injectiontype.class.php +++ b/inc/injectiontype.class.php @@ -78,6 +78,10 @@ public static function getItemtypes($only_primary = false) $name = $plugin->getName() . ': '; } $name .= call_user_func([$type, 'getTypeName']); + + if ($typename == "GlpiPlugin\Datainjection\Glpi\Asset\AssetInjection") { + $typename = $instance->getVirtualType(); + } $values[$typename] = $name; } } @@ -388,7 +392,7 @@ public static function getUsedMappingsOrInfos($options = []) foreach ($options as $option) { if ( isset($option['table']) - && ($option['table'] == getItemTypeForTable($data['itemtype'])) + && ($option['table'] == $injectionClass->getTable()) && ($option['linkfield'] == $data['value']) && ($option['displaytype'] != 'multiline_text') && ($mapping_or_info['value'] != $data['value']) diff --git a/setup.php b/setup.php index 0fbbabe3..c7f834e4 100644 --- a/setup.php +++ b/setup.php @@ -28,6 +28,10 @@ * ------------------------------------------------------------------------- */ +use Glpi\Asset\AssetDefinition; +use Glpi\Asset\AssetDefinitionManager; +use GlpiPlugin\Datainjection\Glpi\Asset\Capacity\IsInjectableCapacity; + use function Safe\define; use function Safe\mkdir; @@ -49,6 +53,12 @@ function plugin_init_datainjection() /** @var array $INJECTABLE_TYPES */ global $PLUGIN_HOOKS, $CFG_GLPI, $INJECTABLE_TYPES; + if (!isset($CFG_GLPI['injectable_types'])) { + $CFG_GLPI['injectable_types'] = []; + } + $asset_definition_manager = AssetDefinitionManager::getInstance(); + $asset_definition_manager->registerCapacity(new IsInjectableCapacity()); + $PLUGIN_HOOKS['csrf_compliant']['datainjection'] = true; $PLUGIN_HOOKS['migratetypes']['datainjection'] = 'plugin_datainjection_migratetypes_datainjection'; @@ -84,6 +94,8 @@ function plugin_init_datainjection() $PLUGIN_HOOKS['add_javascript']['datainjection'] = 'js/datainjection.js'; $INJECTABLE_TYPES = []; + +// plugin_datainjection_creationInjectableAssets(); } } @@ -116,7 +128,7 @@ function getTypesToInject(): void { /** @var array $INJECTABLE_TYPES */ /** @var array $PLUGIN_HOOKS */ - global $INJECTABLE_TYPES,$PLUGIN_HOOKS; + global $INJECTABLE_TYPES,$CFG_GLPI; if (count($INJECTABLE_TYPES)) { // already populated @@ -220,6 +232,101 @@ function getTypesToInject(): void ]; //Add plugins Plugin::doHook('plugin_datainjection_populate'); + + // Register injectable assets dynamically + plugin_datainjection_registerInjectableAssets(); + + plugin_datainjection_creationInjectableAssets(); +} + + +/** + * Register injection classes for each injectable asset definition + */ +function plugin_datainjection_registerInjectableAssets(): void +{ + /** @var array $INJECTABLE_TYPES */ + /** @var array $CFG_GLPI */ + global $INJECTABLE_TYPES, $CFG_GLPI; + + if (!isset($CFG_GLPI['injectable_types']) || empty($CFG_GLPI['injectable_types'])) { + return; + } + + // For each injectable asset definition, create and register a distinct class + foreach ($CFG_GLPI['injectable_types'] as $definition_id => $itemtype) { + // Get the asset definition to extract the system name + + $definition = AssetDefinition::getById($definition_id); + if ($definition->getAssetClassName() === $itemtype) { + // Use the system name to create a nice class name + $system_name = ucfirst($definition->fields['system_name']);//strtolower() + $injection_class = 'PluginDatainjection' . $system_name . 'AssetInjection'; + + // Only create if not already registered + if (!isset($INJECTABLE_TYPES[$injection_class])) { + $INJECTABLE_TYPES[$injection_class] = 'datainjection'; + } + } + } +} + +/** + * Register injection classes for each injectable asset definition + */ +function plugin_datainjection_creationInjectableAssets(): void +{ + /** @var array $CFG_GLPI */ + global $CFG_GLPI; + + if (!isset($CFG_GLPI['injectable_types']) || empty($CFG_GLPI['injectable_types'])) { + return; + } + + + // For each injectable asset definition, create and register a distinct class + foreach ($CFG_GLPI['injectable_types'] as $definition_id => $itemtype) { + $definition = AssetDefinition::getById($definition_id); + // Get the asset definition to extract the system name + if ($definition->getAssetClassName() === $itemtype) { + // Use the system name to create a nice class name + $system_name = ucfirst($definition->fields['system_name']);//strtolower() + $injection_class = 'PluginDatainjection' . $system_name . 'AssetInjection'; + + plugin_datainjection_createAssetInjectionClass($injection_class, $definition_id); + } + } +} + +/** + * Dynamically create an asset injection class + */ +function plugin_datainjection_createAssetInjectionClass(string $class_name, int $definition_id): void +{ + + // Check if class already exists + if (class_exists($class_name)) { + return; + } + + // Create the class dynamically (not final, so it can be extended) + $code = << Date: Thu, 7 May 2026 14:59:27 +0200 Subject: [PATCH 02/20] Add forget files --- src/Glpi/Asset/AssetInjection.php | 227 ++++++++++++++++++ .../Asset/Capacity/IsInjectableCapacity.php | 127 ++++++++++ 2 files changed, 354 insertions(+) create mode 100644 src/Glpi/Asset/AssetInjection.php create mode 100644 src/Glpi/Asset/Capacity/IsInjectableCapacity.php diff --git a/src/Glpi/Asset/AssetInjection.php b/src/Glpi/Asset/AssetInjection.php new file mode 100644 index 00000000..6d00a08b --- /dev/null +++ b/src/Glpi/Asset/AssetInjection.php @@ -0,0 +1,227 @@ +. + * + * --------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Datainjection\Glpi\Asset; + +use Glpi\Asset\Asset; +use Glpi\Asset\AssetDefinition; +use Glpi\Asset\AssetDefinitionManager; +use PluginDatainjectionCommonInjectionLib; +use PluginDatainjectionInjectionInterface; +use Search; + +use function Safe\preg_replace; + +abstract class AssetInjection extends Asset implements PluginDatainjectionInjectionInterface +{ + protected static string $definition_system_name = ''; + protected static int $fixed_asset_definition_id = 0; + + public static function getAssetDefinitionID(): int + { + + // If a fixed ID is set (for dynamically created classes), use it + if (static::$fixed_asset_definition_id > 0) { + return static::$fixed_asset_definition_id; + } + + return 0; + } + + /** + * Get the first active asset definition to use as system name + */ + protected static function getAssetDefinitionSystemName(): string + { + // Get first active asset definition from the database + // This ensures we have a valid definition to use + $manager = AssetDefinitionManager::getInstance(); + foreach ($manager->getDefinitions() as $definition) { + if ($definition->fields['id'] == static::getAssetDefinitionID()) { + return $definition->fields['system_name']; + } + } + + // Fallback to a default if none found + return ''; + } + + public static function getTypeName($nb = 0) + { + $manager = AssetDefinitionManager::getInstance(); + foreach ($manager->getDefinitions() as $definition) { + if ($definition->fields['id'] == static::getAssetDefinitionID()) { + return $definition->fields['label']; + } + } + // Fallback to a default if none found + return ''; + } + + public static function getDefinition(): AssetDefinition + { + if (empty(static::$definition_system_name)) { + static::$definition_system_name = static::getAssetDefinitionSystemName(); + } + + return parent::getDefinition(); + } + + + public static function getVirtualType($classname = null) + { + return 'Glpi\\CustomAsset\\' . static::getAssetDefinitionSystemName() . 'Asset'; + } + + public static function getVirtualTable($classname = null) + { + return getTableForItemType(self::getVirtualType()); + } + + public static function getTable($classname = null) + { + return getTableForItemType(Asset::class); + } + + public static function canCreate(): bool + { + return true; + } + + public function isPrimaryType() + { + return true; + } + + public function connectedTo() + { + return []; + } + + public function isNullable($field) + { + return true; + } + + + public static function replaceTableName(array $data): array + { + foreach ($data as $key => $value) { + if (is_array($value)) { + $data[$key] = self::replaceTableName($value); // récursif + } else { + if ($value === self::getTable()) { + $data[$key] = self::getVirtualTable(); + } + } + } + return $data; + } + /** + * @see plugins/datainjection/inc/PluginDatainjectionInjectionInterface::getOptions() + */ + public function getOptions($primary_type = '') + { + + // Build search options manually to avoid registration checks + // $tab = Search::getOptions(static::class); + $tab = Search::getOptions(self::getVirtualType()); + + $tab = self::replaceTableName($tab); + unset($tab[4]); + unset($tab[40]); + + $tab2 = [ +// [ +// 'id' => '4', +// 'table' => 'glpi_assets_assettypes', +// 'field' => 'name', +// 'linkfield' => 'assets_assettypes_id', +// 'name' => __('Type'), +// 'datatype' => 'dropdown', +// 'injectable' => true, +// ], +// [ +// 'id' => '40', +// 'table' => 'glpi_assets_assetmodels', +// 'field' => 'name', +// 'linkfield' => 'assets_assetmodels_id', +// 'name' => __('Model'), +// 'datatype' => 'dropdown', +// 'injectable' => true, +// ], + [ + 'id' => '200', + 'table' => $this->getTable(), + 'field' => 'assets_assetdefinitions_id', + 'linkfield' => 'assets_assetdefinitions_id', + 'name' => AssetDefinition::getTypeName(), + 'datatype' => 'number', + 'massiveaction' => false, + 'injectable' => true, + ], + ]; + + $tab = array_merge($tab, $tab2); + //Remove some options because some fields cannot be imported + $blacklist = PluginDatainjectionCommonInjectionLib::getBlacklistedOptions(static::class); + $blacklist = []; + $notimportable = ['300', '301']; + $options['ignore_fields'] = array_merge($blacklist, $notimportable); + + return PluginDatainjectionCommonInjectionLib::addToSearchOptions($tab, $options ?? [], $this); + } + + + /** + * @param array $fields_toinject array + **/ + public function getValueForAdditionalMandatoryFields($fields_toinject = []) + { + $fields_toinject[self::getVirtualType()]['assets_assetdefinitions_id'] = static::getAssetDefinitionID(); + + return $fields_toinject; + } + + /** + * @see plugins/datainjection/inc/PluginDatainjectionInjectionInterface::addOrUpdateObject() + */ + public function addOrUpdateObject($values = [], $options = []) + { + + $lib = new PluginDatainjectionCommonInjectionLib($this, $values, $options); + $lib->processAddOrUpdate(); + return $lib->getInjectionResults(); + } +} diff --git a/src/Glpi/Asset/Capacity/IsInjectableCapacity.php b/src/Glpi/Asset/Capacity/IsInjectableCapacity.php new file mode 100644 index 00000000..96c9560e --- /dev/null +++ b/src/Glpi/Asset/Capacity/IsInjectableCapacity.php @@ -0,0 +1,127 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2007-2023 by DataInjection plugin team. + * @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/pluginsGLPI/datainjection + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Datainjection\Glpi\Asset\Capacity; + +use Glpi\Asset\AssetDefinitionManager; +use Glpi\Asset\Capacity\AbstractCapacity; +use Glpi\Asset\CapacityConfig; +use Override; + +final class IsInjectableCapacity extends AbstractCapacity +{ + #[Override] + public function getLabel(): string + { + return __('Injectable', 'datainjection'); + } + + #[Override] + public function getIcon(): string + { + return 'ti ti-download'; + } + + #[Override] + public function getDescription(): string + { + return __("Inject objects list"); + } + +// public function getCloneRelations(): array +// { +// return [ +// Infocom::class, +// ]; +// } +// +// public function isUsed(string $classname): bool +// { +// return parent::isUsed($classname) +// && $this->countAssetsLinkedToPeerItem($classname, Infocom::class) > 0; +// } + + #[Override] + public function getCapacityUsageDescription(string $classname): string + { +// return sprintf( +// __('Used by %1$s of %2$s assets'), +// $this->countAssetsLinkedToPeerItem($classname, Infocom::class), +// $this->countAssets($classname) +// ); + return ''; + } + + public function onClassBootstrap(string $classname, CapacityConfig $config): void + { + global $CFG_GLPI; + +// if (!isset($CFG_GLPI['injectable_types'])) { +// $CFG_GLPI['injectable_types'] = []; +// } + $manager = AssetDefinitionManager::getInstance(); + foreach ($manager->getDefinitions() as $definition) { + $itemtype = $definition->getAssetClassName(); + if ($itemtype == $classname) { + if (!in_array($classname, $CFG_GLPI['injectable_types'])) { + $CFG_GLPI['injectable_types'][$definition->fields['id']] = $classname; + } + } + } + + $this->registerToTypeConfig('injectable_types', $classname); + +// CommonGLPI::registerStandardTab($classname, Infocom::class, 50); + } + + public function onCapacityDisabled(string $classname, CapacityConfig $config): void + { + // Unregister from infocom types +// $this->unregisterFromTypeConfig('injectable_types', $classname); +// +// // Delete related infocom data +// $infocom = new Infocom(); +// $infocom->deleteByCriteria(['itemtype' => $classname], force: true, history: false); +// +// $infocom_search_options = Infocom::rawSearchOptionsToAdd($classname); +// +// // Clean history related to infocoms +// $this->deleteFieldsLogs($classname, $infocom_search_options); +// +// // Clean display preferences +// $this->deleteDisplayPreferences($classname, $infocom_search_options); + } + +// #[Override] +// public function onObjectInstanciation(Asset $object, CapacityConfig $config): void +// { +// $object->fields['_added_by_hasinjectablecapacity'] = 'abc'; +// } +} From 269e08a57d36d1cd903959deb96d9eac51ae847a Mon Sep 17 00:00:00 2001 From: Thetsmr Date: Tue, 21 Jul 2026 11:51:06 +0200 Subject: [PATCH 03/20] Fix php-stan, php-cs-fixer fix, rector --- inc/commoninjectionlib.class.php | 21 +++-- inc/injectiontype.class.php | 3 +- phpstan.neon | 1 + setup.php | 4 +- src/Glpi/Asset/AssetInjection.php | 38 ++++----- .../Asset/Capacity/IsInjectableCapacity.php | 78 +++++++++---------- 6 files changed, 76 insertions(+), 69 deletions(-) diff --git a/inc/commoninjectionlib.class.php b/inc/commoninjectionlib.class.php index acbb40ec..56e3fde2 100644 --- a/inc/commoninjectionlib.class.php +++ b/inc/commoninjectionlib.class.php @@ -30,6 +30,7 @@ use Glpi\Asset\Asset; use Glpi\Exception\Http\HttpException; use Glpi\Features\AssignableItem; +use GlpiPlugin\Datainjection\Glpi\Asset\AssetInjection; use function Safe\preg_match; use function Safe\preg_replace; @@ -335,7 +336,7 @@ public static function getItemtypeByInjection($injectionClassName) public static function getItemtypeByInjectionClass($injectionClass) { - if (is_a($injectionClass, Asset::class, true)) { + if ($injectionClass instanceof AssetInjection) { return Toolbox::ucfirst(getItemTypeForTable($injectionClass->getVirtualTable())); } return Toolbox::ucfirst(getItemTypeForTable($injectionClass->getTable())); @@ -347,7 +348,10 @@ public static function getItemtypeByInjectionClass($injectionClass) * * @param string $itemtype the itemtype * - * @return PluginDatainjectionInjectionInterface the injection class instance + * Every injection class both implements the interface and extends CommonDBTM, + * so the returned instance exposes the CommonDBTM API (getTable(), ...) too. + * + * @return PluginDatainjectionInjectionInterface&CommonDBTM the injection class instance */ public static function getInjectionClassInstance($itemtype) { @@ -364,7 +368,10 @@ public static function getInjectionClassInstance($itemtype) } - if (!is_a($injectionClass, PluginDatainjectionInjectionInterface::class, true)) { + if ( + !is_a($injectionClass, PluginDatainjectionInjectionInterface::class, true) + || !is_a($injectionClass, CommonDBTM::class, true) + ) { throw new HttpException(500, 'Class ' . $injectionClass . ' is not a valid class'); } return new $injectionClass(); @@ -2003,11 +2010,9 @@ private function dataAlreadyInDB($injectionClass, $itemtype) } } - if (is_a($injectionClass, Asset::class, true)) { - if (method_exists($injectionClass, 'getAssetDefinitionID')) { - $assets_assetdefinitions_id = $injectionClass->getAssetDefinitionID(); - $where .= " AND `assets_assetdefinitions_id` = '" . $assets_assetdefinitions_id . "'"; - } + if (is_a($injectionClass, Asset::class, true) && method_exists($injectionClass, 'getAssetDefinitionID')) { + $assets_assetdefinitions_id = $injectionClass->getAssetDefinitionID(); + $where .= " AND `assets_assetdefinitions_id` = '" . $assets_assetdefinitions_id . "'"; } //Add additional parameters specific to this itemtype (or function checkPresent exists) diff --git a/inc/injectiontype.class.php b/inc/injectiontype.class.php index d74aa3cf..33f9be85 100644 --- a/inc/injectiontype.class.php +++ b/inc/injectiontype.class.php @@ -28,6 +28,7 @@ * ------------------------------------------------------------------------- */ use Glpi\Exception\Http\HttpException; +use GlpiPlugin\Datainjection\Glpi\Asset\AssetInjection; use function Safe\json_decode; use function Safe\json_encode; @@ -79,7 +80,7 @@ public static function getItemtypes($only_primary = false) } $name .= call_user_func([$type, 'getTypeName']); - if ($typename == "GlpiPlugin\Datainjection\Glpi\Asset\AssetInjection") { + if ($instance instanceof AssetInjection) { $typename = $instance->getVirtualType(); } $values[$typename] = $name; diff --git a/phpstan.neon b/phpstan.neon index db69ea19..275425e8 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -9,6 +9,7 @@ parameters: - ajax - front - inc + - src - hook.php - setup.php scanDirectories: diff --git a/setup.php b/setup.php index c7f834e4..b056529f 100644 --- a/setup.php +++ b/setup.php @@ -95,7 +95,7 @@ function plugin_init_datainjection() $INJECTABLE_TYPES = []; -// plugin_datainjection_creationInjectableAssets(); + // plugin_datainjection_creationInjectableAssets(); } } @@ -127,7 +127,7 @@ function plugin_version_datainjection() function getTypesToInject(): void { /** @var array $INJECTABLE_TYPES */ - /** @var array $PLUGIN_HOOKS */ + /** @var array $CFG_GLPI */ global $INJECTABLE_TYPES,$CFG_GLPI; if (count($INJECTABLE_TYPES)) { diff --git a/src/Glpi/Asset/AssetInjection.php b/src/Glpi/Asset/AssetInjection.php index 6d00a08b..7a9c58f1 100644 --- a/src/Glpi/Asset/AssetInjection.php +++ b/src/Glpi/Asset/AssetInjection.php @@ -163,24 +163,24 @@ public function getOptions($primary_type = '') unset($tab[40]); $tab2 = [ -// [ -// 'id' => '4', -// 'table' => 'glpi_assets_assettypes', -// 'field' => 'name', -// 'linkfield' => 'assets_assettypes_id', -// 'name' => __('Type'), -// 'datatype' => 'dropdown', -// 'injectable' => true, -// ], -// [ -// 'id' => '40', -// 'table' => 'glpi_assets_assetmodels', -// 'field' => 'name', -// 'linkfield' => 'assets_assetmodels_id', -// 'name' => __('Model'), -// 'datatype' => 'dropdown', -// 'injectable' => true, -// ], + // [ + // 'id' => '4', + // 'table' => 'glpi_assets_assettypes', + // 'field' => 'name', + // 'linkfield' => 'assets_assettypes_id', + // 'name' => __('Type'), + // 'datatype' => 'dropdown', + // 'injectable' => true, + // ], + // [ + // 'id' => '40', + // 'table' => 'glpi_assets_assetmodels', + // 'field' => 'name', + // 'linkfield' => 'assets_assetmodels_id', + // 'name' => __('Model'), + // 'datatype' => 'dropdown', + // 'injectable' => true, + // ], [ 'id' => '200', 'table' => $this->getTable(), @@ -200,7 +200,7 @@ public function getOptions($primary_type = '') $notimportable = ['300', '301']; $options['ignore_fields'] = array_merge($blacklist, $notimportable); - return PluginDatainjectionCommonInjectionLib::addToSearchOptions($tab, $options ?? [], $this); + return PluginDatainjectionCommonInjectionLib::addToSearchOptions($tab, $options, $this); } diff --git a/src/Glpi/Asset/Capacity/IsInjectableCapacity.php b/src/Glpi/Asset/Capacity/IsInjectableCapacity.php index 96c9560e..37a9f0a3 100644 --- a/src/Glpi/Asset/Capacity/IsInjectableCapacity.php +++ b/src/Glpi/Asset/Capacity/IsInjectableCapacity.php @@ -55,27 +55,27 @@ public function getDescription(): string return __("Inject objects list"); } -// public function getCloneRelations(): array -// { -// return [ -// Infocom::class, -// ]; -// } -// -// public function isUsed(string $classname): bool -// { -// return parent::isUsed($classname) -// && $this->countAssetsLinkedToPeerItem($classname, Infocom::class) > 0; -// } + // public function getCloneRelations(): array + // { + // return [ + // Infocom::class, + // ]; + // } + // + // public function isUsed(string $classname): bool + // { + // return parent::isUsed($classname) + // && $this->countAssetsLinkedToPeerItem($classname, Infocom::class) > 0; + // } #[Override] public function getCapacityUsageDescription(string $classname): string { -// return sprintf( -// __('Used by %1$s of %2$s assets'), -// $this->countAssetsLinkedToPeerItem($classname, Infocom::class), -// $this->countAssets($classname) -// ); + // return sprintf( + // __('Used by %1$s of %2$s assets'), + // $this->countAssetsLinkedToPeerItem($classname, Infocom::class), + // $this->countAssets($classname) + // ); return ''; } @@ -83,9 +83,9 @@ public function onClassBootstrap(string $classname, CapacityConfig $config): voi { global $CFG_GLPI; -// if (!isset($CFG_GLPI['injectable_types'])) { -// $CFG_GLPI['injectable_types'] = []; -// } + // if (!isset($CFG_GLPI['injectable_types'])) { + // $CFG_GLPI['injectable_types'] = []; + // } $manager = AssetDefinitionManager::getInstance(); foreach ($manager->getDefinitions() as $definition) { $itemtype = $definition->getAssetClassName(); @@ -98,30 +98,30 @@ public function onClassBootstrap(string $classname, CapacityConfig $config): voi $this->registerToTypeConfig('injectable_types', $classname); -// CommonGLPI::registerStandardTab($classname, Infocom::class, 50); + // CommonGLPI::registerStandardTab($classname, Infocom::class, 50); } public function onCapacityDisabled(string $classname, CapacityConfig $config): void { // Unregister from infocom types -// $this->unregisterFromTypeConfig('injectable_types', $classname); -// -// // Delete related infocom data -// $infocom = new Infocom(); -// $infocom->deleteByCriteria(['itemtype' => $classname], force: true, history: false); -// -// $infocom_search_options = Infocom::rawSearchOptionsToAdd($classname); -// -// // Clean history related to infocoms -// $this->deleteFieldsLogs($classname, $infocom_search_options); -// -// // Clean display preferences -// $this->deleteDisplayPreferences($classname, $infocom_search_options); + // $this->unregisterFromTypeConfig('injectable_types', $classname); + // + // // Delete related infocom data + // $infocom = new Infocom(); + // $infocom->deleteByCriteria(['itemtype' => $classname], force: true, history: false); + // + // $infocom_search_options = Infocom::rawSearchOptionsToAdd($classname); + // + // // Clean history related to infocoms + // $this->deleteFieldsLogs($classname, $infocom_search_options); + // + // // Clean display preferences + // $this->deleteDisplayPreferences($classname, $infocom_search_options); } -// #[Override] -// public function onObjectInstanciation(Asset $object, CapacityConfig $config): void -// { -// $object->fields['_added_by_hasinjectablecapacity'] = 'abc'; -// } + // #[Override] + // public function onObjectInstanciation(Asset $object, CapacityConfig $config): void + // { + // $object->fields['_added_by_hasinjectablecapacity'] = 'abc'; + // } } From ed80738f7ba07c9eeaf73d49f5164c4216c684b5 Mon Sep 17 00:00:00 2001 From: Thetsmr Date: Tue, 21 Jul 2026 12:04:48 +0200 Subject: [PATCH 04/20] Update header --- src/Glpi/Asset/AssetInjection.php | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/Glpi/Asset/AssetInjection.php b/src/Glpi/Asset/AssetInjection.php index 7a9c58f1..7653613a 100644 --- a/src/Glpi/Asset/AssetInjection.php +++ b/src/Glpi/Asset/AssetInjection.php @@ -1,35 +1,31 @@ . - * - * --------------------------------------------------------------------- + * along with DataInjection. If not, see . + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2007-2023 by DataInjection plugin team. + * @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/pluginsGLPI/datainjection + * ------------------------------------------------------------------------- */ namespace GlpiPlugin\Datainjection\Glpi\Asset; From 33fffc83543f6a40bfbf6bd3931017b396c597c5 Mon Sep 17 00:00:00 2001 From: Thetsmr Date: Tue, 21 Jul 2026 12:20:59 +0200 Subject: [PATCH 05/20] Fix reactor --- inc/commoninjectionlib.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/commoninjectionlib.class.php b/inc/commoninjectionlib.class.php index 9c1d4017..fa20c42c 100644 --- a/inc/commoninjectionlib.class.php +++ b/inc/commoninjectionlib.class.php @@ -2015,7 +2015,7 @@ private function dataAlreadyInDB($injectionClass, $itemtype) } } - if (is_a($injectionClass, Asset::class, true) && method_exists($injectionClass, 'getAssetDefinitionID')) { + if ($injectionClass instanceof Asset && method_exists($injectionClass, 'getAssetDefinitionID')) { $assets_assetdefinitions_id = $injectionClass->getAssetDefinitionID(); $where .= " AND `assets_assetdefinitions_id` = '" . $assets_assetdefinitions_id . "'"; } From 730276d8934b659db8c6c317de3cd69f7a69e07d Mon Sep 17 00:00:00 2001 From: Thetsmr Date: Tue, 21 Jul 2026 12:24:06 +0200 Subject: [PATCH 06/20] Other fix phpstan --- inc/commoninjectionlib.class.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/inc/commoninjectionlib.class.php b/inc/commoninjectionlib.class.php index fa20c42c..7e49e5e1 100644 --- a/inc/commoninjectionlib.class.php +++ b/inc/commoninjectionlib.class.php @@ -2016,8 +2016,7 @@ private function dataAlreadyInDB($injectionClass, $itemtype) } if ($injectionClass instanceof Asset && method_exists($injectionClass, 'getAssetDefinitionID')) { - $assets_assetdefinitions_id = $injectionClass->getAssetDefinitionID(); - $where .= " AND `assets_assetdefinitions_id` = '" . $assets_assetdefinitions_id . "'"; + $where['assets_assetdefinitions_id'] = $injectionClass->getAssetDefinitionID(); } //Add additional parameters specific to this itemtype (or function checkPresent exists) From 17230532f3967ac9ac7313cad58eee6de509f364 Mon Sep 17 00:00:00 2001 From: Thetsmr Date: Tue, 21 Jul 2026 12:30:31 +0200 Subject: [PATCH 07/20] Update ChangeLog & .php-cs-fixer.php --- CHANGELOG.md | 4 ++++ inc/commoninjectionlib.class.php | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c9c8ee4..7ffa3c06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [UNRELEASED] +### Added + +- Permit to Inject GlpiAsset + ### Fixed - Fix : confirm dialog js escaping diff --git a/inc/commoninjectionlib.class.php b/inc/commoninjectionlib.class.php index 7e49e5e1..5ac07073 100644 --- a/inc/commoninjectionlib.class.php +++ b/inc/commoninjectionlib.class.php @@ -28,7 +28,6 @@ * ------------------------------------------------------------------------- */ use Glpi\Asset\Asset; - use Glpi\DBAL\QueryExpression; use Glpi\DBAL\QuerySubQuery; use Glpi\Exception\Http\HttpException; From 612f0d5294e50cfb6e3947e72575e54eb3a0015f Mon Sep 17 00:00:00 2001 From: Thetsmr Date: Mon, 27 Jul 2026 15:52:59 +0200 Subject: [PATCH 08/20] Add new feature inject Asset test --- inc/commoninjectionlib.class.php | 7 +- tests/unit/AssetInjectionTest.php | 137 ++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 tests/unit/AssetInjectionTest.php diff --git a/inc/commoninjectionlib.class.php b/inc/commoninjectionlib.class.php index 5ac07073..d2aee186 100644 --- a/inc/commoninjectionlib.class.php +++ b/inc/commoninjectionlib.class.php @@ -339,7 +339,12 @@ public static function getItemtypeByInjectionClass($injectionClass) { if ($injectionClass instanceof AssetInjection) { - return Toolbox::ucfirst(getItemTypeForTable($injectionClass->getVirtualTable())); + // Custom assets all share the "glpi_assets_assets" table, whose canonical + // itemtype is the *abstract* Glpi\Asset\Asset. Resolving through the table + // (getItemTypeForTable) is therefore unreliable and can return that abstract + // class, which is not instantiable. The injection class already knows its + // concrete custom-asset itemtype, so use it directly. + return $injectionClass::getVirtualType(); } return Toolbox::ucfirst(getItemTypeForTable($injectionClass->getTable())); } diff --git a/tests/unit/AssetInjectionTest.php b/tests/unit/AssetInjectionTest.php new file mode 100644 index 00000000..59695794 --- /dev/null +++ b/tests/unit/AssetInjectionTest.php @@ -0,0 +1,137 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2007-2023 by DataInjection plugin team. + * @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/pluginsGLPI/datainjection + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Datainjection\Tests\Unit; + +use Glpi\Asset\AssetDefinitionManager; +use Glpi\Asset\Capacity; +use Glpi\Tests\DbTestCase; +use GlpiPlugin\Datainjection\Glpi\Asset\Capacity\IsInjectableCapacity; +use PluginDatainjectionCommonInjectionLib; + +final class AssetInjectionTest extends DbTestCase +{ + /** + * End-to-end injection into a custom GlpiAsset definition: + * enable IsInjectableCapacity on a definition, let the plugin generate the + * dedicated AssetInjection subclass, inject a row through it and assert the + * resulting custom asset item is persisted and tied to the definition. + */ + public function testRowIsInjectedIntoInjectableCustomAssetDefinition(): void + { + $this->login(); + + // The AssetDefinitionManager singleton is rebuilt between tests and only + // carries core capacities; the plugin capacity is registered from + // plugin_init_datainjection() at runtime, so re-register it explicitly here. + $manager = AssetDefinitionManager::getInstance(); + $manager->registerCapacity(new IsInjectableCapacity()); + + // Create a custom asset definition with the "Injectable" capacity enabled. + $system_name = 'Injectableasset'; + $definition = $this->initAssetDefinition( + $system_name, + [new Capacity(name: IsInjectableCapacity::class)], + ); + + $asset_itemtype = $definition->getAssetClassName(); + + // Reproduce the runtime registration pipeline that turns an injectable + // definition into a concrete injection class: + // - bootDefinitions() re-reads the new definition and triggers + // IsInjectableCapacity::onClassBootstrap(), which populates injectable_types; + // - the two registration helpers then eval() the dedicated AssetInjection subclass. + /** @var array $CFG_GLPI */ + global $CFG_GLPI; + $CFG_GLPI['injectable_types'] = []; + $manager->bootDefinitions(); + + self::assertArrayHasKey( + $definition->getID(), + $CFG_GLPI['injectable_types'], + 'IsInjectableCapacity should register the definition as an injectable type', + ); + self::assertSame($asset_itemtype, $CFG_GLPI['injectable_types'][$definition->getID()]); + + plugin_datainjection_registerInjectableAssets(); + plugin_datainjection_creationInjectableAssets(); + + // The subclass name is built exactly the way setup.php builds it. + $injection_classname = 'PluginDatainjection' . ucfirst($system_name) . 'AssetInjection'; + self::assertTrue( + class_exists($injection_classname), + "Injection class {$injection_classname} should have been generated", + ); + + $injection = new $injection_classname(); + + // The lib keys both the injected values and the results by the itemtype it + // derives from the injection class; reuse that exact value to avoid any + // table round-trip mismatch. + $primary_type = PluginDatainjectionCommonInjectionLib::getItemtypeByInjectionClass($injection); + self::assertSame($asset_itemtype, $primary_type); + + $asset_name = 'Injected custom asset'; + $results = $injection->addOrUpdateObject( + [ + $primary_type => [ + 'name' => $asset_name, + ], + ], + [ + 'rights' => [ + 'can_add' => true, + 'can_update' => true, + 'add_dropdown' => true, + ], + 'mandatory_fields' => [ + $primary_type => ['name' => true], + ], + 'entities_id' => 0, + ], + ); + + self::assertSame(PluginDatainjectionCommonInjectionLib::SUCCESS, $results['status']); + self::assertSame(PluginDatainjectionCommonInjectionLib::IMPORT_ADD, $results['type']); + + $asset_id = $results[$primary_type] ?? null; + self::assertNotNull($asset_id, 'The injection result should expose the created asset id'); + self::assertGreaterThan(0, (int) $asset_id); + + // The row must exist as a real custom asset, tied to our definition. + $asset = new $asset_itemtype(); + self::assertTrue($asset->getFromDB((int) $asset_id)); + self::assertSame($asset_name, $asset->fields['name']); + self::assertSame( + $definition->getID(), + (int) $asset->fields['assets_assetdefinitions_id'], + ); + } +} From 99bbe17dfb56a7c93127bc0e0b0f3f2deff4c7ed Mon Sep 17 00:00:00 2001 From: Xavier CAILLAUD Date: Mon, 17 Aug 2026 11:55:20 +0200 Subject: [PATCH 09/20] Update src/Glpi/Asset/AssetInjection.php Co-authored-by: Romain B. <8530352+Rom1-B@users.noreply.github.com> --- src/Glpi/Asset/AssetInjection.php | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/Glpi/Asset/AssetInjection.php b/src/Glpi/Asset/AssetInjection.php index 7653613a..5aad0b88 100644 --- a/src/Glpi/Asset/AssetInjection.php +++ b/src/Glpi/Asset/AssetInjection.php @@ -159,24 +159,6 @@ public function getOptions($primary_type = '') unset($tab[40]); $tab2 = [ - // [ - // 'id' => '4', - // 'table' => 'glpi_assets_assettypes', - // 'field' => 'name', - // 'linkfield' => 'assets_assettypes_id', - // 'name' => __('Type'), - // 'datatype' => 'dropdown', - // 'injectable' => true, - // ], - // [ - // 'id' => '40', - // 'table' => 'glpi_assets_assetmodels', - // 'field' => 'name', - // 'linkfield' => 'assets_assetmodels_id', - // 'name' => __('Model'), - // 'datatype' => 'dropdown', - // 'injectable' => true, - // ], [ 'id' => '200', 'table' => $this->getTable(), From bf37ab3bd7413bf2eb7180450771d1a3fa86ba61 Mon Sep 17 00:00:00 2001 From: Xavier CAILLAUD Date: Mon, 17 Aug 2026 11:55:48 +0200 Subject: [PATCH 10/20] Update src/Glpi/Asset/AssetInjection.php Co-authored-by: Romain B. <8530352+Rom1-B@users.noreply.github.com> --- src/Glpi/Asset/AssetInjection.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Glpi/Asset/AssetInjection.php b/src/Glpi/Asset/AssetInjection.php index 5aad0b88..3d91ec55 100644 --- a/src/Glpi/Asset/AssetInjection.php +++ b/src/Glpi/Asset/AssetInjection.php @@ -112,7 +112,8 @@ public static function getTable($classname = null) public static function canCreate(): bool { - return true; + $virtual_type = static::getVirtualType(); + return $virtual_type::canCreate(); } public function isPrimaryType() From b3ffc435c42d6c724b3a4082be7f2f642e181eb8 Mon Sep 17 00:00:00 2001 From: Xavier CAILLAUD Date: Mon, 17 Aug 2026 11:56:01 +0200 Subject: [PATCH 11/20] Update src/Glpi/Asset/AssetInjection.php Co-authored-by: Romain B. <8530352+Rom1-B@users.noreply.github.com> --- src/Glpi/Asset/AssetInjection.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Glpi/Asset/AssetInjection.php b/src/Glpi/Asset/AssetInjection.php index 3d91ec55..6561339f 100644 --- a/src/Glpi/Asset/AssetInjection.php +++ b/src/Glpi/Asset/AssetInjection.php @@ -137,10 +137,8 @@ public static function replaceTableName(array $data): array foreach ($data as $key => $value) { if (is_array($value)) { $data[$key] = self::replaceTableName($value); // récursif - } else { - if ($value === self::getTable()) { - $data[$key] = self::getVirtualTable(); - } + } elseif ($value === self::getTable()) { + $data[$key] = self::getVirtualTable(); } } return $data; From f4cb5f831ffee4d801b1bd1b7d1cf733de67ea2b Mon Sep 17 00:00:00 2001 From: Xavier CAILLAUD Date: Mon, 17 Aug 2026 11:56:23 +0200 Subject: [PATCH 12/20] Update src/Glpi/Asset/AssetInjection.php Co-authored-by: Romain B. <8530352+Rom1-B@users.noreply.github.com> --- src/Glpi/Asset/AssetInjection.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Glpi/Asset/AssetInjection.php b/src/Glpi/Asset/AssetInjection.php index 6561339f..35e8bcfd 100644 --- a/src/Glpi/Asset/AssetInjection.php +++ b/src/Glpi/Asset/AssetInjection.php @@ -170,10 +170,11 @@ public function getOptions($primary_type = '') ], ]; - $tab = array_merge($tab, $tab2); + foreach ($tab2 as $entry) { + $tab[(int) $entry['id']] = $entry; + } //Remove some options because some fields cannot be imported $blacklist = PluginDatainjectionCommonInjectionLib::getBlacklistedOptions(static::class); - $blacklist = []; $notimportable = ['300', '301']; $options['ignore_fields'] = array_merge($blacklist, $notimportable); From d8c459c88fd00f6237944c7755dc2f539f30caab Mon Sep 17 00:00:00 2001 From: Xavier CAILLAUD Date: Wed, 19 Aug 2026 12:02:20 +0200 Subject: [PATCH 13/20] Update setup.php Co-authored-by: Stanislas --- setup.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/setup.php b/setup.php index b728ea2b..380988a0 100644 --- a/setup.php +++ b/setup.php @@ -258,6 +258,9 @@ function plugin_datainjection_registerInjectableAssets(): void // Get the asset definition to extract the system name $definition = AssetDefinition::getById($definition_id); + if ($definition === false || $definition === null) { + continue; + } if ($definition->getAssetClassName() === $itemtype) { // Use the system name to create a nice class name $system_name = ucfirst($definition->fields['system_name']);//strtolower() From 336c563443cf70145d90ec23de2a8bdb1e031328 Mon Sep 17 00:00:00 2001 From: Xavier CAILLAUD Date: Wed, 19 Aug 2026 12:02:31 +0200 Subject: [PATCH 14/20] Update setup.php Co-authored-by: Stanislas --- setup.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/setup.php b/setup.php index 380988a0..aa4807a8 100644 --- a/setup.php +++ b/setup.php @@ -328,6 +328,9 @@ public static function getAssetDefinitionID(): int } PHP; + if (!preg_match('/^[A-Za-z][A-Za-z0-9_]*$/', $class_name)) { + return; + } eval($code); } From 452f6ed2c81ecef38125b2b034676d488f166618 Mon Sep 17 00:00:00 2001 From: Xavier CAILLAUD Date: Wed, 19 Aug 2026 12:02:55 +0200 Subject: [PATCH 15/20] Update src/Glpi/Asset/AssetInjection.php Co-authored-by: Stanislas --- src/Glpi/Asset/AssetInjection.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Glpi/Asset/AssetInjection.php b/src/Glpi/Asset/AssetInjection.php index 35e8bcfd..d0f88990 100644 --- a/src/Glpi/Asset/AssetInjection.php +++ b/src/Glpi/Asset/AssetInjection.php @@ -150,7 +150,6 @@ public function getOptions($primary_type = '') { // Build search options manually to avoid registration checks - // $tab = Search::getOptions(static::class); $tab = Search::getOptions(self::getVirtualType()); $tab = self::replaceTableName($tab); From d531a7f07a445baecacfffa1ecfdaf4b2bf6f381 Mon Sep 17 00:00:00 2001 From: Xavier CAILLAUD Date: Wed, 19 Aug 2026 12:03:04 +0200 Subject: [PATCH 16/20] Update setup.php Co-authored-by: Stanislas --- setup.php | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.php b/setup.php index aa4807a8..0e922884 100644 --- a/setup.php +++ b/setup.php @@ -95,7 +95,6 @@ function plugin_init_datainjection() $INJECTABLE_TYPES = []; - // plugin_datainjection_creationInjectableAssets(); } } From 8d5fc516c0630c0b2ff904abd25ae6a9b8d44101 Mon Sep 17 00:00:00 2001 From: Thetsmr Date: Wed, 19 Aug 2026 12:09:32 +0200 Subject: [PATCH 17/20] Clean files --- src/Glpi/Asset/AssetInjection.php | 2 - .../Asset/Capacity/IsInjectableCapacity.php | 48 +------------------ 2 files changed, 1 insertion(+), 49 deletions(-) diff --git a/src/Glpi/Asset/AssetInjection.php b/src/Glpi/Asset/AssetInjection.php index d0f88990..0dc8f57a 100644 --- a/src/Glpi/Asset/AssetInjection.php +++ b/src/Glpi/Asset/AssetInjection.php @@ -37,8 +37,6 @@ use PluginDatainjectionInjectionInterface; use Search; -use function Safe\preg_replace; - abstract class AssetInjection extends Asset implements PluginDatainjectionInjectionInterface { protected static string $definition_system_name = ''; diff --git a/src/Glpi/Asset/Capacity/IsInjectableCapacity.php b/src/Glpi/Asset/Capacity/IsInjectableCapacity.php index 37a9f0a3..aea4aaf2 100644 --- a/src/Glpi/Asset/Capacity/IsInjectableCapacity.php +++ b/src/Glpi/Asset/Capacity/IsInjectableCapacity.php @@ -52,32 +52,9 @@ public function getIcon(): string #[Override] public function getDescription(): string { - return __("Inject objects list"); + return __("Inject objects list", 'datainjection'); } - // public function getCloneRelations(): array - // { - // return [ - // Infocom::class, - // ]; - // } - // - // public function isUsed(string $classname): bool - // { - // return parent::isUsed($classname) - // && $this->countAssetsLinkedToPeerItem($classname, Infocom::class) > 0; - // } - - #[Override] - public function getCapacityUsageDescription(string $classname): string - { - // return sprintf( - // __('Used by %1$s of %2$s assets'), - // $this->countAssetsLinkedToPeerItem($classname, Infocom::class), - // $this->countAssets($classname) - // ); - return ''; - } public function onClassBootstrap(string $classname, CapacityConfig $config): void { @@ -101,27 +78,4 @@ public function onClassBootstrap(string $classname, CapacityConfig $config): voi // CommonGLPI::registerStandardTab($classname, Infocom::class, 50); } - public function onCapacityDisabled(string $classname, CapacityConfig $config): void - { - // Unregister from infocom types - // $this->unregisterFromTypeConfig('injectable_types', $classname); - // - // // Delete related infocom data - // $infocom = new Infocom(); - // $infocom->deleteByCriteria(['itemtype' => $classname], force: true, history: false); - // - // $infocom_search_options = Infocom::rawSearchOptionsToAdd($classname); - // - // // Clean history related to infocoms - // $this->deleteFieldsLogs($classname, $infocom_search_options); - // - // // Clean display preferences - // $this->deleteDisplayPreferences($classname, $infocom_search_options); - } - - // #[Override] - // public function onObjectInstanciation(Asset $object, CapacityConfig $config): void - // { - // $object->fields['_added_by_hasinjectablecapacity'] = 'abc'; - // } } From f26f408af81582d26b0bc00e8dedb31c860946a5 Mon Sep 17 00:00:00 2001 From: Thetsmr Date: Wed, 19 Aug 2026 12:18:12 +0200 Subject: [PATCH 18/20] Fix install --- src/Glpi/Asset/AssetInjection.php | 1 + src/Glpi/Asset/Capacity/IsInjectableCapacity.php | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/Glpi/Asset/AssetInjection.php b/src/Glpi/Asset/AssetInjection.php index 0dc8f57a..9fc0d233 100644 --- a/src/Glpi/Asset/AssetInjection.php +++ b/src/Glpi/Asset/AssetInjection.php @@ -173,6 +173,7 @@ public function getOptions($primary_type = '') //Remove some options because some fields cannot be imported $blacklist = PluginDatainjectionCommonInjectionLib::getBlacklistedOptions(static::class); $notimportable = ['300', '301']; + $options = []; $options['ignore_fields'] = array_merge($blacklist, $notimportable); return PluginDatainjectionCommonInjectionLib::addToSearchOptions($tab, $options, $this); diff --git a/src/Glpi/Asset/Capacity/IsInjectableCapacity.php b/src/Glpi/Asset/Capacity/IsInjectableCapacity.php index aea4aaf2..863171aa 100644 --- a/src/Glpi/Asset/Capacity/IsInjectableCapacity.php +++ b/src/Glpi/Asset/Capacity/IsInjectableCapacity.php @@ -78,4 +78,8 @@ public function onClassBootstrap(string $classname, CapacityConfig $config): voi // CommonGLPI::registerStandardTab($classname, Infocom::class, 50); } + public function getCapacityUsageDescription(string $classname): string + { + // TODO: Implement getCapacityUsageDescription() method. + } } From 99a17182000f0865361486853c6ff112c3bfd3dd Mon Sep 17 00:00:00 2001 From: Thetsmr Date: Wed, 19 Aug 2026 12:23:07 +0200 Subject: [PATCH 19/20] Add fixes --- setup.php | 1 + src/Glpi/Asset/Capacity/IsInjectableCapacity.php | 1 + 2 files changed, 2 insertions(+) diff --git a/setup.php b/setup.php index 0e922884..3e92afce 100644 --- a/setup.php +++ b/setup.php @@ -34,6 +34,7 @@ use function Safe\define; use function Safe\mkdir; +use function Safe\preg_match; define('PLUGIN_DATAINJECTION_VERSION', '2.15.10'); diff --git a/src/Glpi/Asset/Capacity/IsInjectableCapacity.php b/src/Glpi/Asset/Capacity/IsInjectableCapacity.php index 863171aa..e3bd07ce 100644 --- a/src/Glpi/Asset/Capacity/IsInjectableCapacity.php +++ b/src/Glpi/Asset/Capacity/IsInjectableCapacity.php @@ -81,5 +81,6 @@ public function onClassBootstrap(string $classname, CapacityConfig $config): voi public function getCapacityUsageDescription(string $classname): string { // TODO: Implement getCapacityUsageDescription() method. + return ''; } } From bab3a11d14537c2b01b9a7e80647f127e02f3a48 Mon Sep 17 00:00:00 2001 From: Thetsmr Date: Wed, 19 Aug 2026 12:27:36 +0200 Subject: [PATCH 20/20] Fix Rector --- setup.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.php b/setup.php index 3e92afce..fb6f6f20 100644 --- a/setup.php +++ b/setup.php @@ -328,7 +328,7 @@ public static function getAssetDefinitionID(): int } PHP; - if (!preg_match('/^[A-Za-z][A-Za-z0-9_]*$/', $class_name)) { + if (preg_match('/^[A-Za-z][A-Za-z0-9_]*$/', $class_name) === 0) { return; } eval($code);