From 41926d02b0a24cc14ddf4f20999250374ecdee89 Mon Sep 17 00:00:00 2001 From: Thomas Casteleyn Date: Wed, 25 Mar 2026 10:20:40 +0100 Subject: [PATCH 1/4] fix(ModuleInstallerAPI): Rename class in DB recursively --- setup/moduleinstaller.class.inc.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/setup/moduleinstaller.class.inc.php b/setup/moduleinstaller.class.inc.php index 0815fd4ba7..5733bf0134 100644 --- a/setup/moduleinstaller.class.inc.php +++ b/setup/moduleinstaller.class.inc.php @@ -87,12 +87,14 @@ public static function RenameClassInDB($sFrom, $sTo) { try { if (!MetaModel::IsStandaloneClass($sTo)) { - $sRootClass = MetaModel::GetRootClass($sTo); - $sTableName = MetaModel::DBGetTable($sRootClass); - $sFinalClassCol = MetaModel::DBGetClassField($sRootClass); - $sRepair = "UPDATE `$sTableName` SET `$sFinalClassCol` = '$sTo' WHERE `$sFinalClassCol` = BINARY '$sFrom'"; - CMDBSource::Query($sRepair); - $iAffectedRows = CMDBSource::AffectedRows(); + $sClass = $sTo; + foreach (MetaModel::EnumParentClasses($Class) as $sParentClass) { + $sTableName = MetaModel::DBGetTable($sParentClass); + $sFinalClassCol = MetaModel::DBGetClassField($sParentClass); + $sRepair = "UPDATE `$sTableName` SET `$sFinalClassCol` = '$sTo' WHERE `$sFinalClassCol` = BINARY '$sFrom'"; + CMDBSource::Query($sRepair); + $iAffectedRows += CMDBSource::AffectedRows(); + } SetupLog::Info("Renaming class in DB - final class from '$sFrom' to '$sTo': $iAffectedRows rows affected"); } } catch (Exception $e) { From 6d2028804d01249795e7ad9eccdd21dcec91ea57 Mon Sep 17 00:00:00 2001 From: Thomas Casteleyn Date: Wed, 25 Mar 2026 14:01:11 +0100 Subject: [PATCH 2/4] Typo fix --- setup/moduleinstaller.class.inc.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setup/moduleinstaller.class.inc.php b/setup/moduleinstaller.class.inc.php index 5733bf0134..6cfc3f298f 100644 --- a/setup/moduleinstaller.class.inc.php +++ b/setup/moduleinstaller.class.inc.php @@ -87,8 +87,7 @@ public static function RenameClassInDB($sFrom, $sTo) { try { if (!MetaModel::IsStandaloneClass($sTo)) { - $sClass = $sTo; - foreach (MetaModel::EnumParentClasses($Class) as $sParentClass) { + foreach (MetaModel::EnumParentClasses($sTo) as $sParentClass) { $sTableName = MetaModel::DBGetTable($sParentClass); $sFinalClassCol = MetaModel::DBGetClassField($sParentClass); $sRepair = "UPDATE `$sTableName` SET `$sFinalClassCol` = '$sTo' WHERE `$sFinalClassCol` = BINARY '$sFrom'"; From cd8c1974b331c32ce064b6dc4b6e16ab68c74761 Mon Sep 17 00:00:00 2001 From: Thomas Casteleyn Date: Wed, 15 Apr 2026 11:27:39 +0200 Subject: [PATCH 3/4] Add class rename on related references --- setup/moduleinstaller.class.inc.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/setup/moduleinstaller.class.inc.php b/setup/moduleinstaller.class.inc.php index 6cfc3f298f..fc527d41dc 100644 --- a/setup/moduleinstaller.class.inc.php +++ b/setup/moduleinstaller.class.inc.php @@ -96,6 +96,24 @@ public static function RenameClassInDB($sFrom, $sTo) } SetupLog::Info("Renaming class in DB - final class from '$sFrom' to '$sTo': $iAffectedRows rows affected"); } + + // Also rename the class reference on the following classes + $aAdditionalClassReferences = [ + ['class' => CMDBChangeOp::class, 'attcode' => 'objclass'], + ['class' => SynchroReplica::class, 'attcode' => 'dest_class'], + ['class' => TriggerOnObject::class, 'attcode' => 'target_class'], + ['class' => EventOnObject::class, 'attcode' => 'obj_class'], + ]; + foreach ($aAdditionalClassReferences as ['class' => $sClass, 'attcode' => $sAttCode]) { + if (MetaModel::IsValidAttCode($sClass, $sAttCode)) { + $sTableName = MetaModel::DBGetTable($sClass, $sAttCode); + $sClassCol = MetaModel::GetAttributeDef($sClass, $sAttCode)->Get("sql"); + $sRepair = "UPDATE `$sTableName` SET `$sClassCol` = '$sTo' WHERE `$sClassCol` = BINARY '$sFrom'"; + CMDBSource::Query($sRepair); + $iAffectedRows = CMDBSource::AffectedRows(); + SetupLog::Info("Renaming class in DB - $sClass::$sAttCode - from '$sFrom' to '$sTo': $iAffectedRows rows affected"); + } + } } catch (Exception $e) { SetupLog::Warning("Failed to rename class in DB - final class from '$sFrom' to '$sTo'. Reason: ".$e->getMessage()); } From 3f3c1c5228da71e99424d40e0867d606e589540f Mon Sep 17 00:00:00 2001 From: Thomas Casteleyn Date: Wed, 15 Apr 2026 19:22:20 +0200 Subject: [PATCH 4/4] SynchroDataSource must be updated as well or setup will fail --- setup/moduleinstaller.class.inc.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/setup/moduleinstaller.class.inc.php b/setup/moduleinstaller.class.inc.php index fc527d41dc..d1ace36785 100644 --- a/setup/moduleinstaller.class.inc.php +++ b/setup/moduleinstaller.class.inc.php @@ -77,7 +77,7 @@ public static function AfterDataLoad(Config $oConfiguration, $sPreviousVersion, /** * Helper to complete the renaming of a class * The renaming is made in the datamodel definition, but the name has to be changed in the DB as well - * Must be called after DB update, i.e within an implementation of AfterDatabaseCreation() + * Must be called before DB update, i.e within an implementation of BeforeDatabaseCreation() * * @param string $sFrom Original name (already INVALID in the current datamodel) * @param string $sTo New name (valid in the current datamodel) @@ -85,8 +85,14 @@ public static function AfterDataLoad(Config $oConfiguration, $sPreviousVersion, */ public static function RenameClassInDB($sFrom, $sTo) { + if (!MetaModel::DBExists(false)) { + // Install from scratch, no migration + return; + } + try { if (!MetaModel::IsStandaloneClass($sTo)) { + $iAffectedRows = 0; foreach (MetaModel::EnumParentClasses($sTo) as $sParentClass) { $sTableName = MetaModel::DBGetTable($sParentClass); $sFinalClassCol = MetaModel::DBGetClassField($sParentClass); @@ -100,6 +106,7 @@ public static function RenameClassInDB($sFrom, $sTo) // Also rename the class reference on the following classes $aAdditionalClassReferences = [ ['class' => CMDBChangeOp::class, 'attcode' => 'objclass'], + ['class' => SynchroDataSource::class, 'attcode' => 'scope_class'], ['class' => SynchroReplica::class, 'attcode' => 'dest_class'], ['class' => TriggerOnObject::class, 'attcode' => 'target_class'], ['class' => EventOnObject::class, 'attcode' => 'obj_class'],