From 908e11d5079603bfd306b9aaa3eb405d2cb65763 Mon Sep 17 00:00:00 2001 From: Eric Espie Date: Mon, 18 May 2026 16:20:49 +0200 Subject: [PATCH] =?UTF-8?q?N=C2=B09567=20-=20Extension=20Mgmt=20:=20Run=20?= =?UTF-8?q?setup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DataFeatureRemovalController.php | 38 +++++---- setup/modulediscovery.class.inc.php | 3 + setup/setuputils.class.inc.php | 6 +- setup/wizardcontroller.class.inc.php | 7 +- setup/wizardsteps/WizStepDataAudit.php | 38 ++++----- .../wizardsteps/WizStepLandingBeforeAudit.php | 66 +++++++++++++++- setup/wizardsteps/WizStepModulesChoice.php | 14 ++-- setup/wizardsteps/WizStepSummary.php | 3 +- .../simulate-audit-from-setup.php | 78 ++++++++++++++++++- 9 files changed, 200 insertions(+), 53 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 1fb6aa5b19..395f3c8b31 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 @@ -112,10 +112,30 @@ class DataFeatureRemovalController extends Controller } // Display changed extensions - $aAddedExtensions = utils::ReadPostedParam('aAddedExtensions', []); - $aRemovedExtensions = utils::ReadPostedParam('aRemovedExtensions', []); + $aHiddenInputNames = [ + 'selected_modules', + 'selected_extensions', + 'display_choices', + 'added_extensions', + 'removed_extensions', + 'extensions_not_uninstallable', + ]; - IssueLog::Info(__METHOD__.' Extensions given in parameter', null, ['aAddedExtensions' => $aAddedExtensions, 'aRemovedExtensions' => $aRemovedExtensions]); + $aHiddenInputs = []; + foreach ($aHiddenInputNames as $sInputName) { + $aHiddenInputs[$sInputName] = utils::ReadPostedParam($sInputName, "[]", utils::ENUM_SANITIZATION_FILTER_RAW_DATA); + } + $aParams['aHiddenInputs'] = $aHiddenInputs; + + $aAddedExtensions = json_decode($aHiddenInputs['added_extensions'], true); + $aRemovedExtensions = json_decode($aHiddenInputs['removed_extensions'], true); + + $aParams['aAddedExtensions'] = $aAddedExtensions; + $aParams['aRemovedExtensions'] = $aRemovedExtensions; + + IssueLog::Info(__METHOD__.' Extensions given in parameter', null, [ + 'added_extensions' => $aAddedExtensions, + 'removed_extensions' => $aRemovedExtensions]); $this->Compile(array_keys($aRemovedExtensions), false); @@ -126,23 +146,15 @@ class DataFeatureRemovalController extends Controller $aParams['sTransactionId'] = utils::GetNewTransactionId(); $aParams['aClasses'] = $aGetRemovedClasses; - - $aParams['aAddedExtensions'] = $aAddedExtensions; - $aParams['aRemovedExtensions'] = $aRemovedExtensions; $aParams['aExtensions'] = $this->GetExtensionsTableDiff($aAddedExtensions, $aRemovedExtensions); new ContextTag(ContextTag::TAG_SETUP); $aParams['sLaunchSetupUrl'] = utils::GetAbsoluteUrlAppRoot().'setup/wizard.php'; - $aParams['aSetupParams'] = [ + $aParams['aSetupParams'] = array_merge([ "_class" => "WizStepLandingBeforeAudit", "_params[authent]" => SetupUtils::CreateSetupToken(), - '_params[previous_version_dir]' => APPROOT, - "_params[install_mode]" => "upgrade", - '_params[source_dir]' => APPROOT.'datamodels/2.x/', - "_params[selected_components]" => '[{"_0":"_0","_1":"_1","_2":"_2","_3":"_3","_4":"_4"},{"_0":"_0"},{"_0":"_0","_0_0":"_0_0"},{"_0":"_0"},{"_0":"_0","_1":"_1"},{"_0":"_0","_1":"_1"}]', - '_steps' => '[{"class":"WizStepWelcome","state":""},{"class":"WizStepInstallOrUpgrade","state":""},{"class":"WizStepDetectedInfo","state":""},{"class":"WizStepUpgradeMiscParams","state":""},{"class":"WizStepModulesChoice","state":"start_upgrade"},{"class":"WizStepModulesChoice","state":"1"},{"class":"WizStepModulesChoice","state":"2"},{"class":"WizStepModulesChoice","state":"3"}]', "operation" => "next", - ]; + ], $aHiddenInputs); [$aParams['aDeletionPlanSummary'], $aParams['iQueryCount'], $aParams['bDeletionPossible']] = $this->GetDeletionPlanSummaryTable($aGetRemovedClasses); [$aParams['aDeletionExecutionSummary'], $aParams['bHasDeletionExecution']] = $this->GetExecutionSummaryTable(); diff --git a/setup/modulediscovery.class.inc.php b/setup/modulediscovery.class.inc.php index b7f27413a2..101912ad59 100755 --- a/setup/modulediscovery.class.inc.php +++ b/setup/modulediscovery.class.inc.php @@ -357,6 +357,9 @@ class ModuleDiscovery { $sDirectory = $sRootDir.'/'.$sRelDir; + if (!is_dir(utils::RealPath($sDirectory, APPROOT))) { + throw new Exception('Data directory ('.$sDirectory.') Does not exist or is outside iTop.'); + } if ($hDir = opendir($sDirectory)) { // This is the correct way to loop over the directory. (according to the documentation) while (($sFile = readdir($hDir)) !== false) { diff --git a/setup/setuputils.class.inc.php b/setup/setuputils.class.inc.php index d04ceb525f..f48f0a53cc 100644 --- a/setup/setuputils.class.inc.php +++ b/setup/setuputils.class.inc.php @@ -1576,11 +1576,13 @@ JS * @return array * @throws Exception */ - public static function AnalyzeInstallation($oWizard, $bAbortOnMissingDependency = false, $aModulesToLoad = null) + public static function AnalyzeInstallation($oWizard, $bAbortOnMissingDependency = false, $aModulesToLoad = null, Config $oConfig = null) { require_once(APPROOT.'/setup/moduleinstaller.class.inc.php'); - $oConfig = self::GetConfig($oWizard); + if (is_null($oConfig)) { + $oConfig = self::GetConfig($oWizard); + } $aDirsToScan = [$oWizard->GetParameter('source_dir', '')]; diff --git a/setup/wizardcontroller.class.inc.php b/setup/wizardcontroller.class.inc.php index 3c914dd1a5..2f2fd3258d 100644 --- a/setup/wizardcontroller.class.inc.php +++ b/setup/wizardcontroller.class.inc.php @@ -296,7 +296,7 @@ on the page's parameters $sOperation = utils::ReadParam('operation'); $this->aParameters = utils::ReadParam('_params', [], false, 'raw_data'); - $this->aSteps = json_decode(utils::ReadParam('_steps', '[]', false, 'raw_data'), true /* bAssoc */); + $this->SetSteps(json_decode(utils::ReadParam('_steps', '[]', false, 'raw_data'), true)); switch ($sOperation) { case 'next': @@ -371,6 +371,11 @@ on the page's parameters return $sOutput; } + public function SetSteps(array $aSteps): void + { + $this->aSteps = $aSteps; + } + /** * @param string $sCurrentStepClass * @param string $sCurrentState diff --git a/setup/wizardsteps/WizStepDataAudit.php b/setup/wizardsteps/WizStepDataAudit.php index 773619e0b2..97b7ccd8d4 100644 --- a/setup/wizardsteps/WizStepDataAudit.php +++ b/setup/wizardsteps/WizStepDataAudit.php @@ -100,39 +100,29 @@ JS); { $sApplicationUrl = utils::GetAbsoluteUrlModulePage('combodo-data-feature-removal', 'index.php'); - $aRemovedExtensions = json_decode($this->oWizard->GetParameter('removed_extensions', '[]'), true); - $aHiddenRemovedExtensionInputs = ''; - if (!is_array($aRemovedExtensions)) { - IssueLog::Warning('Posted removed_extensions is not an array'); - $aRemovedExtensions = []; - } - foreach ($aRemovedExtensions as $sExtCode => $sExtLabel) { - $sSafeExtCode = utils::HtmlEntities($sExtCode); - $aHiddenRemovedExtensionInputs .= << + $aParams = [ + 'selected_modules', + 'selected_extensions', + 'display_choices', + 'added_extensions', + 'removed_extensions', + 'extensions_not_uninstallable', + ]; + $aHiddenInputs = ''; + foreach ($aParams as $sParamName) { + $sElements = $this->oWizard->GetParameter($sParamName, '[]'); + $aHiddenInputs .= << INPUT; } - $aAddedExtensions = json_decode($this->oWizard->GetParameter('extensions_added', "[]"), true); - $aHiddenAddedExtensionInputs = ""; - if (!is_array($aAddedExtensions)) { - IssueLog::Warning('Posted extensions_added is not an array'); - $aAddedExtensions = []; - } - foreach ($aAddedExtensions as $sExtCode => $sExtLabel) { - $sSafeExtCode = utils::HtmlEntities($sExtCode); - $aHiddenAddedExtensionInputs .= << -INPUT; - } $sUID = Session::Get('setup_token'); $oPage->add( << - $aHiddenRemovedExtensionInputs - $aHiddenAddedExtensionInputs + $aHiddenInputs HTML ); diff --git a/setup/wizardsteps/WizStepLandingBeforeAudit.php b/setup/wizardsteps/WizStepLandingBeforeAudit.php index fda42a2080..d2bf47fc01 100644 --- a/setup/wizardsteps/WizStepLandingBeforeAudit.php +++ b/setup/wizardsteps/WizStepLandingBeforeAudit.php @@ -5,8 +5,29 @@ * @license http://opensource.org/licenses/AGPL-3.0 */ -class WizStepLandingBeforeAudit extends WizardStep +class WizStepLandingBeforeAudit extends WizStepModulesChoice { + public function __construct(WizardController $oWizard, $sCurrentState) + { + $oProductionEnv = new RunTimeEnvironment(); + $sBuildConfigFile = APPCONF.$oProductionEnv->GetBuildEnv().'/'.ITOP_CONFIG_FILE; + $this->oConfig = new Config($sBuildConfigFile); + + $oWizard->SetParameter('previous_version_dir', APPROOT); + $oWizard->SetParameter('install_mode', 'upgrade'); + $oWizard->SetParameter('source_dir', APPROOT.$this->oConfig->Get('source_dir')); + $oWizard->SetParameter('graphviz_path', $this->oConfig->Get('graphviz_path')); + $oWizard->SetParameter('application_url', $this->oConfig->Get('app_root_url')); + $oWizard->SetParameter('datamodel_version', ITOP_CORE_VERSION); + $oWizard->SetParameter('upgrade_type', 'use-compatible'); + + $oWizard->SaveParameter('use_symbolic_links', MFCompiler::UseSymbolicLinks()); + $oWizard->SaveParameter('force-uninstall', ''); + + // should be done at the end + parent::__construct($oWizard, $sCurrentState, false); + } + /** * @inheritDoc */ @@ -17,15 +38,54 @@ class WizStepLandingBeforeAudit extends WizardStep /** * @inheritDoc */ - public function UpdateWizardStateAndGetNextStep(bool $bMoveForward = true): WizardState + public function UpdateWizardStateAndGetNextStep($bMoveForward = true): WizardState { + $this->oWizard->SetParameter('selected_components', '[{"_0":"_0","_1":"_1","_2":"_2","_3":"_3","_4":"_4"},{"_0":"_0"},{"_0":"_0","_0_0":"_0_0"},{"_0":"_0"},{"_0":"_0","_1":"_1"},{"_0":"_0","_1":"_1"}]'); + $aSteps = json_decode( + '[ + {"class":"WizStepWelcome","state":""}, + {"class":"WizStepInstallOrUpgrade","state":""}, + {"class":"WizStepDetectedInfo","state":""}, + {"class":"WizStepUpgradeMiscParams","state":""}, + {"class":"WizStepModulesChoice","state":"start_upgrade"}, + {"class":"WizStepModulesChoice","state":"1"}, + {"class":"WizStepModulesChoice","state":"2"}, + {"class":"WizStepModulesChoice","state":"3"}]', + true + ); + $this->oWizard->SetSteps($aSteps); + $this->aSteps = $aSteps; + + $this->sCurrentState = count($aSteps) - 1; + //parent::UpdateWizardStateAndGetNextStep(true); + + $oProductionEnv = new RunTimeEnvironment(); + $sBuildConfigFile = APPCONF.$oProductionEnv->GetBuildEnv().'/'.ITOP_CONFIG_FILE; + @chmod($sBuildConfigFile, 0770); // In case it exists: RWX for owner and group, nothing for others + + $oConfig = new Config($sBuildConfigFile); + $this->oWizard->SetParameter('db_server', $oConfig->Get('db_host')); + $this->oWizard->SetParameter('db_user', $oConfig->Get('db_user')); + $this->oWizard->SetParameter('db_pwd', $oConfig->Get('db_pwd')); + $this->oWizard->SetParameter('db_name', $oConfig->Get('db_name')); + $this->oWizard->SetParameter('db_prefix', $oConfig->Get('db_subname')); + $this->oWizard->SetParameter('db_tls_enabled', $oConfig->Get('db_tls.enabled')); + $this->oWizard->SetParameter('db_tls_ca', $oConfig->Get('db_tls.ca') ?? ''); + + $this->oWizard->SaveParameter('selected_modules', []); + $this->oWizard->SaveParameter('selected_extensions', []); + $this->oWizard->SaveParameter('display_choices', []); + $this->oWizard->SaveParameter('added_extensions', []); + $this->oWizard->SaveParameter('removed_extensions', []); + $this->oWizard->SaveParameter('extensions_not_uninstallable', []); + return new WizardState(WizStepDataAudit::class); } /** * @inheritDoc */ - public function GetTitle() + public function GetTitle(): string { return 'Before checking compatibility'; } diff --git a/setup/wizardsteps/WizStepModulesChoice.php b/setup/wizardsteps/WizStepModulesChoice.php index 1f0134f615..1ca139445c 100644 --- a/setup/wizardsteps/WizStepModulesChoice.php +++ b/setup/wizardsteps/WizStepModulesChoice.php @@ -38,7 +38,7 @@ class WizStepModulesChoice extends AbstractWizStepInstall */ protected iTopExtensionsMap $oExtensionsMap; - private ?array $aSteps = null; + protected ?array $aSteps = null; protected PhpExpressionEvaluator $oPhpExpressionEvaluator; @@ -51,7 +51,7 @@ class WizStepModulesChoice extends AbstractWizStepInstall private array $aAnalyzeInstallationModules = []; private ?MissingDependencyException $oMissingDependencyException = null; - public function __construct(WizardController $oWizard, $sCurrentState) + public function __construct(WizardController $oWizard, $sCurrentState, bool $bOverWriteConfig = true) { parent::__construct($oWizard, $sCurrentState); $this->bChoicesFromDatabase = false; @@ -69,8 +69,10 @@ class WizStepModulesChoice extends AbstractWizStepInstall if ($sConfigPath !== null) { $this->oConfig = new Config($sConfigPath); - $aParamValues = $oWizard->GetParamForConfigArray(); - $this->oConfig->UpdateFromParams($aParamValues); + if ($bOverWriteConfig) { + $aParamValues = $oWizard->GetParamForConfigArray(); + $this->oConfig->UpdateFromParams($aParamValues); + } $this->oExtensionsMap->LoadChoicesFromDatabase($this->oConfig); $this->bChoicesFromDatabase = true; @@ -78,7 +80,7 @@ class WizStepModulesChoice extends AbstractWizStepInstall // Sanity check (not stopper, to let developers go further...) try { - $this->aAnalyzeInstallationModules = SetupUtils::AnalyzeInstallation($this->oWizard, true); + $this->aAnalyzeInstallationModules = SetupUtils::AnalyzeInstallation($this->oWizard, true, null, $this->oConfig); } catch (MissingDependencyException $e) { $this->oMissingDependencyException = $e; $this->aAnalyzeInstallationModules = SetupUtils::AnalyzeInstallation($this->oWizard); @@ -192,7 +194,7 @@ class WizStepModulesChoice extends AbstractWizStepInstall $this->oWizard->SetParameter('selected_modules', json_encode(array_keys($aModules))); $this->oWizard->SetParameter('selected_extensions', json_encode($aExtensions)); $this->oWizard->SetParameter('display_choices', $sDisplayChoices); - $this->oWizard->SetParameter('extensions_added', json_encode($aExtensionsAdded)); + $this->oWizard->SetParameter('added_extensions', json_encode($aExtensionsAdded)); $this->oWizard->SetParameter('removed_extensions', json_encode($aExtensionsRemoved)); $this->oWizard->SetParameter('extensions_not_uninstallable', json_encode(array_keys($aExtensionsNotUninstallable))); diff --git a/setup/wizardsteps/WizStepSummary.php b/setup/wizardsteps/WizStepSummary.php index 3d70e8ffaa..1b1d9e404d 100644 --- a/setup/wizardsteps/WizStepSummary.php +++ b/setup/wizardsteps/WizStepSummary.php @@ -17,7 +17,6 @@ * * You should have received a copy of the GNU Affero General Public License */ -use Combodo\iTop\Application\WebPage\WebPage; /** * Summary of the installation tasks @@ -84,7 +83,7 @@ class WizStepSummary extends AbstractWizStepInstall $oPage->add('
'); $oPage->add('
Extensions to be installed'); - $aExtensionsAdded = json_decode($this->oWizard->GetParameter('extensions_added'), true); + $aExtensionsAdded = json_decode($this->oWizard->GetParameter('added_extensions'), true); if (count($aExtensionsAdded) > 0) { $sExtensionsAdded = '
    '; diff --git a/tests/php-unit-tests/unitary-tests/datamodels/2.x/combodo-data-feature-removal/simulate-audit-from-setup.php b/tests/php-unit-tests/unitary-tests/datamodels/2.x/combodo-data-feature-removal/simulate-audit-from-setup.php index 93fabb3280..179bea189c 100644 --- a/tests/php-unit-tests/unitary-tests/datamodels/2.x/combodo-data-feature-removal/simulate-audit-from-setup.php +++ b/tests/php-unit-tests/unitary-tests/datamodels/2.x/combodo-data-feature-removal/simulate-audit-from-setup.php @@ -15,13 +15,87 @@ $aParams = [ new ContextTag(ContextTag::TAG_SETUP); $sToken = SetupUtils::CreateSetupToken(); +$aSelectedModules = [ + 'authent-cas', + 'authent-external', + 'authent-ldap', + 'authent-local', + 'combodo-backoffice-darkmoon-theme', + 'combodo-backoffice-fullmoon-high-contrast-theme', + 'combodo-backoffice-fullmoon-protanopia-deuteranopia-theme', + 'combodo-backoffice-fullmoon-tritanopia-theme', + 'combodo-data-feature-removal', + 'itop-backup', + 'itop-config', + 'itop-files-information', + 'itop-portal-base', + 'itop-profiles-itil', + 'itop-sla-computation', + 'itop-structure', + 'itop-welcome-itil', + 'itop-config-mgmt', + 'itop-attachments', + 'itop-tickets', + 'combodo-db-tools', + 'itop-core-update', + 'itop-hub-connector', + 'itop-oauth-client', + 'itop-themes-compat', + 'combodo-my-account', + 'combodo-my-account-user-info', + 'combodo-oauth2-client', + 'itop-attribute-class-set', + 'itop-attribute-encrypted-password', + 'itop-ui-copypaste', + 'itop-datacenter-mgmt', + 'itop-endusers-devices', + 'itop-storage-mgmt', + 'itop-virtualization-mgmt', + 'itop-bridge-cmdb-ticket', + 'itop-bridge-virtualization-storage', + 'itop-service-mgmt', + 'itop-bridge-cmdb-services', + 'itop-bridge-datacenter-mgmt-services', + 'itop-bridge-endusers-devices-services', + 'itop-bridge-storage-mgmt-services', + 'itop-bridge-virtualization-mgmt-services', + 'itop-request-mgmt', + 'itop-portal', + 'itop-change-mgmt', + 'itop-faq-light', + 'itop-knownerror-mgmt', + 'itop-problem-mgmt', + 'itop-system-information', + 'itop-log-mgmt', +]; + +$aSelectedExtensions = [ + 'itop-config-mgmt-core', + 'itop-config-mgmt-datacenter', + 'itop-config-mgmt-end-user', + 'itop-config-mgmt-storage', + 'itop-config-mgmt-virtualization', + 'itop-service-mgmt-enterprise', + 'itop-ticket-mgmt-simple-ticket', + 'itop-ticket-mgmt-simple-ticket-enhanced-portal', + 'itop-change-mgmt-simple', + 'itop-kown-error-mgmt', + 'itop-problem-mgmt', + 'itop-system-information', + 'itop-log-mgmt', +]; + +$aRemovedExtensions = ['itop-container-mgmt' => 'Containerization']; + $aPostParams = [ "auth_user" => 'admin', "auth_pwd" => 'admin', 'login_mode' => 'form', 'operation' => 'AnalysisResult', - 'aRemovedExtensions[itop-container-mgmt]' => 'Containerization', 'setup_token' => $sToken, + 'selected_modules' => utils::HtmlEntities(json_encode($aSelectedModules)), + 'selected_extensions' => utils::HtmlEntities(json_encode($aSelectedExtensions)), + 'removed_extensions' => utils::HtmlEntities(json_encode($aRemovedExtensions)), ]; $sHiddenPostedInput = ""; @@ -45,7 +119,7 @@ $sReadyJs = <<add($sDiv); $oP->add_ready_script($sReadyJs); $oP->output();