Refactor Core Update (+8 squashed commit)

Squashed commit:

[b907bb759] Refactor Core Update

[5da2473aa] Refactor Core Update

[3fce45615] Refactor Core Update

[5f050a828] Refactor Core Update

[4b9b85174] Refactor Core Update

[f637ed358] Refactor Core Update

[56543edce] Refactor Core Update

[7f06900ef] Refactor Core Update
This commit is contained in:
Eric
2020-01-03 16:28:17 +01:00
parent 5cdc58846b
commit 864ded2102
12 changed files with 157 additions and 201 deletions

View File

@@ -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();

View File

@@ -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',

View File

@@ -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',

View File

@@ -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');

View File

@@ -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();

View File

@@ -16,12 +16,6 @@ use utils;
class UpdateController extends Controller
{
public function __construct()
{
parent::__construct();
$this->InitFromModule();
}
public function OperationSelectUpdateFile()
{
$sTransactionId = utils::GetNewTransactionId();

View File

@@ -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');
}

View File

@@ -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');
}
}

View File

@@ -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() {

View File

@@ -1,49 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2019 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
//
// iTop module definition file
//
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-files-information/2.7.0',
array(
// Identification
//
'label' => '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(),
)
);

View File

@@ -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();

View File

@@ -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
{
}