diff --git a/datamodels/2.x/itop-core-update/ajax.php b/datamodels/2.x/itop-core-update/ajax.php index 78f513701..2d0ba9c1a 100644 --- a/datamodels/2.x/itop-core-update/ajax.php +++ b/datamodels/2.x/itop-core-update/ajax.php @@ -20,14 +20,15 @@ require_once(MODULESROOT.'itop-core-update/src/Service/RunTimeEnvironmentCoreUpd require_once(MODULESROOT.'itop-core-update/src/Service/CoreUpdater.php'); require_once(MODULESROOT.'itop-core-update/src/Controller/AjaxController.php'); + MetaModel::LoadConfig(utils::GetConfig()); new ContextTag('Setup'); -$oUpdateController = new AjaxController(); +$oUpdateController = new AjaxController(MODULESROOT.'itop-core-update/view', 'itop-core-update'); $oUpdateController->DisableInDemoMode(); $oUpdateController->AllowOnlyAdmin(); // Allow parallel execution of ajax requests session_write_close(); -$oUpdateController->HandleOperation(); +$oUpdateController->HandleAjaxOperation(); diff --git a/datamodels/2.x/itop-core-update/en.dict.itop-core-update.php b/datamodels/2.x/itop-core-update/en.dict.itop-core-update.php index fd36e98ad..cf0188ac1 100644 --- a/datamodels/2.x/itop-core-update/en.dict.itop-core-update.php +++ b/datamodels/2.x/itop-core-update/en.dict.itop-core-update.php @@ -73,7 +73,9 @@ Dict::Add('EN US', 'English', 'English', array( 'iTopUpdate:UI:SetupMessage:Backup' => 'Database backup', 'iTopUpdate:UI:SetupMessage:FilesArchive' => 'Archive application files', 'iTopUpdate:UI:SetupMessage:CopyFiles' => 'Copy new version files', - 'iTopUpdate:UI:SetupMessage:Compile' => 'Upgrade application and database', + 'iTopUpdate:UI:SetupMessage:CheckCompile' => 'Check application upgrade', + 'iTopUpdate:UI:SetupMessage:Compile' => 'Upgrade application', + 'iTopUpdate:UI:SetupMessage:UpdateDatabase' => 'Upgrade database', 'iTopUpdate:UI:SetupMessage:ExitMaintenance' => 'Exiting maintenance mode', 'iTopUpdate:UI:SetupMessage:UpdateDone' => 'Upgrade completed', diff --git a/datamodels/2.x/itop-core-update/fr.dict.itop-core-update.php b/datamodels/2.x/itop-core-update/fr.dict.itop-core-update.php index b6ce72dde..9cff67412 100644 --- a/datamodels/2.x/itop-core-update/fr.dict.itop-core-update.php +++ b/datamodels/2.x/itop-core-update/fr.dict.itop-core-update.php @@ -72,7 +72,9 @@ Dict::Add('FR FR', 'French', 'Français', array( 'iTopUpdate:UI:SetupMessage:Backup' => 'Sauvegarde des fichiers de l\'application', 'iTopUpdate:UI:SetupMessage:FilesArchive' => 'Archivage des fichiers de l\'application', 'iTopUpdate:UI:SetupMessage:CopyFiles' => 'Copie des fichiers de la nouvelle version', - 'iTopUpdate:UI:SetupMessage:Compile' => 'Mise à jour de l\'application et de la base de données', + 'iTopUpdate:UI:SetupMessage:CheckCompile' => 'Contrôle de la mise à jour', + 'iTopUpdate:UI:SetupMessage:Compile' => 'Mise à jour de l\'application', + 'iTopUpdate:UI:SetupMessage:UpdateDatabase' => 'Mise à jour de la base de données', 'iTopUpdate:UI:SetupMessage:ExitMaintenance' => 'Application en utilisation normale', 'iTopUpdate:UI:SetupMessage:UpdateDone' => 'Installation terminée', diff --git a/datamodels/2.x/itop-core-update/index.php b/datamodels/2.x/itop-core-update/index.php index 91bf6212c..af136b500 100644 --- a/datamodels/2.x/itop-core-update/index.php +++ b/datamodels/2.x/itop-core-update/index.php @@ -12,7 +12,7 @@ use ContextTag; require_once(APPROOT.'application/startup.inc.php'); new ContextTag('Setup'); -$oUpdateController = new UpdateController(); +$oUpdateController = new UpdateController(MODULESROOT.'itop-core-update/view', 'itop-core-update'); $oUpdateController->DisableInDemoMode(); $oUpdateController->AllowOnlyAdmin(); $oUpdateController->SetDefaultOperation('SelectUpdateFile'); diff --git a/datamodels/2.x/itop-core-update/src/Controller/AjaxController.php b/datamodels/2.x/itop-core-update/src/Controller/AjaxController.php index b0176829c..b840795c0 100644 --- a/datamodels/2.x/itop-core-update/src/Controller/AjaxController.php +++ b/datamodels/2.x/itop-core-update/src/Controller/AjaxController.php @@ -22,12 +22,6 @@ use utils; class AjaxController extends Controller { - public function __construct() - { - parent::__construct(); - $this->InitFromModule(); - } - public function OperationCanUpdateCore() { $aParams = array(); @@ -161,23 +155,6 @@ class AjaxController extends Controller $this->DisplayJSONPage($aParams, $iResponseCode); } - public function OperationCheckCompile() - { - $aParams = array(); - try - { - CoreUpdater::CheckCompile(); - $iResponseCode = 200; - } catch (Exception $e) - { - IssueLog::Error("Compile: ".$e->getMessage()); - $aParams['sError'] = $e->getMessage(); - $iResponseCode = 500; - } - - $this->DisplayJSONPage($aParams, $iResponseCode); - } - public function OperationCompile() { $aParams = array(); @@ -185,24 +162,8 @@ class AjaxController extends Controller { CoreUpdater::Compile(); $iResponseCode = 200; - } catch (Exception $e) - { - IssueLog::Error("Compile: ".$e->getMessage()); - $aParams['sError'] = $e->getMessage(); - $iResponseCode = 500; } - - $this->DisplayJSONPage($aParams, $iResponseCode); - } - - public function OperationUpdateDatabase() - { - $aParams = array(); - try - { - CoreUpdater::UpdateDatabase(); - $iResponseCode = 200; - } catch (Exception $e) + catch (Exception $e) { IssueLog::Error("Compile: ".$e->getMessage()); $aParams['sError'] = $e->getMessage(); diff --git a/datamodels/2.x/itop-core-update/src/Controller/UpdateController.php b/datamodels/2.x/itop-core-update/src/Controller/UpdateController.php index 7f686ff0e..3a9afda00 100644 --- a/datamodels/2.x/itop-core-update/src/Controller/UpdateController.php +++ b/datamodels/2.x/itop-core-update/src/Controller/UpdateController.php @@ -16,12 +16,6 @@ use utils; class UpdateController extends Controller { - public function __construct() - { - parent::__construct(); - $this->InitFromModule(); - } - public function OperationSelectUpdateFile() { $sTransactionId = utils::GetNewTransactionId(); diff --git a/datamodels/2.x/itop-core-update/src/Service/CoreUpdater.php b/datamodels/2.x/itop-core-update/src/Service/CoreUpdater.php index 739ef3fb6..026f92c25 100644 --- a/datamodels/2.x/itop-core-update/src/Service/CoreUpdater.php +++ b/datamodels/2.x/itop-core-update/src/Service/CoreUpdater.php @@ -13,11 +13,11 @@ use Combodo\iTop\FilesInformation\Service\FilesIntegrity; use DBBackup; use Dict; use Exception; -use IssueLog; use iTopExtension; use iTopExtensionsMap; use iTopMutex; use MetaModel; +use SetupLog; use SetupUtils; use utils; use ZipArchive; @@ -47,7 +47,7 @@ final class CoreUpdater } if (is_file(self::UPDATE_DIR.'web/setup/appupgradecopy.php')) { - IssueLog::Info('itop-core-update: Use updater provided in the archive'); + SetupLog::Info('itop-core-update: Use updater provided in the archive'); self::CopyFile(self::UPDATE_DIR.'web/setup/appupgradecopy.php', APPROOT.'setup/appupgradecopy.php'); @include_once(APPROOT.'setup/appupgradecopy.php'); } @@ -63,17 +63,27 @@ final class CoreUpdater else { // Local function for older iTop versions - IssueLog::Info('itop-core-update: Use default updater'); + SetupLog::Info('itop-core-update: Use default updater'); self::LocalUpdateCoreFiles(self::UPDATE_DIR.'web/'); } - IssueLog::Info('itop-core-update: Update done, check files integrity'); + SetupLog::Info('itop-core-update: Update done, check files integrity'); FilesIntegrity::CheckInstallationIntegrity(APPROOT); - IssueLog::Info('itop-core-update: Files integrity OK'); - + SetupLog::Info('itop-core-update: Files integrity OK'); + // Reset the opcache since otherwise the "core" files may still be cached !! + if (function_exists('opcache_reset')) + { + // Zend opcode cache + opcache_reset(); + } + if (function_exists('apc_clear_cache')) + { + // APC(u) cache + apc_clear_cache(); + } } catch (Exception $e) { - IssueLog::error($e->getMessage()); - IssueLog::Info('itop-core-update: ended'); + SetupLog::error($e->getMessage()); + SetupLog::Info('itop-core-update: ended'); throw $e; } finally { @@ -81,28 +91,6 @@ final class CoreUpdater } } - /** - * @throws \Exception - */ - public static function CheckCompile() - { - try - { - // Compile code in env-production-build - IssueLog::Info('itop-core-update: Check compilation'); - - $sTargetEnv = 'production'; - $oRuntimeEnv = new RunTimeEnvironmentCoreUpdater($sTargetEnv, false); - $oRuntimeEnv->CheckDirectories($sTargetEnv); - $oRuntimeEnv->CompileFrom('production'); - SetupUtils::tidydir(APPROOT."env-{$sTargetEnv}-build"); - } catch (Exception $e) - { - IssueLog::error($e->getMessage()); - throw $e; - } - } - /** * @throws \Exception */ @@ -111,35 +99,13 @@ final class CoreUpdater try { // Compile code - IssueLog::Info('itop-core-update: Start compilation'); + SetupLog::Info('itop-core-update: Start compilation'); - $sTargetEnv = 'production'; - $oRuntimeEnv = new RunTimeEnvironmentCoreUpdater($sTargetEnv); - $oRuntimeEnv->CheckDirectories($sTargetEnv); + $sFinalEnv = 'production'; + $oRuntimeEnv = new RunTimeEnvironmentCoreUpdater($sFinalEnv, false); + $oRuntimeEnv->CheckDirectories($sFinalEnv); $oRuntimeEnv->CompileFrom('production'); - - IssueLog::Info('itop-core-update: Compilation done'); - } catch (Exception $e) - { - IssueLog::error($e->getMessage()); - throw $e; - } - } - - /** - * @throws \Exception - */ - public static function UpdateDatabase() - { - try - { - // Compile code - IssueLog::Info('itop-core-update: Update database'); - - $sTargetEnv = 'production'; - $oRuntimeEnv = new RunTimeEnvironmentCoreUpdater($sTargetEnv); - $oRuntimeEnv->CheckDirectories($sTargetEnv); - $oConfig = $oRuntimeEnv->MakeConfigFile($sTargetEnv.' (built on '.date('Y-m-d').')'); + $oConfig = $oRuntimeEnv->MakeConfigFile($sFinalEnv.' (built on '.date('Y-m-d').')'); $oConfig->Set('access_mode', ACCESS_FULL); $oRuntimeEnv->WriteConfigFileSafe($oConfig); $oRuntimeEnv->InitDataModel($oConfig, true); @@ -191,10 +157,11 @@ final class CoreUpdater $oRuntimeEnv->Commit(); - IssueLog::Info('itop-core-update: Update database done'); - } catch (Exception $e) + SetupLog::Info('itop-core-update: Compilation done'); + } + catch (Exception $e) { - IssueLog::error($e->getMessage()); + SetupLog::error($e->getMessage()); throw $e; } } @@ -274,16 +241,16 @@ final class CoreUpdater if (!file_exists($sTempFile)) { - IssueLog::Error("Failed to create itop archive $sTempFile"); + SetupLog::Error("Failed to create itop archive $sTempFile"); } if (@rename($sTempFile, $sItopArchiveFile)) { - IssueLog::Info("Archive $sItopArchiveFile Created"); + SetupLog::Info("Archive $sItopArchiveFile Created"); } else { - IssueLog::Error("Failed to create archive $sItopArchiveFile"); + SetupLog::Error("Failed to create archive $sItopArchiveFile"); } } @@ -307,7 +274,7 @@ final class CoreUpdater try { $oBackup->CreateCompressedBackup($sTargetFile); - IssueLog::Info('itop-core-update: Backup done: '.$sTargetFile); + SetupLog::Info('itop-core-update: Backup done: '.$sTargetFile); } catch (Exception $e) { $oMutex->Unlock(); @@ -498,12 +465,12 @@ final class CoreUpdater // Extract archive file self::ExtractUpdateFile($sArchiveFile); - IssueLog::Info('itop-core-update: Archive extracted, check files integrity'); + SetupLog::Info('itop-core-update: Archive extracted, check files integrity'); // Check files integrity FilesIntegrity::CheckInstallationIntegrity(self::UPDATE_DIR.'web/'); - IssueLog::Info('itop-core-update: Files integrity OK'); + SetupLog::Info('itop-core-update: Files integrity OK'); } catch (Exception $e) { self::RRmdir(self::UPDATE_DIR); @@ -553,7 +520,7 @@ final class CoreUpdater } if (is_file(self::UPDATE_DIR.'web/setup/appupgradecheck.php')) { - IssueLog::Info('itop-core-update: Use updater provided in the archive'); + SetupLog::Info('itop-core-update: Use updater provided in the archive'); self::CopyFile(self::UPDATE_DIR.'web/setup/appupgradecheck.php', APPROOT.'setup/appupgradecheck.php'); @include_once(APPROOT.'setup/appupgradecheck.php'); } diff --git a/datamodels/2.x/itop-core-update/src/Service/RunTimeEnvironmentCoreUpdater.php b/datamodels/2.x/itop-core-update/src/Service/RunTimeEnvironmentCoreUpdater.php index 9a6943ab4..fea0abaef 100644 --- a/datamodels/2.x/itop-core-update/src/Service/RunTimeEnvironmentCoreUpdater.php +++ b/datamodels/2.x/itop-core-update/src/Service/RunTimeEnvironmentCoreUpdater.php @@ -42,6 +42,11 @@ class RunTimeEnvironmentCoreUpdater extends RunTimeEnvironment } } + /** + * @param $sTargetEnv + * + * @throws \Exception + */ public function CheckDirectories($sTargetEnv) { $sTargetDir = APPROOT.'env-'.$sTargetEnv; @@ -73,36 +78,35 @@ class RunTimeEnvironmentCoreUpdater extends RunTimeEnvironment @unlink($sTempFile); } + /** + * @param null $sEnvironmentLabel + * + * @return \Config + * @throws \CoreException + */ public function MakeConfigFile($sEnvironmentLabel = null) { - $oConfig = $this->GetConfig(); - if (!is_null($oConfig)) - { - // Return the existing one - $oConfig->UpdateIncludes('env-'.$this->sTargetEnv); - } - else - { - // Clone the default 'production' config file - // - $oConfig = clone($this->GetConfig('production')); + // Clone the default 'production' config file + // + $oConfig = clone($this->GetConfig('production')); - $oConfig->UpdateIncludes('env-'.$this->sTargetEnv); + $oConfig->UpdateIncludes('env-'.$this->sTargetEnv); - if (is_null($sEnvironmentLabel)) - { - $sEnvironmentLabel = $this->sTargetEnv; - } - $oConfig->Set('app_env_label', $sEnvironmentLabel); - if ($this->sFinalEnv !== 'production') - { - $oConfig->Set('db_name', $oConfig->Get('db_name').'_'.$this->sFinalEnv); - } + if (is_null($sEnvironmentLabel)) + { + $sEnvironmentLabel = $this->sTargetEnv; } + $oConfig->Set('app_env_label', $sEnvironmentLabel, 'application updater'); return $oConfig; } + /** + * @param null $sEnvironment + * + * @return \Config + * @throws \Exception + */ protected function GetConfig($sEnvironment = null) { if (is_null($sEnvironment)) @@ -112,12 +116,14 @@ class RunTimeEnvironmentCoreUpdater extends RunTimeEnvironment $sFile = APPCONF.$sEnvironment.'/'.ITOP_CONFIG_FILE; if (file_exists($sFile)) { - $oConfig = new Config($sFile); - return $oConfig; - } - else - { - return null; + try + { + return new Config($sFile); + } + catch (Exception $e) + { + } } + throw new Exception('No configuration file available'); } } diff --git a/datamodels/2.x/itop-core-update/view/UpdateCoreFiles.ready.js.twig b/datamodels/2.x/itop-core-update/view/UpdateCoreFiles.ready.js.twig index 42b278ce4..41e008d3c 100644 --- a/datamodels/2.x/itop-core-update/view/UpdateCoreFiles.ready.js.twig +++ b/datamodels/2.x/itop-core-update/view/UpdateCoreFiles.ready.js.twig @@ -57,7 +57,7 @@ function GetAjaxRequest(sOperation) return oAjaxRequest; } -{% set aSteps = ['EnterMaintenance', 'Backup', 'FilesArchive', 'CopyFiles', 'CheckCompile', 'Compile', 'UpdateDatabase', 'ExitMaintenance', 'UpdateDone'] %} +{% set aSteps = ['EnterMaintenance', 'Backup', 'FilesArchive', 'CopyFiles', 'Compile', 'ExitMaintenance', 'UpdateDone'] %} aStepsName = []; @@ -75,7 +75,7 @@ var sFilesArchiveStep; sFilesArchiveStep = "FilesArchive"; {% endif %} -var aStepsAjaxOperation = ["EnterMaintenance", sBackupStep, sFilesArchiveStep, "CopyFiles", "CheckCompile", "Compile", "UpdateDatabase", "ExitMaintenance", null]; +var aStepsAjaxOperation = ["EnterMaintenance", sBackupStep, sFilesArchiveStep, "CopyFiles", "Compile", "ExitMaintenance", null]; var iNextStep = 0; function ExecNextStep() { diff --git a/datamodels/2.x/itop-files-information/module.itop-files-information.php b/datamodels/2.x/itop-files-information/module.itop-files-information.php deleted file mode 100644 index 4c76472c5..000000000 --- a/datamodels/2.x/itop-files-information/module.itop-files-information.php +++ /dev/null @@ -1,49 +0,0 @@ - 'iTop files information', - 'category' => 'business', - - // Setup - // - 'dependencies' => array( - ), - 'mandatory' => false, - 'visible' => false, - - // Components - // - 'datamodel' => array( - 'model.itop-files-information.php', - 'src/Service/FilesInformation.php', - 'src/Service/FilesInformationException.php', - 'src/Service/FilesInformationUtils.php', - 'src/Service/FilesIntegrity.php', - ), - 'webservice' => array(), - 'data.struct' => array(), - 'data.sample' => array(), - - // Documentation - // - 'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any - 'doc.more_information' => '', // hyperlink to more information, if any - - // Default settings - // - 'settings' => array(), - ) -); diff --git a/setup/runtimeenv.class.inc.php b/setup/runtimeenv.class.inc.php index 2a14c82f0..c6089b03a 100644 --- a/setup/runtimeenv.class.inc.php +++ b/setup/runtimeenv.class.inc.php @@ -544,7 +544,16 @@ class RunTimeEnvironment /** * Helper function to create the database structure + * + * @param \Config $oConfig + * @param $sMode + * * @return boolean true on success, false otherwise + * @throws \CoreException + * @throws \MySQLException + * @throws \MySQLHasGoneAwayException + * @throws \OQLException + * @throws \Exception */ public function CreateDatabaseStructure(Config $oConfig, $sMode) { @@ -554,7 +563,7 @@ class RunTimeEnvironment } else { - $this->log_info("Creating the structure in '".$oConfig->Get('db_subname')."'."); + $this->log_info("Creating the structure in '".$oConfig->Get('db_name')."'."); } //MetaModel::CheckDefinitions(); diff --git a/sources/application/TwigBase/Controller/Controller.php b/sources/application/TwigBase/Controller/Controller.php index 402e74608..18633782c 100644 --- a/sources/application/TwigBase/Controller/Controller.php +++ b/sources/application/TwigBase/Controller/Controller.php @@ -46,12 +46,31 @@ abstract class Controller private $m_aAjaxTabs; - public function __construct() + /** + * Controller constructor. + * + * @param string $sViewPath Path of the twig files + * @param string $sModuleName name of the module (or 'core' if not a module) + */ + public function __construct($sViewPath, $sModuleName = 'core') { $this->m_aLinkedScripts = array(); $this->m_aLinkedStylesheets = array(); $this->m_aAjaxTabs = array(); $this->m_aDefaultParams = array(); + $this->SetViewPath($sViewPath); + $this->SetModuleName($sModuleName); + if ($sModuleName != 'core') + { + try + { + $this->m_aDefaultParams = array('sIndexURL' => utils::GetAbsoluteUrlModulePage($this->m_sModule, 'index.php')); + } + catch (Exception $e) + { + IssueLog::Error($e->getMessage()); + } + } } /** @@ -135,6 +154,36 @@ abstract class Controller } } + /** + * Entry point to handle requests + * + * @api + */ + public function HandleAjaxOperation() + { + try + { + $this->CheckAccess(); + $this->m_sOperation = utils::ReadParam('operation', $this->m_sDefaultOperation); + + $sMethodName = 'Operation'.$this->m_sOperation; + if (method_exists($this, $sMethodName)) + { + $this->$sMethodName(); + } + else + { + $this->DisplayPageNotFound(); + } + } + catch (Exception $e) + { + http_response_code(500); + $aResponse = array('sError' => $e->getMessage()); + echo json_encode($aResponse); + } + } + /** * Overridable "page not found" which is more an "operation not found" */ @@ -294,10 +343,12 @@ abstract class Controller /** * Generate a page, zip it and propose the zipped file for download * - * @api - * * @param array $aParams Params used by the twig template * @param null $sTemplateName Name of the twig template, ie MyTemplate for MyTemplate.html.twig + * + * @throws \Exception + * @api + * */ public function DownloadZippedPage($aParams = array(), $sTemplateName = null) { @@ -413,11 +464,19 @@ abstract class Controller $this->m_aAjaxTabs[] = array('label' => $sLabel, 'url' => $sURL, 'cache' => $bCache); } + /** + * @param $aParams + * @param $sName + * @param $sTemplateFileExtension + * + * @return string + * @throws \Exception + */ private function RenderTemplate($aParams, $sName, $sTemplateFileExtension) { if (empty($this->m_oTwig)) { - return 'Not initialized. Call Controller::InitFromModule() or Controller::SetViewPath() before any display'; + throw new Exception('Not initialized. Call Controller::InitFromModule() or Controller::SetViewPath() before any display'); } try { @@ -507,3 +566,7 @@ abstract class Controller $this->m_oPage->output(); } } + +class PageNotFoundException extends Exception +{ +}