mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-12 23:14:18 +01:00
Some progress on the 2.0 setup...
SVN:trunk[2237]
This commit is contained in:
@@ -532,7 +532,7 @@ class Config
|
||||
'type' => 'string',
|
||||
'description' => 'Source directory for the datamodel files. (which gets compiled to env-production).',
|
||||
// examples... not used
|
||||
'default' => 'datamodels/latest',
|
||||
'default' => '',
|
||||
'value' => '',
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => true,
|
||||
@@ -1420,7 +1420,7 @@ class Config
|
||||
/**
|
||||
* Helper function to initialize a configuration from the page arguments
|
||||
*/
|
||||
public function UpdateFromParams($aParamValues, $sModulesDir = null)
|
||||
public function UpdateFromParams($aParamValues, $sModulesDir = null, $bPreserveModuleSettings = false)
|
||||
{
|
||||
if (isset($aParamValues['application_path']))
|
||||
{
|
||||
@@ -1469,7 +1469,7 @@ class Config
|
||||
// Merge the values with the ones provided by the modules
|
||||
// Make sure when don't load the same file twice...
|
||||
|
||||
$aModules = ModuleDiscovery::GetAvailableModules(APPROOT, $sModulesDir);
|
||||
$aModules = ModuleDiscovery::GetAvailableModules(array(APPROOT.$sModulesDir));
|
||||
foreach($aModules as $sModuleId => $aModuleInfo)
|
||||
{
|
||||
list($sModuleName, $sModuleVersion) = ModuleDiscovery::GetModuleName($sModuleId);
|
||||
@@ -1489,10 +1489,17 @@ class Config
|
||||
}
|
||||
if (isset($aModuleInfo['settings']))
|
||||
{
|
||||
list($sName, $sVersion) = ModuleDiscovery::GetModuleName($sModuleId);
|
||||
foreach($aModuleInfo['settings'] as $sProperty => $value)
|
||||
{
|
||||
list($sName, $sVersion) = ModuleDiscovery::GetModuleName($sModuleId);
|
||||
$this->SetModuleSetting($sName, $sProperty, $value);
|
||||
if ($bPreserveModuleSettings && isset($this->m_aModuleSettings[$sName][$sProperty]))
|
||||
{
|
||||
// Do nothing keep the original value
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->SetModuleSetting($sName, $sProperty, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($aModuleInfo['installer']))
|
||||
|
||||
BIN
images/extension.png
Normal file
BIN
images/extension.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.9 KiB |
@@ -136,18 +136,36 @@ try
|
||||
switch($sOperation)
|
||||
{
|
||||
case 'async_action':
|
||||
require_once(APPROOT.'/setup/wizardcontroller.class.inc.php');
|
||||
require_once(APPROOT.'/setup/wizardsteps.class.inc.php');
|
||||
ini_set('max_execution_time', max(240, ini_get('max_execution_time')));
|
||||
// While running the setup it is desirable to see any error that may happen
|
||||
ini_set('display_errors', true);
|
||||
ini_set('display_startup_errors', true);
|
||||
|
||||
$sClass = utils::ReadParam('step_class', '');
|
||||
$sState = utils::ReadParam('step_state', '');
|
||||
$sActionCode = utils::ReadParam('code', '');
|
||||
$aParams = utils::ReadParam('params', array(), false, 'raw_data');
|
||||
$oPage = new ajax_page('');
|
||||
$oDummyController = new WizardController('');
|
||||
$oStep = new $sClass($oDummyController, $sState);
|
||||
$oStep->AsyncAction($oPage, $sActionCode, $aParams);
|
||||
$oPage->output();
|
||||
$sConfigFile = utils::GetConfigFilePath();
|
||||
if (file_exists($sConfigFile) && !is_writable($sConfigFile))
|
||||
{
|
||||
$oPage->error("<b>Error:</b> the configuration file '".$sConfigFile."' already exists and cannot be overwritten.");
|
||||
$oPage->p("The wizard cannot modify the configuration file for you. If you want to upgrade ".ITOP_APPLICATION.", make sure that the file '<b>".realpath($sConfigFile)."</b>' can be modified by the web server.");
|
||||
$oPage->output();
|
||||
}
|
||||
else
|
||||
{
|
||||
require_once(APPROOT.'/setup/wizardcontroller.class.inc.php');
|
||||
require_once(APPROOT.'/setup/wizardsteps.class.inc.php');
|
||||
|
||||
$sClass = utils::ReadParam('step_class', '');
|
||||
$sState = utils::ReadParam('step_state', '');
|
||||
$sActionCode = utils::ReadParam('code', '');
|
||||
$aParams = utils::ReadParam('params', array(), false, 'raw_data');
|
||||
$oPage = new ajax_page('');
|
||||
$oDummyController = new WizardController('');
|
||||
if (is_subclass_of($sClass, 'WizardStep'))
|
||||
{
|
||||
$oStep = new $sClass($oDummyController, $sState);
|
||||
$oStep->AsyncAction($oPage, $sActionCode, $aParams);
|
||||
}
|
||||
$oPage->output();
|
||||
}
|
||||
break;
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
@@ -126,7 +126,7 @@ class ApplicationInstaller
|
||||
$aPreinstall = $this->oParams->Get('preinstall');
|
||||
$aCopies = $aPreinstall['copies'];
|
||||
|
||||
// disabled - $sReport = self::DoCopy($aCopies);
|
||||
$sReport = self::DoCopy($aCopies);
|
||||
$sReport = "copy disabled...";
|
||||
|
||||
$aResult = array(
|
||||
@@ -167,7 +167,8 @@ class ApplicationInstaller
|
||||
|
||||
case 'compile':
|
||||
$aSelectedModules = $this->oParams->Get('selected_modules');
|
||||
$sSourceDir = $this->oParams->Get('source_dir', 'datamodel');
|
||||
$sSourceDir = $this->oParams->Get('source_dir', 'datamodels/latest');
|
||||
$sExtensionDir = $this->oParams->Get('extensions_dir', 'extensions');
|
||||
$sTargetEnvironment = $this->oParams->Get('target_env', '');
|
||||
if ($sTargetEnvironment == '')
|
||||
{
|
||||
@@ -190,7 +191,7 @@ class ApplicationInstaller
|
||||
}
|
||||
}
|
||||
|
||||
self::DoCompile($aSelectedModules, $sSourceDir, $sTargetDir, $sWorkspaceDir, $bUseSymbolicLinks);
|
||||
self::DoCompile($aSelectedModules, $sSourceDir, $sExtensionDir, $sTargetDir, $sWorkspaceDir, $bUseSymbolicLinks);
|
||||
|
||||
$aResult = array(
|
||||
'status' => self::OK,
|
||||
@@ -215,8 +216,9 @@ class ApplicationInstaller
|
||||
$sDBPwd = $aDBParams['pwd'];
|
||||
$sDBName = $aDBParams['name'];
|
||||
$sDBPrefix = $aDBParams['prefix'];
|
||||
$bOldAddon = $this->oParams->Get('old_addon', false);
|
||||
|
||||
self::DoUpdateDBSchema($sMode, $sTargetDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sTargetEnvironment);
|
||||
self::DoUpdateDBSchema($sMode, $sTargetDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sTargetEnvironment, $bOldAddon);
|
||||
|
||||
$aResult = array(
|
||||
'status' => self::OK,
|
||||
@@ -247,8 +249,12 @@ class ApplicationInstaller
|
||||
$sAdminLanguage = $aAdminParams['language'];
|
||||
$sLanguage = $this->oParams->Get('language');
|
||||
$aSelectedModules = $this->oParams->Get('selected_modules', array());
|
||||
$sDataModelVersion = $this->oParams->Get('datamodel_version', '0.0.0');
|
||||
$bOldAddon = $this->oParams->Get('old_addon', false);
|
||||
$sSourceDir = $this->oParams->Get('source_dir', '');
|
||||
|
||||
self::AfterDBCreate($sMode, $sTargetDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sAdminUser, $sAdminPwd, $sAdminLanguage, $sLanguage, $aSelectedModules, $sTargetEnvironment);
|
||||
self::AfterDBCreate($sMode, $sTargetDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sAdminUser,
|
||||
$sAdminPwd, $sAdminLanguage, $sLanguage, $aSelectedModules, $sTargetEnvironment, $bOldAddon, $sDataModelVersion, $sSourceDir);
|
||||
|
||||
$aResult = array(
|
||||
'status' => self::OK,
|
||||
@@ -277,8 +283,9 @@ class ApplicationInstaller
|
||||
$sDBName = $aDBParams['name'];
|
||||
$sDBPrefix = $aDBParams['prefix'];
|
||||
$aFiles = $this->oParams->Get('files', array());
|
||||
$bOldAddon = $this->oParams->Get('old_addon', false);
|
||||
|
||||
self::DoLoadFiles($aSelectedModules, $sTargetDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sTargetEnvironment);
|
||||
self::DoLoadFiles($aSelectedModules, $sTargetDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sTargetEnvironment, $bOldAddon);
|
||||
|
||||
$aResult = array(
|
||||
'status' => self::INFO,
|
||||
@@ -306,8 +313,11 @@ class ApplicationInstaller
|
||||
$sUrl = $this->oParams->Get('url', '');
|
||||
$sLanguage = $this->oParams->Get('language', '');
|
||||
$aSelectedModules = $this->oParams->Get('selected_modules', array());
|
||||
$bOldAddon = $this->oParams->Get('old_addon', false);
|
||||
$sSourceDir = $this->oParams->Get('source_dir', '');
|
||||
$sPreviousConfigFile = $this->oParams->Get('previous_configuration_file', '');
|
||||
|
||||
self::DoCreateConfig($sMode, $sTargetDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sUrl, $sLanguage, $aSelectedModules, $sTargetEnvironment);
|
||||
self::DoCreateConfig($sMode, $sTargetDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sUrl, $sLanguage, $aSelectedModules, $sTargetEnvironment, $bOldAddon, $sSourceDir, $sPreviousConfigFile);
|
||||
|
||||
$aResult = array(
|
||||
'status' => self::INFO,
|
||||
@@ -338,6 +348,9 @@ class ApplicationInstaller
|
||||
'next-step-label' => '',
|
||||
'percentage-completed' => 100,
|
||||
);
|
||||
|
||||
SetupPage::log_error('An exception occurred: '.$e->getMessage());
|
||||
SetupPage::log("Stack trace:\n".$e->getTraceAsString());
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
@@ -374,7 +387,7 @@ class ApplicationInstaller
|
||||
}
|
||||
|
||||
|
||||
protected static function DoCompile($aSelectedModules, $sSourceDir, $sTargetDir, $sWorkspaceDir = '', $bUseSymbolicLinks = false)
|
||||
protected static function DoCompile($aSelectedModules, $sSourceDir, $sExtensionDir, $sTargetDir, $sWorkspaceDir = '', $bUseSymbolicLinks = false)
|
||||
{
|
||||
SetupPage::log_info("Compiling data model.");
|
||||
|
||||
@@ -388,6 +401,7 @@ class ApplicationInstaller
|
||||
}
|
||||
|
||||
$sSourcePath = APPROOT.$sSourceDir;
|
||||
$sExtensionsPath = APPROOT.$sExtensionDir;
|
||||
$sTargetPath = APPROOT.$sTargetDir;
|
||||
if (!is_dir($sSourcePath))
|
||||
{
|
||||
@@ -407,7 +421,7 @@ class ApplicationInstaller
|
||||
}
|
||||
}
|
||||
|
||||
$oFactory = new ModelFactory($sSourcePath);
|
||||
$oFactory = new ModelFactory(array($sSourcePath, $sExtensionsPath));
|
||||
$aModules = $oFactory->FindModules();
|
||||
|
||||
foreach($aModules as $foo => $oModule)
|
||||
@@ -441,13 +455,24 @@ class ApplicationInstaller
|
||||
}
|
||||
else
|
||||
{
|
||||
$oMFCompiler = new MFCompiler($oFactory, $sSourcePath);
|
||||
$oMFCompiler = new MFCompiler($oFactory);
|
||||
$oMFCompiler->Compile($sTargetPath, null, $bUseSymbolicLinks);
|
||||
SetupPage::log_info("Data model successfully compiled to '$sTargetPath'.");
|
||||
}
|
||||
|
||||
// Special case to patch a ugly patch in itop-config-mgmt
|
||||
$sFileToPatch = $sTargetPath.'/itop-config-mgmt-1.0.0/model.itop-config-mgmt.php';
|
||||
if (file_exists($sFileToPatch))
|
||||
{
|
||||
$sContent = file_get_contents($sFileToPatch);
|
||||
|
||||
$sContent = str_replace("require_once(APPROOT.'modules/itop-welcome-itil/model.itop-welcome-itil.php');", "//\n// The line below is no longer needed in iTop 2.0 -- patched by the setup program\n// require_once(APPROOT.'modules/itop-welcome-itil/model.itop-welcome-itil.php');", $sContent);
|
||||
|
||||
file_put_contents($sFileToPatch, $sContent);
|
||||
}
|
||||
}
|
||||
|
||||
protected static function DoUpdateDBSchema($sMode, $sModulesDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sTargetEnvironment = '')
|
||||
protected static function DoUpdateDBSchema($sMode, $sModulesDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sTargetEnvironment = '', $bOldAddon = false)
|
||||
{
|
||||
SetupPage::log_info("Update Database Schema for environment '$sTargetEnvironment'.");
|
||||
|
||||
@@ -461,7 +486,14 @@ class ApplicationInstaller
|
||||
'db_prefix' => $sDBPrefix,
|
||||
);
|
||||
$oConfig->UpdateFromParams($aParamValues, $sModulesDir);
|
||||
|
||||
if ($bOldAddon)
|
||||
{
|
||||
// Old version of the add-on for backward compatibility with pre-2.0 data models
|
||||
$oConfig->SetAddons(array(
|
||||
'user rights' => 'addons/userrights/userrightsprofile.db.class.inc.php',
|
||||
));
|
||||
}
|
||||
|
||||
$oProductionEnv = new RunTimeEnvironment($sTargetEnvironment);
|
||||
$oProductionEnv->InitDataModel($oConfig, true); // load data model only
|
||||
|
||||
@@ -472,7 +504,7 @@ class ApplicationInstaller
|
||||
SetupPage::log_info("Database Schema Successfully Updated for environment '$sTargetEnvironment'.");
|
||||
}
|
||||
|
||||
protected static function AfterDBCreate($sMode, $sModulesDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sAdminUser, $sAdminPwd, $sAdminLanguage, $sLanguage, $aSelectedModules, $sTargetEnvironment = '')
|
||||
protected static function AfterDBCreate($sMode, $sModulesDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sAdminUser, $sAdminPwd, $sAdminLanguage, $sLanguage, $aSelectedModules, $sTargetEnvironment, $bOldAddon, $sDataModelVersion, $sSourceDir)
|
||||
{
|
||||
|
||||
SetupPage::log_info('After Database Creation');
|
||||
@@ -487,18 +519,27 @@ class ApplicationInstaller
|
||||
'db_prefix' => $sDBPrefix,
|
||||
);
|
||||
$oConfig->UpdateFromParams($aParamValues, $sModulesDir);
|
||||
|
||||
if ($bOldAddon)
|
||||
{
|
||||
// Old version of the add-on for backward compatibility with pre-2.0 data models
|
||||
$oConfig->SetAddons(array(
|
||||
'user rights' => 'addons/userrights/userrightsprofile.db.class.inc.php',
|
||||
));
|
||||
}
|
||||
$oConfig->Set('source_dir', $sSourceDir); // Needed by RecordInstallation below
|
||||
|
||||
$oProductionEnv = new RunTimeEnvironment($sTargetEnvironment);
|
||||
$oProductionEnv->InitDataModel($oConfig, false); // load data model and connect to the database
|
||||
$oProductionEnv->InitDataModel($oConfig, true); // load data model and connect to the database
|
||||
|
||||
self::$bMetaModelStarted = true; // No need to reload the final MetaModel in case the installer runs synchronously
|
||||
|
||||
// Perform here additional DB setup... profiles, etc...
|
||||
//
|
||||
$aAvailableModules = $oProductionEnv->AnalyzeInstallation(MetaModel::GetConfig(), $sModulesDir);
|
||||
$aAvailableModules = $oProductionEnv->AnalyzeInstallation(MetaModel::GetConfig(), APPROOT.$sModulesDir);
|
||||
foreach($aAvailableModules as $sModuleId => $aModule)
|
||||
{
|
||||
if (($sModuleId != ROOT_MODULE) && in_array($sModuleId, $aSelectedModules) &&
|
||||
isset($aAvailableModules[$sModuleId]['installer']) )
|
||||
isset($aAvailableModules[$sModuleId]['installer']) )
|
||||
{
|
||||
$sModuleInstallerClass = $aAvailableModules[$sModuleId]['installer'];
|
||||
SetupPage::log_info("Calling Module Handler: $sModuleInstallerClass::AfterDatabaseCreation(oConfig, {$aModule['version_db']}, {$aModule['version_code']})");
|
||||
@@ -555,7 +596,7 @@ class ApplicationInstaller
|
||||
}
|
||||
}
|
||||
|
||||
if (!$oProductionEnv->RecordInstallation($oConfig, $aSelectedModules, $sModulesDir))
|
||||
if (!$oProductionEnv->RecordInstallation($oConfig, $sDataModelVersion, $aSelectedModules, $sModulesDir))
|
||||
{
|
||||
throw new Exception("Failed to record the installation information");
|
||||
}
|
||||
@@ -591,7 +632,7 @@ class ApplicationInstaller
|
||||
}
|
||||
}
|
||||
|
||||
protected static function DoLoadFiles($aSelectedModules, $sModulesDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sTargetEnvironment = '')
|
||||
protected static function DoLoadFiles($aSelectedModules, $sModulesDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sTargetEnvironment = '', $bOldAddon = false)
|
||||
{
|
||||
$aParamValues = array(
|
||||
'db_server' => $sDBServer,
|
||||
@@ -604,7 +645,14 @@ class ApplicationInstaller
|
||||
$oConfig = new Config();
|
||||
|
||||
$oConfig->UpdateFromParams($aParamValues, $sModulesDir);
|
||||
|
||||
if ($bOldAddon)
|
||||
{
|
||||
// Old version of the add-on for backward compatibility with pre-2.0 data models
|
||||
$oConfig->SetAddons(array(
|
||||
'user rights' => 'addons/userrights/userrightsprofile.db.class.inc.php',
|
||||
));
|
||||
}
|
||||
|
||||
//Load the MetaModel if needed (asynchronous mode)
|
||||
if (!self::$bMetaModelStarted)
|
||||
{
|
||||
@@ -624,7 +672,7 @@ class ApplicationInstaller
|
||||
|
||||
$aFiles = array();
|
||||
$oProductionEnv = new RunTimeEnvironment();
|
||||
$aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, $sModulesDir);
|
||||
$aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, APPROOT.$sModulesDir);
|
||||
foreach($aAvailableModules as $sModuleId => $aModule)
|
||||
{
|
||||
if (($sModuleId != ROOT_MODULE))
|
||||
@@ -658,7 +706,7 @@ class ApplicationInstaller
|
||||
SetupPage::log_info("ending data load session");
|
||||
}
|
||||
|
||||
protected static function DoCreateConfig($sMode, $sModulesDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sUrl, $sLanguage, $aSelectedModules, $sTargetEnvironment = '')
|
||||
protected static function DoCreateConfig($sMode, $sModulesDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sUrl, $sLanguage, $aSelectedModules, $sTargetEnvironment, $bOldAddon, $sSourceDir, $sPreviousConfigFile)
|
||||
{
|
||||
$aParamValues = array(
|
||||
'db_server' => $sDBServer,
|
||||
@@ -668,20 +716,46 @@ class ApplicationInstaller
|
||||
'new_db_name' => $sDBName,
|
||||
'db_prefix' => $sDBPrefix,
|
||||
'application_path' => $sUrl,
|
||||
'mode' => $sMode,
|
||||
'language' => $sLanguage,
|
||||
'selected_modules' => implode(',', $aSelectedModules),
|
||||
);
|
||||
|
||||
$oConfig = new Config();
|
||||
$bPreserveModuleSettings = false;
|
||||
if ($sMode == 'upgrade')
|
||||
{
|
||||
try
|
||||
{
|
||||
$oOldConfig = new Config($sPreviousConfigFile);
|
||||
$oConfig = clone($oOldConfig);
|
||||
$bPreserveModuleSettings = true;
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
// In case the previous configuration is corrupted... start with a blank new one
|
||||
$oConfig = new Config();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$oConfig = new Config();
|
||||
}
|
||||
|
||||
|
||||
// Migration: force utf8_unicode_ci as the collation to make the global search
|
||||
// NON case sensitive
|
||||
$oConfig->SetDBCollation('utf8_unicode_ci');
|
||||
|
||||
// Final config update: add the modules
|
||||
$oConfig->UpdateFromParams($aParamValues, $sModulesDir);
|
||||
|
||||
$oConfig->UpdateFromParams($aParamValues, $sModulesDir, $bPreserveModuleSettings);
|
||||
if ($bOldAddon)
|
||||
{
|
||||
// Old version of the add-on for backward compatibility with pre-2.0 data models
|
||||
$oConfig->SetAddons(array(
|
||||
'user rights' => 'addons/userrights/userrightsprofile.db.class.inc.php',
|
||||
));
|
||||
}
|
||||
$oConfig->Set('source_dir', $sSourceDir);
|
||||
|
||||
// Make sure the root configuration directory exists
|
||||
if (!file_exists(APPCONF))
|
||||
{
|
||||
@@ -700,5 +774,7 @@ class ApplicationInstaller
|
||||
|
||||
// try to make the final config file read-only
|
||||
@chmod($sConfigFile, 0444); // Read-only for owner and group, nothing for others
|
||||
// Ready to go !!
|
||||
MetaModel::ResetCache($sTargetEnvironment);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,15 +27,14 @@ class DOMFormatException extends Exception
|
||||
class MFCompiler
|
||||
{
|
||||
protected $oFactory;
|
||||
protected $sSourceDir;
|
||||
protected $aSourceDirs;
|
||||
|
||||
protected $aRootClasses;
|
||||
protected $aLog;
|
||||
|
||||
public function __construct($oModelFactory, $sSourceDir)
|
||||
public function __construct($oModelFactory)
|
||||
{
|
||||
$this->oFactory = $oModelFactory;
|
||||
$this->sSourceDir = $sSourceDir;
|
||||
|
||||
$this->aLog = array();
|
||||
}
|
||||
@@ -97,7 +96,7 @@ class MFCompiler
|
||||
$sModuleVersion = $oModule->GetVersion();
|
||||
|
||||
$sModuleRootDir = realpath($oModule->GetRootDir());
|
||||
$sRelativeDir = substr($sModuleRootDir, strlen($this->sSourceDir) + 1);
|
||||
$sRelativeDir = basename($sModuleRootDir);
|
||||
|
||||
// Push the other module files
|
||||
SetupUtils::copydir($sModuleRootDir, $sTargetDir.'/'.$sRelativeDir, $bUseSymbolicLinks);
|
||||
@@ -878,11 +877,12 @@ EOF;
|
||||
{
|
||||
$sPHP .= "\nrequire_once('$sIncludeFile'); // Implementation of the class $sParentClass\n";
|
||||
}
|
||||
$sFullPath = $this->sSourceDir.'/'.$sModuleRelativeDir.'/'.$sIncludeFile;
|
||||
if (!file_exists($sFullPath))
|
||||
{
|
||||
throw new Exception("Failed to process class '".$oClass->getAttribute('id')."', from '$sModuleRelativeDir'. The required include file: '$sFullPath' does not exist.");
|
||||
}
|
||||
//TODO fix this !!!
|
||||
// $sFullPath = $this->sSourceDir.'/'.$sModuleRelativeDir.'/'.$sIncludeFile;
|
||||
// if (!file_exists($sFullPath))
|
||||
// {
|
||||
// throw new Exception("Failed to process class '".$oClass->getAttribute('id')."', from '$sModuleRelativeDir'. The required include file: '$sFullPath' does not exist.");
|
||||
// }
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1151,7 +1151,6 @@ EOF;
|
||||
|
||||
$sPHP =
|
||||
<<<EOF
|
||||
|
||||
//
|
||||
// List of constant profiles
|
||||
// - used by the class URP_Profiles at setup (create/update/delete records)
|
||||
|
||||
@@ -30,5 +30,12 @@ require_once(APPROOT.'/setup/setuppage.class.inc.php');
|
||||
require_once(APPROOT.'/setup/wizardcontroller.class.inc.php');
|
||||
require_once(APPROOT.'/setup/wizardsteps.class.inc.php');
|
||||
|
||||
clearstatcache(); // Make sure we know what we are doing !
|
||||
// Set a long (at least 4 minutes) execution time for the setup to avoid timeouts during this phase
|
||||
ini_set('max_execution_time', max(240, ini_get('max_execution_time')));
|
||||
// While running the setup it is desirable to see any error that may happen
|
||||
ini_set('display_errors', true);
|
||||
ini_set('display_startup_errors', true);
|
||||
|
||||
$oWizard = new WizardController('WizStepWelcome');
|
||||
$oWizard->Run();
|
||||
|
||||
@@ -1076,7 +1076,7 @@ EOF
|
||||
*/
|
||||
public function FindModules($sSubDirectory = '')
|
||||
{
|
||||
$aAvailableModules = ModuleDiscovery::GetAvailableModules($this->sRootDir, $sSubDirectory);
|
||||
$aAvailableModules = ModuleDiscovery::GetAvailableModules($this->sRootDir, array($sSubDirectory));
|
||||
$aResult = array();
|
||||
foreach($aAvailableModules as $sId => $aModule)
|
||||
{
|
||||
|
||||
@@ -30,11 +30,8 @@ class ModuleDiscovery
|
||||
);
|
||||
|
||||
|
||||
// Cache the results and the source directory
|
||||
// Note that, as class can be declared within the module files, they cannot be loaded twice.
|
||||
// Then the following assumption is made: within the same execution page, the module
|
||||
// discovery CANNOT be executed on several different paths
|
||||
protected static $m_sModulesRoot = null;
|
||||
// Cache the results and the source directories
|
||||
protected static $m_aSearchDirs = null;
|
||||
protected static $m_aModules = array();
|
||||
|
||||
// All the entries below are list of file paths relative to the module directory
|
||||
@@ -164,45 +161,44 @@ class ModuleDiscovery
|
||||
/**
|
||||
* Search (on the disk) for all defined iTop modules, load them and returns the list (as an array)
|
||||
* of the possible iTop modules to install
|
||||
* @param sRootDir Application root directory
|
||||
* @param sSearchDir Directory to search (relative to root dir)
|
||||
* @param aSearchDirs Array of directories to search (absolute paths)
|
||||
* @return Hash A big array moduleID => ModuleData
|
||||
*/
|
||||
public static function GetAvailableModules($sRootDir, $sSearchDir, $oP = null)
|
||||
public static function GetAvailableModules($aSearchDirs, $oP = null)
|
||||
{
|
||||
$sLookupDir = realpath($sRootDir.'/'.$sSearchDir);
|
||||
|
||||
if (self::$m_sModulesRoot != $sLookupDir)
|
||||
if (self::$m_aSearchDirs != $aSearchDirs)
|
||||
{
|
||||
self::ResetCache();
|
||||
}
|
||||
|
||||
if (is_null(self::$m_sModulesRoot))
|
||||
if (is_null(self::$m_aSearchDirs))
|
||||
{
|
||||
// First call
|
||||
//
|
||||
if ($sLookupDir == '')
|
||||
self::$m_aSearchDirs = $aSearchDirs;
|
||||
|
||||
// Not in cache, let's scan the disk
|
||||
foreach($aSearchDirs as $sSearchDir)
|
||||
{
|
||||
throw new Exception("Invalid directory '$sRootDir/$sSearchDir'");
|
||||
$sLookupDir = realpath($sSearchDir);
|
||||
if ($sLookupDir == '')
|
||||
{
|
||||
throw new Exception("Invalid directory '$sSearchDir'");
|
||||
}
|
||||
|
||||
clearstatcache();
|
||||
self::ListModuleFiles(basename($sSearchDir), dirname($sSearchDir));
|
||||
}
|
||||
self::$m_sModulesRoot = $sLookupDir;
|
||||
|
||||
clearstatcache();
|
||||
self::ListModuleFiles($sSearchDir, $sRootDir);
|
||||
return self::GetModules($oP);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reuse the previous results
|
||||
//
|
||||
return self::GetModules($oP);
|
||||
}
|
||||
}
|
||||
|
||||
public static function ResetCache()
|
||||
{
|
||||
self::$m_sModulesRoot = null;
|
||||
self::$m_sModulesRoot = null;
|
||||
self::$m_aSearchDirs = null;
|
||||
self::$m_aModules = array();
|
||||
}
|
||||
|
||||
@@ -233,6 +229,8 @@ class ModuleDiscovery
|
||||
*/
|
||||
protected static function ListModuleFiles($sRelDir, $sRootDir)
|
||||
{
|
||||
static $iDummyClassIndex = 0;
|
||||
static $aDefinedClasses = array();
|
||||
$sDirectory = $sRootDir.'/'.$sRelDir;
|
||||
|
||||
if ($hDir = opendir($sDirectory))
|
||||
@@ -253,15 +251,35 @@ class ModuleDiscovery
|
||||
self::SetModulePath($sRelDir);
|
||||
try
|
||||
{
|
||||
//echo "<p>Loading: $sDirectory/$sFile...</p>\n";
|
||||
//SetupPage::log_info("Discovered module $sFile");
|
||||
require($sDirectory.'/'.$sFile); // WARNING require_once will NOT work IIF doing an unattended installation WITH symbolic links
|
||||
// since datamodel/xxx/module.xxx.php and env-production/xxx/module.xxx.php are actually the same file (= inode)
|
||||
$sModuleFileContents = file_get_contents($sDirectory.'/'.$sFile);
|
||||
$sModuleFileContents = str_replace(array('<?php', '?>'), '', $sModuleFileContents);
|
||||
$sModuleFileContents = str_replace('__FILE__', "'".addslashes($sDirectory.'/'.$sFile)."'", $sModuleFileContents);
|
||||
preg_match_all('/class ([A-Za-z0-9_]+) extends ([A-Za-z0-9_]+)/', $sModuleFileContents, $aMatches);
|
||||
//print_r($aMatches);
|
||||
$idx = 0;
|
||||
foreach($aMatches[1] as $sClassName)
|
||||
{
|
||||
if (class_exists($sClassName))
|
||||
{
|
||||
// rename the class inside the code to prevent a "duplicate class" declaration
|
||||
// and change its parent class as well so that nobody will find it and try to execute it
|
||||
$sModuleFileContents = str_replace($sClassName.' extends '.$aMatches[2][$idx], $sClassName.'_'.($iDummyClassIndex++).' extends DummyHandler', $sModuleFileContents);
|
||||
}
|
||||
$idx++;
|
||||
}
|
||||
$bRet = eval($sModuleFileContents);
|
||||
|
||||
if ($bRet === false)
|
||||
{
|
||||
SetupPage::log_warning("Eval of $sRelDir/$sFile returned false");
|
||||
}
|
||||
|
||||
//echo "<p>Done.</p>\n";
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
// Continue...
|
||||
SetupPage::log_warning("Eval of $sRelDir/$sFile caused an exception: ".$e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -279,6 +297,41 @@ class ModuleDiscovery
|
||||
* the declaration of a module invokes SetupWebPage::AddModule()
|
||||
* whereas the new form is ModuleDiscovery::AddModule()
|
||||
*/
|
||||
class SetupWebPage extends ModuleDiscovery{}
|
||||
class SetupWebPage extends ModuleDiscovery
|
||||
{
|
||||
// For backward compatibility with old modules...
|
||||
public static function log_error($sText)
|
||||
{
|
||||
SetupPage::log_error($sText);
|
||||
}
|
||||
|
||||
?>
|
||||
public static function log_warning($sText)
|
||||
{
|
||||
SetupPage::log_warning($sText);
|
||||
}
|
||||
|
||||
public static function log_info($sText)
|
||||
{
|
||||
SetupPage::log_info($sText);
|
||||
}
|
||||
|
||||
public static function log_ok($sText)
|
||||
{
|
||||
SetupPage::log_ok($sText);
|
||||
}
|
||||
|
||||
public static function log($sText)
|
||||
{
|
||||
SetupPage::log($sText);
|
||||
}
|
||||
}
|
||||
|
||||
/** Ugly patch !!!
|
||||
* In order to be able to analyse / load several times
|
||||
* the same module file, we rename the class (to avoid duplicate class definitions)
|
||||
* and we make the class extends the dummy class below in order to "deactivate" completely
|
||||
* the class (in case some piece of code enumerate the classes derived from a well known class)
|
||||
* Note that this will not work if someone enumerates the classes that implement a given interface
|
||||
*/
|
||||
class DummyHandler {
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ define ('MODULE_ACTION_OPTIONAL', 1);
|
||||
define ('MODULE_ACTION_MANDATORY', 2);
|
||||
define ('MODULE_ACTION_IMPOSSIBLE', 3);
|
||||
define ('ROOT_MODULE', '_Root_'); // Convention to store IN MEMORY the name/version of the root module i.e. application
|
||||
define ('DATAMODEL_MODULE', 'datamodel'); // Convention to store the version of the datamodel
|
||||
|
||||
class RunTimeEnvironment
|
||||
{
|
||||
@@ -91,7 +92,8 @@ class RunTimeEnvironment
|
||||
/**
|
||||
* Analyzes the current installation and the possibilities
|
||||
*
|
||||
* @param $oConfig Config Defines the target environment (DB)
|
||||
* @param Config $oConfig Defines the target environment (DB)
|
||||
* @param mixed $modulesPath Either a single string or an array of absolute paths
|
||||
* @return hash Array with the following format:
|
||||
* array =>
|
||||
* 'iTop' => array(
|
||||
@@ -115,7 +117,7 @@ class RunTimeEnvironment
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function AnalyzeInstallation($oConfig, $sModulesRelativePath)
|
||||
public function AnalyzeInstallation($oConfig, $modulesPath)
|
||||
{
|
||||
$aRes = array(
|
||||
ROOT_MODULE => array(
|
||||
@@ -126,7 +128,8 @@ class RunTimeEnvironment
|
||||
)
|
||||
);
|
||||
|
||||
$aModules = ModuleDiscovery::GetAvailableModules(APPROOT, $sModulesRelativePath);
|
||||
$aDirs = is_array($modulesPath) ? $modulesPath : array($modulesPath);
|
||||
$aModules = ModuleDiscovery::GetAvailableModules($aDirs);
|
||||
foreach($aModules as $sModuleId => $aModuleInfo)
|
||||
{
|
||||
list($sModuleName, $sModuleVersion) = ModuleDiscovery::GetModuleName($sModuleId);
|
||||
@@ -137,7 +140,8 @@ class RunTimeEnvironment
|
||||
if ($sModuleVersion == '')
|
||||
{
|
||||
// The version must not be empty (it will be used as a criteria to determine wether a module has been installed or not)
|
||||
throw new Exception("Missing version for the module: '$sModuleId'");
|
||||
//throw new Exception("Missing version for the module: '$sModuleId'");
|
||||
$sModuleVersion = '1.0.0';
|
||||
}
|
||||
|
||||
$sModuleAppVersion = $aModuleInfo['itop_version'];
|
||||
@@ -225,7 +229,7 @@ class RunTimeEnvironment
|
||||
//
|
||||
foreach ($aInstallByModule as $sModuleName => $aModuleDB)
|
||||
{
|
||||
if ($sModuleName == ROOT_MODULE) continue; // Skip the main module
|
||||
if ($sModuleName == ROOT_MODULE) continue; // Skip the main module
|
||||
|
||||
if (!array_key_exists($sModuleName, $aRes))
|
||||
{
|
||||
@@ -284,7 +288,7 @@ class RunTimeEnvironment
|
||||
//
|
||||
$oSourceConfig = new Config(APPCONF.$sSourceEnv.'/'.ITOP_CONFIG_FILE);
|
||||
$oSourceEnv = new RunTimeEnvironment($sSourceEnv);
|
||||
$aAvailableModules = $oSourceEnv->AnalyzeInstallation($oSourceConfig, $sSourceDir);
|
||||
$aAvailableModules = $oSourceEnv->AnalyzeInstallation($oSourceConfig, $sSourceDir); //TODO: use an absolute PATH
|
||||
|
||||
// Do load the required modules
|
||||
//
|
||||
@@ -419,8 +423,19 @@ class RunTimeEnvironment
|
||||
return true;
|
||||
}
|
||||
|
||||
public function RecordInstallation(Config $oConfig, $aSelectedModules, $sModulesRelativePath)
|
||||
public function RecordInstallation(Config $oConfig, $sDataModelVersion, $aSelectedModules, $sModulesRelativePath)
|
||||
{
|
||||
// Record datamodel version
|
||||
$aData = array(
|
||||
'source_dir' => $oConfig->Get('source_dir'),
|
||||
);
|
||||
$oInstallRec = new ModuleInstallation();
|
||||
$oInstallRec->Set('name', DATAMODEL_MODULE);
|
||||
$oInstallRec->Set('version', $sDataModelVersion);
|
||||
$oInstallRec->Set('comment', json_encode($aData, true));
|
||||
$oInstallRec->Set('parent_id', 0); // root module
|
||||
$iMainItopRecord = $oInstallRec->DBInsertNoReload();
|
||||
|
||||
// Record main installation
|
||||
$oInstallRec = new ModuleInstallation();
|
||||
$oInstallRec->Set('name', ITOP_APPLICATION);
|
||||
@@ -429,9 +444,10 @@ class RunTimeEnvironment
|
||||
$oInstallRec->Set('parent_id', 0); // root module
|
||||
$iMainItopRecord = $oInstallRec->DBInsertNoReload();
|
||||
|
||||
|
||||
// Record installed modules
|
||||
//
|
||||
$aAvailableModules = $this->AnalyzeInstallation($oConfig, $sModulesRelativePath);
|
||||
$aAvailableModules = $this->AnalyzeInstallation($oConfig, APPROOT.$sModulesRelativePath);
|
||||
foreach($aSelectedModules as $sModuleId)
|
||||
{
|
||||
$aModuleData = $aAvailableModules[$sModuleId];
|
||||
@@ -471,6 +487,60 @@ class RunTimeEnvironment
|
||||
// Database is created, installation has been tracked into it
|
||||
return true;
|
||||
}
|
||||
|
||||
public function GetApplicationVersion(Config $oConfig)
|
||||
{
|
||||
$aResult = false;
|
||||
try
|
||||
{
|
||||
require_once(APPROOT.'/core/cmdbsource.class.inc.php');
|
||||
CMDBSource::Init($oConfig->GetDBHost(), $oConfig->GetDBUser(), $oConfig->GetDBPwd(), $oConfig->GetDBName());
|
||||
$aSelectInstall = CMDBSource::QueryToArray("SELECT * FROM ".$oConfig->GetDBSubname()."priv_module_install");
|
||||
}
|
||||
catch (MySQLException $e)
|
||||
{
|
||||
// No database or erroneous information
|
||||
return false;
|
||||
}
|
||||
|
||||
// Scan the list of installed modules to get the version of the 'ROOT' module which holds the main application version
|
||||
foreach ($aSelectInstall as $aInstall)
|
||||
{
|
||||
$sModuleVersion = $aInstall['version'];
|
||||
if ($sModuleVersion == '')
|
||||
{
|
||||
// Though the version cannot be empty in iTop 2.0, it used to be possible
|
||||
// therefore we have to put something here or the module will not be considered
|
||||
// as being installed
|
||||
$sModuleVersion = '0.0.0';
|
||||
}
|
||||
|
||||
if ($aInstall['parent_id'] == 0)
|
||||
{
|
||||
if ($aInstall['name'] == DATAMODEL_MODULE)
|
||||
{
|
||||
$aResult['datamodel_version'] = $sModuleVersion;
|
||||
$aComments = json_decode($aInstall['comment'], true);
|
||||
if (is_array($aComments))
|
||||
{
|
||||
$aResult = array_merge($aResult, $aComments);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aResult['product_name'] = $aInstall['name'];
|
||||
$aResult['product_version'] = $sModuleVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!array_key_exists('datamodel_version', $aResult))
|
||||
{
|
||||
// Versions prior to 2.0 did not record the version of the datamodel
|
||||
// so assume that the datamodel version is equal to the application version
|
||||
$aResult['datamodel_version'] = $aResult['product_version'];
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
public static function MakeDirSafe($sDir)
|
||||
{
|
||||
@@ -501,6 +571,3 @@ class RunTimeEnvironment
|
||||
SetupPage::log_ok($sText);
|
||||
}
|
||||
} // End of class
|
||||
|
||||
|
||||
?>
|
||||
|
||||
@@ -304,5 +304,3 @@ h3.clickable.open {
|
||||
}
|
||||
}
|
||||
} // End of class
|
||||
|
||||
?>
|
||||
|
||||
@@ -657,7 +657,7 @@ function DoCheckDBConnection()
|
||||
'db_pwd': $("#db_pwd").val(),
|
||||
'db_name': $("#db_name").val()
|
||||
}
|
||||
if (oXHRCheckDB !== null)
|
||||
if ((oXHRCheckDB != null) && (oXHRCheckDB != undefined))
|
||||
{
|
||||
oXHRCheckDB.abort();
|
||||
oXHRCheckDB = null;
|
||||
@@ -937,6 +937,21 @@ EOF
|
||||
{
|
||||
require_once(APPROOT.'/setup/moduleinstaller.class.inc.php');
|
||||
$oConfig = new Config();
|
||||
$sSourceDir = $oWizard->GetParameter('source_dir', '');
|
||||
|
||||
if (strpos($sSourceDir, APPROOT) !== false)
|
||||
{
|
||||
$sRelativeSourceDir = str_replace(APPROOT, '', $sSourceDir);
|
||||
}
|
||||
else if (strpos($sSourceDir, $oWizard->GetParameter('previous_version_dir')) !== false)
|
||||
{
|
||||
$sRelativeSourceDir = str_replace($oWizard->GetParameter('previous_version_dir'), '', $sSourceDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw(new Exception('Internal error: AnalyzeInstallation: source_dir is neither under APPROOT nor under previous_installation_dir ???'));
|
||||
}
|
||||
|
||||
|
||||
$aParamValues = array(
|
||||
'db_server' => $oWizard->GetParameter('db_server', ''),
|
||||
@@ -944,16 +959,43 @@ EOF
|
||||
'db_pwd' => $oWizard->GetParameter('db_pwd', ''),
|
||||
'db_name' => $oWizard->GetParameter('db_name', ''),
|
||||
'db_prefix' => $oWizard->GetParameter('db_prefix', ''),
|
||||
'source_dir' => APPROOT.'datamodel',
|
||||
'source_dir' => $sRelativeSourceDir,
|
||||
);
|
||||
$oConfig->UpdateFromParams($aParamValues, 'datamodel');
|
||||
$aDirsToScan = array($sSourceDir);
|
||||
|
||||
if (is_dir($sSourceDir.'/extensions'))
|
||||
{
|
||||
$aDirsToScan[] = $sSourceDir.'/extensions';
|
||||
}
|
||||
if (is_dir($oWizard->GetParameter('copy_extensions_from')))
|
||||
{
|
||||
$aDirsToScan[] = $oWizard->GetParameter('copy_extensions_from');
|
||||
}
|
||||
$oProductionEnv = new RunTimeEnvironment();
|
||||
$aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, 'datamodel');
|
||||
$aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, $aDirsToScan);
|
||||
|
||||
return $aAvailableModules;
|
||||
}
|
||||
|
||||
public static function GetApplicationVersion($oWizard)
|
||||
{
|
||||
require_once(APPROOT.'/setup/moduleinstaller.class.inc.php');
|
||||
$oConfig = new Config();
|
||||
|
||||
$aParamValues = array(
|
||||
'db_server' => $oWizard->GetParameter('db_server', ''),
|
||||
'db_user' => $oWizard->GetParameter('db_user', ''),
|
||||
'db_pwd' => $oWizard->GetParameter('db_pwd', ''),
|
||||
'db_name' => $oWizard->GetParameter('db_name', ''),
|
||||
'db_prefix' => $oWizard->GetParameter('db_prefix', ''),
|
||||
'source_dir' => '',
|
||||
);
|
||||
$oConfig->UpdateFromParams($aParamValues, 'datamodel');
|
||||
|
||||
$oProductionEnv = new RunTimeEnvironment();
|
||||
return $oProductionEnv->GetApplicationVersion($oConfig);
|
||||
}
|
||||
/**
|
||||
* Checks if the content of a directory matches the given manifest
|
||||
* @param string $sBaseDir Path to the root directory of iTop
|
||||
@@ -964,6 +1006,7 @@ EOF
|
||||
*/
|
||||
public static function CheckDirAgainstManifest($sBaseDir, $sSourceDir, $aManifest, $aExcludeNames = array('.svn'), $aResult = null)
|
||||
{
|
||||
//echo "CheckDirAgainstManifest($sBaseDir, $sSourceDir ...)\n";
|
||||
if ($aResult === null)
|
||||
{
|
||||
$aResult = array('added' => array(), 'removed' => array(), 'modified' => array());
|
||||
@@ -990,10 +1033,13 @@ EOF
|
||||
}
|
||||
}
|
||||
|
||||
//echo "The manifest contains ".count($aDirManifest)." files for the directory '$sSourceDir' (and below)\n";
|
||||
|
||||
// Read the content of the directory
|
||||
foreach(glob($sBaseDir.'/'.$sSourceDir .'/*') as $sFilePath)
|
||||
{
|
||||
$sFile = basename($sFilePath);
|
||||
//echo "Checking $sFile ($sFilePath)\n";
|
||||
|
||||
if (in_array(basename($sFile), $aExcludeNames)) continue;
|
||||
|
||||
@@ -1023,6 +1069,7 @@ EOF
|
||||
if ($sMD5 != $aDirManifest[$sFile]['md5'])
|
||||
{
|
||||
$aResult['modified'][$sSourceDir.'/'.$sFile] = 'Content modified (MD5 checksums differ).';
|
||||
//echo $sSourceDir.'/'.$sFile." modified ($sMD5 == {$aDirManifest[$sFile]['md5']})\n";
|
||||
}
|
||||
//else
|
||||
//{
|
||||
@@ -1051,9 +1098,10 @@ EOF
|
||||
$aManifest[] = array('path' => (string)$oFileInfo->path, 'size' => (int)$oFileInfo->size, 'md5' => (string)$oFileInfo->md5);
|
||||
}
|
||||
|
||||
$sBaseDir = preg_replace('|modules/?$|', '', $sBaseDir);
|
||||
$aResults = self::CheckDirAgainstManifest($sBaseDir, 'modules', $aManifest);
|
||||
|
||||
// echo "<pre>Comparison of ".dirname($sBaseDir)."/modules:\n".print_r($aResults, true)."</pre>";
|
||||
// echo "<pre>Comparison of ".dirname($sBaseDir)."/modules against $sManifestFile:\n".print_r($aResults, true)."</pre>";
|
||||
return $aResults;
|
||||
}
|
||||
|
||||
@@ -1084,7 +1132,7 @@ EOF
|
||||
$aResults = array('added' => array(), 'removed' => array(), 'modified' => array());
|
||||
foreach(array('addons', 'core', 'dictionaries', 'js', 'application', 'css', 'pages', 'synchro', 'webservices') as $sDir)
|
||||
{
|
||||
$aTmp = self::CheckDirAgainstManifest($sBaseDir, 'portal', $aManifest);
|
||||
$aTmp = self::CheckDirAgainstManifest($sBaseDir, $sDir, $aManifest);
|
||||
$aResults['added'] = array_merge($aResults['added'], $aTmp['added']);
|
||||
$aResults['modified'] = array_merge($aResults['modified'], $aTmp['modified']);
|
||||
$aResults['removed'] = array_merge($aResults['removed'], $aTmp['removed']);
|
||||
@@ -1094,4 +1142,99 @@ EOF
|
||||
return $aResults;
|
||||
}
|
||||
|
||||
public static function CheckVersion($sInstalledVersion, $sSourceDir)
|
||||
{
|
||||
$sManifestFilePath = self::GetVersionManifest($sInstalledVersion);
|
||||
if ($sSourceDir != '')
|
||||
{
|
||||
if (file_exists($sManifestFilePath))
|
||||
{
|
||||
$aDMchanges = self::CheckDataModelFiles($sManifestFilePath, $sSourceDir);
|
||||
//$aPortalChanges = self::CheckPortalFiles($sManifestFilePath, $sSourceDir);
|
||||
//$aCodeChanges = self::CheckApplicationFiles($sManifestFilePath, $sSourceDir);
|
||||
|
||||
//echo("Changes detected compared to $sInstalledVersion:<br/>DataModel:<br/><pre>".print_r($aDMchanges, true)."</pre>");
|
||||
//echo("Changes detected compared to $sInstalledVersion:<br/>DataModel:<br/><pre>".print_r($aDMchanges, true)."</pre><br/>Portal:<br/><pre>".print_r($aPortalChanges, true)."</pre><br/>Code:<br/><pre>".print_r($aCodeChanges, true)."</pre>");
|
||||
return $aDMchanges;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw(new Exception("Cannot check version '$sInstalledVersion', no source directory provided to check the files."));
|
||||
}
|
||||
}
|
||||
|
||||
public static function GetVersionManifest($sInstalledVersion)
|
||||
{
|
||||
if (preg_match('/^([0-9]+)\./', $sInstalledVersion, $aMatches))
|
||||
{
|
||||
return APPROOT.'datamodels/'.$aMatches[1].'.x/manifest-'.$sInstalledVersion.'.xml';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function CheckWritableDirs($aWritableDirs)
|
||||
{
|
||||
$aNonWritableDirs = array();
|
||||
foreach($aWritableDirs as $sDir)
|
||||
{
|
||||
$sFullPath = APPROOT.$sDir;
|
||||
if (is_dir($sFullPath) && !is_writable($sFullPath))
|
||||
{
|
||||
$aNonWritableDirs[APPROOT.$sDir] = new CheckResult(CheckResult::ERROR, "The directory '".APPROOT.$sDir."' exists but is not writable for the application.");
|
||||
}
|
||||
else if (file_exists($sFullPath) && !is_dir($sFullPath))
|
||||
{
|
||||
$aNonWritableDirs[APPROOT.$sDir] = new CheckResult(CheckResult::ERROR, "A file with the same name as '".APPROOT.$sDir."' exists.");
|
||||
}
|
||||
else if (!is_dir($sFullPath) && !is_writable(APPROOT))
|
||||
{
|
||||
$aNonWritableDirs[APPROOT] = new CheckResult(CheckResult::ERROR, "The directory '".APPROOT."' is not writable, the application cannot create the directory '$sDir' inside it.");
|
||||
}
|
||||
}
|
||||
return $aNonWritableDirs;
|
||||
}
|
||||
|
||||
public static function GetLatestDataModelDir()
|
||||
{
|
||||
$sBaseDir = APPROOT.'datamodels';
|
||||
|
||||
$aDirs = glob($sBaseDir.'/*', GLOB_MARK | GLOB_ONLYDIR);
|
||||
if ($aDirs !== false)
|
||||
{
|
||||
sort($aDirs);
|
||||
|
||||
return array_pop($aDirs);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function GetCompatibleDataModelDir($sInstalledVersion)
|
||||
{
|
||||
if (preg_match('/^([0-9]+)\./', $sInstalledVersion, $aMatches))
|
||||
{
|
||||
$sMajorVersion = $aMatches[1];
|
||||
$sDir = APPROOT.'datamodels/'.$sMajorVersion.'.x/';
|
||||
if (is_dir($sDir))
|
||||
{
|
||||
return $sDir;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static public function GetDataModelVersion($sDatamodelDir)
|
||||
{
|
||||
$sVersionFile = $sDatamodelDir.'version.xml';
|
||||
if (file_exists($sVersionFile))
|
||||
{
|
||||
$oParams = new XMLParameters($sVersionFile);
|
||||
return $oParams->Get('version');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -164,6 +164,23 @@ class WizardController
|
||||
protected function DisplayStep(WizardStep $oStep)
|
||||
{
|
||||
$oPage = new SetupPage($oStep->GetTitle());
|
||||
if ($oStep->RequiresWritableConfig())
|
||||
{
|
||||
$sConfigFile = utils::GetConfigFilePath();
|
||||
if (file_exists($sConfigFile))
|
||||
{
|
||||
// The configuration file already exists
|
||||
if (!is_writable($sConfigFile))
|
||||
{
|
||||
$oP = new SetupPage('Installation Cannot Continue');
|
||||
$oP->add("<h2>Fatal error</h2>\n");
|
||||
$oP->error("<b>Error:</b> the configuration file '".$sConfigFile."' already exists and cannot be overwritten.");
|
||||
$oP->p("The wizard cannot modify the configuration file for you. If you want to upgrade ".ITOP_APPLICATION.", make sure that the file '<b>".realpath($sConfigFile)."</b>' can be modified by the web server.");
|
||||
$oP->output();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
$oPage->add_linked_script('../setup/setup.js');
|
||||
$oPage->add_script("function CanMoveForward()\n{\n".$oStep->JSCanMoveForward()."\n}\n");
|
||||
$oPage->add_script("function CanMoveBackward()\n{\n".$oStep->JSCanMoveBackward()."\n}\n");
|
||||
@@ -432,6 +449,15 @@ abstract class WizardStep
|
||||
return 'return true;';
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload this function to implement asynchronous action(s) (AJAX)
|
||||
* @param string $sCode The code of the action (if several actions need to be distinguished)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user