Skip to content

Commit 23afefd

Browse files
Rom1-BMyvTsv
authored andcommitted
Migration genericobject fields to core (#996)
* genericobject compatibility * review * glpi_plugin_genericobject_types * Check GenericObject version * Check glpi_plugin_genericobject_types table * fix escape * fix check version * fix(customasset): handle escaped backslashes in json decode itemtypes * Apply suggestion from @Rom1-B --------- Co-authored-by: MyuTsu <[email protected]>
1 parent 940b9db commit 23afefd

File tree

4 files changed

+88
-11
lines changed

4 files changed

+88
-11
lines changed

hook.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ function plugin_fields_install()
7272
PluginFieldsStatusOverride::class,
7373
];
7474

75+
7576
// First, install base data
7677
foreach ($classesToInstall as $class) {
7778
if (method_exists($class, 'installBaseData')) {

inc/container.class.php

Lines changed: 75 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@
2828
* -------------------------------------------------------------------------
2929
*/
3030

31-
use Glpi\Toolbox\Sanitizer;
32-
3331
class PluginFieldsContainer extends CommonDBTM
3432
{
3533
use Glpi\Features\Clonable;
@@ -149,6 +147,72 @@ public static function installBaseData(Migration $migration, $version)
149147
$migration->migrationOneTable($table);
150148
}
151149

150+
// Get itemtypes from PluginGenericobject
151+
if ($DB->tableExists('glpi_plugin_genericobject_types')) {
152+
// Check GenericObject version
153+
$genericobject_info = Plugin::getInfo('genericobject');
154+
if (version_compare($genericobject_info['version'] ?? '0', '3.0.0', '<')) {
155+
throw new \RuntimeException(
156+
'GenericObject plugin cannot be migrated. Please update it to the latest version.',
157+
);
158+
}
159+
160+
// Check glpi_plugin_genericobject_types table
161+
if (!$DB->fieldExists('glpi_plugin_genericobject_types', 'itemtype')) {
162+
throw new \RuntimeException(
163+
'Integrity error on the glpi_plugin_genericobject_types table from the GenericObject plugin.',
164+
);
165+
}
166+
167+
$migration_genericobject_itemtype = [];
168+
$result = $DB->request(['FROM' => 'glpi_plugin_genericobject_types']);
169+
foreach ($result as $type) {
170+
$migration_genericobject_itemtype[$type['itemtype']] = [
171+
'genericobject_itemtype' => $type['itemtype'],
172+
'itemtype' => 'Glpi\CustomAsset\\' . $type['name'] . 'Asset',
173+
'genericobject_name' => $type['name'],
174+
'name' => $type['name'] . 'Asset',
175+
];
176+
}
177+
178+
// Get containers with PluginGenericobject itemtype
179+
$result = $DB->request([
180+
'FROM' => $table,
181+
'WHERE' => [
182+
new Glpi\DBAL\QueryExpression(
183+
$table . ".itemtypes LIKE '%PluginGenericobject%'",
184+
),
185+
],
186+
]);
187+
188+
$container_class = new self();
189+
foreach ($result as $container) {
190+
self::generateTemplate($container);
191+
foreach (json_decode($container['itemtypes']) as $itemtype) {
192+
$classname = self::getClassname($itemtype, $container["name"]);
193+
$old_table = $classname::getTable();
194+
// Rename genericobject container table
195+
if (
196+
$DB->tableExists($old_table) &&
197+
isset($migration_genericobject_itemtype[$itemtype]) &&
198+
strpos($old_table, 'glpi_plugin_fields_plugingenericobject' . $migration_genericobject_itemtype[$itemtype]['genericobject_name']) !== false
199+
) {
200+
$new_table = str_replace('plugingenericobject' . $migration_genericobject_itemtype[$itemtype]['genericobject_name'], 'glpicustomasset' . strtolower($migration_genericobject_itemtype[$itemtype]['name']), $old_table);
201+
$migration->renameTable($old_table, $new_table);
202+
}
203+
}
204+
// Update old genericobject itemtypes in container
205+
$map = array_column($migration_genericobject_itemtype, 'itemtype', 'genericobject_itemtype');
206+
$itemtypes = strtr($container['itemtypes'], $map);
207+
$container_class->update(
208+
[
209+
'id' => $container['id'],
210+
'itemtypes' => $itemtypes,
211+
],
212+
);
213+
}
214+
}
215+
152216
return true;
153217
}
154218

@@ -489,7 +553,7 @@ public static function getSpecificValueToDisplay($field, $values, array $options
489553

490554
return $types[$values[$field]];
491555
case 'itemtypes':
492-
$types = json_decode($values[$field]);
556+
$types = PluginFieldsToolbox::decodeJSONItemtypes($values[$field]);
493557
$obj = '';
494558
$count = count($types);
495559
$i = 1;
@@ -652,7 +716,7 @@ public static function create($fields)
652716
return false;
653717
}
654718

655-
foreach (json_decode($fields['itemtypes']) as $itemtype) {
719+
foreach (PluginFieldsToolbox::decodeJSONItemtypes($fields['itemtypes']) as $itemtype) {
656720
//install table for receive field
657721
$classname = self::getClassname($itemtype, $fields['name']);
658722
$classname::install();
@@ -662,7 +726,7 @@ public static function create($fields)
662726
public static function generateTemplate($fields)
663727
{
664728
$itemtypes = strlen($fields['itemtypes']) > 0
665-
? json_decode($fields['itemtypes'], true)
729+
? PluginFieldsToolbox::decodeJSONItemtypes($fields['itemtypes'], true)
666730
: [];
667731
foreach ($itemtypes as $itemtype) {
668732
// prevent usage of plugin class if not loaded
@@ -1104,7 +1168,7 @@ public static function getEntries($type = 'tab', $full = false): array
11041168
continue;
11051169
}
11061170

1107-
$jsonitemtypes = json_decode($item['itemtypes']);
1171+
$jsonitemtypes = PluginFieldsToolbox::decodeJSONItemtypes($item['itemtypes']);
11081172
//show more info or not
11091173
foreach ($jsonitemtypes as $v) {
11101174
if ($full) {
@@ -1144,8 +1208,10 @@ public static function getUsedItemtypes($type = 'all', $must_be_active = false)
11441208
]);
11451209

11461210
foreach ($iterator as $data) {
1147-
$jsonitemtype = json_decode($data['itemtypes']);
1148-
$itemtypes = array_merge($itemtypes, $jsonitemtype);
1211+
$jsonitemtype = PluginFieldsToolbox::decodeJSONItemtypes($data['itemtypes']);
1212+
if (is_array($jsonitemtype)) {
1213+
$itemtypes = array_merge($itemtypes, $jsonitemtype);
1214+
}
11491215
}
11501216

11511217
return $itemtypes;
@@ -1629,7 +1695,7 @@ public static function findContainer($itemtype, $type = 'tab', $subtype = '')
16291695
}
16301696

16311697
foreach ($itemtypes as $data) {
1632-
$dataitemtypes = json_decode($data['itemtypes']);
1698+
$dataitemtypes = PluginFieldsToolbox::decodeJSONItemtypes($data['itemtypes']);
16331699
if (in_array($itemtype, $dataitemtypes) != false) {
16341700
$id = $data['id'];
16351701
}

inc/toolbox.class.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,4 +361,14 @@ public static function getGlpiItemtypes(): array
361361

362362
return $all_itemtypes;
363363
}
364+
365+
public static function decodeJSONItemtypes(string $itemtypes, ?bool $associative = null)
366+
{
367+
$jsonitemtype = json_decode($itemtypes, $associative);
368+
if ($jsonitemtype === null && json_last_error() !== JSON_ERROR_NONE) {
369+
$fixed_json = str_replace('\\', '\\\\', $itemtypes);
370+
$jsonitemtype = json_decode($fixed_json, $associative);
371+
}
372+
return $jsonitemtype;
373+
}
364374
}

templates/container.class.tpl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class %%CLASSNAME%% extends PluginFieldsAbstractContainerInstance
5151
* This block ensures that the 'entities_id' field is created and populated if it
5252
* associated item type requires entity assignment
5353
*/
54-
if (getItemForItemtype("%%ITEMTYPE%%")->isEntityAssign() && !$DB->fieldExists($table, 'entities_id')) {
54+
if (getItemForItemtype('%%ITEMTYPE%%')->isEntityAssign() && !$DB->fieldExists($table, 'entities_id')) {
5555
$migration->addField($table, 'entities_id', 'fkey', ['after' => 'plugin_fields_containers_id']);
5656
$migration->addKey($table, 'entities_id');
5757
$migration->executeMigration();
@@ -107,7 +107,7 @@ class %%CLASSNAME%% extends PluginFieldsAbstractContainerInstance
107107
* associated item type requires recursive assignment
108108
*/
109109
if (
110-
getItemForItemtype("%%ITEMTYPE%%")->maybeRecursive()
110+
getItemForItemtype('%%ITEMTYPE%%')->maybeRecursive()
111111
&& !$DB->fieldExists($table, 'is_recursive')
112112
&& $DB->fieldExists($table, 'entities_id')) {
113113
$migration->addField($table, 'is_recursive', 'bool', ['after' => 'entities_id']);

0 commit comments

Comments
 (0)