Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [UNRELEASED]

### Fixed

- Prevent MySQL table name overflow during GenericObject to CustomAsset migration

### Added

- Add compatibility with GLPI `CustomAsset`
Expand Down
53 changes: 44 additions & 9 deletions inc/container.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
PRIMARY KEY (`id`),
KEY `entities_id` (`entities_id`)
) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;";
if (!$DB->doQuery($query)) {

Check failure on line 100 in inc/container.class.php

View workflow job for this annotation

GitHub Actions / GLPI 11.0.x - php:8.2 - mariadb:10.6 / Continuous integration

Negated boolean expression is always false.

Check failure on line 100 in inc/container.class.php

View workflow job for this annotation

GitHub Actions / GLPI 11.0.x - php:8.5 - mariadb:11.8 / Continuous integration

Negated boolean expression is always false.
throw new RuntimeException('Error creating plugin_fields_containers table: ' . $DB->error());
}
}
Expand Down Expand Up @@ -210,19 +210,44 @@

$container_class = new self();
foreach ($result as $container) {
self::generateTemplate($container);
foreach (json_decode((string) $container['itemtypes']) as $itemtype) {
$classname = self::getClassname($itemtype, $container["name"]);
if (!isset($migration_genericobject_itemtype[$itemtype])) {
continue;
}

// Use original container name for old table lookup
$classname = self::getClassname($itemtype, $container['name']);
$old_table = $classname::getTable();
// Rename genericobject container table

// Skip table rename if old table doesn't exist (already migrated)
if (
$DB->tableExists($old_table)
&& isset($migration_genericobject_itemtype[$itemtype])
&& str_contains($old_table, 'glpi_plugin_fields_plugingenericobject' . $migration_genericobject_itemtype[$itemtype]['genericobject_name'])
!$DB->tableExists($old_table)
|| !str_contains($old_table, 'glpi_plugin_fields_plugingenericobject' . $migration_genericobject_itemtype[$itemtype]['genericobject_name'])
) {
$new_table = str_replace('plugingenericobject' . $migration_genericobject_itemtype[$itemtype]['genericobject_name'], 'glpicustomasset' . strtolower($migration_genericobject_itemtype[$itemtype]['name']), $old_table);
$migration->renameTable($old_table, $new_table);
continue;
}

// Use abbreviated prefix 'gca' (GLPI CustomAsset) instead of 'glpicustomasset'
// to avoid exceeding MySQL's 64 character table name limit
// This prevents name collisions that would occur if container names were truncated
$new_table = str_replace(
'glpi_plugin_fields_plugingenericobject' . $migration_genericobject_itemtype[$itemtype]['genericobject_name'],
'glpi_plugin_fields_gca' . strtolower($migration_genericobject_itemtype[$itemtype]['name']),
$old_table,
);

if (strlen($new_table) > 64) {
throw new RuntimeException(
sprintf(
'Cannot migrate GenericObject container "%s": resulting table name "%s" (%d characters) would exceed MySQL 64 character limit. Please contact support.',
$container['label'],
$new_table,
strlen($new_table),
),
);
}

$migration->renameTable($old_table, $new_table);
}

// Update old genericobject itemtypes in container
Expand All @@ -234,6 +259,8 @@
'itemtypes' => $itemtypes,
],
);
// Note: Template regeneration is handled by installUserData()
// which runs after all base migrations are complete
}
} else {
throw new RuntimeException(
Expand Down Expand Up @@ -2263,7 +2290,15 @@
*/
protected static function getSystemName(string $itemtype, string $container_name): string
{
return strtolower(str_replace('\\', '', $itemtype) . preg_replace('/s$/', '', $container_name));
$itemtype_cleaned = str_replace('\\', '', $itemtype);

// Use abbreviated prefix 'gca' for GLPI CustomAssets to avoid long table names
// This matches the naming convention used during GenericObject migration
if (str_starts_with($itemtype, 'Glpi\\CustomAsset\\')) {
$itemtype_cleaned = str_replace('GlpiCustomAsset', 'Gca', $itemtype_cleaned);
}

return strtolower($itemtype_cleaned . preg_replace('/s$/', '', $container_name));
}

public static function getIcon()
Expand Down
Loading