mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-12 23:14:18 +01:00
Merge branch 'support/3.2' into develop
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -21,23 +22,23 @@
|
||||
* This page is called to perform "asynchronously" the setup actions
|
||||
* parameters
|
||||
* 'operation': one of 'compile_data_model', 'update_db_schema', 'after_db_creation', 'file'
|
||||
*
|
||||
* if 'operation' == 'update_db_schema':
|
||||
*
|
||||
* if 'operation' == 'update_db_schema':
|
||||
* 'mode': install | upgrade
|
||||
*
|
||||
*
|
||||
* if 'operation' == 'after_db_creation':
|
||||
* 'mode': install | upgrade
|
||||
*
|
||||
* if 'operation' == 'file':
|
||||
*
|
||||
* if 'operation' == 'file':
|
||||
* 'file': string Name of the file to load
|
||||
* 'session_status': string 'start', 'continue' or 'end'
|
||||
* 'percent': integer 0..100 the percentage of completion once the file has been loaded
|
||||
* 'percent': integer 0..100 the percentage of completion once the file has been loaded
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\WebPage\AjaxPage;
|
||||
|
||||
$bBypassMaintenance = true; // Reset maintenance mode in case of problem
|
||||
define('SAFE_MINIMUM_MEMORY', 64*1024*1024);
|
||||
define('SAFE_MINIMUM_MEMORY', 64 * 1024 * 1024);
|
||||
require_once('../approot.inc.php');
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
require_once(APPROOT.'/setup/setuppage.class.inc.php');
|
||||
@@ -47,35 +48,26 @@ ini_set('max_execution_time', max(3600, ini_get('max_execution_time'))); // Unde
|
||||
date_default_timezone_set('Europe/Paris'); // Just to avoid a warning if the timezone is not set in php.ini
|
||||
|
||||
$sMemoryLimit = trim(ini_get('memory_limit'));
|
||||
if (empty($sMemoryLimit))
|
||||
{
|
||||
if (empty($sMemoryLimit)) {
|
||||
// On some PHP installations, memory_limit does not exist as a PHP setting!
|
||||
// (encountered on a 5.2.0 under Windows)
|
||||
// In that case, ini_set will not work, let's keep track of this and proceed with the data load
|
||||
SetupLog::Info("No memory limit has been defined in this instance of PHP");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Check that the limit will allow us to load the data
|
||||
//
|
||||
$iMemoryLimit = utils::ConvertToBytes($sMemoryLimit);
|
||||
if (!utils::IsMemoryLimitOk($iMemoryLimit, SAFE_MINIMUM_MEMORY))
|
||||
{
|
||||
if (ini_set('memory_limit', SAFE_MINIMUM_MEMORY) === FALSE)
|
||||
{
|
||||
if (!utils::IsMemoryLimitOk($iMemoryLimit, SAFE_MINIMUM_MEMORY)) {
|
||||
if (ini_set('memory_limit', SAFE_MINIMUM_MEMORY) === false) {
|
||||
SetupLog::Error("memory_limit is too small: $iMemoryLimit and can not be increased by the script itself.");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
SetupLog::Info("memory_limit increased from $iMemoryLimit to ".SAFE_MINIMUM_MEMORY.".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
define('PHP_FATAL_ERROR_TAG', 'phpfatalerror');
|
||||
|
||||
|
||||
/**
|
||||
* Handler for register_shutdown_function, to catch PHP errors
|
||||
*/
|
||||
@@ -83,8 +75,7 @@ function ShutdownCallback()
|
||||
{
|
||||
$error = error_get_last();
|
||||
$bIsErrorToReport = (($error !== null) && ($error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR)));
|
||||
if (!$bIsErrorToReport)
|
||||
{
|
||||
if (!$bIsErrorToReport) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -97,19 +88,16 @@ function ShutdownCallback()
|
||||
echo '<'.PHP_FATAL_ERROR_TAG.'>'.$sLogMessage.'</'.PHP_FATAL_ERROR_TAG.'>';
|
||||
}
|
||||
|
||||
|
||||
function FatalErrorCatcher($sOutput)
|
||||
{
|
||||
if (preg_match('|<'.PHP_FATAL_ERROR_TAG.'>.*</'.PHP_FATAL_ERROR_TAG.'>|s', $sOutput, $aMatches))
|
||||
{
|
||||
if (preg_match('|<'.PHP_FATAL_ERROR_TAG.'>.*</'.PHP_FATAL_ERROR_TAG.'>|s', $sOutput, $aMatches)) {
|
||||
header("HTTP/1.0 500 Internal server error.");
|
||||
$errors = '';
|
||||
foreach ($aMatches as $sMatch)
|
||||
{
|
||||
foreach ($aMatches as $sMatch) {
|
||||
$errors .= strip_tags($sMatch)."\n";
|
||||
}
|
||||
$sOutput = "$errors\n";
|
||||
// Logging to a file does not work if the whole memory is exhausted...
|
||||
// Logging to a file does not work if the whole memory is exhausted...
|
||||
// SetupLog::Error("Fatal error - in $__FILE__ , $errors");
|
||||
}
|
||||
return $sOutput;
|
||||
@@ -132,7 +120,6 @@ require_once(APPROOT.'/core/kpi.class.inc.php');
|
||||
require_once(APPROOT.'/core/cmdbsource.class.inc.php');
|
||||
require_once('./xmldataloader.class.inc.php');
|
||||
|
||||
|
||||
// Never cache this page
|
||||
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
|
||||
header("Expires: Fri, 17 Jul 1970 05:00:00 GMT"); // Date in the past
|
||||
@@ -141,41 +128,38 @@ header("Expires: Fri, 17 Jul 1970 05:00:00 GMT"); // Date in the past
|
||||
* Main program
|
||||
*/
|
||||
$sOperation = Utils::ReadParam('operation', '');
|
||||
try
|
||||
{
|
||||
try {
|
||||
SetupUtils::CheckSetupToken();
|
||||
|
||||
switch($sOperation)
|
||||
{
|
||||
switch ($sOperation) {
|
||||
case 'async_action':
|
||||
ini_set('max_execution_time', max(240, ini_get('max_execution_time')));
|
||||
// While running the setup it is desirable to see any error that may happen
|
||||
ini_set('display_errors', true);
|
||||
ini_set('display_startup_errors', true);
|
||||
|
||||
require_once(APPROOT.'/setup/wizardcontroller.class.inc.php');
|
||||
require_once(APPROOT.'/setup/wizardsteps.class.inc.php');
|
||||
|
||||
$sClass = utils::ReadParam('step_class', '');
|
||||
$sState = utils::ReadParam('step_state', '');
|
||||
$sActionCode = utils::ReadParam('code', '');
|
||||
$aParams = utils::ReadParam('params', array(), false, 'raw_data');
|
||||
$oPage = new AjaxPage('');
|
||||
$oDummyController = new WizardController('');
|
||||
if (is_subclass_of($sClass, 'WizardStep'))
|
||||
{
|
||||
/** @var WizardStep $oStep */
|
||||
$oStep = new $sClass($oDummyController, $sState);
|
||||
$sConfigFile = utils::GetConfigFilePath();
|
||||
if (file_exists($sConfigFile) && !is_writable($sConfigFile) && $oStep->RequiresWritableConfig()) {
|
||||
$sRelativePath = utils::GetConfigFilePathRelative();
|
||||
$oPage->error("<b>Error:</b> the configuration file '".$sRelativePath."' already exists and cannot be overwritten.");
|
||||
$oPage->p("The wizard cannot modify the configuration file for you. If you want to upgrade ".ITOP_APPLICATION.", make sure that the file '<b>".$sRelativePath."</b>' can be modified by the web server.");
|
||||
$oPage->output();
|
||||
} else {
|
||||
$oStep->AsyncAction($oPage, $sActionCode, $aParams);
|
||||
ini_set('max_execution_time', max(240, ini_get('max_execution_time')));
|
||||
// While running the setup it is desirable to see any error that may happen
|
||||
ini_set('display_errors', true);
|
||||
ini_set('display_startup_errors', true);
|
||||
|
||||
require_once(APPROOT.'/setup/wizardcontroller.class.inc.php');
|
||||
require_once(APPROOT.'/setup/wizardsteps.class.inc.php');
|
||||
|
||||
$sClass = utils::ReadParam('step_class', '');
|
||||
$sState = utils::ReadParam('step_state', '');
|
||||
$sActionCode = utils::ReadParam('code', '');
|
||||
$aParams = utils::ReadParam('params', [], false, 'raw_data');
|
||||
$oPage = new AjaxPage('');
|
||||
$oDummyController = new WizardController('');
|
||||
if (is_subclass_of($sClass, 'WizardStep')) {
|
||||
/** @var WizardStep $oStep */
|
||||
$oStep = new $sClass($oDummyController, $sState);
|
||||
$sConfigFile = utils::GetConfigFilePath();
|
||||
if (file_exists($sConfigFile) && !is_writable($sConfigFile) && $oStep->RequiresWritableConfig()) {
|
||||
$sRelativePath = utils::GetConfigFilePathRelative();
|
||||
$oPage->error("<b>Error:</b> the configuration file '".$sRelativePath."' already exists and cannot be overwritten.");
|
||||
$oPage->p("The wizard cannot modify the configuration file for you. If you want to upgrade ".ITOP_APPLICATION.", make sure that the file '<b>".$sRelativePath."</b>' can be modified by the web server.");
|
||||
$oPage->output();
|
||||
} else {
|
||||
$oStep->AsyncAction($oPage, $sActionCode, $aParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
$oPage->output();
|
||||
break;
|
||||
|
||||
@@ -189,23 +173,17 @@ try
|
||||
default:
|
||||
throw(new Exception("Error unsupported operation '$sOperation'"));
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
header("HTTP/1.0 500 Internal server error.");
|
||||
echo "<p>An error happened while processing the installation:</p>\n";
|
||||
echo '<p>'.$e."</p>\n";
|
||||
SetupLog::Error("An error happened while processing the installation: ".$e);
|
||||
}
|
||||
|
||||
if (function_exists('memory_get_peak_usage'))
|
||||
{
|
||||
if ($sOperation == 'file')
|
||||
{
|
||||
if (function_exists('memory_get_peak_usage')) {
|
||||
if ($sOperation == 'file') {
|
||||
SetupLog::Info("loading file '$sFileName', peak memory usage. ".memory_get_peak_usage());
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
SetupLog::Info("operation '$sOperation', peak memory usage. ".memory_get_peak_usage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,7 @@ function AppUpgradeCopyFiles($sSourceDir)
|
||||
CoreUpdater::CopyDir($sSourceDir, APPROOT);
|
||||
// Update Core update files
|
||||
$sSource = realpath($sSourceDir.'/datamodels/2.x/itop-core-update');
|
||||
if ($sSource !== false)
|
||||
{
|
||||
if ($sSource !== false) {
|
||||
CoreUpdater::CopyDir($sSource, APPROOT.'env-production/itop-core-update');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Combodo SAS
|
||||
*
|
||||
@@ -19,30 +20,34 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Allow the setup page to load and perform its checks (including the check about the required extensions)
|
||||
*/
|
||||
if (!class_exists('DOMDocument'))
|
||||
{
|
||||
if (!class_exists('DOMDocument')) {
|
||||
/**
|
||||
* Class DOMDocument
|
||||
*/
|
||||
class DOMDocument {
|
||||
function __construct(){throw new Exception('The dom extension is not enabled');}
|
||||
class DOMDocument
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
throw new Exception('The dom extension is not enabled');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allow the setup page to load and perform its checks (including the check about the required extensions)
|
||||
*/
|
||||
if (!class_exists('DOMElement'))
|
||||
{
|
||||
if (!class_exists('DOMElement')) {
|
||||
/**
|
||||
* Class DOMElement
|
||||
*/
|
||||
class DOMElement {
|
||||
function __construct(){throw new Exception('The dom extension is not enabled');}
|
||||
class DOMElement
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
throw new Exception('The dom extension is not enabled');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -40,7 +41,6 @@ $oP = new SetupPage('iTop email test utility');
|
||||
// So we're adding this http header to reduce CSRF exposure...
|
||||
$oP->add_http_headers('DENY');
|
||||
|
||||
|
||||
/**
|
||||
* Helper to check server setting required to send an email
|
||||
*/
|
||||
@@ -48,85 +48,64 @@ function CheckEmailSetting($oP)
|
||||
{
|
||||
$bRet = true;
|
||||
|
||||
if (function_exists('php_ini_loaded_file')) // PHP >= 5.2.4
|
||||
{
|
||||
if (function_exists('php_ini_loaded_file')) { // PHP >= 5.2.4
|
||||
$sPhpIniFile = php_ini_loaded_file();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$sPhpIniFile = 'php.ini';
|
||||
}
|
||||
|
||||
$sTransport = MetaModel::GetConfig()->Get('email_transport');
|
||||
switch($sTransport)
|
||||
{
|
||||
switch ($sTransport) {
|
||||
case 'PHPMail':
|
||||
$oP->info("iTop is configured to use PHP's <a style=\"background:transparent;padding:0;color:#000;text-decoration:underline;\" href=\"http://www.php.net/manual/en/function.mail.php\" target=\"_blank\">mail</a> function to send emails.");
|
||||
$bIsWindows = (array_key_exists('WINDIR', $_SERVER) || array_key_exists('windir', $_SERVER));
|
||||
if ($bIsWindows)
|
||||
{
|
||||
$sSmtpServer = ini_get('SMTP');
|
||||
if (empty($sSmtpServer))
|
||||
{
|
||||
$oP->error("The SMTP server is not defined. Please add the 'SMTP' directive into $sPhpIniFile");
|
||||
$bRet = false;
|
||||
$oP->info("iTop is configured to use PHP's <a style=\"background:transparent;padding:0;color:#000;text-decoration:underline;\" href=\"http://www.php.net/manual/en/function.mail.php\" target=\"_blank\">mail</a> function to send emails.");
|
||||
$bIsWindows = (array_key_exists('WINDIR', $_SERVER) || array_key_exists('windir', $_SERVER));
|
||||
if ($bIsWindows) {
|
||||
$sSmtpServer = ini_get('SMTP');
|
||||
if (empty($sSmtpServer)) {
|
||||
$oP->error("The SMTP server is not defined. Please add the 'SMTP' directive into $sPhpIniFile");
|
||||
$bRet = false;
|
||||
} elseif (strcasecmp($sSmtpServer, 'localhost') == 0) {
|
||||
$oP->warning("Your SMTP server is configured to 'localhost'. You might want to set or change the 'SMTP' directive into $sPhpIniFile");
|
||||
} else {
|
||||
$oP->info("Your SMTP server: <strong>$sSmtpServer</strong>. To change this value, modify the 'SMTP' directive into $sPhpIniFile");
|
||||
}
|
||||
|
||||
$iSmtpPort = (int) ini_get('smtp_port');
|
||||
if (empty($iSmtpPort)) {
|
||||
$oP->info("The SMTP port is not defined. Please add the 'smtp_port' directive into $sPhpIniFile");
|
||||
$bRet = false;
|
||||
} elseif ($iSmtpPort == 25) {
|
||||
$oP->info("Your SMTP port is configured to the default value: 25. You might want to set or change the 'smtp_port' directive into $sPhpIniFile");
|
||||
} else {
|
||||
$oP->info("Your SMTP port is configured to $iSmtpPort. You might want to set or change the 'smtp_port' directive into $sPhpIniFile");
|
||||
}
|
||||
} else {
|
||||
// Not a windows system
|
||||
$sSendMail = ini_get('sendmail_path');
|
||||
if (empty($sSendMail)) {
|
||||
$oP->error("The command to send mail is not defined. Please add the 'sendmail_path' directive into $sPhpIniFile. A recommended setting is <em>sendmail_path=sendmail -t -i</em>");
|
||||
$bRet = false;
|
||||
} else {
|
||||
$oP->info("The command to send mail is: <strong>$sSendMail</strong>. To change this value, modify the 'sendmail_path' directive into $sPhpIniFile");
|
||||
}
|
||||
}
|
||||
else if (strcasecmp($sSmtpServer, 'localhost') == 0)
|
||||
{
|
||||
$oP->warning("Your SMTP server is configured to 'localhost'. You might want to set or change the 'SMTP' directive into $sPhpIniFile");
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->info("Your SMTP server: <strong>$sSmtpServer</strong>. To change this value, modify the 'SMTP' directive into $sPhpIniFile");
|
||||
}
|
||||
|
||||
$iSmtpPort = (int) ini_get('smtp_port');
|
||||
if (empty($iSmtpPort))
|
||||
{
|
||||
$oP->info("The SMTP port is not defined. Please add the 'smtp_port' directive into $sPhpIniFile");
|
||||
$bRet = false;
|
||||
}
|
||||
else if ($iSmtpPort == 25)
|
||||
{
|
||||
$oP->info("Your SMTP port is configured to the default value: 25. You might want to set or change the 'smtp_port' directive into $sPhpIniFile");
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->info("Your SMTP port is configured to $iSmtpPort. You might want to set or change the 'smtp_port' directive into $sPhpIniFile");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not a windows system
|
||||
$sSendMail = ini_get('sendmail_path');
|
||||
if (empty($sSendMail))
|
||||
{
|
||||
$oP->error("The command to send mail is not defined. Please add the 'sendmail_path' directive into $sPhpIniFile. A recommended setting is <em>sendmail_path=sendmail -t -i</em>");
|
||||
$bRet = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->info("The command to send mail is: <strong>$sSendMail</strong>. To change this value, modify the 'sendmail_path' directive into $sPhpIniFile");
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'SMTP':
|
||||
$oP->info("iTop is configured to use the <b>$sTransport</b> transport.");
|
||||
$sHost = MetaModel::GetConfig()->Get('email_transport_smtp.host');
|
||||
$sPort = MetaModel::GetConfig()->Get('email_transport_smtp.port');
|
||||
$sEncryption = MetaModel::GetConfig()->Get('email_transport_smtp.encryption');
|
||||
$sDisplayEncryption = empty($sEncryption) ? '<em>no encryption</em> ' : $sEncryption;
|
||||
$sUserName = MetaModel::GetConfig()->Get('email_transport_smtp.username');
|
||||
$sDisplayUserName = empty($sUserName) ? '<em>no user</em> ' : $sUserName;
|
||||
$sPassword = MetaModel::GetConfig()->Get('email_transport_smtp.password');
|
||||
$sDisplayPassword = empty($sPassword) ? '<em>no password</em> ' : str_repeat('*', strlen($sPassword));
|
||||
$oP->info("SMTP configuration (from config-itop.php): host: $sHost, port: $sPort, user: $sDisplayUserName, password: $sDisplayPassword, encryption: $sDisplayEncryption.");
|
||||
if (($sHost == 'localhost') && ($sPort == '25') && ($sUserName == '') && ($sPassword == '') )
|
||||
{
|
||||
$oP->warning("The default settings may not be suitable for your environment. You may want to adjust these values by editing iTop's configuration file (".utils::GetConfigFilePathRelative().").");
|
||||
}
|
||||
break;
|
||||
$oP->info("iTop is configured to use the <b>$sTransport</b> transport.");
|
||||
$sHost = MetaModel::GetConfig()->Get('email_transport_smtp.host');
|
||||
$sPort = MetaModel::GetConfig()->Get('email_transport_smtp.port');
|
||||
$sEncryption = MetaModel::GetConfig()->Get('email_transport_smtp.encryption');
|
||||
$sDisplayEncryption = empty($sEncryption) ? '<em>no encryption</em> ' : $sEncryption;
|
||||
$sUserName = MetaModel::GetConfig()->Get('email_transport_smtp.username');
|
||||
$sDisplayUserName = empty($sUserName) ? '<em>no user</em> ' : $sUserName;
|
||||
$sPassword = MetaModel::GetConfig()->Get('email_transport_smtp.password');
|
||||
$sDisplayPassword = empty($sPassword) ? '<em>no password</em> ' : str_repeat('*', strlen($sPassword));
|
||||
$oP->info("SMTP configuration (from config-itop.php): host: $sHost, port: $sPort, user: $sDisplayUserName, password: $sDisplayPassword, encryption: $sDisplayEncryption.");
|
||||
if (($sHost == 'localhost') && ($sPort == '25') && ($sUserName == '') && ($sPassword == '')) {
|
||||
$oP->warning("The default settings may not be suitable for your environment. You may want to adjust these values by editing iTop's configuration file (".utils::GetConfigFilePathRelative().").");
|
||||
}
|
||||
break;
|
||||
|
||||
case 'SMTP_OAuth':
|
||||
$oP->info("iTop is configured to use the <b>$sTransport</b> transport.");
|
||||
@@ -153,63 +132,58 @@ function CheckEmailSetting($oP)
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'Null':
|
||||
$oP->warning("iTop is configured to use the <b>Null</b> transport: emails sending will have no effect.");
|
||||
$bRet = false;
|
||||
break;
|
||||
|
||||
$oP->warning("iTop is configured to use the <b>Null</b> transport: emails sending will have no effect.");
|
||||
$bRet = false;
|
||||
break;
|
||||
|
||||
case 'LogFile':
|
||||
$oP->warning("iTop is configured to use the <b>LogFile</b> transport: emails will <em>not</em> be sent but logged to the file: 'log/mail.log'.");
|
||||
$bRet = true;
|
||||
break;
|
||||
|
||||
$oP->warning("iTop is configured to use the <b>LogFile</b> transport: emails will <em>not</em> be sent but logged to the file: 'log/mail.log'.");
|
||||
$bRet = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
$oP->error("Unknown transport '$sTransport' configured.");
|
||||
$bRet = false;
|
||||
$oP->error("Unknown transport '$sTransport' configured.");
|
||||
$bRet = false;
|
||||
}
|
||||
if ($bRet)
|
||||
{
|
||||
if ($bRet) {
|
||||
$oP->ok("PHP settings are ok to proceed with a test of the email");
|
||||
}
|
||||
$bConfigAsync = MetaModel::GetConfig()->Get('email_asynchronous');
|
||||
if ($bConfigAsync)
|
||||
{
|
||||
if ($bConfigAsync) {
|
||||
$oP->warning("iTop is configured to send emails <em>asynchronously</em>. Make sure that cron.php is scheduled to run in the background, otherwise regular emails will <em>not</em> be sent. For the purpose of this test, the email will be sent <em>synchronously</em>.");
|
||||
}
|
||||
|
||||
|
||||
return $bRet;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display the form for the first step of the test wizard
|
||||
* which consists in a basic check of the configuration and display of a form for testing
|
||||
*/
|
||||
*/
|
||||
function DisplayStep1(SetupPage $oP)
|
||||
{
|
||||
$sNextOperation = 'step2';
|
||||
$oP->add("<h1>iTop email test</h1>\n");
|
||||
$oP->add("<h2>Checking prerequisites</h2>\n");
|
||||
if (CheckEmailSetting($oP))
|
||||
{
|
||||
if (CheckEmailSetting($oP)) {
|
||||
$sRedStar = '<span class="hilite">*</span>';
|
||||
$oP->add("<h2>Try to send an email</h2>\n");
|
||||
$oP->add("<form method=\"post\" onSubmit=\"return DoSubmit('Sending an email...', 10)\">\n");
|
||||
// Form goes here
|
||||
$oP->add("<fieldset><legend>Test recipient</legend>\n");
|
||||
$aForm = array();
|
||||
$aForm[] = array(
|
||||
$aForm = [];
|
||||
$aForm[] = [
|
||||
'label' => "To$sRedStar:",
|
||||
'input' => "<input id=\"to\" type=\"text\" name=\"to\" value=\"\">",
|
||||
'help' => ' email address (e.g. john.foo@worldcompany.com)',
|
||||
);
|
||||
];
|
||||
$sDefaultFrom = MetaModel::GetConfig()->Get('email_transport_smtp.username');
|
||||
$aForm[] = array(
|
||||
$aForm[] = [
|
||||
'label' => "From:",
|
||||
'input' => "<input id=\"from\" type=\"text\" name=\"from\" value=\"$sDefaultFrom\">",
|
||||
'help' => ' defaults to the configuration param "email_default_sender_address" or "To" field.',
|
||||
);
|
||||
];
|
||||
$oP->form($aForm);
|
||||
$oP->add("</fieldset>\n");
|
||||
$oP->add("<input type=\"hidden\" name=\"operation\" value=\"$sNextOperation\">\n");
|
||||
@@ -225,7 +199,7 @@ function DisplayStep1(SetupPage $oP)
|
||||
/**
|
||||
* Display the form for the second step of the configuration wizard
|
||||
* which consists in sending an email, which maybe a problem under Windows
|
||||
*/
|
||||
*/
|
||||
function DisplayStep2(SetupPage $oP, $sFrom, $sTo)
|
||||
{
|
||||
//$sNextOperation = 'step3';
|
||||
@@ -240,16 +214,12 @@ function DisplayStep2(SetupPage $oP, $sFrom, $sTo)
|
||||
$oEmail->SetSubject("Test iTop");
|
||||
$oEmail->SetBody("<p>Hello,</p><p>The email function is now working fine.</p><p>You may now be able to use the notification function.</p><p>iTop</p>");
|
||||
$iRes = $oEmail->Send($aIssues, true /* force synchronous exec */);
|
||||
switch ($iRes)
|
||||
{
|
||||
switch ($iRes) {
|
||||
case EMAIL_SEND_OK:
|
||||
$sTransport = MetaModel::GetConfig()->Get('email_transport');
|
||||
if ($sTransport == 'LogFile')
|
||||
{
|
||||
if ($sTransport == 'LogFile') {
|
||||
$oP->ok("The email has been logged into the file ".APPROOT."/log/mail.log.");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oP->ok("The email has been sent, check your inbox for the incoming mail...");
|
||||
}
|
||||
$oP->add("<button onClick=\"window.history.back();\"><< Back</button>\n");
|
||||
@@ -261,8 +231,7 @@ function DisplayStep2(SetupPage $oP, $sFrom, $sTo)
|
||||
break;
|
||||
|
||||
case EMAIL_SEND_ERROR:
|
||||
foreach ($aIssues as $sError)
|
||||
{
|
||||
foreach ($aIssues as $sError) {
|
||||
$oP->error(htmlentities($sError, ENT_QUOTES, 'utf-8'));
|
||||
}
|
||||
$oP->add("<button onClick=\"window.history.back();\"><< Back</button>\n");
|
||||
@@ -279,15 +248,12 @@ function DisplayStep2(SetupPage $oP, $sFrom, $sTo)
|
||||
// generate a notice
|
||||
date_default_timezone_set('Europe/Paris');
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
switch($sOperation)
|
||||
{
|
||||
try {
|
||||
switch ($sOperation) {
|
||||
case 'step1':
|
||||
DisplayStep1($oP);
|
||||
break;
|
||||
|
||||
DisplayStep1($oP);
|
||||
break;
|
||||
|
||||
case 'step2':
|
||||
$oP->no_cache();
|
||||
$sTo = Utils::ReadParam('to', '', false, 'raw_data');
|
||||
@@ -296,17 +262,12 @@ try
|
||||
break;
|
||||
|
||||
default:
|
||||
$oP->error("Error: unsupported operation '$sOperation'");
|
||||
|
||||
$oP->error("Error: unsupported operation '$sOperation'");
|
||||
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
$oP->error("Error: '".htmlentities($e->getMessage(), ENT_QUOTES, 'utf-8')."'");
|
||||
}
|
||||
catch(CoreException $e)
|
||||
{
|
||||
$oP->error("Error: '".$e->getHtmlDesc()."'");
|
||||
} catch (CoreException $e) {
|
||||
$oP->error("Error: '".$e->getHtmlDesc()."'");
|
||||
}
|
||||
$oP->output();
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2024 Combodo SAS
|
||||
*
|
||||
@@ -17,7 +18,6 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Simple redirection page to check PHP requirements
|
||||
*
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
@@ -16,12 +17,11 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
require_once(APPROOT.'setup/setuppage.class.inc.php');
|
||||
|
||||
/**
|
||||
* Class ModuleInstaller
|
||||
* Defines the API to implement module specific actions during the setup
|
||||
* Defines the API to implement module specific actions during the setup
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
@@ -43,7 +43,7 @@ abstract class ModuleInstallerAPI
|
||||
public static function BeforeDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handler called after the creation/update of the database schema
|
||||
* @param $oConfiguration Config The new configuration of the application
|
||||
@@ -54,41 +54,39 @@ abstract class ModuleInstallerAPI
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler called at the end of the setup of the database (profiles and admin accounts created), but before the data load
|
||||
* @param $oConfiguration Config The new configuration of the application
|
||||
* @param $sPreviousVersion string Previous version number of the module (empty string in case of first install)
|
||||
* @param $sCurrentVersion string Current version number of the module
|
||||
*/
|
||||
public static function AfterDatabaseSetup(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Handler called at the end of the setup of the database (profiles and admin accounts created), but before the data load
|
||||
* @param $oConfiguration Config The new configuration of the application
|
||||
* @param $sPreviousVersion string Previous version number of the module (empty string in case of first install)
|
||||
* @param $sCurrentVersion string Current version number of the module
|
||||
*/
|
||||
public static function AfterDatabaseSetup(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler called at the end of the data load
|
||||
* @param $oConfiguration Config The new configuration of the application
|
||||
* @param $sPreviousVersion string Previous version number of the module (empty string in case of first install)
|
||||
* @param $sCurrentVersion string Current version number of the module
|
||||
*/
|
||||
public static function AfterDataLoad(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Handler called at the end of the data load
|
||||
* @param $oConfiguration Config The new configuration of the application
|
||||
* @param $sPreviousVersion string Previous version number of the module (empty string in case of first install)
|
||||
* @param $sCurrentVersion string Current version number of the module
|
||||
*/
|
||||
public static function AfterDataLoad(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to complete the renaming of a class
|
||||
* The renaming is made in the datamodel definition, but the name has to be changed in the DB as well
|
||||
* The renaming is made in the datamodel definition, but the name has to be changed in the DB as well
|
||||
* Must be called after DB update, i.e within an implementation of AfterDatabaseCreation()
|
||||
*
|
||||
* @param string $sFrom Original name (already INVALID in the current datamodel)
|
||||
*
|
||||
* @param string $sFrom Original name (already INVALID in the current datamodel)
|
||||
* @param string $sTo New name (valid in the current datamodel)
|
||||
* @return void
|
||||
* @return void
|
||||
*/
|
||||
public static function RenameClassInDB($sFrom, $sTo)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!MetaModel::IsStandaloneClass($sTo))
|
||||
{
|
||||
try {
|
||||
if (!MetaModel::IsStandaloneClass($sTo)) {
|
||||
$sRootClass = MetaModel::GetRootClass($sTo);
|
||||
$sTableName = MetaModel::DBGetTable($sRootClass);
|
||||
$sFinalClassCol = MetaModel::DBGetClassField($sRootClass);
|
||||
@@ -97,77 +95,61 @@ abstract class ModuleInstallerAPI
|
||||
$iAffectedRows = CMDBSource::AffectedRows();
|
||||
SetupLog::Info("Renaming class in DB - final class from '$sFrom' to '$sTo': $iAffectedRows rows affected");
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
SetupLog::Warning("Failed to rename class in DB - final class from '$sFrom' to '$sTo'. Reason: ".$e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to modify an enum value
|
||||
* The change is made in the datamodel definition, but the value has to be changed in the DB as well
|
||||
* Helper to modify an enum value
|
||||
* The change is made in the datamodel definition, but the value has to be changed in the DB as well
|
||||
* Must be called BEFORE DB update, i.e within an implementation of BeforeDatabaseCreation()
|
||||
* This helper does change ONE value at a time
|
||||
*
|
||||
* This helper does change ONE value at a time
|
||||
*
|
||||
* @param string $sClass A valid class name
|
||||
* @param string $sAttCode The enum attribute code
|
||||
* @param string $sFrom Original value (already INVALID in the current datamodel)
|
||||
* @param string $sFrom Original value (already INVALID in the current datamodel)
|
||||
* @param string $sTo New value (valid in the current datamodel)
|
||||
* @return void
|
||||
* @return void
|
||||
*/
|
||||
public static function RenameEnumValueInDB($sClass, $sAttCode, $sFrom, $sTo)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!MetaModel::IsValidAttCode($sClass, $sAttCode))
|
||||
{
|
||||
try {
|
||||
if (!MetaModel::IsValidAttCode($sClass, $sAttCode)) {
|
||||
SetupLog::Warning("Changing enum in DB - $sClass::$sAttCode - from '$sFrom' to '$sTo' failed. Reason '$sAttCode' is not a valid attribute of the class '$sClass'.");
|
||||
return;
|
||||
}
|
||||
$sOriginClass = MetaModel::GetAttributeOrigin($sClass, $sAttCode);
|
||||
$sTableName = MetaModel::DBGetTable($sOriginClass);
|
||||
|
||||
|
||||
$oAttDef = MetaModel::GetAttributeDef($sOriginClass, $sAttCode);
|
||||
if ($oAttDef instanceof AttributeEnum)
|
||||
{
|
||||
if ($oAttDef instanceof AttributeEnum) {
|
||||
$oValDef = $oAttDef->GetValuesDef();
|
||||
if ($oValDef)
|
||||
{
|
||||
$aNewValues = array_keys($oValDef->GetValues(array(), ""));
|
||||
if (in_array($sTo, $aNewValues))
|
||||
{
|
||||
if ($oValDef) {
|
||||
$aNewValues = array_keys($oValDef->GetValues([], ""));
|
||||
if (in_array($sTo, $aNewValues)) {
|
||||
$sEnumCol = $oAttDef->Get("sql");
|
||||
$aFields = CMDBSource::QueryToArray("SHOW COLUMNS FROM `$sTableName` WHERE Field = '$sEnumCol'");
|
||||
if (isset($aFields[0]['Type']))
|
||||
{
|
||||
if (isset($aFields[0]['Type'])) {
|
||||
$sColType = $aFields[0]['Type'];
|
||||
// Note: the parsing should rely on str_getcsv (requires PHP 5.3) to cope with escaped string
|
||||
if (preg_match("/^enum\('(.*)'\)$/", $sColType, $aMatches))
|
||||
{
|
||||
if (preg_match("/^enum\('(.*)'\)$/", $sColType, $aMatches)) {
|
||||
$aCurrentValues = explode("','", $aMatches[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// not an enum currently : return !
|
||||
// we could update values, but a clear error message will be displayed when altering the column
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!in_array($sFrom, $aNewValues))
|
||||
{
|
||||
if (!in_array($sTo, $aCurrentValues)) // if not already transformed!
|
||||
{
|
||||
if (!in_array($sFrom, $aNewValues)) {
|
||||
if (!in_array($sTo, $aCurrentValues)) { // if not already transformed!
|
||||
$sNullSpec = $oAttDef->IsNullAllowed() ? 'NULL' : 'NOT NULL';
|
||||
|
||||
if (strtolower($sTo) == strtolower($sFrom))
|
||||
{
|
||||
|
||||
if (strtolower($sTo) == strtolower($sFrom)) {
|
||||
SetupLog::Info("Changing enum in DB - $sClass::$sAttCode from '$sFrom' to '$sTo' (just a change in the case)");
|
||||
$aTargetValues = array();
|
||||
foreach ($aCurrentValues as $sValue)
|
||||
{
|
||||
if ($sValue == $sFrom)
|
||||
{
|
||||
$aTargetValues = [];
|
||||
foreach ($aCurrentValues as $sValue) {
|
||||
if ($sValue == $sFrom) {
|
||||
$sValue = $sTo;
|
||||
}
|
||||
$aTargetValues[] = $sValue;
|
||||
@@ -175,9 +157,7 @@ abstract class ModuleInstallerAPI
|
||||
$sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aTargetValues)).") $sNullSpec";
|
||||
$sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition";
|
||||
CMDBSource::Query($sRepair);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// 1st - Allow both values in the column definition
|
||||
//
|
||||
SetupLog::Info("Changing enum in DB - $sClass::$sAttCode from '$sFrom' to '$sTo'");
|
||||
@@ -186,21 +166,19 @@ abstract class ModuleInstallerAPI
|
||||
$sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aAllValues)).") $sNullSpec";
|
||||
$sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition";
|
||||
CMDBSource::Query($sRepair);
|
||||
|
||||
|
||||
// 2nd - Change the old value into the new value
|
||||
//
|
||||
$sRepair = "UPDATE `$sTableName` SET `$sEnumCol` = '$sTo' WHERE `$sEnumCol` = BINARY '$sFrom'";
|
||||
CMDBSource::Query($sRepair);
|
||||
$iAffectedRows = CMDBSource::AffectedRows();
|
||||
SetupLog::Info("Changing enum in DB - $iAffectedRows rows updated");
|
||||
|
||||
|
||||
// 3rd - Remove the useless value from the column definition
|
||||
//
|
||||
$aTargetValues = array();
|
||||
foreach ($aCurrentValues as $sValue)
|
||||
{
|
||||
if ($sValue == $sFrom)
|
||||
{
|
||||
$aTargetValues = [];
|
||||
foreach ($aCurrentValues as $sValue) {
|
||||
if ($sValue == $sFrom) {
|
||||
$sValue = $sTo;
|
||||
}
|
||||
$aTargetValues[] = $sValue;
|
||||
@@ -211,21 +189,15 @@ abstract class ModuleInstallerAPI
|
||||
SetupLog::Info("Changing enum in DB - removed useless value '$sFrom'");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
SetupLog::Warning("Changing enum in DB - $sClass::$sAttCode - '$sFrom' is still a valid value (".implode(', ', $aNewValues).")");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
SetupLog::Warning("Changing enum in DB - $sClass::$sAttCode - '$sTo' is not a known value (".implode(', ', $aNewValues).")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
SetupLog::Warning("Changing enum in DB - $sClass::$sAttCode - '$sTo' failed. Reason ".$e->getMessage());
|
||||
}
|
||||
}
|
||||
@@ -253,21 +225,18 @@ abstract class ModuleInstallerAPI
|
||||
*/
|
||||
public static function MoveColumnInDB($sOrigTable, $sOrigColumn, $sDstTable, $sDstColumn, bool $bIgnoreExistingDstColumn = false)
|
||||
{
|
||||
if (!MetaModel::DBExists(false))
|
||||
{
|
||||
if (!MetaModel::DBExists(false)) {
|
||||
// Install from scratch, no migration
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CMDBSource::IsTable($sOrigTable) || !CMDBSource::IsField($sOrigTable, $sOrigColumn))
|
||||
{
|
||||
if (!CMDBSource::IsTable($sOrigTable) || !CMDBSource::IsField($sOrigTable, $sOrigColumn)) {
|
||||
// Original field is not present
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$bDstTableFieldExists = CMDBSource::IsField($sDstTable, $sDstColumn);
|
||||
if (!CMDBSource::IsTable($sDstTable) || ($bDstTableFieldExists && !$bIgnoreExistingDstColumn))
|
||||
{
|
||||
if (!CMDBSource::IsTable($sDstTable) || ($bDstTableFieldExists && !$bIgnoreExistingDstColumn)) {
|
||||
// Destination field is already created, and we are not ignoring it
|
||||
return;
|
||||
}
|
||||
@@ -284,10 +253,10 @@ abstract class ModuleInstallerAPI
|
||||
}
|
||||
|
||||
// Create the destination field if necessary
|
||||
if($bDstTableFieldExists === false){
|
||||
if ($bDstTableFieldExists === false) {
|
||||
$sSpec = CMDBSource::GetFieldSpec($sOrigTable, $sOrigColumn);
|
||||
$sQueryAdd = "ALTER TABLE `{$sDstTable}` ADD `{$sDstColumn}` {$sSpec}";
|
||||
CMDBSource::Query($sQueryAdd);
|
||||
CMDBSource::Query($sQueryAdd);
|
||||
}
|
||||
|
||||
// Copy the data
|
||||
@@ -317,25 +286,21 @@ abstract class ModuleInstallerAPI
|
||||
*/
|
||||
public static function RenameTableInDB(string $sOrigTable, string $sDstTable)
|
||||
{
|
||||
if ($sOrigTable == $sDstTable)
|
||||
{
|
||||
if ($sOrigTable == $sDstTable) {
|
||||
throw new CoreUnexpectedValue("Origin table and destination table are the same");
|
||||
}
|
||||
|
||||
if (!MetaModel::DBExists(false))
|
||||
{
|
||||
if (!MetaModel::DBExists(false)) {
|
||||
// Install from scratch, no migration
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CMDBSource::IsTable($sOrigTable))
|
||||
{
|
||||
if (!CMDBSource::IsTable($sOrigTable)) {
|
||||
SetupLog::Warning(sprintf('Rename table in DB - Origin table %s doesn\'t exist', $sOrigTable));
|
||||
return;
|
||||
}
|
||||
|
||||
if (CMDBSource::IsTable($sDstTable))
|
||||
{
|
||||
if (CMDBSource::IsTable($sDstTable)) {
|
||||
SetupLog::Warning(sprintf('Rename table in DB - Destination table %s already exists', $sDstTable));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
class InvalidParameterException extends Exception
|
||||
{
|
||||
}
|
||||
@@ -6,7 +7,7 @@ class InvalidParameterException extends Exception
|
||||
abstract class Parameters
|
||||
{
|
||||
public $aData = null;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->aData = null;
|
||||
@@ -14,8 +15,7 @@ abstract class Parameters
|
||||
|
||||
public function Get($sCode, $default = '')
|
||||
{
|
||||
if (array_key_exists($sCode, $this->aData))
|
||||
{
|
||||
if (array_key_exists($sCode, $this->aData)) {
|
||||
return $this->aData[$sCode];
|
||||
}
|
||||
return $default;
|
||||
@@ -27,7 +27,7 @@ abstract class Parameters
|
||||
public function GetParamForConfigArray()
|
||||
{
|
||||
$aDBParams = $this->Get('database');
|
||||
$aParamValues = array(
|
||||
$aParamValues = [
|
||||
'mode' => $this->Get('mode'),
|
||||
'db_server' => $aDBParams['server'],
|
||||
'db_user' => $aDBParams['user'],
|
||||
@@ -41,7 +41,7 @@ abstract class Parameters
|
||||
'language' => $this->Get('language', ''),
|
||||
'graphviz_path' => $this->Get('graphviz_path', ''),
|
||||
'source_dir' => $this->Get('source_dir', ''),
|
||||
);
|
||||
];
|
||||
|
||||
return $aParamValues;
|
||||
}
|
||||
@@ -53,51 +53,37 @@ abstract class Parameters
|
||||
|
||||
public function ToXML(DOMNode $oRoot, $data = null, $sNodeName = null)
|
||||
{
|
||||
if ($data === null)
|
||||
{
|
||||
if ($data === null) {
|
||||
$data = $this->aData;
|
||||
}
|
||||
|
||||
if (is_array($data))
|
||||
{
|
||||
if ($oRoot instanceof DOMDocument)
|
||||
{
|
||||
|
||||
if (is_array($data)) {
|
||||
if ($oRoot instanceof DOMDocument) {
|
||||
$oNode = $oRoot->createElement($sNodeName);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oNode = $oRoot->ownerDocument->createElement($sNodeName);
|
||||
}
|
||||
$oRoot->appendChild($oNode);
|
||||
|
||||
$aKeys = array_keys($data);
|
||||
$bNumericKeys = true;
|
||||
foreach($aKeys as $subkey)
|
||||
{
|
||||
if(((int)$subkey) !== $subkey)
|
||||
{
|
||||
foreach ($aKeys as $subkey) {
|
||||
if (((int)$subkey) !== $subkey) {
|
||||
$bNumericKeys = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($bNumericKeys)
|
||||
{
|
||||
if ($bNumericKeys) {
|
||||
$oNode->setAttribute("type", "array");
|
||||
foreach($data as $key => $value)
|
||||
{
|
||||
$this->ToXML($oNode, $value , 'item');
|
||||
foreach ($data as $key => $value) {
|
||||
$this->ToXML($oNode, $value, 'item');
|
||||
}
|
||||
} else {
|
||||
foreach ($data as $key => $value) {
|
||||
$this->ToXML($oNode, $value, $key);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach($data as $key => $value)
|
||||
{
|
||||
$this->ToXML($oNode, $value , $key);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$oNode = $oRoot->ownerDocument->createElement($sNodeName);
|
||||
$oRoot->appendChild($oNode);
|
||||
$oTextNode = $oRoot->ownerDocument->createTextNode($data);
|
||||
@@ -113,11 +99,10 @@ class PHPParameters extends Parameters
|
||||
{
|
||||
$this->aData = $aData;
|
||||
}
|
||||
|
||||
|
||||
public function LoadFromFile($sParametersFile)
|
||||
{
|
||||
if ($this->aData == null)
|
||||
{
|
||||
if ($this->aData == null) {
|
||||
require_once($sParametersFile);
|
||||
$this->aData = $ITOP_PARAMS; // Defined in the file loaded just above
|
||||
}
|
||||
@@ -139,88 +124,75 @@ class XMLParameters extends Parameters
|
||||
public function LoadFromFile($sParametersFile)
|
||||
{
|
||||
$this->sParametersFile = $sParametersFile;
|
||||
if ($this->aData == null)
|
||||
{
|
||||
if ($this->aData == null) {
|
||||
libxml_use_internal_errors(true);
|
||||
$oXML = @simplexml_load_file($this->sParametersFile);
|
||||
if (!$oXML)
|
||||
{
|
||||
$aMessage = array();
|
||||
foreach(libxml_get_errors() as $oError)
|
||||
{
|
||||
if (!$oXML) {
|
||||
$aMessage = [];
|
||||
foreach (libxml_get_errors() as $oError) {
|
||||
$aMessage[] = "(line: {$oError->line}) ".$oError->message; // Beware: $oError->columns sometimes returns wrong (misleading) value
|
||||
}
|
||||
libxml_clear_errors();
|
||||
throw new InvalidParameterException("Invalid Parameters file '{$this->sParametersFile}': ".implode(' ', $aMessage));
|
||||
}
|
||||
|
||||
$this->aData = array();
|
||||
foreach($oXML as $key => $oElement)
|
||||
{
|
||||
|
||||
$this->aData = [];
|
||||
foreach ($oXML as $key => $oElement) {
|
||||
$this->aData[(string)$key] = $this->ReadElement($oElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function ReadElement(SimpleXMLElement $oElement)
|
||||
{
|
||||
$sDefaultNodeType = (count($oElement->children()) > 0) ? 'hash' : 'string';
|
||||
$sNodeType = $this->GetAttribute('type', $oElement, $sDefaultNodeType);
|
||||
switch($sNodeType)
|
||||
{
|
||||
switch ($sNodeType) {
|
||||
case 'array':
|
||||
$value = array();
|
||||
// Treat the current element as zero based array, child tag names are NOT meaningful
|
||||
$sFirstTagName = null;
|
||||
foreach($oElement->children() as $oChildElement)
|
||||
{
|
||||
if ($sFirstTagName == null)
|
||||
{
|
||||
$sFirstTagName = $oChildElement->getName();
|
||||
$value = [];
|
||||
// Treat the current element as zero based array, child tag names are NOT meaningful
|
||||
$sFirstTagName = null;
|
||||
foreach ($oElement->children() as $oChildElement) {
|
||||
if ($sFirstTagName == null) {
|
||||
$sFirstTagName = $oChildElement->getName();
|
||||
} elseif ($sFirstTagName != $oChildElement->getName()) {
|
||||
throw new InvalidParameterException("Invalid Parameters file '{$this->sParametersFile}': mixed tags ('$sFirstTagName' and '".$oChildElement->getName()."') inside array '".$oElement->getName()."'");
|
||||
}
|
||||
$val = $this->ReadElement($oChildElement);
|
||||
$value[] = $val;
|
||||
}
|
||||
else if ($sFirstTagName != $oChildElement->getName())
|
||||
{
|
||||
throw new InvalidParameterException("Invalid Parameters file '{$this->sParametersFile}': mixed tags ('$sFirstTagName' and '".$oChildElement->getName()."') inside array '".$oElement->getName()."'");
|
||||
}
|
||||
$val = $this->ReadElement($oChildElement);
|
||||
$value[] = $val;
|
||||
}
|
||||
break;
|
||||
|
||||
break;
|
||||
|
||||
case 'hash':
|
||||
$value = array();
|
||||
// Treat the current element as a hash, child tag names are keys
|
||||
foreach($oElement->children() as $oChildElement)
|
||||
{
|
||||
if (array_key_exists($oChildElement->getName(), $value))
|
||||
{
|
||||
throw new InvalidParameterException("Invalid Parameters file '{$this->sParametersFile}': duplicate tags '".$oChildElement->getName()."' inside hash '".$oElement->getName()."'");
|
||||
$value = [];
|
||||
// Treat the current element as a hash, child tag names are keys
|
||||
foreach ($oElement->children() as $oChildElement) {
|
||||
if (array_key_exists($oChildElement->getName(), $value)) {
|
||||
throw new InvalidParameterException("Invalid Parameters file '{$this->sParametersFile}': duplicate tags '".$oChildElement->getName()."' inside hash '".$oElement->getName()."'");
|
||||
}
|
||||
$val = $this->ReadElement($oChildElement);
|
||||
$value[$oChildElement->getName()] = $val;
|
||||
}
|
||||
$val = $this->ReadElement($oChildElement);
|
||||
$value[$oChildElement->getName()] = $val;
|
||||
}
|
||||
break;
|
||||
|
||||
break;
|
||||
|
||||
case 'int':
|
||||
case 'integer':
|
||||
$value = (int)$oElement;
|
||||
break;
|
||||
|
||||
$value = (int)$oElement;
|
||||
break;
|
||||
|
||||
case 'string':
|
||||
default:
|
||||
$value = (string)$oElement;
|
||||
$value = (string)$oElement;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
protected function GetAttribute($sAttName, $oElement, $sDefaultValue)
|
||||
{
|
||||
$sRet = $sDefaultValue;
|
||||
|
||||
foreach($oElement->attributes() as $sKey => $oChildElement)
|
||||
{
|
||||
if ((string)$sKey == $sAttName)
|
||||
{
|
||||
foreach ($oElement->attributes() as $sKey => $oChildElement) {
|
||||
if ((string)$sKey == $sAttName) {
|
||||
$sRet = (string)$oChildElement;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
<?php
|
||||
echo '<h1>PHP works!</h1>';
|
||||
|
||||
echo '<h1>PHP works!</h1>';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -40,4 +41,3 @@ LoginWebPage::DoLogin(true); // Check user rights and prompt if needed (N°1934)
|
||||
|
||||
/** @noinspection ForgottenDebugOutputInspection */
|
||||
phpinfo();
|
||||
?>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -28,13 +29,12 @@ require_once(APPROOT.'core/log.class.inc.php');
|
||||
|
||||
SetupLog::Enable(APPROOT.'/log/setup.log');
|
||||
|
||||
|
||||
/**
|
||||
* @uses SetupLog
|
||||
*/
|
||||
class SetupPage extends NiceWebPage
|
||||
{
|
||||
const DEFAULT_PAGE_TEMPLATE_REL_PATH = 'pages/backoffice/setuppage/layout';
|
||||
public const DEFAULT_PAGE_TEMPLATE_REL_PATH = 'pages/backoffice/setuppage/layout';
|
||||
|
||||
public function __construct($sTitle)
|
||||
{
|
||||
@@ -43,7 +43,7 @@ class SetupPage extends NiceWebPage
|
||||
$this->LinkScriptFromAppRoot('node_modules/@popperjs/core/dist/umd/popper.js');
|
||||
$this->LinkScriptFromAppRoot('node_modules/tippy.js/dist/tippy-bundle.umd.js');
|
||||
$this->LinkScriptFromAppRoot("setup/setup.js");
|
||||
$this->LinkScriptFromAppRoot("setup/csp-detection.js?itop_version_wiki_syntax=" . utils::GetItopVersionWikiSyntax());
|
||||
$this->LinkScriptFromAppRoot("setup/csp-detection.js?itop_version_wiki_syntax=".utils::GetItopVersionWikiSyntax());
|
||||
$this->LinkStylesheetFromAppRoot('css/font-awesome/css/all.min.css');
|
||||
$this->LinkStylesheetFromAppRoot('css/font-combodo/font-combodo.css');
|
||||
$this->LinkStylesheetFromAppRoot('node_modules/tippy.js/dist/tippy.css');
|
||||
@@ -72,7 +72,7 @@ class SetupPage extends NiceWebPage
|
||||
/**
|
||||
* Overriden because the application is not fully loaded when the setup is being run
|
||||
*/
|
||||
function GetApplicationContext()
|
||||
public function GetApplicationContext()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
@@ -104,33 +104,22 @@ class SetupPage extends NiceWebPage
|
||||
public function form($aData)
|
||||
{
|
||||
$this->add("<table class=\"formTable\">\n");
|
||||
foreach ($aData as $aRow)
|
||||
{
|
||||
foreach ($aData as $aRow) {
|
||||
$this->add("<tr>\n");
|
||||
if (isset($aRow['label']) && isset($aRow['input']) && isset($aRow['help']))
|
||||
{
|
||||
if (isset($aRow['label']) && isset($aRow['input']) && isset($aRow['help'])) {
|
||||
$this->add("<td class=\"wizlabel\">{$aRow['label']}</td>\n");
|
||||
$this->add("<td class=\"wizinput\">{$aRow['input']}</td>\n");
|
||||
$this->add("<td class=\"wizhelp\">{$aRow['help']}</td>\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isset($aRow['label']) && isset($aRow['help']))
|
||||
{
|
||||
} else {
|
||||
if (isset($aRow['label']) && isset($aRow['help'])) {
|
||||
$this->add("<td colspan=\"2\" class=\"wizlabel\">{$aRow['label']}</td>\n");
|
||||
$this->add("<td class=\"wizhelp\">{$aRow['help']}</td>\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isset($aRow['label']) && isset($aRow['input']))
|
||||
{
|
||||
} else {
|
||||
if (isset($aRow['label']) && isset($aRow['input'])) {
|
||||
$this->add("<td class=\"wizlabel\">{$aRow['label']}</td>\n");
|
||||
$this->add("<td colspan=\"2\" class=\"wizinput\">{$aRow['input']}</td>\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isset($aRow['label']))
|
||||
{
|
||||
} else {
|
||||
if (isset($aRow['label'])) {
|
||||
$this->add("<td colspan=\"3\" class=\"wizlabel\">{$aRow['label']}</td>\n");
|
||||
}
|
||||
}
|
||||
@@ -145,14 +134,12 @@ class SetupPage extends NiceWebPage
|
||||
{
|
||||
$this->add("<h3 class=\"clickable open\" id=\"{$sId}\">$sTitle</h3>");
|
||||
$this->p('<ul id="'.$sId.'_list">');
|
||||
foreach ($aItems as $sItem)
|
||||
{
|
||||
foreach ($aItems as $sItem) {
|
||||
$this->p("<li>$sItem</li>\n");
|
||||
}
|
||||
$this->p('</ul>');
|
||||
$this->add_ready_script("$('#{$sId}').on('click', function() { $(this).toggleClass('open'); $('#{$sId}_list').toggle();} );\n");
|
||||
if (!$bOpen)
|
||||
{
|
||||
if (!$bOpen) {
|
||||
$this->add_ready_script("$('#{$sId}').toggleClass('open'); $('#{$sId}_list').toggle();\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
|
||||
require_once(dirname(__FILE__, 3) . '/approot.inc.php');
|
||||
require_once(__DIR__ . '/InstallationFileService.php');
|
||||
require_once(dirname(__FILE__, 3).'/approot.inc.php');
|
||||
require_once(__DIR__.'/InstallationFileService.php');
|
||||
|
||||
function PrintUsageAndExit()
|
||||
{
|
||||
echo <<<EOF
|
||||
echo <<<EOF
|
||||
Usage: php unattended-install.php --param-file=<path_to_response_file> [--installation_xml=<path_to_installation_xml>] [--use_itop_config]
|
||||
|
||||
Options:
|
||||
@@ -22,27 +22,26 @@ Advanced options:
|
||||
--clean=1 In case of a first installation, cleanup the environment before proceeding: delete the configuration file, the cache directory, the target directory, the database (default: 0)
|
||||
--install=0 Set to 0 to perform a dry-run (default: 1)
|
||||
EOF;
|
||||
exit(-1);
|
||||
exit(-1);
|
||||
}
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
$oCtx = new ContextTag(ContextTag::TAG_SETUP);
|
||||
|
||||
$sCleanName = strtolower(trim(PHP_SAPI));
|
||||
if ($sCleanName !== 'cli')
|
||||
{
|
||||
if ($sCleanName !== 'cli') {
|
||||
echo "Mode CLI only";
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (in_array('--help', $argv)) {
|
||||
PrintUsageAndExit();
|
||||
PrintUsageAndExit();
|
||||
}
|
||||
|
||||
$sParamFile = utils::ReadParam('param-file', null, true /* CLI allowed */, 'raw_data') ?? utils::ReadParam('response_file', null, true /* CLI allowed */, 'raw_data');
|
||||
if (is_null($sParamFile)) {
|
||||
echo "Missing mandatory argument `--param-file`.\n";
|
||||
PrintUsageAndExit();
|
||||
PrintUsageAndExit();
|
||||
}
|
||||
$bCheckConsistency = (utils::ReadParam('check-consistency', '0', true /* CLI allowed */) == '1');
|
||||
|
||||
@@ -56,8 +55,7 @@ $oParams = new XMLParameters($sParamFile);
|
||||
$sMode = $oParams->Get('mode');
|
||||
|
||||
$sTargetEnvironment = $oParams->Get('target_env', '');
|
||||
if ($sTargetEnvironment == '')
|
||||
{
|
||||
if ($sTargetEnvironment == '') {
|
||||
$sTargetEnvironment = 'production';
|
||||
}
|
||||
|
||||
@@ -106,12 +104,12 @@ SetupLog::Info($sMsg, null, $aSelectedModules);
|
||||
// Configuration file
|
||||
$sConfigFile = APPCONF.$sTargetEnvironment.'/'.ITOP_CONFIG_FILE;
|
||||
$bUseItopConfig = in_array('--use_itop_config', $argv);
|
||||
if ($bUseItopConfig && file_exists($sConfigFile)){
|
||||
if ($bUseItopConfig && file_exists($sConfigFile)) {
|
||||
//unattended run based on db settings coming from itop configuration
|
||||
copy($sConfigFile, "$sConfigFile.backup");
|
||||
|
||||
$oConfig = new Config($sConfigFile);
|
||||
$aDBXmlSettings = $oParams->Get('database', array());
|
||||
$aDBXmlSettings = $oParams->Get('database', []);
|
||||
$aDBXmlSettings ['server'] = $oConfig->Get('db_host');
|
||||
$aDBXmlSettings ['user'] = $oConfig->Get('db_user');
|
||||
$aDBXmlSettings ['pwd'] = $oConfig->Get('db_pwd');
|
||||
@@ -127,7 +125,7 @@ if ($bUseItopConfig && file_exists($sConfigFile)){
|
||||
'source_dir' => 'source_dir',
|
||||
'graphviz_path' => 'graphviz_path',
|
||||
];
|
||||
foreach($aFields as $sSetupField => $sConfField){
|
||||
foreach ($aFields as $sSetupField => $sConfField) {
|
||||
$oParams->Set($sSetupField, $oConfig->Get($sConfField));
|
||||
}
|
||||
|
||||
@@ -135,7 +133,7 @@ if ($bUseItopConfig && file_exists($sConfigFile)){
|
||||
$oParams->Set('language', $oConfig->GetDefaultLanguage());
|
||||
} else {
|
||||
//unattended run based on db settings coming from response_file (XML file)
|
||||
$aDBXmlSettings = $oParams->Get('database', array());
|
||||
$aDBXmlSettings = $oParams->Get('database', []);
|
||||
}
|
||||
|
||||
$sDBServer = $aDBXmlSettings['server'];
|
||||
@@ -146,36 +144,29 @@ $sDBPrefix = $aDBXmlSettings['prefix'];
|
||||
$bDBTlsEnabled = $aDBXmlSettings['db_tls_enabled'];
|
||||
$sDBTlsCa = $aDBXmlSettings['db_tls_ca'];
|
||||
|
||||
if ($sMode == 'install')
|
||||
{
|
||||
if ($sMode == 'install') {
|
||||
echo "Installation mode detected.\n";
|
||||
|
||||
$bClean = utils::ReadParam('clean', false, true /* CLI allowed */);
|
||||
if ($bClean)
|
||||
{
|
||||
if ($bClean) {
|
||||
echo "Cleanup mode detected.\n";
|
||||
|
||||
if (file_exists($sConfigFile))
|
||||
{
|
||||
if (file_exists($sConfigFile)) {
|
||||
echo "Trying to delete the configuration file: '$sConfigFile'.\n";
|
||||
@chmod($sConfigFile, 0770); // RWX for owner and group, nothing for others
|
||||
unlink($sConfigFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
echo "No config file to delete ($sConfigFile does not exist).\n";
|
||||
}
|
||||
|
||||
// Starting with iTop 2.7.0, a failed setup leaves some lock files, let's remove them
|
||||
$aLockFiles = array(
|
||||
$aLockFiles = [
|
||||
'data/.readonly' => 'read-only lock file',
|
||||
'data/.maintenance' => 'maintenance mode lock file',
|
||||
);
|
||||
foreach($aLockFiles as $sFile => $sDescription)
|
||||
{
|
||||
$sLockFile = APPROOT.$sFile;
|
||||
if (file_exists($sLockFile))
|
||||
{
|
||||
];
|
||||
foreach ($aLockFiles as $sFile => $sDescription) {
|
||||
$sLockFile = APPROOT.$sFile;
|
||||
if (file_exists($sLockFile)) {
|
||||
echo "Trying to delete the $sDescription: '$sLockFile'.\n";
|
||||
unlink($sLockFile);
|
||||
}
|
||||
@@ -184,69 +175,49 @@ if ($sMode == 'install')
|
||||
// Starting with iTop 2.6.0, let's remove the cache directory as well
|
||||
// Can cause some strange issues in the setup (apparently due to the Dict class being automatically loaded ??)
|
||||
$sCacheDir = APPROOT.'data/cache-'.$sTargetEnvironment;
|
||||
if (file_exists($sCacheDir))
|
||||
{
|
||||
if (is_dir($sCacheDir))
|
||||
{
|
||||
echo "Emptying the cache directory '$sCacheDir'.\n";
|
||||
SetupUtils::tidydir($sCacheDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (file_exists($sCacheDir)) {
|
||||
if (is_dir($sCacheDir)) {
|
||||
echo "Emptying the cache directory '$sCacheDir'.\n";
|
||||
SetupUtils::tidydir($sCacheDir);
|
||||
} else {
|
||||
die("ERROR the cache directory '$sCacheDir' exists, but is NOT a directory !!!\nExiting.\n");
|
||||
}
|
||||
}
|
||||
|
||||
// env-xxx directory
|
||||
$sTargetDir = APPROOT.'env-'.$sTargetEnvironment;
|
||||
if (file_exists($sTargetDir))
|
||||
{
|
||||
if (is_dir($sTargetDir))
|
||||
{
|
||||
echo "Emptying the target directory '$sTargetDir'.\n";
|
||||
SetupUtils::tidydir($sTargetDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (file_exists($sTargetDir)) {
|
||||
if (is_dir($sTargetDir)) {
|
||||
echo "Emptying the target directory '$sTargetDir'.\n";
|
||||
SetupUtils::tidydir($sTargetDir);
|
||||
} else {
|
||||
die("ERROR the target dir '$sTargetDir' exists, but is NOT a directory !!!\nExiting.\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
echo "No target directory to delete ($sTargetDir does not exist).\n";
|
||||
}
|
||||
|
||||
if ($sDBPrefix != '')
|
||||
{
|
||||
if ($sDBPrefix != '') {
|
||||
die("Cleanup not implemented for a partial database (prefix= '$sDBPrefix')\nExiting.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
$oMysqli = CMDBSource::GetMysqliInstance($sDBServer, $sDBUser, $sDBPwd, null, $bDBTlsEnabled, $sDBTlsCa, true);
|
||||
|
||||
if ($oMysqli->select_db($sDBName))
|
||||
{
|
||||
if ($oMysqli->select_db($sDBName)) {
|
||||
echo "Deleting database '$sDBName'\n";
|
||||
$oMysqli->query("DROP DATABASE `$sDBName`");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
echo "The database '$sDBName' does not seem to exist. Nothing to cleanup.\n";
|
||||
}
|
||||
}
|
||||
catch (MySQLException $e)
|
||||
{
|
||||
die($e->getMessage()."\nExiting");
|
||||
} catch (MySQLException $e) {
|
||||
die($e->getMessage()."\nExiting");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
//use settings from itop conf
|
||||
$sTargetEnvironment = $oParams->Get('target_env', '');
|
||||
if ($sTargetEnvironment == '')
|
||||
{
|
||||
if ($sTargetEnvironment == '') {
|
||||
$sTargetEnvironment = 'production';
|
||||
}
|
||||
$sTargetDir = APPROOT.'env-'.$sTargetEnvironment;
|
||||
@@ -260,10 +231,8 @@ $sSourceDir = $oParams->Get('source_dir', 'datamodels/latest');
|
||||
$sExtensionDir = $oParams->Get('extensions_dir', 'extensions');
|
||||
$aChecks = array_merge($aChecks, SetupUtils::CheckSelectedModules($sSourceDir, $sExtensionDir, $aSelectedModules));
|
||||
|
||||
foreach($aChecks as $oCheckResult)
|
||||
{
|
||||
switch ($oCheckResult->iSeverity)
|
||||
{
|
||||
foreach ($aChecks as $oCheckResult) {
|
||||
switch ($oCheckResult->iSeverity) {
|
||||
case CheckResult::ERROR:
|
||||
$bHasErrors = true;
|
||||
$sHeader = "Error";
|
||||
@@ -284,15 +253,13 @@ foreach($aChecks as $oCheckResult)
|
||||
break;
|
||||
}
|
||||
echo $sHeader.": ".$oCheckResult->sLabel;
|
||||
if (strlen($oCheckResult->sDescription))
|
||||
{
|
||||
if (strlen($oCheckResult->sDescription)) {
|
||||
echo ' - '.$oCheckResult->sDescription;
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
if ($bHasErrors)
|
||||
{
|
||||
if ($bHasErrors) {
|
||||
echo "Encountered stopper issues. Aborting...\n";
|
||||
$sLogMsg = "Encountered stopper issues. Aborting...";
|
||||
echo "$sLogMsg\n";
|
||||
@@ -303,103 +270,76 @@ if ($bHasErrors)
|
||||
$bFoundIssues = false;
|
||||
|
||||
$bInstall = utils::ReadParam('install', true, true /* CLI allowed */);
|
||||
if ($bInstall)
|
||||
{
|
||||
if ($bInstall) {
|
||||
echo "Starting the unattended installation...\n";
|
||||
$oWizard = new ApplicationInstaller($oParams);
|
||||
$bRes = $oWizard->ExecuteAllSteps();
|
||||
if (!$bRes)
|
||||
{
|
||||
if (!$bRes) {
|
||||
echo "\nencountered installation issues!";
|
||||
$bFoundIssues = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
} else {
|
||||
try {
|
||||
$oMysqli = CMDBSource::GetMysqliInstance($sDBServer, $sDBUser, $sDBPwd, null, $bDBTlsEnabled, $sDBTlsCa, true);
|
||||
if ($oMysqli->select_db($sDBName))
|
||||
{
|
||||
if ($oMysqli->select_db($sDBName)) {
|
||||
// Check the presence of a table to record information about the MTP (from the Designer)
|
||||
$sDesignerUpdatesTable = $sDBPrefix.'priv_designer_update';
|
||||
$sSQL = "SELECT id FROM `$sDesignerUpdatesTable`";
|
||||
if ($oMysqli->query($sSQL) !== false)
|
||||
{
|
||||
if ($oMysqli->query($sSQL) !== false) {
|
||||
// Record the Designer Udpates in the priv_designer_update table
|
||||
$sDeltaFile = APPROOT.'data/'.$sTargetEnvironment.'.delta.xml';
|
||||
if (is_readable($sDeltaFile))
|
||||
{
|
||||
if (is_readable($sDeltaFile)) {
|
||||
// Retrieve the revision
|
||||
$oDoc = new DOMDocument();
|
||||
$oDoc->load($sDeltaFile);
|
||||
$iRevision = 0;
|
||||
$iRevision = $oDoc->firstChild->getAttribute('revision_id');
|
||||
if ($iRevision > 0) // Safety net, just in case...
|
||||
{
|
||||
if ($iRevision > 0) { // Safety net, just in case...
|
||||
$sDate = date('Y-m-d H:i:s');
|
||||
$sSQL = "INSERT INTO `$sDesignerUpdatesTable` (revision_id, compilation_date, comment) VALUES ($iRevision, '$sDate', 'Deployed using unattended.php.')";
|
||||
if ($oMysqli->query($sSQL) !== false)
|
||||
{
|
||||
if ($oMysqli->query($sSQL) !== false) {
|
||||
echo "\nDesigner update (MTP at revision $iRevision) successfully recorded.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
echo "\nFailed to record designer updates(".$oMysqli->error.").\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
echo "\nFailed to read the revision from $sDeltaFile file. No designer update information will be recorded.\n";
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
echo "\nNo $sDeltaFile file (or the file is not accessible). No designer update information to record.\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (MySQLException $e)
|
||||
{
|
||||
// Continue anyway
|
||||
} catch (MySQLException $e) {
|
||||
// Continue anyway
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
echo "No installation requested.\n";
|
||||
}
|
||||
if (!$bFoundIssues && $bCheckConsistency)
|
||||
{
|
||||
if (!$bFoundIssues && $bCheckConsistency) {
|
||||
echo "Checking data model consistency.\n";
|
||||
ob_start();
|
||||
$sCheckRes = '';
|
||||
try
|
||||
{
|
||||
try {
|
||||
MetaModel::CheckDefinitions(false);
|
||||
$sCheckRes = ob_get_clean();
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
$sCheckRes = ob_get_clean()."\nException: ".$e->getMessage();
|
||||
}
|
||||
if (strlen($sCheckRes) > 0)
|
||||
{
|
||||
if (strlen($sCheckRes) > 0) {
|
||||
echo $sCheckRes;
|
||||
echo "\nfound consistency issues!";
|
||||
$bFoundIssues = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $bFoundIssues)
|
||||
{
|
||||
if (! $bFoundIssues) {
|
||||
// last line: used to check the install
|
||||
// the only way to track issues in case of Fatal error or even parsing error!
|
||||
$sLogMsg = "installed!";
|
||||
|
||||
if ($bUseItopConfig && is_file("$sConfigFile.backup"))
|
||||
{
|
||||
if ($bUseItopConfig && is_file("$sConfigFile.backup")) {
|
||||
echo "\nuse config file provided by backup in $sConfigFile.";
|
||||
copy("$sConfigFile.backup", $sConfigFile);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2013-2024 Combodo SAS
|
||||
*
|
||||
@@ -42,12 +43,10 @@ ini_set('display_errors', true);
|
||||
ini_set('display_startup_errors', true);
|
||||
date_default_timezone_set('Europe/Paris'); // Just to avoid a warning if the timezone is not set in php.ini
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Fake functions to protect the first run of the installer
|
||||
// in case the PHP JSON module is not installed...
|
||||
if (!function_exists('json_encode'))
|
||||
{
|
||||
if (!function_exists('json_encode')) {
|
||||
function json_encode($value, $options = null)
|
||||
{
|
||||
return '[]';
|
||||
@@ -56,7 +55,7 @@ if (!function_exists('json_encode'))
|
||||
if (!function_exists('json_decode')) {
|
||||
function json_decode($json, $assoc = null)
|
||||
{
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024 Combodo SAS
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
@@ -37,7 +38,7 @@ class WizardController
|
||||
protected $sInitialStepClass;
|
||||
protected $sInitialState;
|
||||
protected $aParameters;
|
||||
|
||||
|
||||
/**
|
||||
* Initiailization of the wizard controller
|
||||
* @param string $sInitialStepClass Class of the initial step/page of the wizard
|
||||
@@ -47,10 +48,10 @@ class WizardController
|
||||
{
|
||||
$this->sInitialStepClass = $sInitialStepClass;
|
||||
$this->sInitialState = $sInitialState;
|
||||
$this->aParameters = array();
|
||||
$this->aSteps = array();
|
||||
$this->aParameters = [];
|
||||
$this->aSteps = [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pushes information about the current step onto the stack
|
||||
* @param hash $aStepInfo Array('class' => , 'state' => )
|
||||
@@ -59,7 +60,7 @@ class WizardController
|
||||
{
|
||||
array_push($this->aSteps, $aStepInfo);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes information about the previous step from the stack
|
||||
* @return hash Array('class' => , 'state' => )
|
||||
@@ -68,7 +69,7 @@ class WizardController
|
||||
{
|
||||
return array_pop($this->aSteps);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads a "persistent" parameter from the wizard's context
|
||||
* @param string $sParamCode The code identifying this parameter
|
||||
@@ -91,7 +92,7 @@ class WizardController
|
||||
public function GetParamForConfigArray(): array
|
||||
{
|
||||
/** @noinspection PhpUnnecessaryLocalVariableInspection */
|
||||
$aParamValues = array(
|
||||
$aParamValues = [
|
||||
'db_server' => $this->GetParameter('db_server', ''),
|
||||
'db_user' => $this->GetParameter('db_user', ''),
|
||||
'db_pwd' => $this->GetParameter('db_pwd', ''),
|
||||
@@ -99,7 +100,7 @@ class WizardController
|
||||
'db_prefix' => $this->GetParameter('db_prefix', ''),
|
||||
'db_tls_enabled' => $this->GetParameter('db_tls_enabled', false),
|
||||
'db_tls_ca' => $this->GetParameter('db_tls_ca', ''),
|
||||
);
|
||||
];
|
||||
|
||||
return $aParamValues;
|
||||
}
|
||||
@@ -114,7 +115,7 @@ class WizardController
|
||||
{
|
||||
$this->aParameters[$sParamCode] = $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stores the value of the page's parameter in a "persistent" parameter in the wizard's context
|
||||
* @param string $sParamCode The code identifying this parameter
|
||||
@@ -126,7 +127,7 @@ class WizardController
|
||||
$value = utils::ReadParam($sParamCode, $defaultValue, false, $sSanitizationFilter);
|
||||
$this->aParameters[$sParamCode] = $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Starts the wizard by displaying it in its initial state
|
||||
*/
|
||||
@@ -146,23 +147,17 @@ class WizardController
|
||||
$sCurrentState = utils::ReadParam('_state', $this->sInitialState);
|
||||
/** @var \WizardStep $oStep */
|
||||
$oStep = new $sCurrentStepClass($this, $sCurrentState);
|
||||
if ($oStep->ValidateParams())
|
||||
{
|
||||
$this->PushStep(array('class' => $sCurrentStepClass, 'state' => $sCurrentState));
|
||||
if ($oStep->ValidateParams()) {
|
||||
$this->PushStep(['class' => $sCurrentStepClass, 'state' => $sCurrentState]);
|
||||
$aPossibleSteps = $oStep->GetPossibleSteps();
|
||||
$aNextStepInfo = $oStep->ProcessParams(true); // true => moving forward
|
||||
if (in_array($aNextStepInfo['class'], $aPossibleSteps))
|
||||
{
|
||||
if (in_array($aNextStepInfo['class'], $aPossibleSteps)) {
|
||||
$oNextStep = new $aNextStepInfo['class']($this, $aNextStepInfo['state']);
|
||||
$this->DisplayStep($oNextStep);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
throw new Exception("Internal error: Unexpected next step '{$aNextStepInfo['class']}'. The possible next steps are: ".implode(', ', $aPossibleSteps));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$this->DisplayStep($oStep);
|
||||
}
|
||||
}
|
||||
@@ -176,13 +171,13 @@ class WizardController
|
||||
$sCurrentState = utils::ReadParam('_state', $this->sInitialState);
|
||||
$oStep = new $sCurrentStepClass($this, $sCurrentState);
|
||||
$aNextStepInfo = $oStep->ProcessParams(false); // false => Moving backwards
|
||||
|
||||
|
||||
// Display the previous step
|
||||
$aCurrentStepInfo = $this->PopStep();
|
||||
$oStep = new $aCurrentStepInfo['class']($this, $aCurrentStepInfo['state']);
|
||||
$this->DisplayStep($oStep);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Displays the specified 'step' of the wizard
|
||||
* @param WizardStep $oStep The 'step' to display
|
||||
@@ -190,14 +185,11 @@ class WizardController
|
||||
protected function DisplayStep(WizardStep $oStep)
|
||||
{
|
||||
$oPage = new SetupPage($oStep->GetTitle());
|
||||
if ($oStep->RequiresWritableConfig())
|
||||
{
|
||||
if ($oStep->RequiresWritableConfig()) {
|
||||
$sConfigFile = utils::GetConfigFilePath();
|
||||
if (file_exists($sConfigFile))
|
||||
{
|
||||
if (file_exists($sConfigFile)) {
|
||||
// The configuration file already exists
|
||||
if (!is_writable($sConfigFile))
|
||||
{
|
||||
if (!is_writable($sConfigFile)) {
|
||||
SetupUtils::ExitReadOnlyMode(false); // Reset readonly mode in case of problem
|
||||
SetupUtils::EraseSetupToken();
|
||||
$sRelativePath = utils::GetConfigFilePathRelative();
|
||||
@@ -215,7 +207,7 @@ HTML;
|
||||
// Prevent token creation
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$oPage->LinkScriptFromAppRoot('setup/setup.js');
|
||||
$oPage->add_script("function CanMoveForward()\n{\n".$oStep->JSCanMoveForward()."\n}\n");
|
||||
@@ -247,7 +239,7 @@ HTML;
|
||||
|
||||
// Hack to have the "Next >>" button, be the default button, since the first submit button in the form is the default one
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
<<<EOF
|
||||
|
||||
$('form').each(function () {
|
||||
var thisform = $(this);
|
||||
@@ -292,24 +284,23 @@ on the page's parameters
|
||||
$oContextTag = new ContextTag(ContextTag::TAG_SETUP);
|
||||
|
||||
$sOperation = utils::ReadParam('operation');
|
||||
$this->aParameters = utils::ReadParam('_params', array(), false, 'raw_data');
|
||||
$this->aParameters = utils::ReadParam('_params', [], false, 'raw_data');
|
||||
$this->aSteps = json_decode(utils::ReadParam('_steps', '[]', false, 'raw_data'), true /* bAssoc */);
|
||||
|
||||
switch($sOperation)
|
||||
{
|
||||
|
||||
switch ($sOperation) {
|
||||
case 'next':
|
||||
$this->Next();
|
||||
break;
|
||||
|
||||
$this->Next();
|
||||
break;
|
||||
|
||||
case 'back':
|
||||
$this->Back();
|
||||
break;
|
||||
|
||||
$this->Back();
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->Start();
|
||||
$this->Start();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provides information about the structure/workflow of the wizard by listing
|
||||
* the possible list of 'steps' and their dependencies
|
||||
@@ -318,22 +309,24 @@ on the page's parameters
|
||||
*/
|
||||
public function DumpStructure($sStep = '', $aAllSteps = null)
|
||||
{
|
||||
if ($aAllSteps == null) $aAllSteps = array();
|
||||
if ($sStep == '') $sStep = $this->sInitialStepClass;
|
||||
|
||||
if ($aAllSteps == null) {
|
||||
$aAllSteps = [];
|
||||
}
|
||||
if ($sStep == '') {
|
||||
$sStep = $this->sInitialStepClass;
|
||||
}
|
||||
|
||||
$oStep = new $sStep($this, '');
|
||||
$aAllSteps[$sStep] = $oStep->GetPossibleSteps();
|
||||
foreach($aAllSteps[$sStep] as $sNextStep)
|
||||
{
|
||||
if (!array_key_exists($sNextStep, $aAllSteps))
|
||||
{
|
||||
$aAllSteps = $this->DumpStructure($sNextStep , $aAllSteps);
|
||||
foreach ($aAllSteps[$sStep] as $sNextStep) {
|
||||
if (!array_key_exists($sNextStep, $aAllSteps)) {
|
||||
$aAllSteps = $this->DumpStructure($sNextStep, $aAllSteps);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $aAllSteps;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump the wizard's structure as a string suitable to produce a chart
|
||||
* using graphviz's "dot" program
|
||||
@@ -345,25 +338,20 @@ on the page's parameters
|
||||
$sOutput = "digraph finite_state_machine {\n";
|
||||
//$sOutput .= "\trankdir=LR;";
|
||||
$sOutput .= "\tsize=\"10,12\"\n";
|
||||
|
||||
$aDeadEnds = array($this->sInitialStepClass);
|
||||
foreach($aAllSteps as $sStep => $aNextSteps)
|
||||
{
|
||||
if (count($aNextSteps) == 0)
|
||||
{
|
||||
|
||||
$aDeadEnds = [$this->sInitialStepClass];
|
||||
foreach ($aAllSteps as $sStep => $aNextSteps) {
|
||||
if (count($aNextSteps) == 0) {
|
||||
$aDeadEnds[] = $sStep;
|
||||
}
|
||||
}
|
||||
$sOutput .= "\tnode [shape = doublecircle]; ".implode(' ', $aDeadEnds).";\n";
|
||||
$sOutput .= "\tnode [shape = box];\n";
|
||||
foreach($aAllSteps as $sStep => $aNextSteps)
|
||||
{
|
||||
foreach ($aAllSteps as $sStep => $aNextSteps) {
|
||||
$oStep = new $sStep($this, '');
|
||||
$sOutput .= "\t$sStep [ label = \"".$oStep->GetTitle()."\"];\n";
|
||||
if (count($aNextSteps) > 0)
|
||||
{
|
||||
foreach($aNextSteps as $sNextStep)
|
||||
{
|
||||
if (count($aNextSteps) > 0) {
|
||||
foreach ($aNextSteps as $sNextStep) {
|
||||
$sOutput .= "\t$sStep -> $sNextStep;\n";
|
||||
}
|
||||
}
|
||||
@@ -394,18 +382,18 @@ abstract class WizardStep
|
||||
* @var string
|
||||
*/
|
||||
protected $sCurrentState;
|
||||
|
||||
|
||||
public function __construct(WizardController $oWizard, $sCurrentState)
|
||||
{
|
||||
$this->oWizard = $oWizard;
|
||||
$this->sCurrentState = $sCurrentState;
|
||||
}
|
||||
|
||||
|
||||
public function GetState()
|
||||
{
|
||||
return $this->sCurrentState;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Displays the wizard page for the current class/state
|
||||
* The page can contain any number of "<input/>" fields, but no "<form>...</form>" tag
|
||||
@@ -445,7 +433,7 @@ abstract class WizardStep
|
||||
* @return string The title of the wizard page for the current step
|
||||
*/
|
||||
abstract public function GetTitle();
|
||||
|
||||
|
||||
/**
|
||||
* Tells whether the parameters are Ok to move forward
|
||||
* @return boolean True to move forward, false to stey on the same step
|
||||
@@ -454,7 +442,7 @@ abstract class WizardStep
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tells whether this step/state is the last one of the wizard (dead-end)
|
||||
* @return boolean True if the 'Next >>' button should be displayed
|
||||
@@ -463,7 +451,7 @@ abstract class WizardStep
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tells whether the "Next" button should be enabled interactively
|
||||
* @return string A piece of javascript code returning either true or false
|
||||
@@ -472,7 +460,7 @@ abstract class WizardStep
|
||||
{
|
||||
return 'return true;';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the label for the " Next >> " button
|
||||
* @return string The label for the button
|
||||
@@ -481,7 +469,7 @@ abstract class WizardStep
|
||||
{
|
||||
return 'Next';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tells whether this step/state allows to go back or not
|
||||
* @return boolean True if the '<< Back' button should be displayed
|
||||
@@ -490,7 +478,7 @@ abstract class WizardStep
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tells whether the "Back" button should be enabled interactively
|
||||
* @return string A piece of javascript code returning either true or false
|
||||
@@ -523,9 +511,9 @@ abstract class WizardStep
|
||||
* Example of a simple Setup Wizard with some parameters to store
|
||||
* the installation mode (install | upgrade) and a simple asynchronous
|
||||
* (AJAX) action.
|
||||
*
|
||||
*
|
||||
* The setup wizard is executed by the following code:
|
||||
*
|
||||
*
|
||||
* $oWizard = new WizardController('Step1');
|
||||
* $oWizard->Run();
|
||||
*
|
||||
@@ -535,12 +523,12 @@ class Step1 extends WizardStep
|
||||
{
|
||||
return 'Welcome';
|
||||
}
|
||||
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array('Step2', 'Step2bis');
|
||||
}
|
||||
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
$sNextStep = '';
|
||||
@@ -554,11 +542,11 @@ class Step1 extends WizardStep
|
||||
{
|
||||
$this->oWizard->SetParameter('install_mode', 'upgrade');
|
||||
$sNextStep = 'Step2bis';
|
||||
|
||||
|
||||
}
|
||||
return array('class' => $sNextStep, 'state' => '');
|
||||
}
|
||||
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('This is Step 1!');
|
||||
@@ -576,17 +564,17 @@ class Step2 extends WizardStep
|
||||
{
|
||||
return 'Installation Parameters';
|
||||
}
|
||||
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array('Step3');
|
||||
}
|
||||
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
return array('class' => 'Step3', 'state' => '');
|
||||
}
|
||||
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('This is Step 2! (Installation)');
|
||||
@@ -599,12 +587,12 @@ class Step2bis extends WizardStep
|
||||
{
|
||||
return 'Upgrade Parameters';
|
||||
}
|
||||
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array('Step2ter');
|
||||
}
|
||||
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
$sUpgradeInfo = utils::ReadParam('upgrade_info');
|
||||
@@ -613,7 +601,7 @@ class Step2bis extends WizardStep
|
||||
$this->oWizard->SetParameter('additional_upgrade_info', $sAdditionalUpgradeInfo);
|
||||
return array('class' => 'Step2ter', 'state' => '');
|
||||
}
|
||||
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('This is Step 2bis! (Upgrade)');
|
||||
@@ -621,18 +609,18 @@ class Step2bis extends WizardStep
|
||||
$oPage->p('Type your name here: <input type="text" id="upgrade_info" name="upgrade_info" value="'.$sUpgradeInfo.'" size="20"/><span id="v_upgrade_info"></span>');
|
||||
$sAdditionalUpgradeInfo = $this->oWizard->GetParameter('additional_upgrade_info', '');
|
||||
$oPage->p('The installer replies: <input type="text" name="additional_upgrade_info" value="'.$sAdditionalUpgradeInfo.'" size="20"/>');
|
||||
|
||||
|
||||
$oPage->add_ready_script("$('#upgrade_info').change(function() {
|
||||
$('#v_upgrade_info').html('<img src=\"../images/indicator.gif\"/>');
|
||||
WizardAsyncAction('', { upgrade_info: $('#upgrade_info').val() }); });");
|
||||
}
|
||||
|
||||
|
||||
public function AsyncAction(WebPage $oPage, $sCode, $aParameters)
|
||||
{
|
||||
usleep(300000); // 300 ms
|
||||
$sName = $aParameters['upgrade_info'];
|
||||
$sReply = addslashes("Hello ".$sName);
|
||||
|
||||
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
$("#v_upgrade_info").html('');
|
||||
@@ -648,17 +636,17 @@ class Step2ter extends WizardStep
|
||||
{
|
||||
return 'Additional Upgrade Info';
|
||||
}
|
||||
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array('Step3');
|
||||
}
|
||||
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
return array('class' => 'Step3', 'state' => '');
|
||||
}
|
||||
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('This is Step 2ter! (Upgrade)');
|
||||
@@ -671,22 +659,22 @@ class Step3 extends WizardStep
|
||||
{
|
||||
return 'Installation Complete';
|
||||
}
|
||||
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
return array('class' => '', 'state' => '');
|
||||
}
|
||||
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('This is the FINAL Step');
|
||||
}
|
||||
|
||||
|
||||
public function CanMoveForward()
|
||||
{
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user