From 99bce2b2b28141706779faab7b025774427709e8 Mon Sep 17 00:00:00 2001 From: Eric Espie Date: Tue, 7 Jul 2026 11:14:20 +0200 Subject: [PATCH] Refactor DataFeatureRemovalController and related classes for improved session management and cleanup processes --- .../DataFeatureRemovalController.php | 44 +++++----- .../DryRemovalRuntimeEnvironment.php | 2 +- setup/runtimeenv.class.inc.php | 82 +++++++++---------- 3 files changed, 65 insertions(+), 63 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 bcc30828c2..5c767f2dfa 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 @@ -18,6 +18,8 @@ use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalHelper; use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalLog; use Combodo\iTop\DataFeatureRemoval\Service\DataCleanupService; use Combodo\iTop\DataFeatureRemoval\Service\DataFeatureRemoverExtensionService; +use Combodo\iTop\DataFeatureRemoval\Service\StaticDeletionPlan; +use Combodo\iTop\Service\Session\SessionParameters; use Combodo\iTop\Setup\FeatureRemoval\DryRemovalRuntimeEnvironment; use Combodo\iTop\Setup\FeatureRemoval\SetupAudit; use ContextTag; @@ -47,6 +49,9 @@ class DataFeatureRemovalController extends Controller { $aParams = []; + SetupUtils::EraseSetupToken(); + (new SessionParameters(SetupUtils::SESSION_PARAMETERS_NAME))->Erase(); + $this->AddAnalyzeParams(); $aParams['sTransactionId'] = utils::GetNewTransactionId(); $aParams['iColumnCount'] = $this->iColumnCount; @@ -100,9 +105,9 @@ class DataFeatureRemovalController extends Controller 'removed_extensions' => '[]', 'extensions_not_uninstallable' => '[]', 'copy_setup_files' => 1, - 'force-uninstall' => "", + 'force-uninstall' => '', 'use_symbolic_links' => MFCompiler::UseSymbolicLinks() ? 'on' : '', - 'return_button_label' => '', + 'return_application' => '', 'target_env' => ITOP_DEFAULT_ENV, ]; @@ -112,10 +117,6 @@ class DataFeatureRemovalController extends Controller } $aParams['aHiddenInputs'] = $aHiddenInputs; - if ($aHiddenInputs['return_button_label'] !== '') { - $aParams['sReturnButtonURL'] = utils::GetAbsoluteUrlModulePage('itsm-designer-connector', 'launch.php'); - } - $aAddedExtensions = json_decode($aHiddenInputs['added_extensions'], true); $aRemovedExtensions = json_decode($aHiddenInputs['removed_extensions'], true); @@ -143,24 +144,26 @@ class DataFeatureRemovalController extends Controller $aParams['aAvailableExtensions'] = $this->SplitArrayIntoColumns($this->GetExtensionsDiff($aAddedExtensions, $aRemovedExtensions), $this->iColumnCount); //to make setup redirection work, we need to pass complex data structures to setup wizards (ie extension/module lists) - $oConfig = MetaModel::GetConfig(); - $aSelectedExtensions = DataFeatureRemoverExtensionService::GetInstance()->GetExtensionMap()->GetSelectedExtensions($oConfig, array_keys($aAddedExtensions), array_keys($aRemovedExtensions)); - - $oRunTimeEnvironment = $this->GetRuntimeEnvironment($aAddedExtensions, $aRemovedExtensions); - $aSearchDirs = [$oRunTimeEnvironment->GetBuildDir()]; - $aSelectedModules = $oRunTimeEnvironment->GetModulesToLoadFromChoices($oConfig, $aSelectedExtensions, $aSearchDirs); if ('[]' === $aHiddenInputs['selected_modules']) { + $oConfig = MetaModel::GetConfig(); + $aSelectedExtensions = DataFeatureRemoverExtensionService::GetInstance()->GetExtensionMap()->GetSelectedExtensions($oConfig, array_keys($aAddedExtensions), array_keys($aRemovedExtensions)); + + $oRunTimeEnvironment = $this->GetRuntimeEnvironment($aAddedExtensions, $aRemovedExtensions); + [$aDummy, $aSearchDirs] = $oRunTimeEnvironment->GetDirsToCompile($oConfig->Get('source_dir')); + $aSelectedModules = $oRunTimeEnvironment->GetModulesToLoadFromChoices($oConfig, $aSelectedExtensions, $aSearchDirs); $aHiddenInputs['selected_extensions'] = $this->ConvertIntoSetupFormat($aSelectedExtensions); $aHiddenInputs['selected_modules'] = $this->ConvertIntoSetupFormat($aSelectedModules); + } else { + $aSelectedExtensions = json_decode($aHiddenInputs['selected_extensions'], true); + $aSelectedModules = json_decode($aHiddenInputs['selected_modules'], true); } IssueLog::Info(sMessage: '$aSelectedExtensions', aContext: $aSelectedExtensions); IssueLog::Info(sMessage: '$aRemovedExtensions', aContext: $aRemovedExtensions); IssueLog::Info(sMessage: '$aSelectedModules', aContext: $aSelectedModules); - $bForceCompilation = Session::Get('bForceCompilation', false); try { - $this->Compile($aSelectedExtensions, array_keys($aRemovedExtensions), $aSelectedModules, $bForceCompilation); + $this->Compile($aSelectedExtensions, array_keys($aRemovedExtensions), $aSelectedModules); } catch (CoreException $e) { $aParams['DataFeatureRemovalErrorMessage'] = $e->getHtmlDesc(); $this->DisplayPage($aParams, 'AnalysisResult'); @@ -186,11 +189,7 @@ class DataFeatureRemovalController extends Controller ]; foreach ($aHiddenInputs as $sInputName => $sInputValue) { - $aParams['aSetupParams']["_params[$sInputName]"] = $sInputValue; - } - - if ($aHiddenInputs['return_button_label'] !== '') { - $aParams['sReturnButtonURL'] = utils::GetAbsoluteUrlModulePage('itsm-designer-connector', 'launch.php'); + $aParams['aSetupParams'][$sInputName] = $sInputValue; } [$aParams['aDeletionPlanSummary'], $aParams['iQueryCount'], $aParams['bDeletionPossible']] = $this->GetDeletionPlanSummaryTable($aGetRemovedClasses); @@ -199,6 +198,7 @@ class DataFeatureRemovalController extends Controller Session::Set('aDeletionExecutionSummary', serialize($this->aDeletionExecutionSummary)); if (!$aParams['bDeletionNeeded']) { + // Erase session setup parameters SetupUtils::CreateSetupToken(); } @@ -225,7 +225,7 @@ class DataFeatureRemovalController extends Controller * @throws \ConfigException * @throws \CoreException */ - private function Compile(array $aSelectedExtensionCodes, array $aRemovedExtensionCodes, array $aSelectedModules, bool $bForceCompilation = true): void + private function Compile(array $aSelectedExtensionCodes, array $aRemovedExtensionCodes, array $aSelectedModules): void { $sSourceEnv = MetaModel::GetEnvironment(); $sBuildDir = APPROOT."/env-$sSourceEnv-build"; @@ -233,8 +233,10 @@ class DataFeatureRemovalController extends Controller SetupUtils::builddir($sBuildDir); } $bIsDirEmpty = count(scandir($sBuildDir)) === 2; + $bForceCompilation = Session::Get('bForceCompilation', false); if ($bIsDirEmpty || $bForceCompilation) { + Session::Unset('bForceCompilation'); DataFeatureRemovalLog::Debug( __METHOD__, null, @@ -286,7 +288,7 @@ class DataFeatureRemovalController extends Controller private function GetDeletionPlanSummaryTable(array $aRemovedClasses): array { $sName = 'DeletionPlanSummary'; - $oDataCleanupService = new DataCleanupService(); + $oDataCleanupService = new StaticDeletionPlan(); $aDeletionPlanSummaryEntities = $oDataCleanupService->GetCleanupSummary($aRemovedClasses); $aColumns = ['Class', 'Delete Count' , 'Update Count', 'Issue Count']; $aRows = []; diff --git a/setup/feature_removal/DryRemovalRuntimeEnvironment.php b/setup/feature_removal/DryRemovalRuntimeEnvironment.php index fc4ffd84c2..48eb7d041c 100644 --- a/setup/feature_removal/DryRemovalRuntimeEnvironment.php +++ b/setup/feature_removal/DryRemovalRuntimeEnvironment.php @@ -38,7 +38,7 @@ class DryRemovalRuntimeEnvironment extends RunTimeEnvironment $oSourceConfig = new Config(APPCONF.$sSourceEnv.'/'.ITOP_CONFIG_FILE); $sSourceDir = $oSourceConfig->Get('source_dir'); - list($aExtraDirs, ) = $this->GetDirsToCompile($sSourceDir, $sSourceEnv); + [$aExtraDirs] = $this->GetDirsToCompile($sSourceDir); $this->InitExtensionMap($aExtraDirs, $oSourceConfig); $this->GetExtensionMap()->DeclareExtensionAsRemoved($this->aExtensionsToRemoveByCode); diff --git a/setup/runtimeenv.class.inc.php b/setup/runtimeenv.class.inc.php index 5010c1e3e2..75d5df9491 100644 --- a/setup/runtimeenv.class.inc.php +++ b/setup/runtimeenv.class.inc.php @@ -71,7 +71,7 @@ class RunTimeEnvironment return $this->oExtensionsMap; } - protected function GetDirsToCompile(string $sSourceDir, string $sSourceEnv): array + public function GetDirsToCompile(string $sSourceDir): array { $sSourceDirFull = APPROOT.$sSourceDir; if (!is_dir($sSourceDirFull)) { @@ -470,7 +470,7 @@ class RunTimeEnvironment */ protected function GetMFModulesToCompile($sSourceEnv, $sSourceDir): array { - list($aExtraDirs, $aDirsToCompile) = $this->GetDirsToCompile($sSourceDir, $sSourceEnv); + list($aExtraDirs, $aDirsToCompile) = $this->GetDirsToCompile($sSourceDir); $oSourceConfig = new Config(APPCONF.$sSourceEnv.'/'.ITOP_CONFIG_FILE); $this->InitExtensionMap($aExtraDirs, $oSourceConfig); $this->GetExtensionMap()->LoadChoicesFromDatabase($oSourceConfig); @@ -480,9 +480,9 @@ class RunTimeEnvironment } } $aModulesToLoad = $this->GetModulesToLoad($this->sFinalEnv, $aDirsToCompile); - foreach ($aModulesToLoad as $sKey){ - if (false !== strpos($sKey, 'enduser')){ - SetupLog::Error(__METHOD__ . ':'.__LINE__. ' aModulesToLoad: ' . $sKey) ; + foreach ($aModulesToLoad as $sKey) { + if (false !== strpos($sKey, 'enduser')) { + SetupLog::Error(__METHOD__.':'.__LINE__.' aModulesToLoad: '.$sKey) ; } } $aAvailableModules = $this->AnalyzeInstallation($oSourceConfig, $aDirsToCompile, true, $aModulesToLoad); @@ -509,8 +509,8 @@ class RunTimeEnvironment foreach ($aModules as $oModule) { $sModule = $oModule->GetName(); - if (false !== strpos($sModule, 'enduser')){ - SetupLog::Error(__METHOD__ . ':'.__LINE__. ' oFactory->FindModules: ' . $sModule) ; + if (false !== strpos($sModule, 'enduser')) { + SetupLog::Error(__METHOD__.':'.__LINE__.' oFactory->FindModules: '.$sModule) ; } $bIsExtra = $this->GetExtensionMap()->ModuleIsChosenAsPartOfAnExtension($sModule, iTopExtension::SOURCE_REMOTE); if (array_key_exists($sModule, $aAvailableModules)) { @@ -528,8 +528,8 @@ class RunTimeEnvironment $bModuleAdded = false; foreach ($aModules as $oModule) { if (!array_key_exists($oModule->GetName(), $aRet) && $oModule->IsAutoSelect()) { - if (false !== strpos($oModule->GetName(), 'enduser')){ - SetupLog::Error(__METHOD__ . ':'.__LINE__. ' IsAutoSelect: ' . $oModule->GetName()) ; + if (false !== strpos($oModule->GetName(), 'enduser')) { + SetupLog::Error(__METHOD__.':'.__LINE__.' IsAutoSelect: '.$oModule->GetName()) ; } SetupInfo::SetSelectedModules($aRet); try { @@ -1393,49 +1393,49 @@ class RunTimeEnvironment { $oConfig = new Config(utils::GetConfigFilePath($sSourceEnv)); $sSourceDir = $oConfig->Get('source_dir'); - list($aExtraDirs, ) = $this->GetDirsToCompile($sSourceDir, $sSourceEnv); + list($aExtraDirs, ) = $this->GetDirsToCompile($sSourceDir); $this->InitExtensionMap($aExtraDirs, $oConfig); $aSelectedExtensions = $this->GetExtensionMap()->GetSelectedExtensions($oConfig, [], []); $aSelectedModules = $this->GetModulesToLoadFromChoices($oConfig, $aSelectedExtensions, $this->GetExtensionMap()->GetScannedModulesRootDirs()); return $this->DoCompile(array_keys($aSelectedExtensions), [], $aSelectedModules, $bUseSymLinks ?? false); -/* + /* - $oSourceConfig = new Config(utils::GetConfigFilePath($sSourceEnv)); - $sSourceDir = $oSourceConfig->Get('source_dir'); + $oSourceConfig = new Config(utils::GetConfigFilePath($sSourceEnv)); + $sSourceDir = $oSourceConfig->Get('source_dir'); - $sSourceDirFull = APPROOT.$sSourceDir; - // Do load the required modules - // - $oFactory = new ModelFactory($sSourceDirFull); - $aModulesToCompile = $this->GetMFModulesToCompile($sSourceEnv, $sSourceDir); - $oModule = null; - foreach ($aModulesToCompile as $oModule) { - if ($oModule instanceof MFDeltaModule) { - // Just before loading the delta, let's save an image of the datamodel - // in case there is no delta the operation will be done after the end of the loop - $oFactory->SaveToFile(utils::GetDataPath().'datamodel-'.$this->sBuildEnv.'.xml'); - } - $oFactory->LoadModule($oModule); - } + $sSourceDirFull = APPROOT.$sSourceDir; + // Do load the required modules + // + $oFactory = new ModelFactory($sSourceDirFull); + $aModulesToCompile = $this->GetMFModulesToCompile($sSourceEnv, $sSourceDir); + $oModule = null; + foreach ($aModulesToCompile as $oModule) { + if ($oModule instanceof MFDeltaModule) { + // Just before loading the delta, let's save an image of the datamodel + // in case there is no delta the operation will be done after the end of the loop + $oFactory->SaveToFile(utils::GetDataPath().'datamodel-'.$this->sBuildEnv.'.xml'); + } + $oFactory->LoadModule($oModule); + } - if (!is_null($oModule) && ($oModule instanceof MFDeltaModule)) { - // A delta was loaded, let's save a second copy of the datamodel - $oFactory->SaveToFile(utils::GetDataPath().'datamodel-'.$this->sBuildEnv.'-with-delta.xml'); - } else { - // No delta was loaded, let's save the datamodel now - $oFactory->SaveToFile(utils::GetDataPath().'datamodel-'.$this->sBuildEnv.'.xml'); - } + if (!is_null($oModule) && ($oModule instanceof MFDeltaModule)) { + // A delta was loaded, let's save a second copy of the datamodel + $oFactory->SaveToFile(utils::GetDataPath().'datamodel-'.$this->sBuildEnv.'-with-delta.xml'); + } else { + // No delta was loaded, let's save the datamodel now + $oFactory->SaveToFile(utils::GetDataPath().'datamodel-'.$this->sBuildEnv.'.xml'); + } - $sBuildDir = APPROOT.'env-'.$this->sBuildEnv; - self::MakeDirSafe($sBuildDir); - $bSkipTempDir = ($this->sFinalEnv != $this->sBuildEnv); // No need for a temporary directory if sBuildEnv is already a temporary directory - $oMFCompiler = new MFCompiler($oFactory, $this->sFinalEnv); - $oMFCompiler->Compile($sBuildDir, $bUseSymLinks, $bSkipTempDir); + $sBuildDir = APPROOT.'env-'.$this->sBuildEnv; + self::MakeDirSafe($sBuildDir); + $bSkipTempDir = ($this->sFinalEnv != $this->sBuildEnv); // No need for a temporary directory if sBuildEnv is already a temporary directory + $oMFCompiler = new MFCompiler($oFactory, $this->sFinalEnv); + $oMFCompiler->Compile($sBuildDir, $bUseSymLinks, $bSkipTempDir); - MetaModel::ResetAllCaches($this->sBuildEnv); + MetaModel::ResetAllCaches($this->sBuildEnv); - return array_keys($aModulesToCompile);*/ + return array_keys($aModulesToCompile);*/ } /**