/**
* All the steps of the iTop installation wizard
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
require_once(APPROOT.'setup/setuputils.class.inc.php');
require_once(APPROOT.'setup/parameters.class.inc.php');
require_once(APPROOT.'setup/applicationinstaller.class.inc.php');
require_once(APPROOT.'setup/parameters.class.inc.php');
/**
* First step of the iTop Installation Wizard: Welcome screen
*/
class WizStepWelcome extends WizardStep
{
protected $bCanMoveForward;
public function GetTitle()
{
return 'Welcome to '.ITOP_APPLICATION.' version '.ITOP_VERSION;
}
/**
* Returns the label for the " Next >> " button
* @return string The label for the button
*/
public function GetNextButtonLabel()
{
return ' Continue >> ';
}
public function GetPossibleSteps()
{
return array('WizStepInstallOrUpgrade');
}
public function ProcessParams($bMoveForward = true)
{
return array('class' => 'WizStepInstallOrUpgrade', 'state' => '');
}
public function Display(WebPage $oPage)
{
// Store the misc_options for the future...
$aMiscOptions = utils::ReadParam('option', array(), false, 'raw_data');
$sMiscOptions = $this->oWizard->GetParameter('misc_options', json_encode($aMiscOptions));
$this->oWizard->SetParameter('misc_options', $sMiscOptions);
$oPage->add('
');
foreach($aErrors as $sText)
{
$oPage->error($sText);
}
foreach($aWarnings as $sText)
{
$oPage->warning($sText);
}
foreach($aInfo as $sText)
{
$oPage->ok($sText);
}
$oPage->add('
');
if (!$this->bCanMoveForward)
{
$oPage->p('Sorry, the installation cannot continue. Please fix the errors and reload this page to launch the installation again.');
}
}
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');
$this->oWizard->SaveParameter('previous_version_dir', '');
$this->oWizard->SaveParameter('db_server', '');
$this->oWizard->SaveParameter('db_user', '');
$this->oWizard->SaveParameter('db_pwd', '');
$this->oWizard->SaveParameter('db_name', '');
$this->oWizard->SaveParameter('db_prefix', '');
$this->oWizard->SaveParameter('db_backup', false);
$this->oWizard->SaveParameter('db_backup_path', '');
if ($sInstallMode == 'install')
{
$this->oWizard->SetParameter('install_mode', 'install');
$sFullSourceDir = SetupUtils::GetLatestDataModelDir();
$this->oWizard->SetParameter('source_dir', $sFullSourceDir);
$this->oWizard->SetParameter('datamodel_version', SetupUtils::GetDataModelVersion($sFullSourceDir));
$sNextStep = 'WizStepLicense';
}
else
{
$this->oWizard->SetParameter('install_mode', 'upgrade');
$sNextStep = 'WizStepDetectedInfo';
}
return array('class' => $sNextStep, 'state' => '');
}
public function Display(WebPage $oPage)
{
$sInstallMode = $this->oWizard->GetParameter('install_mode', '');
$sDBServer = $this->oWizard->GetParameter('db_server', '');
$sDBUser = $this->oWizard->GetParameter('db_user', '');
$sDBPwd = $this->oWizard->GetParameter('db_pwd', '');
$sDBName = $this->oWizard->GetParameter('db_name', '');
$sDBPrefix = $this->oWizard->GetParameter('db_prefix', '');
$bDBBackup = $this->oWizard->GetParameter('db_backup', false);
$sDBBackupPath = $this->oWizard->GetParameter('db_backup_path', '');
$sPreviousVersionDir = '';
if ($sInstallMode == '')
{
$sDBBackupPath = APPROOT.'data/'.ITOP_APPLICATION.strftime('-backup-%Y-%m-%d.zip');
$bDBBackup = true;
$aPreviousInstance = SetupUtils::GetPreviousInstance(APPROOT);
if ($aPreviousInstance['found'])
{
$sInstallMode = 'upgrade';
$sSourceDir = APPROOT;
$sDBServer = $aPreviousInstance['db_server'];
$sDBUser = $aPreviousInstance['db_user'];
$sDBPwd = $aPreviousInstance['db_pwd'];
$sDBName = $aPreviousInstance['db_name'];
$sDBPrefix = $aPreviousInstance['db_prefix'];
$sStyle = '';
$sPreviousVersionDir = APPROOT;
}
else
{
$sInstallMode = 'install';
}
}
$sPreviousVersionDir = $this->oWizard->GetParameter('previous_version_dir', $sPreviousVersionDir);
$sUpgradeInfoStyle = '';
if ($sInstallMode == 'install')
{
$sUpgradeInfoStyle = ' style="display: none;" ';
}
$oPage->add('
What do you want to do?
');
$sChecked = ($sInstallMode == 'install') ? ' checked ' : '';
$oPage->p('');
$sChecked = ($sInstallMode == 'upgrade') ? ' checked ' : '';
$oPage->p('');
//$oPage->add('');
$oPage->add_ready_script(
<<add_ready_script(
<<add_ready_script(
<<add_ready_script(
<<oWizard->SetParameter('mode', 'upgrade');
$this->oWizard->SetParameter('upgrade_type', $sUpgradeType);
$this->oWizard->SaveParameter('copy_extensions_from', '');
$bDisplayLicense = $this->oWizard->GetParameter('display_license');
switch ($sUpgradeType)
{
case 'keep-previous':
$sSourceDir = utils::ReadParam('relative_source_dir', '', false, 'raw_data');
$this->oWizard->SetParameter('source_dir', $this->oWizard->GetParameter('previous_version_dir').'/'.$sSourceDir);
$this->oWizard->SetParameter('datamodel_version', utils::ReadParam('datamodel_previous_version', '', false, 'raw_data'));
break;
case 'use-compatible':
$sDataModelPath = utils::ReadParam('datamodel_path', '', false, 'raw_data');
$this->oWizard->SetParameter('source_dir', $sDataModelPath);
$this->oWizard->SaveParameter('datamodel_version', '');
break;
default:
// Do nothing, maybe the user pressed the Back button
}
if ($bDisplayLicense)
{
$aRet = array('class' => 'WizStepLicense2', 'state' => '');
}
else
{
$aRet = array('class' => 'WizStepUpgradeMiscParams', 'state' => '');
}
return $aRet;
}
public function Display(WebPage $oPage)
{
$oPage->add_style(
<<bCanMoveForward = true;
$bDisplayLicense = true;
$sPreviousVersionDir = $this->oWizard->GetParameter('previous_version_dir', '');
$aInstalledInfo = SetupUtils::GetApplicationVersion($this->oWizard);
if ($aInstalledInfo === false)
{
throw(new Exception('No previous version of '.ITOP_APPLICATION.' found in the supplied database. The upgrade cannot continue.'));
}
else if (strcasecmp($aInstalledInfo['product_name'], ITOP_APPLICATION) != 0)
{
$oPage->p("Warning: The installed products seem different. Are you sure the you want to upgrade {$aInstalledInfo['product_name']} with ".ITOP_APPLICATION."?");
}
$sInstalledVersion = $aInstalledInfo['product_version'];
$sInstalledDataModelVersion = $aInstalledInfo['datamodel_version'];
$oPage->add("
Information about the upgrade from version $sInstalledVersion to ".ITOP_VERSION.'.'.ITOP_REVISION."
");
if ($sInstalledVersion == (ITOP_VERSION.'.'.ITOP_REVISION))
{
// Reinstalling the same version let's skip the license agreement...
$bDisplayLicense = false;
}
$this->oWizard->SetParameter('license', $bDisplayLicense); // Remember for later
if ($sInstalledDataModelVersion == '$ITOP_VERSION$.$WCREV$')
{
// Special case for upgrading some development versions (temporary)
$sCompatibleDMDir = SetupUtils::GetLatestDataModelDir();
$sInstalledDataModelVersion = SetupUtils::GetDataModelVersion($sLatestDMDir);
}
else
{
$sCompatibleDMDir = SetupUtils::GetCompatibleDataModelDir($sInstalledDataModelVersion);
}
if ($sCompatibleDMDir === false)
{
// No compatible version exists... cannot upgrade. Either it is too old, or too new (downgrade !)
$this->bCanMoveForward = false;
$oPage->p("The current version of ".ITOP_APPLICATION." (".ITOP_VERSION.'.'.ITOP_REVISION.") does not seem to be compatible with the installed version ($sInstalledVersion).");
$oPage->p("The upgrade cannot continue, sorry.");
}
else
{
$sUpgradeDMVersion = SetupUtils::GetDataModelVersion($sCompatibleDMDir);
$sPreviousSourceDir = isset($aInstalledInfo['source_dir']) ? $aInstalledInfo['source_dir'] : 'modules';
$aChanges = false;
if (is_dir($sPreviousVersionDir))
{
// Check if the previous version is a "genuine" one or not...
$aChanges = SetupUtils::CheckVersion($sInstalledDataModelVersion, $sPreviousVersionDir.'/'.$sPreviousSourceDir);
}
if (($aChanges !== false) && ( (count($aChanges['added']) > 0) || (count($aChanges['removed']) > 0) || (count($aChanges['modified']) > 0)) )
{
// Some changes were detected, prompt the user to keep or discard them
$oPage->p(" Some modifications were detected between the ".ITOP_APPLICATION." version in '$sPreviousVersionDir' and a genuine $sInstalledVersion version.");
$oPage->p("What do you want to do?");
$aWritableDirs = array('modules', 'portal');
$aErrors = SetupUtils::CheckWritableDirs($aWritableDirs);
$sChecked = ($this->oWizard->GetParameter('upgrade_type') == 'keep-previous') ? ' checked ' : '';
$sDisabled = (count($aErrors) > 0) ? ' disabled ' : '';
$oPage->p('');
$oPage->add('');
$oPage->add('');
if (count($aErrors) > 0)
{
$oPage->p("Cannot copy the installed version due to the following access rights issue(s):");
foreach($aErrors as $sDir => $oCheckResult)
{
$oPage->p(' '.$oCheckResult->sLabel);
}
}
$sChecked = ($this->oWizard->GetParameter('upgrade_type') == 'use-compatible') ? ' checked ' : '';
$oPage->p('');
$oPage->add('');
$oPage->add('');
$oPage->add('
Details of the modifications
');
if (count($aChanges['added']) > 0)
{
$oPage->add('
New files added:');
foreach($aChanges['added'] as $sFilePath => $void)
{
$oPage->add('
'.$sFilePath.'
');
}
$oPage->add('
');
}
if (count($aChanges['removed']) > 0)
{
$oPage->add('
Deleted files:');
foreach($aChanges['removed'] as $sFilePath => $void)
{
$oPage->add('
'.$sFilePath.'
');
}
$oPage->add('
');
}
if (count($aChanges['modified']) > 0)
{
$oPage->add('
Modified files:');
foreach($aChanges['modified'] as $sFilePath => $void)
{
$oPage->add('
'.$sFilePath.'
');
}
$oPage->add('
');
}
$oPage->add('
');
}
else
{
// No changes detected... or no way to tell because of the lack of a manifest or previous source dir
// Use the "compatible" datamodel as-is.
$oPage->p(" The datamodel will be upgraded from version $sInstalledDataModelVersion to version $sUpgradeDMVersion.");
$oPage->add('');
$oPage->add('');
$oPage->add('');
}
// Check if there are "extensions" to preserve and if it's possible
if (is_dir($sPreviousVersionDir.'/extensions'))
{
$aExtensions = glob($sPreviousVersionDir.'/extensions/*', GLOB_ONLYDIR);
if (($aExtensions !== false) && (count($aExtensions)>0) && (realpath($sPreviousVersionDir.'/extensions') != realpath(APPROOT.'extensions')) )
{
$aWritableDirs = array('extensions');
$aErrors = SetupUtils::CheckWritableDirs($aWritableDirs);
if (count($aErrors) > 0)
{
$oPage->p("Cannot copy the extensions from '$sPreviousVersionDir/extensions' to '".APPROOT."extensions' due to the following access rights issue(s):");
foreach($aErrors as $sDir => $oCheckResult)
{
$oPage->p(' '.$oCheckResult->sLabel);
}
}
else
{
$oPage->p("Note: The extensions present in '$sPreviousVersionDir/extensions' will be copied to '".APPROOT."extensions'.");
$oPage->add('');
}
}
}
$oPage->add_ready_script(
<<bCanMoveForward;
}
/**
* Tells whether the "Next" button should be enabled interactively
* @return string A piece of javascript code returning either true or false
*/
public function JSCanMoveForward()
{
return
<< 0);
return bRet;
EOF
;
}
}
/**
* License acceptation screen
*/
class WizStepLicense extends WizardStep
{
public function GetTitle()
{
return 'License Agreement';
}
public function GetPossibleSteps()
{
return array('WizStepDBParams');
}
public function ProcessParams($bMoveForward = true)
{
$this->oWizard->SaveParameter('accept_license', 'no');
return array('class' => 'WizStepDBParams', 'state' => '');
}
public function Display(WebPage $oPage)
{
$aLicenses = array();
foreach (glob(APPROOT.'setup/licenses/*.xml') as $sFile)
{
$oXml = simplexml_load_file($sFile);
foreach($oXml->license as $oLicense)
{
$aLicenses[] = $oLicense;
}
}
$oPage->add('
Licenses agreements for the components of '.ITOP_APPLICATION.'
');
$oPage->add_style('div a.no-arrow { background:transparent; padding-left:0;}');
$oPage->add_style('.toggle { cursor:pointer; text-decoration:underline; color:#1C94C4; }');
$oPage->add('');
$sChecked = ($this->oWizard->GetParameter('accept_license', 'no') == 'yes') ? ' checked ' : '';
$oPage->p('');
$oPage->add_ready_script('$("#accept").bind("click change", function() { WizardUpdateButtons(); });');
}
/**
* Tells whether the "Next" button should be enabled interactively
* @return string A piece of javascript code returning either true or false
*/
public function JSCanMoveForward()
{
return 'return ($("#accept").attr("checked") === "checked");';
}
}
/**
* License acceptation screen (when upgrading)
*/
class WizStepLicense2 extends WizStepLicense
{
public function GetPossibleSteps()
{
return array('WizStepUpgradeMiscParams');
}
public function ProcessParams($bMoveForward = true)
{
return array('class' => 'WizStepUpgradeMiscParams', '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)
{
$this->oWizard->SaveParameter('db_server', '');
$this->oWizard->SaveParameter('db_user', '');
$this->oWizard->SaveParameter('db_pwd', '');
$this->oWizard->SaveParameter('db_name', '');
$this->oWizard->SaveParameter('db_prefix', '');
$this->oWizard->SaveParameter('new_db_name', '');
$this->oWizard->SaveParameter('create_db', '');
$this->oWizard->SaveParameter('db_new_name', '');
return array('class' => 'WizStepAdminAccount', 'state' => '');
}
public function Display(WebPage $oPage)
{
$oPage->add('
');
$oPage->add_script(
<<add_ready_script(
<< $aChoice)
{
$sChoiceId = $sParentId.self::$SEP.$index;
if (!$this->bUpgrade && isset($aChoice['default']) && $aChoice['default'])
{
$aDefaults[$sChoiceId] = $sChoiceId;
}
if ($this->bUpgrade)
{
// In upgrade mode, the defaults are the installed modules
foreach($aChoice['modules'] as $sModuleId)
{
if ($aModules[$sModuleId]['version_db'] != '')
{
// A module corresponding to this choice is installed, the whole choice is selected
$aDefaults[$sChoiceId] = $sChoiceId;
$iScore = 99; // The whole parent choice is selected
break;
}
}
}
if (isset($aChoice['sub_options']))
{
$aScores[$sChoiceId] = $this->GetDefaults($aChoice['sub_options'], $aDefaults, $sChoiceId);
}
$index++;
}
$aAlternatives = isset($aInfo['alternatives']) ? $aInfo['alternatives'] : array();
$sChoiceName = null;
$aScores = array();
$sChoiceIdNone = null;
foreach($aAlternatives as $index => $aChoice)
{
$sChoiceId = $sParentId.self::$SEP.$index;
if ($sChoiceName == null)
{
$sChoiceName = $sChoiceId;
}
if (!$this->bUpgrade && isset($aChoice['default']) && $aChoice['default'])
{
$aDefaults[$sChoiceName] = $sChoiceId;
}
if (isset($aChoice['sub_options']))
{
$aScores[$sChoiceId] = $this->GetDefaults($aChoice['sub_options'], $aDefaults, $aModules, $sChoiceId);
}
$index++;
}
$iMaxScore = 0;
if ($this->bUpgrade && (count($aAlternatives) > 0))
{
// The installed choices have precedence over the 'default' choices
// In case several choices share the same base modules, let's weight the alternative choices
// based on their number of installed modules
$sChoiceName = null;
foreach($aAlternatives as $index => $aChoice)
{
$sChoiceId = $sParentId.self::$SEP.$index;
if ($sChoiceName == null)
{
$sChoiceName = $sChoiceId;
}
$aScores[$sChoiceId] = 0;
if (array_key_exists('modules', $aChoice))
{
foreach($aChoice['modules'] as $sModuleId)
{
if ($aModules[$sModuleId]['version_db'] != '')
{
// A module corresponding to this choice is installed, increase the score of this choice
if (!isset($aScores[$sChoiceId])) $aScores[$sChoiceId] = 0;
$aScores[$sChoiceId]++;
$iMaxScore = max($iMaxScore, $aScores[$sChoiceId]);
$iScore = 99; // The whole parent choice is selected
}
}
}
}
}
if ($iMaxScore > 0)
{
//echo "Scores:
".print_r($aScores, true)."
";
// The choice with the bigger score wins !
asort($aScores, SORT_NUMERIC);
$aKeys = array_keys($aScores);
$sBetterChoiceId = array_pop($aKeys);
$aDefaults[$sChoiceName] = $sBetterChoiceId;
}
return $iScore;
}
/**
* Converts the list of selected "choices" into a list of "modules": take into account the selected and the mandatory modules
* @param hash $aInfo Info about the "choice" array('options' => array(...), 'alternatives' => array(...))
* @param hash $aSelectedChoices List of selected choices array('name' => 'selected_value_id')
* @param hash $aModules Return parameter: List of selected modules array('module_id' => true)
* @param string $sParentId Used for recursion
* @return void
*/
protected function GetSelectedModules($aInfo, $aSelectedChoices, &$aModules, $sParentId = '', $sDisplayChoices = '')
{
if ($sParentId == '')
{
// Check once (before recursing) that the hidden modules are selected
foreach(SetupUtils::AnalyzeInstallation($this->oWizard) as $sModuleId => $aModule)
{
if ($sModuleId != ROOT_MODULE)
{
if (($aModule['category'] == 'authentication') || (!$aModule['visible']))
{
$aModules[$sModuleId] = true;
}
}
}
}
$aOptions = isset($aInfo['options']) ? $aInfo['options'] : array();
foreach($aOptions as $index => $aChoice)
{
$sChoiceId = $sParentId.self::$SEP.$index;
if ( (isset($aChoice['mandatory']) && $aChoice['mandatory']) ||
(isset($aSelectedChoices[$sChoiceId]) && ($aSelectedChoices[$sChoiceId] == $sChoiceId)) )
{
$sDisplayChoices .= '
'.$aChoice['title'].'
';
if (isset($aChoice['modules']))
{
foreach($aChoice['modules'] as $sModuleId)
{
$aModules[$sModuleId] = true; // store the Id of the selected module
}
}
// Recurse only for selected choices
if (isset($aChoice['sub_options']))
{
$sDisplayChoices .= '
';
if (isset($aChoice['modules']))
{
foreach($aChoice['modules'] as $sModuleId)
{
$aModules[$sModuleId] = true; // store the Id of the selected module
}
}
// Recurse only for selected choices
if (isset($aChoice['sub_options']))
{
$sDisplayChoices .= '
';
}
$sDisplayChoices .= '';
}
$index++;
}
if ($sParentId == '')
{
// Last pass (after all the user's choices are turned into "selected" modules):
// Process 'auto_select' modules for modules that are not already selected
$aAvailableModules = SetupUtils::AnalyzeInstallation($this->oWizard);
do
{
// Loop while new modules are added...
$bModuleAdded = false;
foreach($aAvailableModules as $sModuleId => $aModule)
{
if (($sModuleId != ROOT_MODULE) && !array_key_exists($sModuleId, $aModules) && isset($aModule['auto_select']))
{
try
{
$bSelected = false;
SetupInfo::SetSelectedModules($aModules);
eval('$bSelected = ('.$aModule['auto_select'].');');
}
catch(Exception $e)
{
$sDisplayChoices .= '
Warning: auto_select failed with exception ('.$e->getMessage().') for module "'.$sModuleId.'"
';
$bSelected = false;
}
if ($bSelected)
{
$aModules[$sModuleId] = true; // store the Id of the selected module
$bModuleAdded = true;
}
}
}
}
while($bModuleAdded);
}
return $sDisplayChoices;
}
protected function GetStepIndex()
{
switch($this->sCurrentState)
{
case 'start_install':
case 'start_upgrade':
$index = 0;
break;
default:
$index = (integer)$this->sCurrentState;
}
return $index;
}
protected function GetStepInfo($idx = null)
{
$aStepInfo = null;
if ($idx === null)
{
$index = $this->GetStepIndex();
}
else
{
$index = $idx;
}
$aSteps = array();
if (@file_exists($this->GetSourceFilePath()))
{
$aParams = new XMLParameters($this->GetSourceFilePath());
$aSteps = $aParams->Get('steps', array());
$bAddExtensionsOnly = true;
}
else
{
// No wizard configuration provided, build a standard one:
$bAddExtensionsOnly = false;
$aSteps[] = array(
'title' => 'Modules Selection',
'description' => '
Select the modules to install. You can launch the installation again to install new modules, but you cannot remove already installed modules.
Select additional extensions to install. You can launch the installation again to install new extensions, but you cannot remove already installed extensions.
',
'banner' => '/images/extension.png',
'options' => array()
);
try
{
$sDefaultAppPath = utils::GetDefaultUrlAppRoot();
}
catch(Exception $e)
{
$sDefaultAppPath = '..';
}
$aAvailableModules = SetupUtils::AnalyzeInstallation($this->oWizard);
foreach($aAvailableModules as $sModuleId => $aModule)
{
if ($sModuleId == ROOT_MODULE) continue; // Convention: the version number of the application (and datamodel) are stored as a module named ROOT_MODULE
$sModuleLabel = $aModule['label'];
$sModuleHelp = $aModule['doc.more_information'];
$sMoreInfo = (!empty($aModule['doc.more_information'])) ? "more info": '';
if (($aModule['category'] != 'authentication') && ($aModule['visible']))
{
if (($bAddExtensionsOnly) && (!$this->IsExtension($aModule))) continue;
if ($this->IsExtension($aModule))
{
$iStepIndex = count($aSteps) - 1;
}
else
{
$iStepIndex = 0;
}
$aSteps[$iStepIndex]['options'][] = array(
'title' => $sModuleLabel,
'description' => '',
'more_info' => $sMoreInfo,
'default' => true, // by default offer to install all modules
'modules' => array($sModuleId),
'mandatory' => ($aModule['install']['flag'] & MODULE_ACTION_MANDATORY) ? true : false,
);
}
}
if (count($aSteps[count($aSteps) - 1]['options']) == 0)
{
// No extensions at all, remove the last step
array_pop($aSteps);
}
if (array_key_exists($index, $aSteps))
{
$aStepInfo = $aSteps[$index];
}
return $aStepInfo;
}
protected function GetExtensionsStepInfo()
{
// let the user select from the list of modules located in the "extensions" folder
}
protected function IsExtension($aModule)
{
// root_dir is the directory containing the module, check if its parent is "extensions"
if (basename(dirname($aModule['root_dir'])) == 'extensions')
{
return true;
}
return false;
}
protected function DisplayOptions($oPage, $aStepInfo, $aSelectedComponents, $aDefaults, $sParentId = '')
{
$aOptions = isset($aStepInfo['options']) ? $aStepInfo['options'] : array();
$aAlternatives = isset($aStepInfo['alternatives']) ? $aStepInfo['alternatives'] : array();
$index = 0;
foreach($aOptions as $index => $aChoice)
{
$sAttributes = '';
$sChoiceId = $sParentId.self::$SEP.$index;
$bIsDefault = array_key_exists($sChoiceId, $aDefaults);
$bSelected = isset($aSelectedComponents[$sChoiceId]) && ($aSelectedComponents[$sChoiceId] == $sChoiceId);
$bMandatory = (isset($aChoice['mandatory']) && $aChoice['mandatory']) || ($this->bUpgrade && $bIsDefault);
if ($bMandatory)
{
$oPage->add('
');
}
protected function GetSourceFilePath()
{
$sSourceDir = $this->oWizard->GetParameter('source_dir');
return $sSourceDir.'/installation.xml';
}
}
/**
* Summary of the installation tasks
*/
class WizStepSummary extends WizardStep
{
public function GetTitle()
{
$sMode = $this->oWizard->GetParameter('mode', 'install');
if ($sMode == 'install')
{
return 'Ready to install';
}
else
{
return 'Ready to upgrade';
}
}
public function GetPossibleSteps()
{
return array('WizStepDone');
}
/**
* Returns the label for the " Next >> " button
* @return string The label for the button
*/
public function GetNextButtonLabel()
{
return ' Install ! ';
}
public function ProcessParams($bMoveForward = true)
{
return array('class' => 'WizStepDone', 'state' => '');
}
public function Display(WebPage $oPage)
{
$oPage->add_style(
<<BuildConfig();
$sMode = $aInstallParams['mode'];
$sPreinstallationPhase = '';
$sDestination = ITOP_APPLICATION.(($sMode == 'install') ? ' version '.ITOP_VERSION.' is about to be installed ' : ' is about to be upgraded ');
$sDBDescription = ' existing database '.$aInstallParams['database']['name'].'';
if (($sMode == 'install') && ($this->oWizard->GetParameter('create_db') == 'yes'))
{
$sDBDescription = ' new database '.$aInstallParams['database']['name'].'';
}
$sDestination .= 'into the '.$sDBDescription.' on the server '.$aInstallParams['database']['server'].'.';
$oPage->add('
'.$sDestination.'
');
$oPage->add('');
$oPage->add('');
$sJSONData = json_encode($aInstallParams);
$oPage->add('');
$oPage->add_ready_script(
<<oWizard->GetParameter('install_mode', 'install');
$aSelectedModules = json_decode($this->oWizard->GetParameter('selected_modules'), true);
$sBackupDestination = '';
$sPreviousConfigurationFile = '';
$sDBName = $this->oWizard->GetParameter('db_name');
if ($sMode == 'upgrade')
{
$sPreviousVersionDir = $this->oWizard->GetParameter('previous_version_dir', '');
if (!empty($sPreviousVersionDir))
{
$aPreviousInstance = SetupUtils::GetPreviousInstance($sPreviousVersionDir);
if ($aPreviousInstance['found'])
{
$sPreviousConfigurationFile = $aPreviousInstance['configuration_file'];
}
}
if ($this->oWizard->GetParameter('db_backup', false))
{
$sBackupDestination = $this->oWizard->GetParameter('db_backup_path', '');
}
}
else
{
$sDBNewName = $this->oWizard->GetParameter('db_new_name', '');
if ($sDBNewName != '')
{
$sDBName = $sDBNewName; // Database will be created
}
}
$sSourceDir = $this->oWizard->GetParameter('source_dir');
$aCopies = array();
if (($sMode == 'upgrade') && ($this->oWizard->GetParameter('upgrade_type') == 'keep-previous'))
{
$sPreviousVersionDir = $this->oWizard->GetParameter('previous_version_dir');
$aCopies[] = array('source' => $sSourceDir, 'destination' => 'modules'); // Source is an absolute path, destination is relative to APPROOT
$aCopies[] = array('source' => $sPreviousVersionDir.'/portal', 'destination' => 'portal'); // Source is an absolute path, destination is relative to APPROOT
$sSourceDir = APPROOT.'modules';
}
if (($sMode == 'upgrade'))
{
// Copy the previous extensions, if any
$sPreviousExtensionsDir = $this->oWizard->GetParameter('copy_extensions_from');
if (is_dir($sPreviousExtensionsDir))
{
// Copy the extensions one by one to merge them with the existing extensions in /extensions
$aExtensions = glob($sPreviousExtensionsDir.'/*', GLOB_ONLYDIR);
foreach($aExtensions as $sDirPath)
{
$sExtName = basename($sDirPath);
$aCopies[] = array('source' => $sDirPath, 'destination' => 'extensions/'.$sExtName); // Source is an absolute path, destination is relative to APPROOT
}
}
}
$aInstallParams = array (
'mode' => $sMode,
'preinstall' => array (
'copies' => $aCopies,
// 'backup' => see below
),
'source_dir' => str_replace(APPROOT, '', $sSourceDir),
'datamodel_version' => $this->oWizard->GetParameter('datamodel_version'), //TODO: let the installer compute this automatically...
'previous_configuration_file' => $sPreviousConfigurationFile,
'extensions_dir' => 'extensions',
'target_env' => 'production',
'workspace_dir' => '',
'database' => array (
'server' => $this->oWizard->GetParameter('db_server'),
'user' => $this->oWizard->GetParameter('db_user'),
'pwd' => $this->oWizard->GetParameter('db_pwd'),
'name' => $sDBName,
'prefix' => $this->oWizard->GetParameter('db_prefix'),
),
'url' => $this->oWizard->GetParameter('application_url'),
'admin_account' => array (
'user' => $this->oWizard->GetParameter('admin_user'),
'pwd' => $this->oWizard->GetParameter('admin_pwd'),
'language' => $this->oWizard->GetParameter('admin_language'),
),
'language' => $this->oWizard->GetParameter('default_language'),
'selected_modules' => $aSelectedModules,
'sample_data' => ($this->oWizard->GetParameter('sample_data', '') == 'yes') ? true : false ,
'old_addon' => $this->oWizard->GetParameter('old_addon', false), // whether or not to use the "old" userrights profile addon
'options' => json_decode($this->oWizard->GetParameter('misc_options', '[]'), true),
);
if ($sBackupDestination != '')
{
$aInstallParams['preinstall']['backup'] = array (
'destination' => $sBackupDestination,
'configuration_file' => $sPreviousConfigurationFile,
);
}
return $aInstallParams;
}
public function AsyncAction(WebPage $oPage, $sCode, $aParameters)
{
$oParameters = new PHPParameters();
$sStep = $aParameters['installer_step'];
$sJSONParameters = $aParameters['installer_config'];
$oParameters->LoadFromHash(json_decode($sJSONParameters, true /* bAssoc */));
$oInstaller = new ApplicationInstaller($oParameters);
$aRes = $oInstaller->ExecuteStep($sStep);
if (($aRes['status'] != ApplicationInstaller::ERROR) && ($aRes['next-step'] != ''))
{
// Tell the web page to move the progress bar and to launch the next step
$sMessage = addslashes(htmlentities($aRes['next-step-label'], ENT_QUOTES, 'UTF-8'));
$oPage->add_ready_script(
<<{$aRes['next-step-label']}');
ExecuteStep('{$aRes['next-step']}');
EOF
);
}
else if ($aRes['status'] != ApplicationInstaller::ERROR)
{
// Installation complete, move to the next step of the wizard
$oPage->add_ready_script(
<<add_ready_script(
<< '', 'state' => '');
}
public function Display(WebPage $oPage)
{
// Check if there are some manual steps required:
$aManualSteps = array();
$aAvailableModules = SetupUtils::AnalyzeInstallation($this->oWizard);
$sRootUrl = utils::GetAbsoluteUrlAppRoot();
$aSelectedModules = json_decode($this->oWizard->GetParameter('selected_modules'), true);
foreach($aSelectedModules as $sModuleId)
{
if (!empty($aAvailableModules[$sModuleId]['doc.manual_setup']))
{
$aManualSteps[$aAvailableModules[$sModuleId]['label']] = $sRootUrl.$aAvailableModules[$sModuleId]['doc.manual_setup'];
}
}
if (count($aManualSteps) > 0)
{
$oPage->add("
Manual operations required
");
$oPage->p("In order to complete the installation, the following manual operations are required:");
foreach($aManualSteps as $sModuleLabel => $sUrl)
{
$oPage->p("Manual instructions for $sModuleLabel");
}
$oPage->add("
Congratulations for installing ".ITOP_APPLICATION."
");
}
else
{
$oPage->add("
Congratulations for installing ".ITOP_APPLICATION."
");
$oPage->ok("The installation completed successfully.");
}
if (($this->oWizard->GetParameter('mode', '') == 'upgrade') && $this->oWizard->GetParameter('db_backup', false))
{
$sBackupDestination = $this->oWizard->GetParameter('db_backup_path', '');
if (file_exists($sBackupDestination))
{
// To mitigate security risks: pass only the filename without the extension, the download will add the extension itself
$sTruncatedFilePath = preg_replace('/\.zip$/', '', $sBackupDestination);
$oPage->p('Your backup is ready');
$oPage->p(' Download '.basename($sBackupDestination).'');
}
else
{
$oPage->p(' Warning: Backup creation failed !');
}
}
// Form goes here.. No back button since the job is done !
$oPage->add('
');
$oPage->add("
");
$oPage->add("
");
$oPage->add("
");
$oPage->add('
');
$sForm = '';
$sPHPVersion = phpversion();
$sMySQLVersion = SetupUtils::GetMySQLVersion($this->oWizard->GetParameter('db_server'), $this->oWizard->GetParameter('db_user'), $this->oWizard->GetParameter('db_pwd'));
$oPage->add('');
$sForm = addslashes($sForm);
$oPage->add_ready_script("$('#wiz_form').after('$sForm');");
}
public function CanMoveForward()
{
return false;
}
public function CanMoveBackward()
{
return false;
}
/**
* Tells whether this step of the wizard requires that the configuration file be writable
* @return bool True if the wizard will possibly need to modify the configuration at some point
*/
public function RequiresWritableConfig()
{
return false; //This step executes once the config was written and secured
}
public function AsyncAction(WebPage $oPage, $sCode, $aParameters)
{
$oParameters = new PHPParameters();
// For security reasons: add the extension now so that this action can be used to read *only* .zip files from the disk...
$sBackupFile = $aParameters['backup'].'.zip';
if (file_exists($sBackupFile))
{
// Make sure there is NO output at all before our content, otherwise the document will be corrupted
$sPreviousContent = ob_get_clean();
$oPage->SetContentType('application/zip');
$oPage->SetContentDisposition('attachment', basename($sBackupFile));
$oPage->add(file_get_contents($sBackupFile));
}
}
}