N°8724 - refactoring for maintenability

This commit is contained in:
odain
2025-11-27 15:47:25 +01:00
parent 03e25a226e
commit 5a2157ba21
4 changed files with 133 additions and 93 deletions

View File

@@ -3,6 +3,7 @@
namespace Combodo\iTop\Setup\ModuleDependency;
require_once(APPROOT.'/setup/runtimeenv.class.inc.php');
use Combodo\iTop\PhpParser\Evaluation\PhpExpressionEvaluator;
use ModuleFileReaderException;
use RunTimeEnvironment;
@@ -38,7 +39,7 @@ class DependencyExpression
if (preg_match_all('/([^\(\)&| ]+)/', $sDependencyExpression, $aMatches)) {
foreach ($aMatches as $aMatch) {
foreach ($aMatch as $sModuleId) {
if (! array_key_exists($sModuleId, $this->aParamsPerModuleId)) {
if (!array_key_exists($sModuleId, $this->aParamsPerModuleId)) {
// $sModuleId in the dependency string is made of a <name>/<optional_operator><version>
// where the operator is < <= = > >= (by default >=)
$aModuleMatches = [];
@@ -71,6 +72,7 @@ class DependencyExpression
/**
* Return module names potentially required by current dependency
*
* @return array
*/
public function GetRemainingModuleNamesToResolve(): array
@@ -85,22 +87,25 @@ class DependencyExpression
/**
* Check if dependency is resolved with current list of module versions
* @param array $aModuleVersions: versions by module names dict
* @param array $aSelectedModules: modules names dict
*
* @param array $aResolvedModuleVersions : versions by module names dict
* @param array $aAllModuleNames : modules names dict
*
* @return void
*/
public function UpdateModuleResolutionState(array $aModuleVersions, array $aSelectedModules): void
public function UpdateModuleResolutionState(array $aResolvedModuleVersions, array $aAllModuleNames): void
{
if (!$this->bValid) {
return;
}
$aReplacements = [];
$bDelayEvaluation = false;
foreach ($this->aParamsPerModuleId as $sModuleId => list($sModuleName, $sOperator, $sExpectedVersion)) {
if (array_key_exists($sModuleName, $aModuleVersions)) {
// module is present, check the version
$sCurrentVersion = $aModuleVersions[$sModuleName];
if (array_key_exists($sModuleName, $aResolvedModuleVersions)) {
// module is resolved, check the version
$sCurrentVersion = $aResolvedModuleVersions[$sModuleName];
if (version_compare($sCurrentVersion, $sExpectedVersion, $sOperator)) {
if (array_key_exists($sModuleName, $this->aRemainingModuleNamesToResolve)) {
unset($this->aRemainingModuleNamesToResolve[$sModuleName]);
@@ -112,19 +117,23 @@ class DependencyExpression
// a function call that results in a runtime fatal error
}
} else {
// module is not present
$aReplacements[$sModuleId] = '(false)'; // Add parentheses to protect against invalid condition causing
// a function call that results in a runtime fatal error
// module is not resolved yet
if (array_key_exists($sModuleName, $aAllModuleNames)) {
//Weird piece of code that covers below usecase:
//module B dependency: 'moduleA || true'
// if moduleA not present on disk, whole expression can be evaluated and may be resolved
// if moduleA present on disk, we need to sort moduleB after moduleA. expression cannot be resolved yet
$bDelayEvaluation = true;
} else {
$aReplacements[$sModuleId] = '(false)'; // Add parentheses to protect against invalid condition causing
}
}
}
foreach ($this->aRemainingModuleNamesToResolve as $sModuleName => $c) {
if (array_key_exists($sModuleName, $aSelectedModules)) {
// This module is actually a prerequisite
if (!array_key_exists($sModuleName, $aModuleVersions)) {
return;
}
}
if ($bDelayEvaluation) {
return;
}
$bResult = false;

View File

@@ -93,18 +93,18 @@ class Module
/**
* Check if module dependencies are resolved with current list of module versions
* @param array $aModuleVersions : versions by module names dict
* @param array $aSelectedModules : modules names dict
* @param array<string, string> $aResolvedModuleVersions : versions by module names dict
* @param array<string> $aAllModuleNames : resolved modules names
*
* @return void
*/
public function UpdateModuleResolutionState(array $aModuleVersions, array $aSelectedModules): void
public function UpdateModuleResolutionState(array $aResolvedModuleVersions, array $aAllModuleNames): void
{
$aNextDependencies = [];
foreach ($this->aRemainingDependenciesToResolve as $sDependencyExpression => $oModuleDependency) {
/** @var DependencyExpression $oModuleDependency*/
$oModuleDependency->UpdateModuleResolutionState($aModuleVersions, $aSelectedModules);
$oModuleDependency->UpdateModuleResolutionState($aResolvedModuleVersions, $aAllModuleNames);
if (!$oModuleDependency->IsResolved()) {
$aNextDependencies[$sDependencyExpression] = $oModuleDependency;
}

View File

@@ -33,8 +33,10 @@ class ModuleDependencySort
/**
* Sort a list of modules, based on their (inter) dependencies
*
* @param array $aModules The list of modules to process: 'id' => $aModuleInfo
* @param bool $bAbortOnMissingDependency ...
*
* @return array
* @throws \MissingDependencyException
*/
@@ -42,13 +44,13 @@ class ModuleDependencySort
{
// Filter modules to compute
$aUnresolvedDependencyModules = [];
$aModuleNames = [];
$aAllModuleNames = [];
foreach ($aModules as $sModuleId => $aModule) {
$oModule = new Module($sModuleId);
$sModuleName = $oModule->GetModuleName();
$oModule->SetDependencies($aModule['dependencies']);
$aUnresolvedDependencyModules[$sModuleId] = $oModule;
$aModuleNames[$sModuleName] = true;
$aAllModuleNames[$sModuleName] = true;
}
// Make sure order is deterministic (alphabtical order)
@@ -56,7 +58,7 @@ class ModuleDependencySort
//Attempt to resolve module dependencies
$aOrderedModules = [];
$aModuleVersions = [];
$aResolvedModuleVersions = [];
$iPreviousUnresolvedCount = -1;
//loop until no dependency is resolved
while ($iPreviousUnresolvedCount !== count($aUnresolvedDependencyModules)) {
@@ -67,10 +69,10 @@ class ModuleDependencySort
foreach ($aUnresolvedDependencyModules as $sModuleId => $oModule) {
/** @var Module $oModule */
$oModule->UpdateModuleResolutionState($aModuleVersions, $aModuleNames);
$oModule->UpdateModuleResolutionState($aResolvedModuleVersions, $aAllModuleNames);
if ($oModule->IsResolved()) {
$aOrderedModules[] = $sModuleId;
$aModuleVersions[$oModule->GetModuleName()] = $oModule->GetVersion();
$aResolvedModuleVersions[$oModule->GetModuleName()] = $oModule->GetVersion();
unset($aUnresolvedDependencyModules[$sModuleId]);
}
}
@@ -100,6 +102,7 @@ class ModuleDependencySort
foreach ($aOrderedModules as $sId) {
$aResult[$sId] = $aModules[$sId];
}
return $aResult;
}
@@ -111,7 +114,7 @@ class ModuleDependencySort
* - cyclic dependencies
* - further versions of same module (name)
*
* @param array $aUnresolvedDependencyModules: dict of Module objects by moduleId key
* @param array $aUnresolvedDependencyModules : dict of Module objects by moduleId key
*
* @return void
*/
@@ -146,7 +149,7 @@ class ModuleDependencySort
uasort($aCountDepsByModuleId, function (array $aDeps1, array $aDeps2) {
//compare $iInDegreeCounter
$res = $aDeps1[0] - $aDeps2[0];
$res = $aDeps1[0] - $aDeps2[0];
if ($res != 0) {
return $res;
}
@@ -177,7 +180,7 @@ class ModuleDependencySort
//when 2 versions of the same module (name) below array has been removed already
if (array_key_exists($oModule->GetModuleName(), $aDependsOnModuleName)) {
foreach ($aDependsOnModuleName[$oModule->GetModuleName()] as $sModuleId2) {
if (! array_key_exists($sModuleId2, $aCountDepsByModuleId)) {
if (!array_key_exists($sModuleId2, $aCountDepsByModuleId)) {
continue;
}
$aDepCount = $aCountDepsByModuleId[$sModuleId2];