From d0ac19c8d1db7c0eee0974b04df173ca7d0618ac Mon Sep 17 00:00:00 2001 From: Timothee Date: Wed, 4 Feb 2026 11:42:16 +0100 Subject: [PATCH] =?UTF-8?q?N=C2=B09144=20Button=20Back=20from=20recap=20sc?= =?UTF-8?q?reen=20return=20to=20extensions=20choice=20instead=20of=20data?= =?UTF-8?q?=20audit,=20Catch=20exception=20during=20compilation=20to=20exi?= =?UTF-8?q?t=20maintenance=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setup/applicationinstaller.class.inc.php | 111 ++++++++++-------- .../ModelReflectionSerializer.php | 1 + setup/wizardcontroller.class.inc.php | 6 +- setup/wizardsteps/WizStepDataAudit.php | 7 +- setup/wizardsteps/WizStepModulesChoice.php | 10 +- setup/wizardsteps/WizStepSummary.php | 1 - setup/wizardsteps/WizardStep.php | 9 ++ 7 files changed, 88 insertions(+), 57 deletions(-) diff --git a/setup/applicationinstaller.class.inc.php b/setup/applicationinstaller.class.inc.php index eb97d32ca..77963a199 100644 --- a/setup/applicationinstaller.class.inc.php +++ b/setup/applicationinstaller.class.inc.php @@ -486,67 +486,74 @@ class ApplicationInstallSequencer extends StepSequencer SetupUtils::EnterMaintenanceMode($oConfig); } } - - if (!is_dir($sTargetPath)) { - if (!mkdir($sTargetPath)) { - throw new Exception("Failed to create directory '$sTargetPath', please check the rights of the web server"); - } else { - // adjust the rights if and only if the directory was just created - // owner:rwx user/group:rx - chmod($sTargetPath, 0755); + try{ + if (!is_dir($sTargetPath)) { + if (!mkdir($sTargetPath)) { + throw new Exception("Failed to create directory '$sTargetPath', please check the rights of the web server"); + } else { + // adjust the rights if and only if the directory was just created + // owner:rwx user/group:rx + chmod($sTargetPath, 0755); + } + } elseif (substr($sTargetPath, 0, strlen(APPROOT)) == APPROOT) { + // If the directory is under the root folder - as expected - let's clean-it before compiling + SetupUtils::tidydir($sTargetPath); } - } elseif (substr($sTargetPath, 0, strlen(APPROOT)) == APPROOT) { - // If the directory is under the root folder - as expected - let's clean-it before compiling - SetupUtils::tidydir($sTargetPath); - } - $oExtensionsMap = new iTopExtensionsMap('production', $aDirsToScan); - $oExtensionsMap->DeclareExtensionAsRemoved($aRemovedExtensionCodes); + $oExtensionsMap = new iTopExtensionsMap('production', $aDirsToScan); + $oExtensionsMap->DeclareExtensionAsRemoved($aRemovedExtensionCodes); - $oFactory = new ModelFactory($aDirsToScan); + $oFactory = new ModelFactory($aDirsToScan); - $oDictModule = new MFDictModule('dictionaries', 'iTop Dictionaries', APPROOT.'dictionaries'); - $oFactory->LoadModule($oDictModule); + $oDictModule = new MFDictModule('dictionaries', 'iTop Dictionaries', APPROOT.'dictionaries'); + $oFactory->LoadModule($oDictModule); - $sDeltaFile = APPROOT.'core/datamodel.core.xml'; - if (file_exists($sDeltaFile)) { - $oCoreModule = new MFCoreModule('core', 'Core Module', $sDeltaFile); - $oFactory->LoadModule($oCoreModule); - } - $sDeltaFile = APPROOT.'application/datamodel.application.xml'; - if (file_exists($sDeltaFile)) { - $oApplicationModule = new MFCoreModule('application', 'Application Module', $sDeltaFile); - $oFactory->LoadModule($oApplicationModule); - } - - $aModules = $oFactory->FindModules(); - - foreach ($aModules as $oModule) { - $sModule = $oModule->GetName(); - if (in_array($sModule, $aSelectedModules)) { - $oFactory->LoadModule($oModule); + $sDeltaFile = APPROOT.'core/datamodel.core.xml'; + if (file_exists($sDeltaFile)) { + $oCoreModule = new MFCoreModule('core', 'Core Module', $sDeltaFile); + $oFactory->LoadModule($oCoreModule); } + $sDeltaFile = APPROOT.'application/datamodel.application.xml'; + if (file_exists($sDeltaFile)) { + $oApplicationModule = new MFCoreModule('application', 'Application Module', $sDeltaFile); + $oFactory->LoadModule($oApplicationModule); + } + + $aModules = $oFactory->FindModules(); + + foreach ($aModules as $oModule) { + $sModule = $oModule->GetName(); + if (in_array($sModule, $aSelectedModules)) { + $oFactory->LoadModule($oModule); + } + } + // Dump the "reference" model, just before loading any actual delta + $oFactory->SaveToFile(utils::GetDataPath().'datamodel-'.$sEnvironment.'.xml'); + + $sDeltaFile = utils::GetDataPath().$sEnvironment.'.delta.xml'; + if (file_exists($sDeltaFile)) { + $oDelta = new MFDeltaModule($sDeltaFile); + $oFactory->LoadModule($oDelta); + $oFactory->SaveToFile(utils::GetDataPath().'datamodel-'.$sEnvironment.'-with-delta.xml'); + } + + $oMFCompiler = new MFCompiler($oFactory, $sEnvironment); + $oMFCompiler->Compile($sTargetPath, null, $bUseSymbolicLinks); + //$aCompilerLog = $oMFCompiler->GetLog(); + //SetupLog::Info(implode("\n", $aCompilerLog)); + SetupLog::Info("Data model successfully compiled to '$sTargetPath'."); + + $sCacheDir = APPROOT.'/data/cache-'.$sEnvironment.'/'; + SetupUtils::builddir($sCacheDir); + SetupUtils::tidydir($sCacheDir); } - // Dump the "reference" model, just before loading any actual delta - $oFactory->SaveToFile(utils::GetDataPath().'datamodel-'.$sEnvironment.'.xml'); - - $sDeltaFile = utils::GetDataPath().$sEnvironment.'.delta.xml'; - if (file_exists($sDeltaFile)) { - $oDelta = new MFDeltaModule($sDeltaFile); - $oFactory->LoadModule($oDelta); - $oFactory->SaveToFile(utils::GetDataPath().'datamodel-'.$sEnvironment.'-with-delta.xml'); + catch(Exception $e){ + if (($sEnvironment == 'production') && !$bIsAlreadyInMaintenanceMode) { + SetupUtils::ExitMaintenanceMode(); + } + throw $e; } - $oMFCompiler = new MFCompiler($oFactory, $sEnvironment); - $oMFCompiler->Compile($sTargetPath, null, $bUseSymbolicLinks); - //$aCompilerLog = $oMFCompiler->GetLog(); - //SetupLog::Info(implode("\n", $aCompilerLog)); - SetupLog::Info("Data model successfully compiled to '$sTargetPath'."); - - $sCacheDir = APPROOT.'/data/cache-'.$sEnvironment.'/'; - SetupUtils::builddir($sCacheDir); - SetupUtils::tidydir($sCacheDir); - // Special case to patch a ugly patch in itop-config-mgmt $sFileToPatch = $sTargetPath.'/itop-config-mgmt-1.0.0/model.itop-config-mgmt.php'; if (file_exists($sFileToPatch)) { diff --git a/setup/feature_removal/ModelReflectionSerializer.php b/setup/feature_removal/ModelReflectionSerializer.php index 9091ef3e4..d3de6b9c9 100644 --- a/setup/feature_removal/ModelReflectionSerializer.php +++ b/setup/feature_removal/ModelReflectionSerializer.php @@ -46,6 +46,7 @@ class ModelReflectionSerializer } $aClasses = json_decode($sOutput[0] ?? null, true); +file_put_contents('C:/tmp/uninstall.log', "\n\n".var_export($sOutput, true), FILE_APPEND); if (false === $aClasses) { $this->LogErrorWithProperLogger("Invalid JSON", null, ['env' => $sEnv, "output" => $sOutput]); throw new Exception("cannot get classes"); diff --git a/setup/wizardcontroller.class.inc.php b/setup/wizardcontroller.class.inc.php index 352ec0ea0..2f472e850 100644 --- a/setup/wizardcontroller.class.inc.php +++ b/setup/wizardcontroller.class.inc.php @@ -78,7 +78,7 @@ class WizardController /** * Pushes information about the current step onto the stack - * @param hash $aStepInfo Array('class' => , 'state' => ) + * @param array $aStepInfo Array('class' => , 'state' => ) */ protected function PushStep($aStepInfo) { @@ -172,7 +172,9 @@ class WizardController /** @var \WizardStep $oStep */ $oStep = new $sCurrentStepClass($this, $sCurrentState); if ($oStep->ValidateParams()) { - $this->PushStep(['class' => $sCurrentStepClass, 'state' => $sCurrentState]); + if($oStep->CanComeBack()) { + $this->PushStep(['class' => $sCurrentStepClass, 'state' => $sCurrentState]); + } $aPossibleSteps = $oStep->GetPossibleSteps(); $aNextStepInfo = $oStep->ProcessParams(true); // true => moving forward if (in_array($aNextStepInfo['class'], $aPossibleSteps)) { diff --git a/setup/wizardsteps/WizStepDataAudit.php b/setup/wizardsteps/WizStepDataAudit.php index 953f2c473..df8527b8b 100644 --- a/setup/wizardsteps/WizStepDataAudit.php +++ b/setup/wizardsteps/WizStepDataAudit.php @@ -27,7 +27,7 @@ class WizStepDataAudit extends WizStepInstall public function GetTitle() { - return 'Checking upgrade'; + return 'Checking compatibility'; } @@ -56,6 +56,11 @@ class WizStepDataAudit extends WizStepInstall return ['class' => 'WizStepSummary', 'state' => '']; } + public function CanComeBack() + { + return false; + } + public function Display(WebPage $oPage) { diff --git a/setup/wizardsteps/WizStepModulesChoice.php b/setup/wizardsteps/WizStepModulesChoice.php index 4754fde49..d1c03f352 100644 --- a/setup/wizardsteps/WizStepModulesChoice.php +++ b/setup/wizardsteps/WizStepModulesChoice.php @@ -814,7 +814,15 @@ EOF public function GetNextButtonLabel() { - return $this->bCanMoveForward ? 'Next' : 'Non-uninstallable extension missing'; + if (!$this->bCanMoveForward) { + return 'Non-uninstallable extension missing'; + } + + if ($this->GetStepInfo(1 + $this->GetStepIndex()) === null) { + return 'Check compatibility'; + } + + return 'Next'; } } diff --git a/setup/wizardsteps/WizStepSummary.php b/setup/wizardsteps/WizStepSummary.php index 85e38e708..97d830451 100644 --- a/setup/wizardsteps/WizStepSummary.php +++ b/setup/wizardsteps/WizStepSummary.php @@ -232,7 +232,6 @@ class WizStepSummary extends AbstractWizStepInstall $sMessage .= SetupUtils::HumanReadableSize($fFreeSpace).' free in '.dirname($sDBBackupPath); } $oPage->add($sMySQLDumpMessage.''.$sMessage.''); - $oPage->add(''); $sAuthentToken = $this->oWizard->GetParameter('authent', ''); $oPage->add(''); diff --git a/setup/wizardsteps/WizardStep.php b/setup/wizardsteps/WizardStep.php index 5aaaea37a..4fc6a65e1 100644 --- a/setup/wizardsteps/WizardStep.php +++ b/setup/wizardsteps/WizardStep.php @@ -137,6 +137,15 @@ abstract class WizardStep return true; } + /** + * Tells whether the user will come back to this step/state if he click on "Back" + * @return boolean True if the 'Back' button should display this step + */ + public function CanComeBack() + { + return true; + } + /** * Tells whether the "Next" button should be enabled interactively * @return string A piece of javascript code returning either true or false