From 0c01be9d32336e5a0bea8e484187e6685e8bd0c6 Mon Sep 17 00:00:00 2001 From: Timmy38 Date: Fri, 31 Jul 2026 09:41:25 +0200 Subject: [PATCH] =?UTF-8?q?N=C2=B08908=20Use=20it=20in=20ext=20mgmt=20too?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DataFeatureRemovalController.php | 33 +++++++- .../templates/AnalysisResult.html.twig | 4 +- .../templates/Features.html.twig | 4 +- setup/setuputils.class.inc.php | 68 +++++++++++++++++ setup/wizardsteps/WizStepModulesChoice.php | 76 +++---------------- 5 files changed, 113 insertions(+), 72 deletions(-) diff --git a/datamodels/2.x/combodo-data-feature-removal/src/Controller/DataFeatureRemovalController.php b/datamodels/2.x/combodo-data-feature-removal/src/Controller/DataFeatureRemovalController.php index e6b3ce0a72..5d35f4cedc 100644 --- a/datamodels/2.x/combodo-data-feature-removal/src/Controller/DataFeatureRemovalController.php +++ b/datamodels/2.x/combodo-data-feature-removal/src/Controller/DataFeatureRemovalController.php @@ -37,6 +37,7 @@ class DataFeatureRemovalController extends Controller private array $aCountClassesToCleanup = []; private array $aAnalysisDataTable = []; private array $aDeletionExecutionSummary = []; + private ?array $aBasePackageModules = null; private int $iCount = 0; private int $iColumnCount = 2; @@ -349,20 +350,32 @@ class DataFeatureRemovalController extends Controller private function GetAvailableExtensions(bool $bIncludePackageExtensions = false): array { $aExtensionsData = []; + $oExtensionMap = DataFeatureRemoverExtensionService::GetInstance()->GetExtensionMap(); + $aBasePackageModules = $this->GetBasePackageModules(); if ($bIncludePackageExtensions) { - $aExtensionsRef = DataFeatureRemoverExtensionService::GetInstance()->GetExtensionMap()->GetAllExtensionsWithPreviouslyInstalled(); + $aExtensionsRef = $oExtensionMap->GetAllExtensionsWithPreviouslyInstalled(); } else { $aExtensionsRef = DataFeatureRemoverExtensionService::GetInstance()->ReadItopExtensions(); } foreach ($aExtensionsRef as $oExtension) { /** @var \iTopExtension $oExtension */ + $aMetaData = [$oExtension->sVersion, $oExtension->GetExtensionSourceLabel()]; + if (SetupUtils::IsIncludedInBasePackage( + $oExtensionMap, + $oExtension->sCode, + $aBasePackageModules + )) { + $aMetaData[] = 'Included in package'; + } + $aExtensionsData[$oExtension->sCode] = [ 'version' => $oExtension->sVersion, 'label' => $oExtension->sLabel, 'code' => $oExtension->sCode, 'description' => $oExtension->sDescription, 'source' => $oExtension->GetExtensionSourceLabel(), + 'metadata' => $aMetaData, 'installed' => $oExtension->bInstalled, 'extra_flags' => [ 'uninstallable' => $oExtension->CanBeUninstalled(), @@ -377,6 +390,24 @@ class DataFeatureRemovalController extends Controller return $aExtensionsData; } + private function GetBasePackageModules(): array + { + if ($this->aBasePackageModules !== null) { + return $this->aBasePackageModules; + } + + try { + $oRuntimeEnvironment = new RunTimeEnvironment(MetaModel::GetEnvironment(), false); + $aAvailableModules = $oRuntimeEnvironment->AnalyzeInstallation(MetaModel::GetConfig(), [APPROOT], false, null); + $this->aBasePackageModules = SetupUtils::GetBasePackageModules($aAvailableModules, APPROOT.'datamodels'); + } catch (Exception $e) { + DataFeatureRemovalLog::Warning(__METHOD__, null, ['error' => $e->getMessage()]); + $this->aBasePackageModules = []; + } + + return $this->aBasePackageModules; + } + private function GetExtensionsDiff(array $aAddedExtensions, array $aRemovedExtensions): array { $aExtensions = []; diff --git a/datamodels/2.x/combodo-data-feature-removal/templates/AnalysisResult.html.twig b/datamodels/2.x/combodo-data-feature-removal/templates/AnalysisResult.html.twig index e7e9853ef7..16e02a2633 100644 --- a/datamodels/2.x/combodo-data-feature-removal/templates/AnalysisResult.html.twig +++ b/datamodels/2.x/combodo-data-feature-removal/templates/AnalysisResult.html.twig @@ -32,9 +32,9 @@ {% UIColumn Standard {} %} {% for aExtension in aAvailableExtensions[iColumnIndex] %} {% if aExtension['installed'] %} - {% UIExtensionDetails Installed { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : [aExtension['version'], aExtension['source']], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %} + {% UIExtensionDetails Installed { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : aExtension['metadata'], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %} {% else %} - {% UIExtensionDetails NotInstalled { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : [aExtension['version'], aExtension['source']], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %} + {% UIExtensionDetails NotInstalled { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : aExtension['metadata'], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %} {% endif %} {% endfor %} {% EndUIColumn %} diff --git a/datamodels/2.x/combodo-data-feature-removal/templates/Features.html.twig b/datamodels/2.x/combodo-data-feature-removal/templates/Features.html.twig index a2c2c84f18..29ae3623e2 100644 --- a/datamodels/2.x/combodo-data-feature-removal/templates/Features.html.twig +++ b/datamodels/2.x/combodo-data-feature-removal/templates/Features.html.twig @@ -12,9 +12,9 @@ {% UIColumn Standard {} %} {% for aExtension in aAvailableExtensions[iColumnIndex] %} {% if aExtension['installed'] %} - {% UIExtensionDetails Installed { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : [aExtension['version'], aExtension['source']], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %} + {% UIExtensionDetails Installed { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : aExtension['metadata'], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %} {% else %} - {% UIExtensionDetails NotInstalled { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : [aExtension['version'], aExtension['source']], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %} + {% UIExtensionDetails NotInstalled { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : aExtension['metadata'], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %} {% endif %} {% endfor %} {% EndUIColumn %} diff --git a/setup/setuputils.class.inc.php b/setup/setuputils.class.inc.php index e6abac18dc..d08da17d4b 100644 --- a/setup/setuputils.class.inc.php +++ b/setup/setuputils.class.inc.php @@ -1707,6 +1707,74 @@ JS return array_key_exists('itsm-designer-connector', $aModules); } + /** + * Build a map of modules that belong to the package base scope. + * + * @param array $aAnalyzeInstallationModules Output from AnalyzeInstallation-like methods + * @param string $sSourceDir Base directory used as package scope + * + * @return array + */ + public static function GetBasePackageModules(array $aAnalyzeInstallationModules, string $sSourceDir): array + { + $aBasePackageModules = []; + $sNormalizedSourceDir = self::NormalizePathForComparison($sSourceDir); + if ($sNormalizedSourceDir === '') { + return $aBasePackageModules; + } + + foreach ($aAnalyzeInstallationModules as $sModuleId => $aModuleInfo) { + if ($sModuleId === ROOT_MODULE) { + continue; + } + + $sRootDir = $aModuleInfo['root_dir'] ?? ''; + if ($sRootDir === '') { + continue; + } + + $sModuleRootDir = self::NormalizePathForComparison($sRootDir); + if (utils::StartsWith($sModuleRootDir, $sNormalizedSourceDir)) { + $aBasePackageModules[$sModuleId] = true; + } + } + + return $aBasePackageModules; + } + + /** + * Returns true when all modules of a non-package extension are already included in base package modules. + */ + public static function IsIncludedInBasePackage(iTopExtensionsMap $oExtensionsMap, string $sExtensionCode, array $aBasePackageModules): bool + { + if ($sExtensionCode === '') { + return false; + } + + $oExtension = $oExtensionsMap->GetFromExtensionCode($sExtensionCode); + if (($oExtension === null) || ($oExtension->sSource === iTopExtension::SOURCE_WIZARD)) { + return false; + } + + $aModules = $oExtension->aModules ?? []; + if (!is_array($aModules) || empty($aModules)) { + return false; + } + + foreach ($aModules as $sModuleId) { + if (!array_key_exists($sModuleId, $aBasePackageModules)) { + return false; + } + } + + return true; + } + + private static function NormalizePathForComparison(string $sPath): string + { + return rtrim(str_replace('\\', '/', $sPath), '/'); + } + /** * @param array $aModules List of available module codes * diff --git a/setup/wizardsteps/WizStepModulesChoice.php b/setup/wizardsteps/WizStepModulesChoice.php index bcf35fbe20..8e401d1ad1 100644 --- a/setup/wizardsteps/WizStepModulesChoice.php +++ b/setup/wizardsteps/WizStepModulesChoice.php @@ -899,9 +899,15 @@ EOF $sMetadata = ''; if (isset($aChoice['version']) && isset($aChoice['source_label'])) { $sMetadata = 'v'.$aChoice['version'].''.$aChoice['source_label'].''; - } - if ($this->IsIncludedInBasePackage($aChoice)) { - $sMetadata .= 'Included in package'; + if ($this->aBasePackageModules === null) { + $this->aBasePackageModules = SetupUtils::GetBasePackageModules( + $this->aAnalyzeInstallationModules, + $this->oWizard->GetParameter('source_dir', '') + ); + } + if (SetupUtils::IsIncludedInBasePackage($this->oExtensionsMap, $aChoice['extension_code'] ?? '', $this->aBasePackageModules)) { + $sMetadata .= 'Included in package'; + } } $sChoiceDisabled = $aFlags['disabled'] && !$aFlags['checked'] ? 'choice-disabled' : ''; @@ -942,70 +948,6 @@ EOF return $sSourceDir.'/installation.xml'; } - private function GetBasePackageModules(): array - { - if ($this->aBasePackageModules !== null) { - return $this->aBasePackageModules; - } - - $this->aBasePackageModules = []; - $sSourceDir = $this->NormalizePath($this->oWizard->GetParameter('source_dir', '')); - echo "
";
-
-		foreach ($this->aAnalyzeInstallationModules as $sModuleId => $aModuleInfo) {
-			var_dump($sModuleId);
-			if ($sModuleId === ROOT_MODULE) {
-				continue;
-			}
-
-			$sRootDir = $aModuleInfo['root_dir'] ?? '';
-			var_dump($sRootDir);
-			if ($sRootDir === '') {
-				continue;
-			}
-
-			$sModuleRootDir = $this->NormalizePath($sRootDir);
-			if (($sSourceDir !== '') && utils::StartsWith($sModuleRootDir, $sSourceDir)) {
-				$this->aBasePackageModules[$sModuleId] = true;
-			}
-		}
-		echo "
"; - - return $this->aBasePackageModules; - } - - - private function IsIncludedInBasePackage(array $aChoice): bool - { - $sExtensionCode = $aChoice['extension_code'] ?? ''; - if ($sExtensionCode === '') { - return false; - } - - $oExtension = $this->oExtensionsMap->GetFromExtensionCode($sExtensionCode); - if (($oExtension === null) || ($oExtension->sSource === iTopExtension::SOURCE_WIZARD)) { - return false; - } - - $aModules = $aChoice['modules'] ?? []; - if (!is_array($aModules) || empty($aModules)) { - return false; - } - - $aBasePackageModules = $this->GetBasePackageModules(); - foreach ($aModules as $sModuleId) { - if (!array_key_exists($sModuleId, $aBasePackageModules)) { - return false; - } - } - - return true; - } - - private function NormalizePath(string $sPath): string - { - return rtrim(str_replace('\\', '/', $sPath), '/'); - } public function CanMoveForward() {