/** * All the steps of the iTop installation wizard * @copyright Copyright (C) 2010-2017 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'); require_once(APPROOT.'core/mutex.class.inc.php'); require_once(APPROOT.'setup/extensionsmap.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(""); $oPage->add_ready_script( << 0) { alert("Internet Explorer version 7 or older is NOT supported! (Check that IE is not running in compatibility mode)"); } EOF ); $oPage->add('

'.ITOP_APPLICATION.' Installation Wizard

'); $aResults = SetupUtils::CheckPHPVersion($oPage); $this->bCanMoveForward = true; $aInfo = array(); $aWarnings = array(); $aErrors = array(); foreach($aResults as $oCheckResult) { switch($oCheckResult->iSeverity) { case CheckResult::ERROR: $aErrors[] = $oCheckResult->sLabel; $this->bCanMoveForward = false; break; case CheckResult::WARNING: $aWarnings[] = $oCheckResult->sLabel; break; case CheckResult::INFO: $aInfo[] = $oCheckResult->sLabel; break; } } $sStyle = 'style="display:none;max-height:196px;overflow:auto;"'; $sToggleButtons = ''; if (count($aErrors)> 0) { $sStyle = 'style="max-height:196px;overflow:auto;"'; $sImage = "stop-mid.png"; $sTitle = count($aErrors).' Error(s), '.count($aWarnings).' Warning(s).'; } else if (count($aWarnings)> 0) { $sTitle = count($aWarnings).' Warning(s) '.$sToggleButtons; $sImage = "messagebox_warning-mid.png"; } else { $sTitle = 'Ok. '.$sToggleButtons; $sImage = "clean-mid.png"; } $oPage->add('

Prerequisites validation: '); $oPage->add(" "); $oPage->add($sTitle); $oPage->add('

'); $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.'); $oPage->p(''); } } 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'); $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']; $this->oWizard->SaveParameter('graphviz_path', $aPreviousInstance['graphviz_path']); $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('Information about the previous instance:'); $oPage->add(''); $oPage->add(''); SetupUtils::DisplayDBParameters($oPage, false, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix); $aBackupChecks = SetupUtils::CheckBackupPrerequisites($sDBBackupPath); $bCanBackup = true; $sMySQLDumpMessage = ''; foreach($aBackupChecks as $oCheck) { if ($oCheck->iSeverity == CheckResult::ERROR) { $bCanBackup = false; $sMySQLDumpMessage .= '  Warning: '.$oCheck->sLabel; } else { $sMySQLDumpMessage .= ' '.$oCheck->sLabel.' '; } } $sChecked = ($bCanBackup && $bDBBackup) ? ' checked ' : ''; $sDisabled = $bCanBackup ? '' : ' disabled '; $oPage->add(''); $oPage->add(''); $fFreeSpace = SetupUtils::CheckDiskSpace($sDBBackupPath); $sMessage = ''; if ($fFreeSpace !== false) { $sMessage .= SetupUtils::HumanReadableSize($fFreeSpace).' free in '.dirname($sDBBackupPath); } $oPage->add(''); $oPage->add('
Location on the disk:
Save the backup to:
'); $oPage->add($sMySQLDumpMessage.'
'.$sMessage.'
'); //$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($sCompatibleDMDir); } 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( <<oWizard->GetParameter('db_name', '').$this->oWizard->GetParameter('db_prefix', ''), $this->oWizard->GetParameter('db_server', ''), $this->oWizard->GetParameter('db_user', ''), $this->oWizard->GetParameter('db_pwd', '') ); if ($oMutex->IsLocked()) { $oPage->p(" An iTop CRON process is being executed on the target database. It is highly recommended to stop any iTop CRON process prior to running the setup program."); } } } public function CanMoveForward() { return $this->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' => ''); } /** * @param WebPage $oPage */ public function Display(WebPage $oPage) { $aLicenses = SetupUtils::GetLicenses(); $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('
'); $oPage->add('Components of '.ITOP_APPLICATION.''); $oPage->add('
    '); $index = 0; foreach ($aLicenses as $oLicense) { $oPage->add('
  • '.$oLicense->product.', © '.$oLicense->author.' is licensed under the '.$oLicense->license_type.' license. (Details)'); $oPage->add(''); $oPage->add_ready_script('$(".license_text a").attr("target", "_blank").addClass("no-arrow");'); $oPage->add_ready_script('$("#toggle_'.$index.'").click( function() { $("#license_'.$index.'").toggle(); } );'); $index++; } $oPage->add('
'); $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('

Configuration of the database connection:

'); $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', ''); $sNewDBName = $this->oWizard->GetParameter('db_new_name', false); $oPage->add(''); SetupUtils::DisplayDBParameters($oPage, true, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sNewDBName); $oPage->add('
'); $sCreateDB = $this->oWizard->GetParameter('create_db', 'yes'); if ($sCreateDB == 'no') { $oPage->add_ready_script('$("#existing_db").attr("checked", "checked");'); } else { $oPage->add_ready_script('$("#create_db").attr("checked", "checked");'); } } public function AsyncAction(WebPage $oPage, $sCode, $aParameters) { switch($sCode) { case 'check_db': SetupUtils:: AsyncCheckDB($oPage, $aParameters); break; } } /** * 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 <<oWizard->SaveParameter('admin_user', ''); $this->oWizard->SaveParameter('admin_pwd', ''); $this->oWizard->SaveParameter('confirm_pwd', ''); $this->oWizard->SaveParameter('admin_language', 'EN US'); return array('class' => 'WizStepMiscParams', 'state' => ''); } public function Display(WebPage $oPage) { $sAdminUser = $this->oWizard->GetParameter('admin_user', 'admin'); $sAdminPwd = $this->oWizard->GetParameter('admin_pwd', ''); $sConfirmPwd = $this->oWizard->GetParameter('confirm_pwd', ''); $sAdminLanguage = $this->oWizard->GetParameter('admin_language', 'EN US'); $oPage->add('

Definition of the Administrator Account

'); $oPage->add('
'); $oPage->add('Administrator Account'); $oPage->add(''); $oPage->add(''); $oPage->add(''); $oPage->add(''); $sSourceDir = APPROOT.'dictionaries/'; $aLanguages = SetupUtils::GetAvailableLanguages($sSourceDir); $oPage->add(''); $oPage->add('
Login:
Password:
Confirm password:
Language: '); $oPage->add(SetupUtils::GetLanguageSelect($sSourceDir, 'admin_language', $sAdminLanguage)); $oPage->add('
'); $oPage->add('
'); $oPage->add_ready_script( <<'); } else { $("#v_admin_user").html(''); } bPasswordsMatch = ($('#admin_pwd').val() == $('#confirm_pwd').val()); if (!bPasswordsMatch) { $('#v_admin_pwd').html(''); } else { $('#v_admin_pwd').html(''); } bRet = bPasswordsMatch && bRet; return bRet; EOF ; }} /** * 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) { $this->oWizard->SaveParameter('default_language', ''); $this->oWizard->SaveParameter('application_url', ''); $this->oWizard->SaveParameter('graphviz_path', ''); $this->oWizard->SaveParameter('sample_data', 'yes'); return array('class' => 'WizStepModulesChoice', 'state' => 'start_install'); } public function Display(WebPage $oPage) { $sDefaultLanguage = $this->oWizard->GetParameter('default_language', $this->oWizard->GetParameter('admin_language')); $sApplicationURL = $this->oWizard->GetParameter('application_url', utils::GetDefaultUrlAppRoot()); $sDefaultGraphvizPath = (strtolower(substr(PHP_OS, 0, 3)) === 'win') ? 'C:\\Program Files\\Graphviz\\bin\\dot.exe' : '/usr/bin/dot'; $sGraphvizPath = $this->oWizard->GetParameter('graphviz_path', $sDefaultGraphvizPath); $sSampleData = $this->oWizard->GetParameter('sample_data', 'yes'); $oPage->add('

Additional parameters

'); $oPage->add('
'); $oPage->add('Default Language'); $oPage->add(''); $sSourceDir = APPROOT.'dictionaries/'; $aLanguages = SetupUtils::GetAvailableLanguages($sSourceDir); $oPage->add(''); $oPage->add('
Default Language: '); $oPage->add(SetupUtils::GetLanguageSelect($sSourceDir, 'default_language', $sDefaultLanguage)); $oPage->add('
'); $oPage->add('
'); $oPage->add('
'); $oPage->add('Application URL'); $oPage->add(''); $oPage->add(''); $oPage->add(''); $oPage->add('
URL:
Change the value above if the end-users will be accessing the application by another path due to a specific configuration of the web server.
'); $oPage->add('
'); $oPage->add('
'); $oPage->add('Path to Graphviz\' dot application'); $oPage->add(''); $oPage->add(''); $oPage->add(''); $oPage->add(''); $oPage->add('
Path:
Graphviz is required to display the impact analysis graph (i.e. impacts / depends on).
'); $oPage->add('
'); $oPage->add('
'); $oPage->add('Sample Data'); $sChecked = ($sSampleData == 'yes') ? 'checked ' : ''; $oPage->p('
'); $oPage->add_ready_script( <<sLabel); switch($oCheck->iSeverity) { case CheckResult::INFO: $sStatus = 'ok'; $sMessage = json_encode(' '.$oCheck->sLabel); break; default: case CheckResult::ERROR: case CheckResult::WARNING: $sStatus = 'ko'; $sMessage = json_encode(' '.$oCheck->sLabel); } $oPage->add_ready_script( <<'); } else { $("#v_application_url").html(''); } bGraphviz = ($('#graphviz_path').val() != ''); if (!bGraphviz) { // Does not prevent to move forward $("#v_graphviz_path").html(''); } else { $("#v_graphviz_path").html(''); } return bRet; EOF ; } } /** * Miscellaneous Parameters (URL...) in case of upgrade */ class WizStepUpgradeMiscParams extends WizardStep { public function GetTitle() { return 'Miscellaneous Parameters'; } public function GetPossibleSteps() { return array('WizStepModulesChoice'); } public function ProcessParams($bMoveForward = true) { $this->oWizard->SaveParameter('application_url', ''); $this->oWizard->SaveParameter('graphviz_path', ''); return array('class' => 'WizStepModulesChoice', 'state' => 'start_upgrade'); } public function Display(WebPage $oPage) { $sApplicationURL = $this->oWizard->GetParameter('application_url', utils::GetDefaultUrlAppRoot()); $sDefaultGraphvizPath = (strtolower(substr(PHP_OS, 0, 3)) === 'win') ? 'C:\\Program Files\\Graphviz\\bin\\dot.exe' : '/usr/bin/dot'; $sGraphvizPath = $this->oWizard->GetParameter('graphviz_path', $sDefaultGraphvizPath); $oPage->add('

Additional parameters

'); $oPage->add('
'); $oPage->add('Application URL'); $oPage->add(''); $oPage->add(''); $oPage->add(''); $oPage->add('
URL:
Change the value above if the end-users will be accessing the application by another path due to a specific configuration of the web server.
'); $oPage->add('
'); $oPage->add('
'); $oPage->add('Path to Graphviz\' dot application'); $oPage->add(''); $oPage->add(''); $oPage->add(''); $oPage->add(''); $oPage->add('
Path:
Graphviz is required to display the impact analysis graph (i.e. impacts / depends on).
'); $oPage->add('
'); $oPage->add_ready_script( <<sLabel); switch($oCheck->iSeverity) { case CheckResult::INFO: $sStatus = 'ok'; $sMessage = json_encode(' '.$oCheck->sLabel); break; default: case CheckResult::ERROR: case CheckResult::WARNING: $sStatus = 'ko'; $sMessage = json_encode(' '.$oCheck->sLabel); } $oPage->add_ready_script( <<'); } else { $("#v_application_url").html(''); } bGraphviz = ($('#graphviz_path').val() != ''); if (!bGraphviz) { // Does not prevent to move forward $("#v_graphviz_path").html(''); } else { $("#v_graphviz_path").html(''); } return bRet; EOF ; } } /** * Choice of the modules to be installed */ class WizStepModulesChoice extends WizardStep { static protected $SEP = '_'; protected $bUpgrade = false; /** * * @var iTopExtensionsMap */ protected $oExtensionsMap; /** * Whether we were able to load the choices from the database or not * @var bool */ protected $bChoicesFromDatabase; public function __construct(WizardController $oWizard, $sCurrentState) { parent::__construct($oWizard, $sCurrentState); $this->bChoicesFromDatabase = false; $this->oExtensionsMap = new iTopExtensionsMap(); $sPreviousSourceDir = $this->oWizard->GetParameter('previous_version_dir', ''); $sConfigPath = null; if (($sPreviousSourceDir !== '') && is_readable($sPreviousSourceDir.'/conf/production/config-itop.php')) { $sConfigPath = $sPreviousSourceDir.'/conf/production/config-itop.php'; } else if (is_readable(utils::GetConfigFilePath('production'))) { $sConfigPath = utils::GetConfigFilePath('production'); } if ($sConfigPath !== null) { $oConfig = new Config($sConfigPath); $this->bChoicesFromDatabase = $this->oExtensionsMap->LoadChoicesFromDatabase($oConfig); } //echo '
Default: '.($this->bChoicesFromDatabase ? 'DB' : 'Guess').'
'; } public function GetTitle() { $aStepInfo = $this->GetStepInfo(); $sTitle = isset($aStepInfo['title']) ? $aStepInfo['title'] : 'Modules selection'; return $sTitle; } public function GetPossibleSteps() { return array('WizStepModulesChoice', 'WizStepSummary'); } public function ProcessParams($bMoveForward = true) { // Accumulates the selected modules: $index = $this->GetStepIndex(); // use json_encode:decode to store a hash array: step_id => array(input_name => selected_input_id) $aSelectedChoices = json_decode($this->oWizard->GetParameter('selected_components', '{}'), true); $aSelected = utils::ReadParam('choice', array()); $aSelectedChoices[$index] = $aSelected; $this->oWizard->SetParameter('selected_components', json_encode($aSelectedChoices)); if ($this->GetStepInfo($index) == null) { throw new Exception('Internal error: invalid step "'.$index.'" for the choice of modules.'); } else if ($bMoveForward) { if ($this->GetStepInfo(1 + $index) != null) { return array('class' => 'WizStepModulesChoice', 'state' => (1+$index)); } else { // Exiting this step of the wizard, let's convert the selection into a list of modules $aModules = array(); $aExtensions = array(); $sDisplayChoices = '
    '; for($i = 0; $i <= $index; $i++) { $aStepInfo = $this->GetStepInfo($i); $sDisplayChoices .= $this->GetSelectedModules($aStepInfo, $aSelectedChoices[$i], $aModules, '', '', $aExtensions); } $sDisplayChoices .= '
'; if (class_exists('CreateITILProfilesInstaller')) { $this->oWizard->SetParameter('old_addon', true); } $this->oWizard->SetParameter('selected_modules', json_encode(array_keys($aModules))); $this->oWizard->SetParameter('selected_extensions', json_encode($aExtensions)); $this->oWizard->SetParameter('display_choices', $sDisplayChoices); return array('class' => 'WizStepSummary', 'state' => ''); } } } public function Display(WebPage $oPage) { $this->DisplayStep($oPage); } protected function DisplayStep($oPage) { // Sanity check (not stopper, to let developpers go further...) try { SetupUtils::AnalyzeInstallation($this->oWizard, true); } catch(MissingDependencyException $e) { $oPage->warning($e->getMessage()); } $this->bUpgrade = ($this->oWizard->GetParameter('install_mode') != 'install'); $aStepInfo = $this->GetStepInfo(); $oPage->add_style("div.choice { margin: 0.5em;}"); $oPage->add_style("div.choice a { text-decoration:none; font-weight: bold; color: #1C94C4 }"); $oPage->add_style("div.description { margin-left: 2em; }"); $oPage->add_style(".choice-disabled { color: #999; }"); $oPage->add(''); $sBannerPath = isset($aStepInfo['banner']) ? $aStepInfo['banner'] : ''; if (!empty($sBannerPath)) { if (substr($sBannerPath, 0, 1) == '/') { // absolute path, means relative to APPROOT $sBannerUrl = utils::GetDefaultUrlAppRoot().$sBannerPath; } else { // relative path: i.e. relative to the directory containing the XML file $sFullPath = dirname($this->GetSourceFilePath()).'/'.$sBannerPath; $sRealPath = realpath($sFullPath); $sBannerUrl = utils::GetDefaultUrlAppRoot().str_replace(realpath(APPROOT), '', $sRealPath); } $oPage->add('
'); } $sDescription = isset($aStepInfo['description']) ? $aStepInfo['description'] : ''; $oPage->add(''.$sDescription.''); $oPage->add('
'); // Build the default choices $aDefaults = array(); $aModules = SetupUtils::AnalyzeInstallation($this->oWizard); $aDefaults = $this->GetDefaults($aStepInfo, $aModules); //echo "
aStepInfo:\n ".print_r($aStepInfo, true)."
"; //echo "
aDefaults:\n ".print_r($aDefaults, true)."
"; $index = $this->GetStepIndex(); // retrieve the saved selection // use json_encode:decode to store a hash array: step_id => array(input_name => selected_input_id) $aParameters = json_decode($this->oWizard->GetParameter('selected_components', '{}'), true); if (!isset($aParameters[$index])) { $aParameters[$index] = $aDefaults; } $aSelectedComponents = $aParameters[$index]; $oPage->add('
'); $this->DisplayOptions($oPage, $aStepInfo, $aSelectedComponents, $aDefaults); $oPage->add('
'); $oPage->add_script( <<add_ready_script( <<bChoicesFromDatabase) { $this->GuessDefaultsFromModules($aInfo, $aDefaults, $aModules, $sParentId); } else { $this->GetDefaultsFromDatabase($aInfo, $aDefaults, $sParentId); } return $aDefaults; } protected function GetDefaultsFromDatabase($aInfo, &$aDefaults, $sParentId) { $aOptions = isset($aInfo['options']) ? $aInfo['options'] : array(); foreach($aOptions as $index => $aChoice) { $sChoiceId = $sParentId.self::$SEP.$index; if ($this->bUpgrade) { if ($this->oExtensionsMap->IsMarkedAsChosen($aChoice['extension_code'])) { $aDefaults[$sChoiceId] = $sChoiceId; } } else if (isset($aChoice['default']) && $aChoice['default']) { $aDefaults[$sChoiceId] = $sChoiceId; } // Recurse for sub_options (if any) if (isset($aChoice['sub_options'])) { $this->GetDefaultsFromDatabase($aChoice['sub_options'], $aDefaults, $sChoiceId); } } $aAlternatives = isset($aInfo['alternatives']) ? $aInfo['alternatives'] : array(); $sChoiceName = null; foreach($aAlternatives as $index => $aChoice) { $sChoiceId = $sParentId.self::$SEP.$index; if ($sChoiceName == null) { $sChoiceName = $sChoiceId; // All radios share the same name } if ($this->bUpgrade) { if ($this->oExtensionsMap->IsMarkedAsChosen($aChoice['extension_code'])) { $aDefaults[$sChoiceName] = $sChoiceId; } } else if (isset($aChoice['default']) && $aChoice['default']) { $aDefaults[$sChoiceName] = $sChoiceId; } // Recurse for sub_options (if any) if (isset($aChoice['sub_options'])) { $this->GetDefaultsFromDatabase($aChoice['sub_options'], $aDefaults, $sChoiceId); } } } /** * Try to guess the user choices based on the current list of installed modules... * @param array $aInfo * @param array $aDefaults * @param array $aModules * @param string $sParentId * @return array */ protected function GuessDefaultsFromModules($aInfo, &$aDefaults, $aModules, $sParentId = '') { $aRetScore = array(); $aScores = array(); $aOptions = isset($aInfo['options']) ? $aInfo['options'] : array(); foreach($aOptions as $index => $aChoice) { $sChoiceId = $sParentId.self::$SEP.$index; $aScores[$sChoiceId] = array(); 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 $aScores[$sChoiceId][$sModuleId] = true; } } if (count($aScores[$sChoiceId]) == count($aChoice['modules'])) { // All the modules are installed, this choice is selected $aDefaults[$sChoiceId] = $sChoiceId; } $aRetScore = array_merge($aRetScore, $aScores[$sChoiceId]); } if (isset($aChoice['sub_options'])) { $aScores[$sChoiceId] = array_merge($aScores[$sChoiceId], $this->GuessDefaultsFromModules($aChoice['sub_options'], $aDefaults, $sChoiceId)); } $index++; } $aAlternatives = isset($aInfo['alternatives']) ? $aInfo['alternatives'] : array(); $sChoiceName = null; $sChoiceIdNone = null; foreach($aAlternatives as $index => $aChoice) { $sChoiceId = $sParentId.self::$SEP.$index; $aScores[$sChoiceId] = array(); if ($sChoiceName == null) { $sChoiceName = $sChoiceId; } if (!$this->bUpgrade && isset($aChoice['default']) && $aChoice['default']) { $aDefaults[$sChoiceName] = $sChoiceId; } if (isset($aChoice['sub_options'])) { // By default (i.e. install-mode), sub options can only be checked if the parent option is checked by default if ($this->bUpgrade || (isset($aChoice['default']) && $aChoice['default'])) { $aScores[$sChoiceId] = $this->GuessDefaultsFromModules($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; } 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] = array(); $aScores[$sChoiceId][$sModuleId] = true; $iMaxScore = max($iMaxScore, count($aScores[$sChoiceId])); } } //if (count($aScores[$sChoiceId]) == count($aChoice['modules'])) //{ // $iScore += 100; // Bonus for the parent when a choice is complete //} $aRetScore = array_merge($aRetScore, $aScores[$sChoiceId]); } $iMaxScore = max($iMaxScore, isset($aScores[$sChoiceId]) ? count($aScores[$sChoiceId]) : 0); } } if ($iMaxScore > 0) { $aNumericScores = array(); foreach($aScores as $sChoiceId => $aModules) { $aNumericScores[$sChoiceId] = count($aModules); } // The choice with the bigger score wins ! asort($aNumericScores, SORT_NUMERIC); $aKeys = array_keys($aNumericScores); $sBetterChoiceId = array_pop($aKeys); $aDefaults[$sChoiceName] = $sBetterChoiceId; } // echo "Scores:
".print_r($aScores, true)."

"; // echo "Defaults:
".print_r($aDefaults, true)."

"; return $aRetScore; } /** * 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 string A text representation of what will be installed */ protected function GetSelectedModules($aInfo, $aSelectedChoices, &$aModules, $sParentId = '', $sDisplayChoices = '', &$aSelectedExtensions = null) { if ($sParentId == '') { // Check once (before recursing) that the hidden modules are selected foreach(SetupUtils::AnalyzeInstallation($this->oWizard) as $sModuleId => $aModule) { if (($sModuleId != ROOT_MODULE) && !isset($aModules[$sModuleId])) { if (($aModule['category'] == 'authentication') || (!$aModule['visible'] && !isset($aModule['auto_select']))) { $aModules[$sModuleId] = true; $sDisplayChoices .= '
  • '.$aModule['label'].' (hidden)
  • '; } } } } $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 } } $sChoiceType = isset($aChoice['type']) ? $aChoice['type'] : 'wizard_option'; if ($aSelectedExtensions !== null) { $aSelectedExtensions[] = $aChoice['extension_code']; } // Recurse only for selected choices if (isset($aChoice['sub_options'])) { $sDisplayChoices .= '
      '; $sDisplayChoices = $this->GetSelectedModules($aChoice['sub_options'], $aSelectedChoices, $aModules, $sChoiceId, $sDisplayChoices, $aSelectedExtensions); $sDisplayChoices .= '
    '; } $sDisplayChoices .= ''; } $index++; } $aAlternatives = isset($aInfo['alternatives']) ? $aInfo['alternatives'] : array(); $sChoiceName = null; foreach($aAlternatives as $index => $aChoice) { $sChoiceId = $sParentId.self::$SEP.$index; if ($sChoiceName == null) { $sChoiceName = $sChoiceId; } if ( (isset($aChoice['mandatory']) && $aChoice['mandatory']) || (isset($aSelectedChoices[$sChoiceName]) && ($aSelectedChoices[$sChoiceName] == $sChoiceId)) ) { $sDisplayChoices .= '
  • '.$aChoice['title'].'
  • '; if ($aSelectedExtensions !== null) { $aSelectedExtensions[] = $aChoice['extension_code']; } 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 = $this->GetSelectedModules($aChoice['sub_options'], $aSelectedChoices, $aModules, $sChoiceId, $sDisplayChoices, $aSelectedExtensions); $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 $sDisplayChoices .= '
  • '.$aModule['label'].' (auto_select)
  • '; $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(); $this->oWizard->SetParameter('additional_extensions_modules', json_encode(array())); // Default value, no additional extensions if (@file_exists($this->GetSourceFilePath())) { // Found an "installation.xml" file, let's us tis definition for the wizard $aParams = new XMLParameters($this->GetSourceFilePath()); $aSteps = $aParams->Get('steps', array()); // Additional step for the "extensions" $aStepDefinition = array( 'title' => 'Extensions', 'description' => '

    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() ); foreach($this->oExtensionsMap->GetAllExtensions() as $oExtension) { if ($oExtension->sSource !== iTopExtension::SOURCE_WIZARD) { $aStepDefinition['options'][] = array( 'extension_code' => $oExtension->sCode, 'title' => $oExtension->sLabel, 'description' => $oExtension->sDescription, 'more_info' => $oExtension->sMoreInfoUrl, 'default' => true, // by default offer to install all modules 'modules' => $oExtension->aModules, 'mandatory' => $oExtension->bMandatory || ($oExtension->sSource === iTopExtension::SOURCE_REMOTE), 'source_label' => $this->GetExtensionSourceLabel($oExtension->sSource), ); } } // Display this step of the wizard only if there is something to display if (count($aStepDefinition['options']) !== 0) { $aSteps[] = $aStepDefinition; $this->oWizard->SetParameter('additional_extensions_modules', json_encode($aStepDefinition['options'])); } } else { // No wizard configuration provided, build a standard one with just one big list $aStepDefinition = 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.

    ', 'banner' => '/images/modules.png', 'options' => array() ); foreach($this->oExtensionsMap->GetAllExtensions() as $oExtension) { if ($oExtension->sSource) { $aStepDefinition['options'][] = array( 'extension_code' => $oExtension->sCode, 'title' => $oExtension->sLabel, 'description' => $oExtension->sDescription, 'more_info' => $oExtension->sMoreInfoUrl, 'default' => true, // by default offer to install all modules 'modules' => $oExtension->aModules, 'mandatory' => $oExtension->bMandatory || ($oExtension->sSource !== iTopExtension::SOURCE_REMOTE), 'source_label' => $this->GetExtensionSourceLabel($oExtension->sSource), ); } } $aSteps[] = $aStepDefinition; } if (array_key_exists($index, $aSteps)) { $aStepInfo = $aSteps[$index]; } return $aStepInfo; } protected function GetExtensionSourceLabel($sSource) { switch($sSource) { case iTopExtension::SOURCE_MANUAL: $sResult = 'Extension'; break; case iTopExtension::SOURCE_REMOTE: $sResult = (ITOP_APPLICATION == 'iTop') ? 'iTop-Hub' : 'ITSM-Designer'; break; default: $sResult = ''; } if ($sResult == '') { return ''; } return ''.$sResult.''; } protected function DisplayOptions($oPage, $aStepInfo, $aSelectedComponents, $aDefaults, $sParentId = '', $bAllDisabled = false) { $aOptions = isset($aStepInfo['options']) ? $aStepInfo['options'] : array(); $aAlternatives = isset($aStepInfo['alternatives']) ? $aStepInfo['alternatives'] : array(); $index = 0; $sAllDisabled = ''; if ($bAllDisabled) { $sAllDisabled = 'disabled data-disabled="disabled" '; } foreach($aOptions as $index => $aChoice) { $sAttributes = ''; $sChoiceId = $sParentId.self::$SEP.$index; $sDataId = 'data-id="'.htmlentities($aChoice['extension_code'], ENT_QUOTES, 'UTF-8').'"'; $sId = htmlentities($aChoice['extension_code'], ENT_QUOTES, 'UTF-8'); $bIsDefault = array_key_exists($sChoiceId, $aDefaults); $bSelected = isset($aSelectedComponents[$sChoiceId]) && ($aSelectedComponents[$sChoiceId] == $sChoiceId); $bMandatory = (isset($aChoice['mandatory']) && $aChoice['mandatory']) || ($this->bUpgrade && $bIsDefault); $bDisabled = false; if ($bMandatory) { $oPage->add('
     '); $bDisabled = true; } else if ($bSelected) { $oPage->add('
     '); } else { $oPage->add('
     '); } $this->DisplayChoice($oPage, $aChoice, $aSelectedComponents, $aDefaults, $sChoiceId, $bDisabled); $oPage->add('
    '); $index++; } $sChoiceName = null; $sDisabled = ''; $bDisabled = false; $sChoiceIdNone = null; foreach($aAlternatives as $index => $aChoice) { $sChoiceId = $sParentId.self::$SEP.$index; if ($sChoiceName == null) { $sChoiceName = $sChoiceId; // All radios share the same name } $bIsDefault = array_key_exists($sChoiceName, $aDefaults) && ($aDefaults[$sChoiceName] == $sChoiceId); $bMandatory = (isset($aChoice['mandatory']) && $aChoice['mandatory']) || ($this->bUpgrade && $bIsDefault); if ($bMandatory || $bAllDisabled) { // One choice is mandatory, all alternatives are disabled $sDisabled = ' disabled data-disabled="disabled"'; $bDisabled = true; } if ( (!isset($aChoice['sub_options']) || (count($aChoice['sub_options']) == 0)) && (!isset($aChoice['modules']) || (count($aChoice['modules']) == 0)) ) { $sChoiceIdNone = $sChoiceId; // the "None" / empty choice } } if (!array_key_exists($sChoiceName, $aDefaults) || ($aDefaults[$sChoiceName] == $sChoiceIdNone)) { // The "none" choice does not disable the selection !! $sDisabled = ''; $bDisabled = false; } foreach($aAlternatives as $index => $aChoice) { $sAttributes = ''; $sChoiceId = $sParentId.self::$SEP.$index; $sDataId = 'data-id="'.htmlentities($aChoice['extension_code'], ENT_QUOTES, 'UTF-8').'"'; $sId = htmlentities($aChoice['extension_code'], ENT_QUOTES, 'UTF-8'); if ($sChoiceName == null) { $sChoiceName = $sChoiceId; // All radios share the same name } $bIsDefault = array_key_exists($sChoiceName, $aDefaults) && ($aDefaults[$sChoiceName] == $sChoiceId); $bSelected = isset($aSelectedComponents[$sChoiceName]) && ($aSelectedComponents[$sChoiceName] == $sChoiceId); if ( !isset($aSelectedComponents[$sChoiceName]) && ($sChoiceIdNone != null)) { // No choice selected, select the "None" option $bSelected = ($sChoiceId == $sChoiceIdNone); } $bMandatory = (isset($aChoice['mandatory']) && $aChoice['mandatory']) || ($this->bUpgrade && $bIsDefault); if ($bSelected) { $sAttributes = ' checked '; } $sHidden = ''; if ($bMandatory) { $sAttributes = ' checked '; $sHidden = ''; } $oPage->add('
    '.$sHidden.' '); $this->DisplayChoice($oPage, $aChoice, $aSelectedComponents, $aDefaults, $sChoiceId, $bDisabled); $oPage->add('
    '); $index++; } } protected function DisplayChoice($oPage, $aChoice, $aSelectedComponents, $aDefaults, $sChoiceId, $bDisabled = false) { $sMoreInfo = (isset($aChoice['more_info']) && ($aChoice['more_info'] != '')) ? 'More information' : ''; $sSourceLabel = isset($aChoice['source_label']) ? $aChoice['source_label'] : ''; $sId = htmlentities($aChoice['extension_code'], ENT_QUOTES, 'UTF-8'); $oPage->add(' '.$sMoreInfo); $sDescription = isset($aChoice['description']) ? htmlentities($aChoice['description'], ENT_QUOTES, 'UTF-8') : ''; $oPage->add('
    '.$sDescription.''); if (isset($aChoice['sub_options'])) { $this->DisplayOptions($oPage, $aChoice['sub_options'], $aSelectedComponents, $aDefaults, $sChoiceId, $bDisabled); } $oPage->add('
    '); } protected function GetSourceFilePath() { $sSourceDir = $this->oWizard->GetParameter('source_dir'); return $sSourceDir.'/installation.xml'; } } /** * Summary of the installation tasks */ class WizStepSummary extends WizardStep { protected $bDependencyCheck = null; protected $sDependencyIssue = null; protected function CheckDependencies() { if (is_null($this->bDependencyCheck)) { $aSelectedModules = json_decode($this->oWizard->GetParameter('selected_modules'), true); $this->bDependencyCheck = true; try { SetupUtils::AnalyzeInstallation($this->oWizard, true, $aSelectedModules); } catch(MissingDependencyException $e) { $this->bDependencyCheck = false; $this->sDependencyIssue = $e->getMessage(); } } return $this->bDependencyCheck; } 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 CanMoveForward() { if ($this->CheckDependencies()) { return true; } else { return false; } } public function ProcessParams($bMoveForward = true) { return array('class' => 'WizStepDone', 'state' => ''); } public function Display(WebPage $oPage) { $oPage->add_style( <<BuildConfig(); $sMode = $aInstallParams['mode']; $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('
    Installation Parameters'); $oPage->add('
    '); $oPage->add('
    Database Parameters
      '); $oPage->add('
    • Server Name: '.$aInstallParams['database']['server'].'
    • '); $oPage->add('
    • DB User Name: '.$aInstallParams['database']['user'].'
    • '); $oPage->add('
    • DB user password: '.$aInstallParams['database']['pwd'].'
    • '); if (($sMode == 'install') && ($this->oWizard->GetParameter('create_db') == 'yes')) { $oPage->add('
    • Database Name: '.$aInstallParams['database']['name'].' (will be created)
    • '); } else { $oPage->add('
    • Database Name: '.$aInstallParams['database']['name'].'
    • '); } if ($aInstallParams['database']['prefix'] != '') { $oPage->add('
    • Prefix for the '.ITOP_APPLICATION.' tables: '.$aInstallParams['database']['prefix'].'
    • '); } else { $oPage->add('
    • Prefix for the '.ITOP_APPLICATION.' tables: none
    • '); } $oPage->add('
    '); $oPage->add('
    Data Model Configuration'); $oPage->add($this->oWizard->GetParameter('display_choices')); $oPage->add('
    '); $oPage->add('
    Other Parameters
      '); if ($sMode == 'install') { $oPage->add('
    • Default language: '.$aInstallParams['language'].'
    • '); } $oPage->add('
    • URL to access the application: '.$aInstallParams['url'].'
    • '); $oPage->add('
    • Graphviz\' dot path: '.$aInstallParams['graphviz_path'].'
    • '); if ($aInstallParams['sample_data'] == 'yes') { $oPage->add('
    • Sample data will be loaded into the database.
    • '); } if ($aInstallParams['old_addon']) { $oPage->add('
    • Compatibility mode: Using the version 1.2 of the UserRightsProfiles add-on.
    • '); } $oPage->add('
    '); if ($sMode == 'install') { $oPage->add('
    Admininistrator Account
      '); $oPage->add('
    • Login: '.$aInstallParams['admin_account']['user'].'
    • '); $oPage->add('
    • Password: '.$aInstallParams['admin_account']['pwd'].'
    • '); $oPage->add('
    • Language: '.$aInstallParams['admin_account']['language'].'
    • '); $oPage->add('
    '); } $aMiscOptions = $aInstallParams['options']; if (count($aMiscOptions) > 0) { $oPage->add('
    Miscellaneous Options
      '); foreach($aMiscOptions as $sKey => $sValue) { $oPage->add('
    • '.$sKey.': '.$sValue.'
    • '); } $oPage->add('
    '); } $aSelectedModules = $aInstallParams['selected_modules']; if (isset($aMiscOptions['generate_config'])) { $oDoc = new DOMDocument('1.0', 'UTF-8'); $oDoc->preserveWhiteSpace = false; $oDoc->formatOutput = true; $oParams = new PHPParameters(); $oParams->LoadFromHash($aInstallParams); $oParams->ToXML($oDoc, null, 'installation'); $sXML = $oDoc->saveXML(); $oPage->add('
    XML Config file
      ');
      			$oPage->add(htmlentities($sXML, ENT_QUOTES, 'UTF-8'));
      			$oPage->add('
    '); } $oPage->add('
    '); // params_summary $oPage->add('
    '); $oPage->add('
    Progress of the installation'); $oPage->add('
    '); $oPage->add_linked_script('../setup/jquery.progression.js'); $oPage->add('

    Ready to start...

    0%
    '); $oPage->add('
    '); // progress_content $oPage->add('
    '); $sJSONData = json_encode($aInstallParams); $oPage->add(''); if (!$this->CheckDependencies()) { $oPage->error($this->sDependencyIssue); } $oPage->add_ready_script( <<oWizard->GetParameter('install_mode', 'install'); $aSelectedModules = json_decode($this->oWizard->GetParameter('selected_modules'), true); $aSelectedExtensions = json_decode($this->oWizard->GetParameter('selected_extensions'), 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'), 'graphviz_path' => $this->oWizard->GetParameter('graphviz_path'), '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, 'selected_extensions' => $aSelectedExtensions, '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.'.tar.gz')) { // To mitigate security risks: pass only the filename without the extension, the download will add the extension itself $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('
    '); $oConfig = new Config(utils::GetConfigFilePath()); $sIframeUrl = $oConfig->GetModuleSetting('itop-hub-connector', 'setup_url', ''); if ($sIframeUrl != '') { $oPage->add(''); $oPage->add_script("window.addEventListener('message', function(event) { if (event.data === 'itophub_load_completed') { $('#fresh_content').height($('#placeholder').height()); $('#placeholder').hide(); $('#fresh_content').show(); } }, false); "); } $sForm = '
    '; $sForm .= ''; $sForm .= ''; $sForm .= "

    "; $sForm .= '
    '; $sPHPVersion = phpversion(); $sMySQLVersion = SetupUtils::GetMySQLVersion($this->oWizard->GetParameter('db_server'), $this->oWizard->GetParameter('db_user'), $this->oWizard->GetParameter('db_pwd')); $aParameters = json_decode($this->oWizard->GetParameter('selected_components', '{}'), true); $sCompactWizChoices = array(); foreach($aParameters as $iStep => $aChoices) { $aShortChoices = array(); foreach($aChoices as $sChoiceCode) { $sShortCode = str_replace('_', '', $sChoiceCode); $aShortChoices[] = $sShortCode; } $sCompactWizChoices[] = implode(' ',$aShortChoices); } $sInstallMode = 'i'; if ($this->oWizard->GetParameter('install_mode', 'install') == 'upgrade') { if (!$this->oWizard->GetParameter('license')) { // When the version does not change we don't ask for the licence again $sInstallMode = 'r'; } else { // An actual upgrade $sInstallMode = 'u'; } } $aUrlParams = array( 'p' => ITOP_APPLICATION, 'v' => ITOP_VERSION, 'php' => $sPHPVersion, 'mysql' => $sMySQLVersion, 'os' => PHP_OS, 's' => ($this->oWizard->GetParameter('sample_data', '') == 'yes') ? 1 : 0 , 'l' => $this->oWizard->GetParameter('default_language'), 'i' => $sInstallMode, 'w' => json_encode($sCompactWizChoices), ); $aSafeParams = array(); foreach($aUrlParams as $sCode => $sValue) { $aSafeParams[] = $sCode.'='.urlencode($sValue); } $sImgUrl = 'http://www.combodo.com/stats/?'.implode('&', $aSafeParams); $aAdditionalModules = array(); foreach(json_decode($this->oWizard->GetParameter('additional_extensions_modules'), true) as $idx => $aModuleInfo) { if (in_array('_'.$idx, $aParameters[count($aParameters)-1])) { // Extensions "choices" can now have more than one module foreach($aModuleInfo['modules'] as $sModuleName) { $aAdditionalModules[] = $sModuleName; } } } $idx = 0; $aReportedModules = array(); while($idx < count($aAdditionalModules) && (strlen($sImgUrl.'&m='.urlencode(implode(' ', $aReportedModules))) < 2000)) // reasonable limit for the URL: 2000 chars { $aReportedModules[] = $aAdditionalModules[$idx]; $idx++; } $sImgUrl .= '&m='.urlencode(implode(' ', $aReportedModules)); $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) { // For security reasons: add the extension now so that this action can be used to read *only* .tar.gz files from the disk... $sBackupFile = $aParameters['backup'].'.tar.gz'; 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/gzip'); $oPage->SetContentDisposition('attachment', basename($sBackupFile)); $oPage->add(file_get_contents($sBackupFile)); } } }