From 2f0b1221013e309eae1d43067abc48d177fa51c7 Mon Sep 17 00:00:00 2001 From: Denis Flaven Date: Fri, 14 Aug 2015 12:42:51 +0000 Subject: [PATCH] Automatic installation of modules: remove duplicates if needed. SVN:trunk[3678] --- setup/modulediscovery.class.inc.php | 84 +++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 5 deletions(-) diff --git a/setup/modulediscovery.class.inc.php b/setup/modulediscovery.class.inc.php index f0e1c8651..4181021ab 100644 --- a/setup/modulediscovery.class.inc.php +++ b/setup/modulediscovery.class.inc.php @@ -111,15 +111,28 @@ class ModuleDiscovery } /** - * + * Get the list of "discovered" modules, ordered based on their (inter) dependencies * @param bool $bAbortOnMissingDependency ... * @param hash $aModulesToLoad List of modules to search for, defaults to all if ommitted */ protected static function GetModules($bAbortOnMissingDependency = false, $aModulesToLoad = null) + { + // Order the modules to take into account their inter-dependencies + return self::OrderModulesByDependencies(self::$m_aModules, $bAbortOnMissingDependency, $aModulesToLoad); + } + + /** + * Arrange an list of modules, based on their (inter) dependencies + * @param hash $aModules The list of modules to process: 'id' => $aModuleInfo + * @param bool $bAbortOnMissingDependency ... + * @param hash $aModulesToLoad List of modules to search for, defaults to all if ommitted + * @return hash + */ + public static function OrderModulesByDependencies($aModules, $bAbortOnMissingDependency = false, $aModulesToLoad = null) { // Order the modules to take into account their inter-dependencies $aDependencies = array(); - foreach(self::$m_aModules as $sId => $aModule) + foreach($aModules as $sId => $aModule) { list($sModuleName, $sModuleVersion) = self::GetModuleName($sId); if (is_null($aModulesToLoad) || in_array($sModuleName, $aModulesToLoad)) @@ -130,7 +143,7 @@ class ModuleDiscovery ksort($aDependencies); $aOrderedModules = array(); $iLoopCount = 1; - while(($iLoopCount < count(self::$m_aModules)) && (count($aDependencies) > 0) ) + while(($iLoopCount < count($aModules)) && (count($aDependencies) > 0) ) { foreach($aDependencies as $sId => $aRemainingDeps) { @@ -155,7 +168,7 @@ class ModuleDiscovery $aModuleDeps = array(); foreach($aDependencies as $sId => $aDeps) { - $aModule = self::$m_aModules[$sId]; + $aModule = $aModules[$sId]; $aModuleDeps[] = "{$aModule['label']} (id: $sId) depends on ".implode(' + ', $aDeps); } $sMessage = "The following modules have unmet dependencies: ".implode(', ', $aModuleDeps); @@ -165,11 +178,72 @@ class ModuleDiscovery $aResult = array(); foreach($aOrderedModules as $sId) { - $aResult[$sId] = self::$m_aModules[$sId]; + $aResult[$sId] = $aModules[$sId]; } return $aResult; } + + /** + * Remove the duplicate modules (i.e. modules with the same name but with a different version) from the supplied list of modules + * @param hash $aModules + * @return hash The ordered a duplicate-free list of modules + */ + public static function RemoveDuplicateModules($aModules) + { + $aRes = array(); + $aIndex = array(); + foreach($aModules as $sModuleId => $aModuleInfo) + { + if (preg_match('|^([^/]+)/(.*)$|', $sModuleId, $aMatches)) + { + $sModuleName = $aMatches[1]; + $sModuleVersion = $aMatches[2]; + } + else + { + // No version number found, assume 1.0.0 + $sModuleName = str_replace('/', '', $sModuleId); + $sModuleVersion = '1.0.0'; + } + // The last version encountered has precedence + $aIndex[$sModuleName] = $sModuleVersion; + } + foreach($aModules as $sModuleId => $aModuleInfo) + { + if (preg_match('|^([^/]+)/(.*)$|', $sModuleId, $aMatches)) + { + $sModuleName = $aMatches[1]; + $sModuleVersion = $aMatches[2]; + } + else + { + // No version number found, assume 1.0.0 + $sModuleName = str_replace('/', '', $sModuleId); + $sModuleVersion = '1.0.0'; + } + if ($aIndex[$sModuleName] == $sModuleVersion) + { + // Ok, this this the last (or only) version of this module in the list, keep it + $aRes[$sModuleId] = $aModuleInfo; + } + else + { + if(version_compare($sModuleVersion, $aIndex[$sModuleName], '<')) + { + SetupPage::log_info("Module $sModuleId will be upgraded to $sModuleName/{$aIndex[$sModuleName]}."); + } + else + { + SetupPage::log_warning("Module $sModuleId will be DOWNGRADED to $sModuleName/{$aIndex[$sModuleName]} since the older version is to be loaded AFTER the more recent version."); + } + } + } + // If needed re-arrange the list ot take care of inter dependencies + $aRes = self::OrderModulesByDependencies($aRes, true); + return $aRes; + } + protected static function DependencyIsResolved($sDepString, $aOrderedModules) { $bResult = false;