From ea035d581402b811b1d508847aedf312007fe04f Mon Sep 17 00:00:00 2001 From: MyuTsu Date: Wed, 20 May 2026 17:10:29 +0200 Subject: [PATCH 1/7] fix(migration): ensure GenericObject type dropdowns are migrated --- inc/container.class.php | 33 +-------------------------------- inc/field.class.php | 40 ++++++++++++++++++++++++++++++++++++++++ inc/migration.class.php | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 32 deletions(-) diff --git a/inc/container.class.php b/inc/container.class.php index 6f38c4dd..703d81fc 100644 --- a/inc/container.class.php +++ b/inc/container.class.php @@ -163,38 +163,7 @@ public static function installBaseData(Migration $migration, $version) // Get itemtypes from PluginGenericobject if ($DB->tableExists('glpi_plugin_genericobject_types')) { - // Check GenericObject version - $genericobject_info = Plugin::getInfo('genericobject'); - if (version_compare($genericobject_info['version'] ?? '0', '3.0.0', '<')) { - throw new RuntimeException( - 'GenericObject plugin cannot be migrated. Please update it to the latest version.', - ); - } - - // Check glpi_plugin_genericobject_types table - if (!$DB->fieldExists('glpi_plugin_genericobject_types', 'itemtype')) { - throw new RuntimeException( - 'Integrity error on the glpi_plugin_genericobject_types table from the GenericObject plugin.', - ); - } - - $migration_genericobject_itemtype = []; - $result = $DB->request(['FROM' => 'glpi_plugin_genericobject_types']); - foreach ($result as $type) { - $customasset_classname = 'Glpi\\\\CustomAsset\\\\' . $type['name'] . 'Asset'; - if (str_ends_with((string) $type['itemtype'], 'Model')) { - $customasset_classname = 'Glpi\\\\CustomAsset\\\\' . $type['name'] . 'AssetModel'; - } elseif (str_ends_with((string) $type['itemtype'], 'Type')) { - $customasset_classname = 'Glpi\\\\CustomAsset\\\\' . $type['name'] . 'AssetType'; - } - - $migration_genericobject_itemtype[$type['itemtype']] = [ - 'genericobject_itemtype' => $type['itemtype'], - 'itemtype' => $customasset_classname, - 'genericobject_name' => $type['name'], - 'name' => $type['name'] . 'Asset', - ]; - } + $migration_genericobject_itemtype = PluginFieldsMigration::getGenericObjectTypes(); // Get containers with PluginGenericobject itemtype $result = $DB->request([ diff --git a/inc/field.class.php b/inc/field.class.php index 7f47d65b..87db00bd 100644 --- a/inc/field.class.php +++ b/inc/field.class.php @@ -28,6 +28,7 @@ * ------------------------------------------------------------------------- */ use Glpi\Application\View\TemplateRenderer; +use Glpi\Asset\AssetDefinitionManager; use Glpi\DBAL\QueryExpression; use Glpi\Features\Clonable; use Glpi\Form\Question; @@ -153,6 +154,45 @@ public static function installBaseData(Migration $migration, $version) $migration->addConfig(['stable_search_options' => 'yes'], 'plugin:fields'); } + /* Update old genericobject_itemtype dropdown fields to customasset_itemtype dropdown fields */ + + // Get all types from PluginGenericobject + $migration_genericobject_itemtypes = PluginFieldsMigration::getGenericObjectTypes(); + + foreach($migration_genericobject_itemtypes as $type) { + // Check if genericobject and customasset itemtypes exist + if (!class_exists($type['genericobject_itemtype'])) { + $migration->addDebugMessage(sprintf( + 'The itemtype %s does not exist, please check if %s.class.php is present', + $type['genericobject_itemtype'], + $type['genericobject_name'], + )); + continue; + } + $itemtype = str_replace('\\\\', '\\', $type['itemtype']); + if (!class_exists($itemtype)) { + $migration->addDebugMessage(sprintf( + 'The itemtype %s does not exist, please check if %s.class.php is present', + $itemtype, + $type['name'], + )); + continue; + } + + // If corresponding customasset_itemtype exists, update field type + $migration->addPostQuery( + $DB->buildUpdate( + self::getTable(), + [ + 'type' => 'dropdown-' . $itemtype, + ], + [ + 'type' => ['LIKE', 'dropdown-' . $type['genericobject_itemtype'] . '%'], + ], + ), + ); + } + return true; } diff --git a/inc/migration.class.php b/inc/migration.class.php index 0e970ee0..cc9c6b7f 100644 --- a/inc/migration.class.php +++ b/inc/migration.class.php @@ -200,4 +200,44 @@ private static function getCustomFieldsInContainerTable( fn(string $field) => !in_array($field, $basic_fields, true), ); } + + public static function getGenericObjectTypes() { + /** @var DBmysql $DB */ + global $DB; + + // Check GenericObject version + $genericobject_info = Plugin::getInfo('genericobject'); + if (version_compare($genericobject_info['version'] ?? '0', '3.0.0', '<')) { + throw new RuntimeException( + 'GenericObject plugin cannot be migrated. Please update it to the latest version.', + ); + } + + // Check glpi_plugin_genericobject_types table + if (!$DB->fieldExists('glpi_plugin_genericobject_types', 'itemtype')) { + throw new RuntimeException( + 'Integrity error on the glpi_plugin_genericobject_types table from the GenericObject plugin.', + ); + } + + $migration_genericobject_itemtype = []; + $result = $DB->request(['FROM' => 'glpi_plugin_genericobject_types']); + foreach ($result as $type) { + $customasset_classname = 'Glpi\\\\CustomAsset\\\\' . $type['name'] . 'Asset'; + if (str_ends_with((string) $type['itemtype'], 'Model')) { + $customasset_classname = 'Glpi\\\\CustomAsset\\\\' . $type['name'] . 'AssetModel'; + } elseif (str_ends_with((string) $type['itemtype'], 'Type')) { + $customasset_classname = 'Glpi\\\\CustomAsset\\\\' . $type['name'] . 'AssetType'; + } + + $migration_genericobject_itemtype[$type['itemtype']] = [ + 'genericobject_itemtype' => $type['itemtype'], + 'itemtype' => $customasset_classname, + 'genericobject_name' => $type['name'], + 'name' => $type['name'] . 'Asset', + ]; + } + + return $migration_genericobject_itemtype; + } } From f08d4986003a9a887683914187a4046c0afabd94 Mon Sep 17 00:00:00 2001 From: MyuTsu Date: Wed, 20 May 2026 17:24:10 +0200 Subject: [PATCH 2/7] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f81f8269..80607883 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [unreleased] +- Fix GenericObject type dropdowns migration ## [1.24.2] - 2026-06-30 From 95c04004814d3e7bdb88b361e640e3169933fd05 Mon Sep 17 00:00:00 2001 From: MyuTsu Date: Thu, 21 May 2026 11:10:20 +0200 Subject: [PATCH 3/7] fix CI --- inc/field.class.php | 71 +++++++++++++++++++++-------------------- inc/migration.class.php | 3 +- 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/inc/field.class.php b/inc/field.class.php index 87db00bd..007c06f4 100644 --- a/inc/field.class.php +++ b/inc/field.class.php @@ -28,7 +28,6 @@ * ------------------------------------------------------------------------- */ use Glpi\Application\View\TemplateRenderer; -use Glpi\Asset\AssetDefinitionManager; use Glpi\DBAL\QueryExpression; use Glpi\Features\Clonable; use Glpi\Form\Question; @@ -154,43 +153,45 @@ public static function installBaseData(Migration $migration, $version) $migration->addConfig(['stable_search_options' => 'yes'], 'plugin:fields'); } - /* Update old genericobject_itemtype dropdown fields to customasset_itemtype dropdown fields */ + // Update old genericobject_itemtype dropdown fields to customasset_itemtype dropdown fields + if ($DB->tableExists('glpi_plugin_genericobject_types')) { + // Get all types from PluginGenericobject + $migration_genericobject_itemtypes = PluginFieldsMigration::getGenericObjectTypes(); + + foreach ($migration_genericobject_itemtypes as $type) { + // Check if genericobject and customasset itemtypes exist + if (!class_exists($type['genericobject_itemtype'])) { + $migration->addDebugMessage(sprintf( + 'The itemtype %s does not exist, please check if %s.class.php is present', + $type['genericobject_itemtype'], + $type['genericobject_name'], + )); + continue; + } - // Get all types from PluginGenericobject - $migration_genericobject_itemtypes = PluginFieldsMigration::getGenericObjectTypes(); + $itemtype = str_replace('\\\\', '\\', $type['itemtype']); + if (!class_exists($itemtype)) { + $migration->addDebugMessage(sprintf( + 'The itemtype %s does not exist, please check if %s.class.php is present', + $itemtype, + $type['name'], + )); + continue; + } - foreach($migration_genericobject_itemtypes as $type) { - // Check if genericobject and customasset itemtypes exist - if (!class_exists($type['genericobject_itemtype'])) { - $migration->addDebugMessage(sprintf( - 'The itemtype %s does not exist, please check if %s.class.php is present', - $type['genericobject_itemtype'], - $type['genericobject_name'], - )); - continue; - } - $itemtype = str_replace('\\\\', '\\', $type['itemtype']); - if (!class_exists($itemtype)) { - $migration->addDebugMessage(sprintf( - 'The itemtype %s does not exist, please check if %s.class.php is present', - $itemtype, - $type['name'], - )); - continue; + // If corresponding customasset_itemtype exists, update field type + $migration->addPostQuery( + $DB->buildUpdate( + self::getTable(), + [ + 'type' => 'dropdown-' . $itemtype, + ], + [ + 'type' => ['LIKE', 'dropdown-' . $type['genericobject_itemtype'] . '%'], + ], + ), + ); } - - // If corresponding customasset_itemtype exists, update field type - $migration->addPostQuery( - $DB->buildUpdate( - self::getTable(), - [ - 'type' => 'dropdown-' . $itemtype, - ], - [ - 'type' => ['LIKE', 'dropdown-' . $type['genericobject_itemtype'] . '%'], - ], - ), - ); } return true; diff --git a/inc/migration.class.php b/inc/migration.class.php index cc9c6b7f..7206266c 100644 --- a/inc/migration.class.php +++ b/inc/migration.class.php @@ -201,7 +201,8 @@ private static function getCustomFieldsInContainerTable( ); } - public static function getGenericObjectTypes() { + public static function getGenericObjectTypes() + { /** @var DBmysql $DB */ global $DB; From f1ab6ace8d0c8488313508692609a7deca490901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Langlois=20Ga=C3=ABtan?= <64356364+MyvTsv@users.noreply.github.com> Date: Fri, 22 May 2026 12:28:20 +0200 Subject: [PATCH 4/7] Update inc/field.class.php Co-authored-by: Romain B. <8530352+Rom1-B@users.noreply.github.com> --- inc/field.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/field.class.php b/inc/field.class.php index 007c06f4..55033438 100644 --- a/inc/field.class.php +++ b/inc/field.class.php @@ -187,7 +187,7 @@ public static function installBaseData(Migration $migration, $version) 'type' => 'dropdown-' . $itemtype, ], [ - 'type' => ['LIKE', 'dropdown-' . $type['genericobject_itemtype'] . '%'], + 'type' => ['LIKE', 'dropdown-' . $type['genericobject_itemtype']], ], ), ); From 1b12702d830ae519a49f415b604131e18018ed70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Langlois=20Ga=C3=ABtan?= <64356364+MyvTsv@users.noreply.github.com> Date: Fri, 22 May 2026 12:28:31 +0200 Subject: [PATCH 5/7] Update inc/migration.class.php Co-authored-by: Romain B. <8530352+Rom1-B@users.noreply.github.com> --- inc/migration.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/migration.class.php b/inc/migration.class.php index 7206266c..e9e3fc45 100644 --- a/inc/migration.class.php +++ b/inc/migration.class.php @@ -201,7 +201,7 @@ private static function getCustomFieldsInContainerTable( ); } - public static function getGenericObjectTypes() + public static function getGenericObjectTypes(): array { /** @var DBmysql $DB */ global $DB; From 02719e80f7a755d11f5e2a6efcb9326fc237c039 Mon Sep 17 00:00:00 2001 From: MyuTsu Date: Fri, 22 May 2026 16:20:07 +0200 Subject: [PATCH 6/7] review --- inc/field.class.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/inc/field.class.php b/inc/field.class.php index 55033438..c7bf1c81 100644 --- a/inc/field.class.php +++ b/inc/field.class.php @@ -159,16 +159,6 @@ public static function installBaseData(Migration $migration, $version) $migration_genericobject_itemtypes = PluginFieldsMigration::getGenericObjectTypes(); foreach ($migration_genericobject_itemtypes as $type) { - // Check if genericobject and customasset itemtypes exist - if (!class_exists($type['genericobject_itemtype'])) { - $migration->addDebugMessage(sprintf( - 'The itemtype %s does not exist, please check if %s.class.php is present', - $type['genericobject_itemtype'], - $type['genericobject_name'], - )); - continue; - } - $itemtype = str_replace('\\\\', '\\', $type['itemtype']); if (!class_exists($itemtype)) { $migration->addDebugMessage(sprintf( From ce5c8e8695b415eed5495fbe676ea137f79b5334 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Langlois=20Ga=C3=ABtan?= <64356364+MyvTsv@users.noreply.github.com> Date: Wed, 1 Jul 2026 17:06:10 +0200 Subject: [PATCH 7/7] Update inc/field.class.php Co-authored-by: Stanislas --- inc/field.class.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/inc/field.class.php b/inc/field.class.php index c7bf1c81..b759de12 100644 --- a/inc/field.class.php +++ b/inc/field.class.php @@ -154,7 +154,14 @@ public static function installBaseData(Migration $migration, $version) } // Update old genericobject_itemtype dropdown fields to customasset_itemtype dropdown fields - if ($DB->tableExists('glpi_plugin_genericobject_types')) { + // Update old genericobject_itemtype dropdown fields to customasset_itemtype dropdown fields + $has_genericobject_fields = $DB->tableExists('glpi_plugin_genericobject_types') + && $DB->request([ + 'COUNT' => 'id', + 'FROM' => self::getTable(), + 'WHERE' => ['type' => ['LIKE', 'dropdown-PluginGenericobject%']], + ])->current()['COUNT(id)'] > 0; + if ($has_genericobject_fields) { // Get all types from PluginGenericobject $migration_genericobject_itemtypes = PluginFieldsMigration::getGenericObjectTypes();