mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-21 17:48:43 +02:00
The new 2.0 setup is under way...
SVN:trunk[2179]
This commit is contained in:
@@ -120,6 +120,8 @@ require_once(APPROOT.'/core/log.class.inc.php');
|
||||
require_once(APPROOT.'/core/kpi.class.inc.php');
|
||||
require_once(APPROOT.'/core/cmdbsource.class.inc.php');
|
||||
require_once('./xmldataloader.class.inc.php');
|
||||
require_once(APPROOT.'/application/ajaxwebpage.class.inc.php');
|
||||
require_once(APPROOT.'/setup/wizardcontroller.class.inc.php');
|
||||
|
||||
|
||||
// Never cache this page
|
||||
@@ -134,6 +136,18 @@ try
|
||||
{
|
||||
switch($sOperation)
|
||||
{
|
||||
case 'async_action':
|
||||
$sClass = utils::ReadParam('step_class', '');
|
||||
$sState = utils::ReadParam('step_state', '');
|
||||
$sActionCode = utils::ReadParam('code', '');
|
||||
$aParams = utils::ReadParam('params', array(), false, 'raw_data');
|
||||
$oPage = new ajax_page('');
|
||||
$oDummyController = new WizardController('');
|
||||
$oStep = new $sClass($oDummyController, $sState);
|
||||
$oStep->AsyncAction($oPage, $sActionCode, $aParams);
|
||||
$oPage->output();
|
||||
break;
|
||||
|
||||
//////////////////////////////
|
||||
//
|
||||
case 'compile_data_model':
|
||||
|
||||
578
setup/applicationinstaller.class.inc.php
Normal file
578
setup/applicationinstaller.class.inc.php
Normal file
@@ -0,0 +1,578 @@
|
||||
<?php
|
||||
// Copyright (C) 2012 Combodo SARL
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 3 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
require_once(APPROOT.'setup/parameters.class.inc.php');
|
||||
require_once(APPROOT.'setup/xmldataloader.class.inc.php');
|
||||
|
||||
/**
|
||||
* The base class for the installation process.
|
||||
* The installation process is split into a sequence of unitary steps
|
||||
* for performance reasons (i.e; timeout, memory usage) and also in order
|
||||
* to provide some feedback about the progress of the installation.
|
||||
*
|
||||
* This class can be used for a step by step interactive installation
|
||||
* while displaying a progress bar, or in an unattended manner
|
||||
* (for example from the command line), to run all the steps
|
||||
* in one go.
|
||||
* @author Erwan Taloc <erwan.taloc@combodo.com>
|
||||
* @author Romain Quetiez <romain.quetiez@combodo.com>
|
||||
* @author Denis Flaven <denis.flaven@combodo.com>
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html GPL
|
||||
*/
|
||||
|
||||
class ApplicationInstaller
|
||||
{
|
||||
const OK = 1;
|
||||
const ERROR = 2;
|
||||
const WARNING = 3;
|
||||
const INFO = 4;
|
||||
|
||||
protected $sXMLResponseFile;
|
||||
|
||||
public function __construct($sXMLResponseFile)
|
||||
{
|
||||
$this->sXMLResponseFile = $sXMLResponseFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs all the installation steps in one go and directly outputs
|
||||
* some information about the progress and the success of the various
|
||||
* sequential steps.
|
||||
* @return boolean True if the installation was successful, false otherwise
|
||||
*/
|
||||
public function ExecuteAllSteps()
|
||||
{
|
||||
$sStep = '';
|
||||
$sStepLabel = '';
|
||||
do
|
||||
{
|
||||
if($sStep != '')
|
||||
{
|
||||
echo "$sStepLabel\n";
|
||||
echo "Executing '$sStep'\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "Starting the installation...\n";
|
||||
}
|
||||
$aRes = $this->ExecuteStep($sStep);
|
||||
$sStep = $aRes['next-step'];
|
||||
$sStepLabel = $aRes['next-step-label'];
|
||||
|
||||
switch($aRes['status'])
|
||||
{
|
||||
case self::OK;
|
||||
echo "Ok. ".$aRes['percentage-completed']." % done.\n";
|
||||
break;
|
||||
|
||||
case self::ERROR:
|
||||
echo "Error: ".$aRes['message']."\n";
|
||||
break;
|
||||
|
||||
case self::WARNING:
|
||||
echo "Warning: ".$aRes['message']."\n";
|
||||
echo $aRes['percentage-completed']." % done.\n";
|
||||
break;
|
||||
|
||||
case self::INFO:
|
||||
echo "Info: ".$aRes['message']."\n";
|
||||
echo $aRes['percentage-completed']." % done.\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(($aRes['status'] != self::ERROR) && ($aRes['next-step'] != ''));
|
||||
|
||||
return ($aRes['status'] == self::OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the next step of the installation and reports about the progress
|
||||
* and the next step to perform
|
||||
* @param string $sStep The identifier of the step to execute
|
||||
* @return hash An array of (status => , message => , percentage-completed => , next-step => , next-step-label => )
|
||||
*/
|
||||
public function ExecuteStep($sStep = '')
|
||||
{
|
||||
try
|
||||
{
|
||||
switch($sStep)
|
||||
{
|
||||
case '':
|
||||
$aResult = array(
|
||||
'status' => self::OK,
|
||||
'message' => '',
|
||||
'percentage-completed' => 0,
|
||||
'next-step' => 'copy',
|
||||
'next-step-label' => 'Copying data model files',
|
||||
);
|
||||
break;
|
||||
|
||||
case 'copy':
|
||||
$aResult = array(
|
||||
'status' => self::WARNING,
|
||||
'message' => 'Dummy setup - Nothing to copy',
|
||||
'next-step' => 'compile',
|
||||
'next-step-label' => 'Compiling the data model',
|
||||
'percentage-completed' => 20,
|
||||
);
|
||||
break;
|
||||
|
||||
case 'compile':
|
||||
$oParams = new XMLParameters($this->sXMLResponseFile);
|
||||
$aSelectedModules = $oParams->Get('selected_modules');
|
||||
$sSourceDir = $oParams->Get('source_dir', 'datamodel');
|
||||
$sTargetDir = $oParams->Get('target_dir', 'env-setup-test');
|
||||
$sWorkspaceDir = $oParams->Get('workspace_dir', 'workspace');
|
||||
|
||||
self::DoCompile($aSelectedModules, $sSourceDir, $sTargetDir, $sWorkspaceDir);
|
||||
|
||||
$aResult = array(
|
||||
'status' => self::OK,
|
||||
'message' => '',
|
||||
'next-step' => 'db-schema',
|
||||
'next-step-label' => 'Updating database schema',
|
||||
'percentage-completed' => 40,
|
||||
);
|
||||
break;
|
||||
|
||||
case 'db-schema':
|
||||
$oParams = new XMLParameters($this->sXMLResponseFile);
|
||||
$sMode = $oParams->Get('mode');
|
||||
$sTargetDir = $oParams->Get('target_dir', 'env-setup-test');
|
||||
$sDBServer = $oParams->Get('db_server', '');
|
||||
$sDBUser = $oParams->Get('db_user', '');
|
||||
$sDBPwd = $oParams->Get('db_pwd', '');
|
||||
$sDBName = $oParams->Get('db_name', '');
|
||||
$sDBNewName = $oParams->Get('db_new_name', '');
|
||||
$sDBPrefix = $oParams->Get('db_prefix', '');
|
||||
$sTargetEnvironment = $oParams->Get('target_env', '');
|
||||
|
||||
self::DoUpdateDBSchema($sMode, $sTargetDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBNewName, $sDBPrefix, $sTargetEnvironment);
|
||||
|
||||
$aResult = array(
|
||||
'status' => self::OK,
|
||||
'message' => '',
|
||||
'next-step' => 'after-db-create',
|
||||
'next-step-label' => 'Creating Profiles',
|
||||
'percentage-completed' => 60,
|
||||
);
|
||||
break;
|
||||
|
||||
case 'after-db-create':
|
||||
$oParams = new XMLParameters($this->sXMLResponseFile);
|
||||
$sMode = $oParams->Get('mode');
|
||||
$sTargetDir = $oParams->Get('target_dir', 'env-setup-test');
|
||||
$sDBServer = $oParams->Get('db_server', '');
|
||||
$sDBUser = $oParams->Get('db_user', '');
|
||||
$sDBPwd = $oParams->Get('db_pwd', '');
|
||||
$sDBName = $oParams->Get('db_name', '');
|
||||
$sDBNewName = $oParams->Get('db_new_name', '');
|
||||
$sDBPrefix = $oParams->Get('db_prefix', '');
|
||||
$sAdminUser = $oParams->Get('admin_user', '');
|
||||
$sAdminPwd = $oParams->Get('admin_pwd', '');
|
||||
$sLanguage = $oParams->Get('language', '');
|
||||
$aSelectedModules = $oParams->Get('selected_modules', array());
|
||||
$sTargetEnvironment = $oParams->Get('target_env', '');
|
||||
|
||||
self::AfterDBCreate($sMode, $sTargetDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBNewName, $sDBPrefix, $sAdminUser, $sAdminPwd, $sLanguage, $aSelectedModules, $sTargetEnvironment);
|
||||
|
||||
$aResult = array(
|
||||
'status' => self::OK,
|
||||
'message' => '',
|
||||
'next-step' => 'sample-data',
|
||||
'next-step-label' => 'Loading Sample Data',
|
||||
'percentage-completed' => 80,
|
||||
);
|
||||
break;
|
||||
|
||||
case 'sample-data':
|
||||
$oParams = new XMLParameters($this->sXMLResponseFile);
|
||||
$sMode = $oParams->Get('mode');
|
||||
$sTargetDir = $oParams->Get('target_dir', 'env-setup-test');
|
||||
$sDBServer = $oParams->Get('db_server', '');
|
||||
$sDBUser = $oParams->Get('db_user', '');
|
||||
$sDBPwd = $oParams->Get('db_pwd', '');
|
||||
$sDBName = $oParams->Get('db_name', '');
|
||||
$sDBNewName = $oParams->Get('db_new_name', '');
|
||||
$sDBPrefix = $oParams->Get('db_prefix', '');
|
||||
$aFiles = $oParams->Get('files', array());
|
||||
$sTargetEnvironment = $oParams->Get('target_env', '');
|
||||
|
||||
self::DoLoadFiles($aFiles, $sTargetDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sTargetEnvironment);
|
||||
|
||||
$aResult = array(
|
||||
'status' => self::INFO,
|
||||
'message' => 'All data loaded',
|
||||
'next-step' => 'create-config',
|
||||
'next-step-label' => 'Creating the Configuration File',
|
||||
'percentage-completed' => 99,
|
||||
);
|
||||
break;
|
||||
|
||||
case 'create-config':
|
||||
$oParams = new XMLParameters($this->sXMLResponseFile);
|
||||
$sMode = $oParams->Get('mode');
|
||||
$sTargetDir = $oParams->Get('target_dir', 'env-setup-test');
|
||||
$sDBServer = $oParams->Get('db_server', '');
|
||||
$sDBUser = $oParams->Get('db_user', '');
|
||||
$sDBPwd = $oParams->Get('db_pwd', '');
|
||||
$sDBName = $oParams->Get('db_name', '');
|
||||
$sDBNewName = $oParams->Get('db_new_name', '');
|
||||
$sDBPrefix = $oParams->Get('db_prefix', '');
|
||||
$sUrl = $oParams->Get('url', '');
|
||||
$sLanguage = $oParams->Get('language', '');
|
||||
$aSelectedModules = $oParams->Get('selected_modules', array());
|
||||
$sTargetEnvironment = $oParams->Get('target_env', '');
|
||||
|
||||
self::DoCreateConfig($sMode, $sTargetDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sUrl, $sLanguage, $aSelectedModules, $sTargetEnvironment);
|
||||
|
||||
$aResult = array(
|
||||
'status' => self::INFO,
|
||||
'message' => 'Configuration file created',
|
||||
'next-step' => '',
|
||||
'next-step-label' => 'Completed',
|
||||
'percentage-completed' => 100,
|
||||
);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
$aResult = array(
|
||||
'status' => self::ERROR,
|
||||
'message' => '',
|
||||
'next-step' => '',
|
||||
'next-step-label' => "Unknown setup step '$sStep'.",
|
||||
'percentage-completed' => 100,
|
||||
);
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$aResult = array(
|
||||
'status' => self::ERROR,
|
||||
'message' => $e->getMessage(),
|
||||
'next-step' => '',
|
||||
'next-step-label' => '',
|
||||
'percentage-completed' => 100,
|
||||
);
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
protected static function DoCompile($aSelectedModules, $sSourceDir, $sTargetDir, $sWorkspaceDir = '')
|
||||
{
|
||||
SetupPage::log_info("Compiling data model.");
|
||||
|
||||
require_once(APPROOT.'setup/modulediscovery.class.inc.php');
|
||||
require_once(APPROOT.'setup/modelfactory.class.inc.php');
|
||||
require_once(APPROOT.'setup/compiler.class.inc.php');
|
||||
|
||||
if (empty($sSourceDir) || empty($sTargetDir))
|
||||
{
|
||||
throw new Exception("missing parameter source_dir and/or target_dir");
|
||||
}
|
||||
|
||||
$sSourcePath = APPROOT.$sSourceDir;
|
||||
$sTargetPath = APPROOT.$sTargetDir;
|
||||
if (!is_dir($sSourcePath))
|
||||
{
|
||||
throw new Exception("Failed to find the source directory '$sSourcePath', please check the rights of the web server");
|
||||
}
|
||||
if (!is_dir($sTargetPath) && !mkdir($sTargetPath))
|
||||
{
|
||||
throw new Exception("Failed to create directory '$sTargetPath', please check the rights of the web server");
|
||||
}
|
||||
// owner:rwx user/group:rx
|
||||
chmod($sTargetPath, 0755);
|
||||
|
||||
$oFactory = new ModelFactory($sSourcePath);
|
||||
$aModules = $oFactory->FindModules();
|
||||
|
||||
foreach($aModules as $foo => $oModule)
|
||||
{
|
||||
$sModule = $oModule->GetName();
|
||||
if (in_array($sModule, $aSelectedModules))
|
||||
{
|
||||
$oFactory->LoadModule($oModule);
|
||||
}
|
||||
}
|
||||
if (strlen($sWorkspaceDir) > 0)
|
||||
{
|
||||
$oWorkspace = new MFWorkspace(APPROOT.$sWorkspaceDir);
|
||||
if (file_exists($oWorkspace->GetWorkspacePath()))
|
||||
{
|
||||
$oFactory->LoadModule($oWorkspace);
|
||||
}
|
||||
}
|
||||
//$oFactory->Dump();
|
||||
if ($oFactory->HasLoadErrors())
|
||||
{
|
||||
foreach($oFactory->GetLoadErrors() as $sModuleId => $aErrors)
|
||||
{
|
||||
SetupPage::log_error("Data model source file (xml) could not be loaded - found errors in module: $sModuleId");
|
||||
foreach($aErrors as $oXmlError)
|
||||
{
|
||||
SetupPage::log_error("Load error: File: ".$oXmlError->file." Line:".$oXmlError->line." Message:".$oXmlError->message);
|
||||
}
|
||||
}
|
||||
throw new Exception("The data model could not be compiled. Please check the setup error log");
|
||||
}
|
||||
else
|
||||
{
|
||||
$oMFCompiler = new MFCompiler($oFactory, $sSourcePath);
|
||||
$oMFCompiler->Compile($sTargetPath);
|
||||
SetupPage::log_info("Data model successfully compiled to '$sTargetPath'.");
|
||||
}
|
||||
}
|
||||
|
||||
protected static function DoUpdateDBSchema($sMode, $sModulesDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBNewName, $sDBPrefix, $sTargetEnvironment = '')
|
||||
{
|
||||
SetupPage::log_info("Update Database Schema for environment '$sTargetEnvironment'.");
|
||||
|
||||
$oConfig = new Config();
|
||||
|
||||
$aParamValues = array(
|
||||
'db_server' => $sDBServer,
|
||||
'db_user' => $sDBUser,
|
||||
'db_pwd' => $sDBPwd,
|
||||
'db_name' => $sDBName,
|
||||
'new_db_name' => $sDBNewName,
|
||||
'db_prefix' => $sDBPrefix,
|
||||
);
|
||||
$oConfig->UpdateFromParams($aParamValues, $sModulesDir);
|
||||
|
||||
$oProductionEnv = new RunTimeEnvironment($sTargetEnvironment);
|
||||
$oProductionEnv->InitDataModel($oConfig, true); // load data model only
|
||||
|
||||
if(!$oProductionEnv->CreateDatabaseStructure(MetaModel::GetConfig(), $sMode))
|
||||
{
|
||||
throw(new Exception("Failed to create/upgrade the database structure for environment '$sTargetEnvironment'"));
|
||||
}
|
||||
SetupPage::log_info("Database Schema Successfully Updated for environment '$sTargetEnvironment'.");
|
||||
}
|
||||
|
||||
protected static function AfterDBCreate($sMode, $sModulesDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBNewName, $sDBPrefix, $sAdminUser, $sAdminPwd, $sLanguage, $aSelectedModules, $sTargetEnvironment = '')
|
||||
{
|
||||
|
||||
SetupPage::log_info('After Database Creation');
|
||||
|
||||
$oConfig = new Config();
|
||||
|
||||
$aParamValues = array(
|
||||
'db_server' => $sDBServer,
|
||||
'db_user' => $sDBUser,
|
||||
'db_pwd' => $sDBPwd,
|
||||
'db_name' => $sDBName,
|
||||
'new_db_name' => $sDBNewName,
|
||||
'db_prefix' => $sDBPrefix,
|
||||
);
|
||||
$oConfig->UpdateFromParams($aParamValues, $sModulesDir);
|
||||
|
||||
$oProductionEnv = new RunTimeEnvironment($sTargetEnvironment);
|
||||
$oProductionEnv->InitDataModel($oConfig, false); // load data model and connect to the database
|
||||
|
||||
// Perform here additional DB setup... profiles, etc...
|
||||
//
|
||||
$aAvailableModules = $oProductionEnv->AnalyzeInstallation(MetaModel::GetConfig(), $sModulesDir);
|
||||
foreach($aAvailableModules as $sModuleId => $aModule)
|
||||
{
|
||||
if (($sModuleId != ROOT_MODULE) && in_array($sModuleId, $aSelectedModules) &&
|
||||
isset($aAvailableModules[$sModuleId]['installer']) )
|
||||
{
|
||||
$sModuleInstallerClass = $aAvailableModules[$sModuleId]['installer'];
|
||||
SetupPage::log_info("Calling Module Handler: $sModuleInstallerClass::AfterDatabaseCreation(oConfig, {$aModule['version_db']}, {$aModule['version_code']})");
|
||||
// The validity of the sModuleInstallerClass has been established in BuildConfig()
|
||||
$aCallSpec = array($sModuleInstallerClass, 'AfterDatabaseCreation');
|
||||
call_user_func_array($aCallSpec, array(MetaModel::GetConfig(), $aModule['version_db'], $aModule['version_code']));
|
||||
}
|
||||
}
|
||||
|
||||
// Constant classes (e.g. User profiles)
|
||||
//
|
||||
foreach (MetaModel::GetClasses() as $sClass)
|
||||
{
|
||||
$aPredefinedObjects = call_user_func(array($sClass, 'GetPredefinedObjects'));
|
||||
if ($aPredefinedObjects != null)
|
||||
{
|
||||
// Temporary... until this get really encapsulated as the default and transparent behavior
|
||||
$oMyChange = MetaModel::NewObject("CMDBChange");
|
||||
$oMyChange->Set("date", time());
|
||||
$sUserString = CMDBChange::GetCurrentUserName();
|
||||
$oMyChange->Set("userinfo", $sUserString);
|
||||
$iChangeId = $oMyChange->DBInsert();
|
||||
|
||||
// Create/Delete/Update objects of this class,
|
||||
// according to the given constant values
|
||||
//
|
||||
$aDBIds = array();
|
||||
$oAll = new DBObjectSet(new DBObjectSearch($sClass));
|
||||
while ($oObj = $oAll->Fetch())
|
||||
{
|
||||
if (array_key_exists($oObj->GetKey(), $aPredefinedObjects))
|
||||
{
|
||||
$aObjValues = $aPredefinedObjects[$oObj->GetKey()];
|
||||
foreach ($aObjValues as $sAttCode => $value)
|
||||
{
|
||||
$oObj->Set($sAttCode, $value);
|
||||
}
|
||||
$oObj->DBUpdateTracked($oMyChange);
|
||||
$aDBIds[$oObj->GetKey()] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$oObj->DBDeleteTracked($oMyChange);
|
||||
}
|
||||
}
|
||||
foreach ($aPredefinedObjects as $iRefId => $aObjValues)
|
||||
{
|
||||
if (!array_key_exists($iRefId, $aDBIds))
|
||||
{
|
||||
$oNewObj = MetaModel::NewObject($sClass);
|
||||
$oNewObj->SetKey($iRefId);
|
||||
foreach ($aObjValues as $sAttCode => $value)
|
||||
{
|
||||
$oNewObj->Set($sAttCode, $value);
|
||||
}
|
||||
$oNewObj->DBInsertTracked($oMyChange);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$oProductionEnv->RecordInstallation($oConfig, $aSelectedModules, $sModulesDir))
|
||||
{
|
||||
throw(new Exception("Failed to record the installation information"));
|
||||
}
|
||||
|
||||
if($sMode == 'install')
|
||||
{
|
||||
if (!self::CreateAdminAccount(MetaModel::GetConfig(), $sAdminUser, $sAdminPwd, $sLanguage))
|
||||
{
|
||||
throw(new Exception("Failed to create the administrator account '$sAdminUser'"));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetupPage::log_info("Administrator account '$sAdminUser' created.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to create and administrator account for iTop
|
||||
* @return boolean true on success, false otherwise
|
||||
*/
|
||||
protected static function CreateAdminAccount(Config $oConfig, $sAdminUser, $sAdminPwd, $sLanguage)
|
||||
{
|
||||
SetupPage::log_info('CreateAdminAccount');
|
||||
|
||||
if (UserRights::CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected static function DoLoadFiles($aFiles, $sModulesDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sTargetEnvironment = '')
|
||||
{
|
||||
$aParamValues = array(
|
||||
'db_server' => $sDBServer,
|
||||
'db_user' => $sDBUser,
|
||||
'db_pwd' => $sDBPwd,
|
||||
'db_name' => $sDBName,
|
||||
'new_db_name' => $sDBName,
|
||||
'db_prefix' => $sDBPrefix,
|
||||
);
|
||||
$oConfig = new Config();
|
||||
|
||||
$oConfig->UpdateFromParams($aParamValues, $sModulesDir);
|
||||
|
||||
//TODO: load the MetaModel if needed (async mode)
|
||||
//$oProductionEnv = new RunTimeEnvironment($sTargetEnvironment);
|
||||
//$oProductionEnv->InitDataModel($oConfig, false); // load data model and connect to the database
|
||||
|
||||
$oDataLoader = new XMLDataLoader();
|
||||
$oChange = MetaModel::NewObject("CMDBChange");
|
||||
$oChange->Set("date", time());
|
||||
$oChange->Set("userinfo", "Initialization");
|
||||
$iChangeId = $oChange->DBInsert();
|
||||
SetupPage::log_info("starting data load session");
|
||||
$oDataLoader->StartSession($oChange);
|
||||
|
||||
foreach($aFiles as $sFileRelativePath)
|
||||
{
|
||||
$sFileName = APPROOT.'env-'.(($sTargetEnvironment == '') ? 'production' : $sTargetEnvironment).'/'.$sFileRelativePath;
|
||||
SetupPage::log_info("Loading file: $sFileName");
|
||||
if (empty($sFileName) || !file_exists($sFileName))
|
||||
{
|
||||
throw(new Exception("File $sFileName does not exist"));
|
||||
}
|
||||
|
||||
$oDataLoader->LoadFile($sFileName);
|
||||
$sResult = sprintf("loading of %s done.", basename($sFileName));
|
||||
SetupPage::log_info($sResult);
|
||||
}
|
||||
|
||||
$oDataLoader->EndSession();
|
||||
SetupPage::log_info("ending data load session");
|
||||
}
|
||||
|
||||
protected static function DoCreateConfig($sMode, $sModulesDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sUrl, $sLanguage, $aSelectedModules, $sTargetEnvironment = '')
|
||||
{
|
||||
$aParamValues = array(
|
||||
'db_server' => $sDBServer,
|
||||
'db_user' => $sDBUser,
|
||||
'db_pwd' => $sDBPwd,
|
||||
'db_name' => $sDBName,
|
||||
'new_db_name' => $sDBName,
|
||||
'db_prefix' => $sDBPrefix,
|
||||
'application_path' => $sUrl,
|
||||
'mode' => $sMode,
|
||||
'language' => $sLanguage,
|
||||
'selected_modules' => implode(',', $aSelectedModules),
|
||||
);
|
||||
|
||||
$oConfig = new Config();
|
||||
|
||||
// Migration: force utf8_unicode_ci as the collation to make the global search
|
||||
// NON case sensitive
|
||||
$oConfig->SetDBCollation('utf8_unicode_ci');
|
||||
|
||||
// Final config update: add the modules
|
||||
$oConfig->UpdateFromParams($aParamValues, $sModulesDir);
|
||||
|
||||
// Make sure the root configuration directory exists
|
||||
if (!file_exists(APPCONF))
|
||||
{
|
||||
mkdir(APPCONF);
|
||||
chmod(APPCONF, 0770); // RWX for owner and group, nothing for others
|
||||
SetupPage::log_info("Created configuration directory: ".APPCONF);
|
||||
}
|
||||
|
||||
// Write the final configuration file
|
||||
$sConfigFile = APPCONF.(($sTargetEnvironment == '') ? 'production' : $sTargetEnvironment).'/'.ITOP_CONFIG_FILE;
|
||||
$sConfigDir = dirname($sConfigFile);
|
||||
@mkdir($sConfigDir);
|
||||
@chmod($sConfigDir, 0770); // RWX for owner and group, nothing for others
|
||||
|
||||
$oConfig->WriteToFile($sConfigFile);
|
||||
|
||||
// try to make the final config file read-only
|
||||
@chmod($sConfigFile, 0444); // Read-only for owner and group, nothing for others
|
||||
}
|
||||
}
|
||||
@@ -172,6 +172,11 @@ class ModuleDiscovery
|
||||
{
|
||||
$sLookupDir = realpath($sRootDir.'/'.$sSearchDir);
|
||||
|
||||
if (self::$m_sModulesRoot != $sLookupDir)
|
||||
{
|
||||
self::ResetCache();
|
||||
}
|
||||
|
||||
if (is_null(self::$m_sModulesRoot))
|
||||
{
|
||||
// First call
|
||||
@@ -186,10 +191,6 @@ class ModuleDiscovery
|
||||
self::ListModuleFiles($sSearchDir, $sRootDir);
|
||||
return self::GetModules($oP);
|
||||
}
|
||||
elseif (self::$m_sModulesRoot != $sLookupDir)
|
||||
{
|
||||
throw new Exception("Design issue: the discovery of modules cannot be made on two different paths (previous: ".self::$m_sModulesRoot.", new: $sLookupDir)");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reuse the previous results
|
||||
@@ -197,6 +198,13 @@ class ModuleDiscovery
|
||||
return self::GetModules($oP);
|
||||
}
|
||||
}
|
||||
|
||||
public static function ResetCache()
|
||||
{
|
||||
self::$m_sModulesRoot = null;
|
||||
self::$m_sModulesRoot = null;
|
||||
self::$m_aModules = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to interpret the name of a module
|
||||
|
||||
138
setup/parameters.class.inc.php
Normal file
138
setup/parameters.class.inc.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
class InvalidParameterException extends Exception
|
||||
{
|
||||
}
|
||||
|
||||
abstract class Parameters
|
||||
{
|
||||
protected $aData = null;
|
||||
protected $sParametersFile = null;
|
||||
|
||||
public function __construct($sParametersFile)
|
||||
{
|
||||
$this->aData = null;
|
||||
$this->sParametersFile = $sParametersFile;
|
||||
$this->Load($sParametersFile);
|
||||
}
|
||||
|
||||
abstract public function Load($sParametersFile);
|
||||
|
||||
public function Get($sCode, $default = '')
|
||||
{
|
||||
if (array_key_exists($sCode, $this->aData))
|
||||
{
|
||||
return $this->aData[$sCode];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
|
||||
class PHPParameters extends Parameters
|
||||
{
|
||||
public function Load($sParametersFile)
|
||||
{
|
||||
if ($this->aData == null)
|
||||
{
|
||||
require_once($sParametersFile);
|
||||
$this->aData = $ITOP_PARAMS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class XMLParameters extends Parameters
|
||||
{
|
||||
protected $aData = null;
|
||||
|
||||
public function Load($sParametersFile)
|
||||
{
|
||||
if ($this->aData == null)
|
||||
{
|
||||
libxml_use_internal_errors(true);
|
||||
$oXML = @simplexml_load_file($sParametersFile);
|
||||
if (!$oXML)
|
||||
{
|
||||
$aMessage = array();
|
||||
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[(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)
|
||||
{
|
||||
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();
|
||||
}
|
||||
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;
|
||||
|
||||
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()."'");
|
||||
}
|
||||
$val = $this->ReadElement($oChildElement);
|
||||
$value[$oChildElement->getName()] = $val;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'int':
|
||||
case 'integer':
|
||||
$value = (int)$oElement;
|
||||
break;
|
||||
|
||||
case 'string':
|
||||
default:
|
||||
$value = (string)$oElement;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
protected function GetAttribute($sAttName, $oElement, $sDefaultValue)
|
||||
{
|
||||
$sRet = $sDefaultValue;
|
||||
|
||||
foreach($oElement->attributes() as $sKey => $oChildElement)
|
||||
{
|
||||
if ((string)$sKey == $sAttName)
|
||||
{
|
||||
$sRet = (string)$oChildElement;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $sRet;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -335,4 +335,16 @@ function GetSelectedModules()
|
||||
var aModules = new Array();
|
||||
$(':input[name^=module]').each(function() { aModules.push($(this).val()); } );
|
||||
return aModules.join(',');
|
||||
}
|
||||
}
|
||||
|
||||
function WizardAsyncAction(sActionCode, oParams)
|
||||
{
|
||||
var sStepClass = $('#_class').val();
|
||||
var sStepState = $('#_state').val();
|
||||
|
||||
var oMap = { operation: 'async_action', step_class: sStepClass, step_state: sStepState, code: sActionCode, params: oParams };
|
||||
|
||||
$.post(GetAbsoluteUrlAppRoot()+'setup/ajax.dataloader.php', oMap, function(data) {
|
||||
$('#async_action').html(data);
|
||||
});
|
||||
}
|
||||
|
||||
322
setup/setuputils.class.inc.php
Normal file
322
setup/setuputils.class.inc.php
Normal file
@@ -0,0 +1,322 @@
|
||||
<?php
|
||||
// Copyright (C) 2012 Combodo SARL
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 3 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
/**
|
||||
* The standardized result of any pass/fail check performed by the setup
|
||||
* @author Erwan Taloc <erwan.taloc@combodo.com>
|
||||
* @author Romain Quetiez <romain.quetiez@combodo.com>
|
||||
* @author Denis Flaven <denis.flaven@combodo.com>
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html GPL
|
||||
*/
|
||||
|
||||
class CheckResult
|
||||
{
|
||||
// Severity levels
|
||||
const ERROR = 0;
|
||||
const WARNING = 1;
|
||||
const INFO = 2;
|
||||
|
||||
public $iSeverity;
|
||||
public $sLabel;
|
||||
public $sDescription;
|
||||
|
||||
public function __construct($iSeverity, $sLabel, $sDescription = '')
|
||||
{
|
||||
$this->iSeverity = $iSeverity;
|
||||
$this->sLabel = $sLabel;
|
||||
$this->sDescription = $sDescription;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Namespace for storing all the functions/utilities needed by both
|
||||
* the setup wizard and the installation process
|
||||
* @author Erwan Taloc <erwan.taloc@combodo.com>
|
||||
* @author Romain Quetiez <romain.quetiez@combodo.com>
|
||||
* @author Denis Flaven <denis.flaven@combodo.com>
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html GPL
|
||||
*/
|
||||
|
||||
class SetupUtils
|
||||
{
|
||||
const PHP_MIN_VERSION = '5.2.0';
|
||||
const MYSQL_MIN_VERSION = '5.0.0';
|
||||
const MIN_MEMORY_LIMIT = 33554432; // = 32*1024*1024 Beware: Computations are not allowed in defining constants
|
||||
const SUHOSIN_GET_MAX_VALUE_LENGTH = 2048;
|
||||
|
||||
/**
|
||||
* Check the version of PHP, the needed PHP extension and a number
|
||||
* of configuration parameters (memory_limit, max_upload_file_size, etc...)
|
||||
* @param SetupPage $oP The page used only for its 'log' method
|
||||
* @return array An array of CheckResults objects
|
||||
*/
|
||||
static function CheckPHPVersion(SetupPage $oP)
|
||||
{
|
||||
$aResult = array();
|
||||
$bResult = true;
|
||||
$aErrors = array();
|
||||
$aWarnings = array();
|
||||
$aOk = array();
|
||||
|
||||
$oP->log('Info - CheckPHPVersion');
|
||||
if (version_compare(phpversion(), self::PHP_MIN_VERSION, '>='))
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::INFO, "The current PHP Version (".phpversion().") is greater than the minimum required version (".self::PHP_MIN_VERSION.")");
|
||||
}
|
||||
else
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "Error: The current PHP Version (".phpversion().") is lower than the minimum required version (".self::PHP_MIN_VERSION.")");
|
||||
}
|
||||
$aMandatoryExtensions = array('mysqli', 'iconv', 'simplexml', 'soap', 'hash', 'json', 'session', 'pcre', 'dom');
|
||||
$aOptionalExtensions = array('mcrypt' => 'Strong encryption will not be used.',
|
||||
'ldap' => 'LDAP authentication will be disabled.');
|
||||
asort($aMandatoryExtensions); // Sort the list to look clean !
|
||||
ksort($aOptionalExtensions); // Sort the list to look clean !
|
||||
$aExtensionsOk = array();
|
||||
$aMissingExtensions = array();
|
||||
$aMissingExtensionsLinks = array();
|
||||
// First check the mandatory extensions
|
||||
foreach($aMandatoryExtensions as $sExtension)
|
||||
{
|
||||
if (extension_loaded($sExtension))
|
||||
{
|
||||
$aExtensionsOk[] = $sExtension;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aMissingExtensions[] = $sExtension;
|
||||
$aMissingExtensionsLinks[] = "<a href=\"http://www.php.net/manual/en/book.$sExtension.php\" target=\"_blank\">$sExtension</a>";
|
||||
}
|
||||
}
|
||||
if (count($aExtensionsOk) > 0)
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::INFO, "Required PHP extension(s): ".implode(', ', $aExtensionsOk).".");
|
||||
}
|
||||
if (count($aMissingExtensions) > 0)
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "Missing PHP extension(s): ".implode(', ', $aMissingExtensionsLinks).".");
|
||||
}
|
||||
// Next check the optional extensions
|
||||
$aExtensionsOk = array();
|
||||
$aMissingExtensions = array();
|
||||
foreach($aOptionalExtensions as $sExtension => $sMessage)
|
||||
{
|
||||
if (extension_loaded($sExtension))
|
||||
{
|
||||
$aExtensionsOk[] = $sExtension;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aMissingExtensions[$sExtension] = $sMessage;
|
||||
}
|
||||
}
|
||||
if (count($aExtensionsOk) > 0)
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::INFO, "Optional PHP extension(s): ".implode(', ', $aExtensionsOk).".");
|
||||
}
|
||||
if (count($aMissingExtensions) > 0)
|
||||
{
|
||||
foreach($aMissingExtensions as $sExtension => $sMessage)
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::WARNING, "Missing optional PHP extension: $sExtension. ".$sMessage);
|
||||
}
|
||||
}
|
||||
// Check some ini settings here
|
||||
if (function_exists('php_ini_loaded_file')) // PHP >= 5.2.4
|
||||
{
|
||||
$sPhpIniFile = php_ini_loaded_file();
|
||||
// Other included/scanned files
|
||||
if ($sFileList = php_ini_scanned_files())
|
||||
{
|
||||
if (strlen($sFileList) > 0)
|
||||
{
|
||||
$aFiles = explode(',', $sFileList);
|
||||
|
||||
foreach ($aFiles as $sFile)
|
||||
{
|
||||
$sPhpIniFile .= ', '.trim($sFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
$oP->log("Info - php.ini file(s): '$sPhpIniFile'");
|
||||
}
|
||||
else
|
||||
{
|
||||
$sPhpIniFile = 'php.ini';
|
||||
}
|
||||
if (!ini_get('file_uploads'))
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "Files upload is not allowed on this server (file_uploads = ".ini_get('file_uploads').").");
|
||||
}
|
||||
|
||||
$sUploadTmpDir = self::GetUploadTmpDir();
|
||||
if (empty($sUploadTmpDir))
|
||||
{
|
||||
$sUploadTmpDir = '/tmp';
|
||||
$aResult[] = new CheckResult(CheckResult::WARNING, "Temporary directory for files upload is not defined (upload_tmp_dir), assuming that $sUploadTmpDir is used.");
|
||||
}
|
||||
// check that the upload directory is indeed writable from PHP
|
||||
if (!empty($sUploadTmpDir))
|
||||
{
|
||||
if (!file_exists($sUploadTmpDir))
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "Temporary directory for files upload ($sUploadTmpDir) does not exist or cannot be read by PHP.");
|
||||
}
|
||||
else if (!is_writable($sUploadTmpDir))
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "Temporary directory for files upload ($sUploadTmpDir) is not writable.");
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->log("Info - Temporary directory for files upload ($sUploadTmpDir) is writable.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!ini_get('upload_max_filesize'))
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "File upload is not allowed on this server (upload_max_filesize = ".ini_get('upload_max_filesize').").");
|
||||
}
|
||||
|
||||
$iMaxFileUploads = ini_get('max_file_uploads');
|
||||
if (!empty($iMaxFileUploads) && ($iMaxFileUploads < 1))
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "File upload is not allowed on this server (max_file_uploads = ".ini_get('max_file_uploads').").");
|
||||
}
|
||||
|
||||
$iMaxUploadSize = utils::ConvertToBytes(ini_get('upload_max_filesize'));
|
||||
$iMaxPostSize = utils::ConvertToBytes(ini_get('post_max_size'));
|
||||
|
||||
if ($iMaxPostSize <= $iMaxUploadSize)
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::WARNING, "post_max_size (".ini_get('post_max_size').") must be bigger than upload_max_filesize (".ini_get('upload_max_filesize')."). You may want to check the PHP configuration file(s): '$sPhpIniFile'. Be aware that this setting can also be overridden in the apache configuration.");
|
||||
}
|
||||
|
||||
|
||||
$oP->log("Info - upload_max_filesize: ".ini_get('upload_max_filesize'));
|
||||
$oP->log("Info - post_max_size: ".ini_get('post_max_size'));
|
||||
$oP->log("Info - max_file_uploads: ".ini_get('max_file_uploads'));
|
||||
|
||||
// Check some more ini settings here, needed for file upload
|
||||
if (function_exists('get_magic_quotes_gpc'))
|
||||
{
|
||||
if (@get_magic_quotes_gpc())
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "'magic_quotes_gpc' is set to On. Please turn it Off before continuing. You may want to check the PHP configuration file(s): '$sPhpIniFile'. Be aware that this setting can also be overridden in the apache configuration.");
|
||||
}
|
||||
}
|
||||
if (function_exists('magic_quotes_runtime'))
|
||||
{
|
||||
if (@magic_quotes_runtime())
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "'magic_quotes_runtime' is set to On. Please turn it Off before continuing. You may want to check the PHP configuration file(s): '$sPhpIniFile'. Be aware that this setting can also be overridden in the apache configuration.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$sMemoryLimit = trim(ini_get('memory_limit'));
|
||||
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 anyway
|
||||
$aResult[] = new CheckResult(CheckResult::WARNING, "No memory limit has been defined in this instance of PHP");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check that the limit will allow us to load the data
|
||||
//
|
||||
$iMemoryLimit = utils::ConvertToBytes($sMemoryLimit);
|
||||
if ($iMemoryLimit < self::MIN_MEMORY_LIMIT)
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "memory_limit ($iMemoryLimit) is too small, the minimum value to run the application is ".self::MIN_MEMORY_LIMIT.".");
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->log_info("memory_limit is $iMemoryLimit, ok.");
|
||||
}
|
||||
}
|
||||
|
||||
// Special case for APC
|
||||
if (extension_loaded('apc'))
|
||||
{
|
||||
$sAPCVersion = phpversion('apc');
|
||||
$aResult[] = new CheckResult(CheckResult::INFO, "APC detected (version $sAPCVersion). The APC cache will be used to speed-up the application.");
|
||||
}
|
||||
|
||||
// Special case Suhosin extension
|
||||
if (extension_loaded('suhosin'))
|
||||
{
|
||||
$sSuhosinVersion = phpversion('suhosin');
|
||||
$aOk[] = "Suhosin extension detected (version $sSuhosinVersion).";
|
||||
|
||||
$iGetMaxValueLength = ini_get('suhosin.get.max_value_length');
|
||||
if ($iGetMaxValueLength < self::SUHOSIN_GET_MAX_VALUE_LENGTH)
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::INFO, "suhosin.get.max_value_length ($iGetMaxValueLength) is too small, the minimum value to run the application is ".self::SUHOSIN_GET_MAX_VALUE_LENGTH.". This value is set by the PHP configuration file(s): '$sPhpIniFile'. Be aware that this setting can also be overridden in the apache configuration.");
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->log_info("suhosin.get.max_value_length = $iGetMaxValueLength, ok.");
|
||||
}
|
||||
}
|
||||
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to retrieve the system's temporary directory
|
||||
* Emulates sys_get_temp_dir if neeed (PHP < 5.2.1)
|
||||
* @return string Path to the system's temp directory
|
||||
*/
|
||||
static function GetTmpDir()
|
||||
{
|
||||
// try to figure out what is the temporary directory
|
||||
// prior to PHP 5.2.1 the function sys_get_temp_dir
|
||||
// did not exist
|
||||
if ( !function_exists('sys_get_temp_dir'))
|
||||
{
|
||||
if( $temp=getenv('TMP') ) return realpath($temp);
|
||||
if( $temp=getenv('TEMP') ) return realpath($temp);
|
||||
if( $temp=getenv('TMPDIR') ) return realpath($temp);
|
||||
$temp=tempnam(__FILE__,'');
|
||||
if (file_exists($temp))
|
||||
{
|
||||
unlink($temp);
|
||||
return realpath(dirname($temp));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return realpath(sys_get_temp_dir());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to retrieve the directory where files are to be uploaded
|
||||
* @return string Path to the temp directory used for uploading files
|
||||
*/
|
||||
static function GetUploadTmpDir()
|
||||
{
|
||||
$sPath = ini_get('upload_tmp_dir');
|
||||
if (empty($sPath))
|
||||
{
|
||||
$sPath = self::GetTmpDir();
|
||||
}
|
||||
return $sPath;
|
||||
}
|
||||
}
|
||||
533
setup/wizardcontroller.class.inc.php
Normal file
533
setup/wizardcontroller.class.inc.php
Normal file
@@ -0,0 +1,533 @@
|
||||
<?php
|
||||
// Copyright (C) 2012 Combodo SARL
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 3 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
/**
|
||||
* Engine for displaying the various pages of a "wizard"
|
||||
* Each "step" of the wizard must be implemented as
|
||||
* separate class derived from WizardStep. each 'step' can also have its own
|
||||
* internal 'state' for developing complex wizards.
|
||||
* The WizardController provides the "<< Back" feature by storing a stack
|
||||
* of the previous screens. The WizardController also maintains from page
|
||||
* to page a list of "parameters" to be dispayed/edited by each of the steps.
|
||||
* @author Erwan Taloc <erwan.taloc@combodo.com>
|
||||
* @author Romain Quetiez <romain.quetiez@combodo.com>
|
||||
* @author Denis Flaven <denis.flaven@combodo.com>
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html GPL
|
||||
*/
|
||||
|
||||
class WizardController
|
||||
{
|
||||
protected $aSteps;
|
||||
protected $sInitialStepClass;
|
||||
protected $sInitialState;
|
||||
protected $aParameters;
|
||||
|
||||
/**
|
||||
* Initiailization of the wizard controller
|
||||
* @param string $sInitialStepClass Class of the initial step/page of the wizard
|
||||
* @param string $sInitialState Initial state of the initial page (if this class manages states)
|
||||
*/
|
||||
public function __construct($sInitialStepClass, $sInitialState = '')
|
||||
{
|
||||
$this->sInitialStepClass = $sInitialStepClass;
|
||||
$this->sInitialState = $sInitialState;
|
||||
$this->aParameters = array();
|
||||
$this->aSteps = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes information about the current step onto the stack
|
||||
* @param hash $aStepInfo Array('class' => , 'state' => )
|
||||
*/
|
||||
protected function PushStep($aStepInfo)
|
||||
{
|
||||
array_push($this->aSteps, $aStepInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes information about the previous step from the stack
|
||||
* @return hash Array('class' => , 'state' => )
|
||||
*/
|
||||
protected function PopStep()
|
||||
{
|
||||
return array_pop($this->aSteps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a "persistent" parameter from the wizard's context
|
||||
* @param string $sParamCode The code identifying this parameter
|
||||
* @param mixed $defaultValue The default value of the parameter in case it was not set
|
||||
*/
|
||||
public function GetParameter($sParamCode, $defaultValue = '')
|
||||
{
|
||||
if (array_key_exists($sParamCode, $this->aParameters))
|
||||
{
|
||||
return $this->aParameters[$sParamCode];
|
||||
}
|
||||
return $defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a "persistent" parameter in the wizard's context
|
||||
* @param string $sParamCode The code identifying this parameter
|
||||
* @param mixed $value The value to store
|
||||
*/
|
||||
public function SetParameter($sParamCode, $value)
|
||||
{
|
||||
$this->aParameters[$sParamCode] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the wizard by displaying it in its initial state
|
||||
*/
|
||||
protected function Start()
|
||||
{
|
||||
$sCurrentStepClass = $this->sInitialStepClass;
|
||||
$oStep = new $sCurrentStepClass($this, $this->sInitialState);
|
||||
$this->DisplayStep($oStep);
|
||||
}
|
||||
/**
|
||||
* Progress towards the next step of the wizard
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function Next()
|
||||
{
|
||||
$sCurrentStepClass = utils::ReadParam('_class', $this->sInitialStepClass);
|
||||
$sCurrentState = utils::ReadParam('_state', $this->sInitialState);
|
||||
$oStep = new $sCurrentStepClass($this, $sCurrentState);
|
||||
if ($oStep->ValidateParams($sCurrentState))
|
||||
{
|
||||
$this->PushStep(array('class' => $sCurrentStepClass, 'state' => $sCurrentState));
|
||||
$aPossibleSteps = $oStep->GetPossibleSteps();
|
||||
$aNextStepInfo = $oStep->ProcessParams(true); // true => moving forward
|
||||
if (in_array($aNextStepInfo['class'], $aPossibleSteps))
|
||||
{
|
||||
$oNextStep = new $aNextStepInfo['class']($this, $aNextStepInfo['state']);
|
||||
$this->DisplayStep($oNextStep);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Internal error: Unexpected next step '{$aNextStepInfo['class']}'. The possible next steps are: ".implode(', ', $aPossibleSteps));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->DisplayStep($oStep);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Move one step back
|
||||
*/
|
||||
protected function Back()
|
||||
{
|
||||
// let the current step save its parameters
|
||||
$sCurrentStepClass = utils::ReadParam('_class', $this->sInitialStepClass);
|
||||
$sCurrentState = utils::ReadParam('_state', $this->sInitialState);
|
||||
$oStep = new $sCurrentStepClass($this, $sCurrentState);
|
||||
$aNextStepInfo = $oStep->ProcessParams();
|
||||
|
||||
// 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
|
||||
*/
|
||||
protected function DisplayStep(WizardStep $oStep)
|
||||
{
|
||||
$oPage = new SetupPage($oStep->GetTitle());
|
||||
$oPage->add_linked_script('../setup/setup.js');
|
||||
$oPage->add('<form method="post">');
|
||||
$oStep->Display($oPage);
|
||||
|
||||
// Add the back / next buttons and the hidden form
|
||||
// to store the parameters
|
||||
$oPage->add('<input type="hidden" id="_class" name="_class" value="'.get_class($oStep).'"/>');
|
||||
$oPage->add('<input type="hidden" id="_state" name="_state" value="'.$oStep->GetState().'"/>');
|
||||
foreach($this->aParameters as $sCode => $value)
|
||||
{
|
||||
$oPage->add('<input type="hidden" name="_params['.$sCode.']" value="'.htmlentities($value, ENT_QUOTES, 'UTF-8').'"/>');
|
||||
}
|
||||
|
||||
$oPage->add('<input type="hidden" name="_steps" value="'.htmlentities(json_encode($this->aSteps), ENT_QUOTES, 'UTF-8').'"/>');
|
||||
if (count($this->aSteps) > 0)
|
||||
{
|
||||
$oPage->add('<input type="submit" name="operation" value="back"/>');
|
||||
}
|
||||
if ($oStep->CanMoveForward())
|
||||
{
|
||||
$oPage->add('<input type="submit" name="operation" value="next"/>');
|
||||
}
|
||||
$oPage->add("</form>");
|
||||
$oPage->add('<div id="async_action" style="display:none"></div>');
|
||||
$oPage->output();
|
||||
}
|
||||
/**
|
||||
* Make the wizard run: Start, Next or Back depending on the page's parameters
|
||||
*/
|
||||
public function Run()
|
||||
{
|
||||
$sOperation = utils::ReadParam('operation');
|
||||
$this->aParameters = utils::ReadParam('_params', array(), false, 'raw_data');
|
||||
$this->aSteps = json_decode(utils::ReadParam('_steps', '[]', false, 'raw_data'), true /* bAssoc */);
|
||||
|
||||
switch($sOperation)
|
||||
{
|
||||
case 'next':
|
||||
$this->Next();
|
||||
break;
|
||||
|
||||
case 'back':
|
||||
$this->Back();
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->Start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides information about the structure/workflow of the wizard by listing
|
||||
* the possible list of 'steps' and their dependencies
|
||||
* @param string $sStep Name of the class to start from (used for recursion)
|
||||
* @param hash $aAllSteps List of steps (used for recursion)
|
||||
*/
|
||||
public function DumpStructure($sStep = '', $aAllSteps = null)
|
||||
{
|
||||
if ($aAllSteps == null) $aAllSteps = array();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return $aAllSteps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump the wizard's structure as a string suitable to produce a chart
|
||||
* using graphviz's "dot" program
|
||||
* @return string The 'dot' formatted output
|
||||
*/
|
||||
public function DumpStructureAsDot()
|
||||
{
|
||||
$aAllSteps = $this->DumpStructure();
|
||||
$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[] = $sStep;
|
||||
}
|
||||
}
|
||||
$sOutput .= "\tnode [shape = doublecircle]; ".implode(' ', $aDeadEnds).";\n";
|
||||
$sOutput .= "\tnode [shape = box];\n";
|
||||
foreach($aAllSteps as $sStep => $aNextSteps)
|
||||
{
|
||||
$oStep = new $sStep($this, '');
|
||||
$sOutput .= "\t$sStep [ label = \"".$oStep->GetTitle()."\"];\n";
|
||||
if (count($aNextSteps) > 0)
|
||||
{
|
||||
foreach($aNextSteps as $sNextStep)
|
||||
{
|
||||
$sOutput .= "\t$sStep -> $sNextStep;\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
$sOutput .= "}\n";
|
||||
return $sOutput;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract class to build "steps" for the wizard controller
|
||||
* If a step needs to maintain an internal "state" (for complex steps)
|
||||
* then it's up to the derived class to implement the behavior based on
|
||||
* the internal 'sCurrentState' variable.
|
||||
* @author Erwan Taloc <erwan.taloc@combodo.com>
|
||||
* @author Romain Quetiez <romain.quetiez@combodo.com>
|
||||
* @author Denis Flaven <denis.flaven@combodo.com>
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html GPL
|
||||
*/
|
||||
|
||||
abstract class WizardStep
|
||||
{
|
||||
/**
|
||||
* A reference to the WizardController
|
||||
* @var WizardController
|
||||
*/
|
||||
protected $oWizard;
|
||||
/**
|
||||
* Current 'state' of the wizard step. Simple 'steps' can ignore it
|
||||
* @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
|
||||
* The name of the input fields (and their id if one is supplied) MUST NOT start with "_"
|
||||
* (this is reserved for the wizard's own parameters)
|
||||
* @return void
|
||||
*/
|
||||
abstract public function Display(WebPage $oPage);
|
||||
|
||||
/**
|
||||
* Processes the page's parameters and (if moving forward) returns the next step/state to be displayed
|
||||
* @param bool $bMoveForward True if the wizard is moving forward 'Next >>' button pressed, false otherwise
|
||||
* @return hash array('class' => $sNextClass, 'state' => $sNextState)
|
||||
*/
|
||||
abstract public function ProcessParams($bMoveForward = true);
|
||||
|
||||
/**
|
||||
* Returns the list of possible steps from this step forward
|
||||
* @return array Array of strings (step classes)
|
||||
*/
|
||||
abstract public function GetPossibleSteps();
|
||||
|
||||
/**
|
||||
* Returns title of the current step
|
||||
* @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
|
||||
*/
|
||||
public function ValidateParams()
|
||||
{
|
||||
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
|
||||
*/
|
||||
public function CanMoveForward()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload this function to implement asynchronous action(s) (AJAX)
|
||||
* @param string $sCode The code of the action (if several actions need to be distinguished)
|
||||
* @param hash $aParameters The action's parameters name => value
|
||||
*/
|
||||
public function AsyncAction(WebPage $oPage, $sCode, $aParameters)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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();
|
||||
*
|
||||
class Step1 extends WizardStep
|
||||
{
|
||||
public function GetTitle()
|
||||
{
|
||||
return 'Welcome';
|
||||
}
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array('Step2', 'Step2bis');
|
||||
}
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
$sNextStep = '';
|
||||
$sInstallMode = utils::ReadParam('install_mode');
|
||||
if ($sInstallMode == 'install')
|
||||
{
|
||||
$this->oWizard->SetParameter('install_mode', 'install');
|
||||
$sNextStep = 'Step2';
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->oWizard->SetParameter('install_mode', 'upgrade');
|
||||
$sNextStep = 'Step2bis';
|
||||
|
||||
}
|
||||
return array('class' => $sNextStep, 'state' => '');
|
||||
}
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('This is Step 1!');
|
||||
$sInstallMode = $this->oWizard->GetParameter('install_mode', 'install');
|
||||
$sChecked = ($sInstallMode == 'install') ? ' checked ' : '';
|
||||
$oPage->p('<input type="radio" name="install_mode" value="install"'.$sChecked.'/> Install');
|
||||
$sChecked = ($sInstallMode == 'upgrade') ? ' checked ' : '';
|
||||
$oPage->p('<input type="radio" name="install_mode" value="upgrade"'.$sChecked.'/> Upgrade');
|
||||
}
|
||||
}
|
||||
|
||||
class Step2 extends WizardStep
|
||||
{
|
||||
public function GetTitle()
|
||||
{
|
||||
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)');
|
||||
}
|
||||
}
|
||||
|
||||
class Step2bis extends WizardStep
|
||||
{
|
||||
public function GetTitle()
|
||||
{
|
||||
return 'Upgrade Parameters';
|
||||
}
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array('Step2ter');
|
||||
}
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
$sUpgradeInfo = utils::ReadParam('upgrade_info');
|
||||
$this->oWizard->SetParameter('upgrade_info', $sUpgradeInfo);
|
||||
$sAdditionalUpgradeInfo = utils::ReadParam('additional_upgrade_info');
|
||||
$this->oWizard->SetParameter('additional_upgrade_info', $sAdditionalUpgradeInfo);
|
||||
return array('class' => 'Step2ter', 'state' => '');
|
||||
}
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('This is Step 2bis! (Upgrade)');
|
||||
$sUpgradeInfo = $this->oWizard->GetParameter('upgrade_info', '');
|
||||
$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('');
|
||||
$("input[name=additional_upgrade_info]").val("$sReply");
|
||||
EOF
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Step2ter extends WizardStep
|
||||
{
|
||||
public function GetTitle()
|
||||
{
|
||||
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)');
|
||||
}
|
||||
}
|
||||
|
||||
class Step3 extends WizardStep
|
||||
{
|
||||
public function GetTitle()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
End of the example */
|
||||
405
setup/wizardsteps.class.inc.php
Normal file
405
setup/wizardsteps.class.inc.php
Normal file
@@ -0,0 +1,405 @@
|
||||
<?php
|
||||
// Copyright (C) 2012 Combodo SARL
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 3 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
/**
|
||||
* All the steps of the iTop installation wizard
|
||||
* @author Erwan Taloc <erwan.taloc@combodo.com>
|
||||
* @author Romain Quetiez <romain.quetiez@combodo.com>
|
||||
* @author Denis Flaven <denis.flaven@combodo.com>
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html GPL
|
||||
*/
|
||||
|
||||
require_once(APPROOT.'setup/setuputils.class.inc.php');
|
||||
|
||||
/**
|
||||
* First step of the iTop Installation Wizard: Welcome screen
|
||||
*/
|
||||
class WizStepWelcome extends WizardStep
|
||||
{
|
||||
protected $bCanMoveForward;
|
||||
|
||||
public function GetTitle()
|
||||
{
|
||||
return 'Welcome';
|
||||
}
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array('WizStepInstallOrUpgrade');
|
||||
}
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
return array('class' => 'WizStepInstallOrUpgrade', 'state' => '');
|
||||
}
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('First step of the installation: check of the prerequisites');
|
||||
$aResults = SetupUtils::CheckPHPVersion($oPage);
|
||||
$this->bCanMoveForward = true;
|
||||
foreach($aResults as $oCheckResult)
|
||||
{
|
||||
switch($oCheckResult->iSeverity)
|
||||
{
|
||||
case CheckResult::ERROR:
|
||||
$this->bCanMoveForward = false;
|
||||
$oPage->error($oCheckResult->sLabel);
|
||||
break;
|
||||
|
||||
case CheckResult::WARNING:
|
||||
$oPage->warning($oCheckResult->sLabel);
|
||||
break;
|
||||
|
||||
case CheckResult::INFO:
|
||||
$oPage->ok($oCheckResult->sLabel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function CanMoveForward()
|
||||
{
|
||||
return $this->bCanMoveForward;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Second step of the iTop Installation Wizard: Install or Upgrade
|
||||
*/
|
||||
class WizStepInstallOrUpgrade extends WizardStep
|
||||
{
|
||||
public function GetTitle()
|
||||
{
|
||||
return 'Install or Upgrade choice';
|
||||
}
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array('WizStepDetectedInfo', 'WizStepLicense');
|
||||
}
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
$sNextStep = '';
|
||||
$sInstallMode = utils::ReadParam('install_mode');
|
||||
if ($sInstallMode == 'install')
|
||||
{
|
||||
$this->oWizard->SetParameter('install_mode', 'install');
|
||||
$sNextStep = 'WizStepLicense';
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->oWizard->SetParameter('install_mode', 'upgrade');
|
||||
$sNextStep = 'WizStepDetectedInfo';
|
||||
|
||||
}
|
||||
return array('class' => $sNextStep, 'state' => '');
|
||||
}
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('What do you want to do?');
|
||||
$sInstallMode = $this->oWizard->GetParameter('install_mode', 'install');
|
||||
$sChecked = ($sInstallMode == 'install') ? ' checked ' : '';
|
||||
$oPage->p('<input type="radio" name="install_mode" value="install"'.$sChecked.'/> Install a new iTop');
|
||||
$sChecked = ($sInstallMode == 'upgrade') ? ' checked ' : '';
|
||||
$oPage->p('<input type="radio" name="install_mode" value="upgrade"'.$sChecked.'/> Upgrade an existing iTop');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upgrade information
|
||||
*/
|
||||
class WizStepDetectedInfo extends WizardStep
|
||||
{
|
||||
public function GetTitle()
|
||||
{
|
||||
return 'Detected Info';
|
||||
}
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array('WizStepUpgradeKeep', 'WizStepUpgradeAuto', 'WizStepLicense2');
|
||||
}
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
|
||||
return array('class' => 'WizStepUpgradeAuto', 'state' => '');
|
||||
}
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('Info about the detected version');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep or Upgrade choice
|
||||
*/
|
||||
class WizStepUpgradeKeep extends WizardStep
|
||||
{
|
||||
public function GetTitle()
|
||||
{
|
||||
return 'Keep or Upgrade';
|
||||
}
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array('WizStepModulesChoice');
|
||||
}
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
|
||||
return array('class' => 'WizStepModulesChoice', 'state' => 'start_upgrade');
|
||||
}
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('Keep or Upgrade the data model');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatic Upgrade info
|
||||
*/
|
||||
class WizStepUpgradeAuto extends WizardStep
|
||||
{
|
||||
public function GetTitle()
|
||||
{
|
||||
return 'Upgrade Information';
|
||||
}
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array('WizStepModulesChoice');
|
||||
}
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
|
||||
return array('class' => 'WizStepModulesChoice', 'state' => 'start_upgrade');
|
||||
}
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('Automatic Upgrade information');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* License acceptation screen
|
||||
*/
|
||||
class WizStepLicense extends WizardStep
|
||||
{
|
||||
public function GetTitle()
|
||||
{
|
||||
return 'License Agreement';
|
||||
}
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array('WizStepDBParams');
|
||||
}
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
return array('class' => 'WizStepDBParams', 'state' => '');
|
||||
}
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('Do you accept ALL the licenses?');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* License acceptation screen (when upgrading)
|
||||
*/
|
||||
class WizStepLicense2 extends WizStepLicense
|
||||
{
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array('WizStepUpgradeKeep', 'WizStepUpgradeAuto');
|
||||
}
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
return array('class' => 'WizStepUpgradeAuto', 'state' => '');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Database Connection parameters screen
|
||||
*/
|
||||
class WizStepDBParams extends WizardStep
|
||||
{
|
||||
public function GetTitle()
|
||||
{
|
||||
return 'Database Configuration';
|
||||
}
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array('WizStepAdminAccount');
|
||||
}
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
return array('class' => 'WizStepAdminAccount', 'state' => '');
|
||||
}
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('Please enter the DB parameters');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Administrator Account definition screen
|
||||
*/
|
||||
class WizStepAdminAccount extends WizardStep
|
||||
{
|
||||
public function GetTitle()
|
||||
{
|
||||
return 'Administrator Account';
|
||||
}
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array('WizStepMiscParams');
|
||||
}
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
return array('class' => 'WizStepMiscParams', 'state' => '');
|
||||
}
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('Please enter Admin Account name/pwd');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Miscellaneous Parameters (URL, Sample Data)
|
||||
*/
|
||||
class WizStepMiscParams extends WizardStep
|
||||
{
|
||||
public function GetTitle()
|
||||
{
|
||||
return 'Miscellaneous Parameters';
|
||||
}
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array('WizStepModulesChoice');
|
||||
}
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
return array('class' => 'WizStepModulesChoice', 'state' => 'start_install');
|
||||
}
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('Additional Parameters (URl, Sample Data)');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Choice of the modules to be installed
|
||||
*/
|
||||
class WizStepModulesChoice extends WizardStep
|
||||
{
|
||||
public function GetTitle()
|
||||
{
|
||||
return 'Modules Selection';
|
||||
}
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array('WizStepSummary');
|
||||
}
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
return array('class' => 'WizStepSummary', 'state' => '');
|
||||
}
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('Select the modules to install/upgrade.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Summary of the installation tasks
|
||||
*/
|
||||
class WizStepSummary extends WizardStep
|
||||
{
|
||||
public function GetTitle()
|
||||
{
|
||||
return 'Installation summary';
|
||||
}
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array('WizStepDone');
|
||||
}
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
return array('class' => 'WizStepDone', 'state' => '');
|
||||
}
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('Summary of the installation.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Summary of the installation tasks
|
||||
*/
|
||||
class WizStepDone extends WizardStep
|
||||
{
|
||||
public function GetTitle()
|
||||
{
|
||||
return 'Done';
|
||||
}
|
||||
|
||||
public function GetPossibleSteps()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function ProcessParams($bMoveForward = true)
|
||||
{
|
||||
return array('class' => '', 'state' => '');
|
||||
}
|
||||
|
||||
public function Display(WebPage $oPage)
|
||||
{
|
||||
$oPage->p('Installation Completed.');
|
||||
}
|
||||
|
||||
public function CanMoveForward()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user