Skip to content

Commit b9a465c

Browse files
Handle generic object references in forms migrations
1 parent 3a7efa3 commit b9a465c

File tree

3 files changed

+84
-1
lines changed

3 files changed

+84
-1
lines changed

src/Glpi/Asset/AssetDefinitionManager.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,32 @@ public function getCapacity(string $classname): ?CapacityInterface
390390
return $this->capacities[$classname] ?? null;
391391
}
392392

393+
public function getAssetClassNameFromLegacyClassName(string $legacy): ?string
394+
{
395+
/** @var \DBmysql $DB */
396+
global $DB;
397+
398+
// Try to load glpi_plugin_genericobject_types row for this legacy item
399+
if (!$DB->tableExists('glpi_plugin_genericobject_types')) {
400+
return null;
401+
}
402+
$rows = $DB->request([
403+
'FROM' => 'glpi_plugin_genericobject_types',
404+
'WHERE' => ['itemtype' => $legacy],
405+
]);
406+
if (count($rows) !== 1) {
407+
return null;
408+
}
409+
410+
$row = $rows->current();
411+
$name = $row['name'];
412+
return AssetDefinition::getCustomObjectNamespace()
413+
. "\\"
414+
. $name
415+
. AssetDefinition::getCustomObjectClassSuffix()
416+
;
417+
}
418+
393419
private function loadConcreteClass(AssetDefinition $definition): void
394420
{
395421
$rightname = $definition->getCustomObjectRightname();

src/Glpi/Form/QuestionType/QuestionTypeItem.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
use DbUtils;
4343
use Dropdown;
4444
use Glpi\Application\View\TemplateRenderer;
45+
use Glpi\Asset\AssetDefinitionManager;
4546
use Glpi\DBAL\JsonFieldInterface;
4647
use Glpi\Form\Condition\ConditionHandler\ItemAsTextConditionHandler;
4748
use Glpi\Form\Condition\ConditionHandler\ItemConditionHandler;
@@ -133,8 +134,15 @@ public function convertExtraData(array $rawData): mixed
133134
$selectable_tree_root = (bool) $values['selectable_tree_root'];
134135
}
135136

137+
$itemtype = $rawData['itemtype'] ?? null;
138+
// Replace generic object name with asset name if migrated
139+
if (str_starts_with($itemtype, 'PluginGenericobject')) {
140+
$manager = AssetDefinitionManager::getInstance();
141+
$itemtype = $manager->getAssetClassNameFromLegacyClassName($itemtype);
142+
}
143+
136144
return (new QuestionTypeItemExtraDataConfig(
137-
itemtype: $rawData['itemtype'] ?? null,
145+
itemtype: $itemtype,
138146
root_items_id: $root_items_id,
139147
subtree_depth: $subtree_depth,
140148
selectable_tree_root: $selectable_tree_root

tests/functional/Glpi/Form/Migration/FormMigrationTest.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
use Glpi\Form\QuestionType\QuestionTypeUrgency;
8787
use Glpi\Form\Section;
8888
use Glpi\Message\MessageType;
89+
use Glpi\Migration\GenericobjectPluginMigration;
8990
use Glpi\Migration\PluginMigrationResult;
9091
use Glpi\Tests\FormTesterTrait;
9192
use GlpiPlugin\Tester\Form\QuestionTypeIpConverter;
@@ -112,6 +113,13 @@ public static function setUpBeforeClass(): void
112113
foreach ($queries as $query) {
113114
$DB->doQuery($query);
114115
}
116+
117+
// Some tests in this file also require generic objects migration so
118+
// we also load its tables.
119+
$queries = $DB->getQueriesFromFile(sprintf('%s/tests/fixtures/genericobject-migration/genericobject-db.sql', GLPI_ROOT));
120+
foreach ($queries as $query) {
121+
$DB->doQuery($query);
122+
}
115123
}
116124

117125
public static function tearDownAfterClass(): void
@@ -123,6 +131,11 @@ public static function tearDownAfterClass(): void
123131
$DB->dropTable($table['TABLE_NAME']);
124132
}
125133

134+
$tables = $DB->listTables('glpi\_plugin\_genericobject\_%');
135+
foreach ($tables as $table) {
136+
$DB->dropTable($table['TABLE_NAME']);
137+
}
138+
126139
parent::tearDownAfterClass();
127140
}
128141

@@ -3587,6 +3600,42 @@ public function testVisiblePrivateFormMigration(): void
35873600
);
35883601
}
35893602

3603+
public function testFormWithQuestionReferencingGenericObject(): void
3604+
{
3605+
/** @var \DBmysql $DB */
3606+
global $DB;
3607+
3608+
// Arrange: create a form with a reference to generic object assets
3609+
$this->createSimpleFormcreatorForm("With generic object", [
3610+
[
3611+
'name' => 'Generic object',
3612+
'fieldtype' => 'glpiselect',
3613+
'itemtype' => "PluginGenericobjectSmartphone",
3614+
],
3615+
]);
3616+
// Migrated asset definition
3617+
$asset_migrations = new GenericobjectPluginMigration($DB);
3618+
$asset_migrations->execute();
3619+
3620+
// Act: try to import the form
3621+
$migration = new FormMigration($DB, FormAccessControlManager::getInstance());
3622+
$migration->execute();
3623+
3624+
// Assert: make sure the question was imported with the correct type
3625+
$form = getItemByTypeName(Form::class, "With generic object");
3626+
$question_id = $this->getQuestionId($form, "Generic object");
3627+
$question = Question::getById($question_id);
3628+
3629+
$config = $question->getExtraDataConfig();
3630+
if (!$config instanceof QuestionTypeItemExtraDataConfig) {
3631+
$this->fail("Unexpected config class");
3632+
}
3633+
$this->assertEquals(
3634+
"Glpi\CustomAsset\smartphoneAsset",
3635+
$config->getItemtype()
3636+
);
3637+
}
3638+
35903639
public function testNonVisiblePrivateFormMigration(): void
35913640
{
35923641
/** @var \DBmysql $DB */

0 commit comments

Comments
 (0)