public function __construct($sId, $sRootDir, $sLabel) { $this->sId = $sId; list($this->sName, $this->sVersion) = ModuleDiscovery::GetModuleName($sId); if (strlen($this->sVersion) == 0) { $this->sVersion = '1.0.0'; } $this->sRootDir = $sRootDir; $this->sLabel = $sLabel; $this->aDataModels = array(); // Scan the module's root directory to find the datamodel(*).xml files if ($hDir = opendir($sRootDir)) { // This is the correct way to loop over the directory. (according to the documentation) while (($sFile = readdir($hDir)) !== false) { if (preg_match('/^datamodel(.*)\\.xml$/i', $sFile, $aMatches)) { $this->aDataModels[] = $this->sRootDir . '/' . $aMatches[0]; } } closedir($hDir); } }
/** * Helper function to rebuild the default configuration and the list of includes from a directory and a list of selected modules * @param string $sModulesDir The relative path to the directory to scan for modules (typically the 'env-xxx' directory resulting from the compilation) * @param array $aSelectedModules An array of selected modules' identifiers. If null all modules found will be considered as installed * @throws Exception */ public function UpdateIncludes($sModulesDir, $aSelectedModules = null) { if (!is_null($sModulesDir)) { // Initialize the arrays below with default values for the application... $oEmptyConfig = new Config('dummy_file', false); // Do NOT load any config file, just set the default values $aAddOns = $oEmptyConfig->GetAddOns(); $aAppModules = $oEmptyConfig->GetAppModules(); if (file_exists(APPROOT . $sModulesDir . '/core/main.php')) { $aAppModules[] = $sModulesDir . '/core/main.php'; } $aDataModels = $oEmptyConfig->GetDataModels(); $aWebServiceCategories = $oEmptyConfig->GetWebServiceCategories(); $aDictionaries = $oEmptyConfig->GetDictionaries(); // Merge the values with the ones provided by the modules // Make sure when don't load the same file twice... $aModules = ModuleDiscovery::GetAvailableModules(array(APPROOT . $sModulesDir)); foreach ($aModules as $sModuleId => $aModuleInfo) { list($sModuleName, $sModuleVersion) = ModuleDiscovery::GetModuleName($sModuleId); if (is_null($aSelectedModules) || in_array($sModuleName, $aSelectedModules)) { if (isset($aModuleInfo['datamodel'])) { $aDataModels = array_unique(array_merge($aDataModels, $aModuleInfo['datamodel'])); } if (isset($aModuleInfo['webservice'])) { $aWebServiceCategories = array_unique(array_merge($aWebServiceCategories, $aModuleInfo['webservice'])); } if (isset($aModuleInfo['settings'])) { list($sName, $sVersion) = ModuleDiscovery::GetModuleName($sModuleId); foreach ($aModuleInfo['settings'] as $sProperty => $value) { if (isset($this->m_aModuleSettings[$sName][$sProperty])) { // Do nothing keep the original value } else { $this->SetModuleSetting($sName, $sProperty, $value); } } } if (isset($aModuleInfo['installer'])) { $sModuleInstallerClass = $aModuleInfo['installer']; if (!class_exists($sModuleInstallerClass)) { throw new Exception("Wrong installer class: '{$sModuleInstallerClass}' is not a PHP class - Module: " . $aModuleInfo['label']); } if (!is_subclass_of($sModuleInstallerClass, 'ModuleInstallerAPI')) { throw new Exception("Wrong installer class: '{$sModuleInstallerClass}' is not derived from 'ModuleInstallerAPI' - Module: " . $aModuleInfo['label']); } $aCallSpec = array($sModuleInstallerClass, 'BeforeWritingConfig'); call_user_func_array($aCallSpec, array($this)); } } } $this->SetAddOns($aAddOns); $this->SetAppModules($aAppModules); $this->SetDataModels($aDataModels); $this->SetWebServiceCategories($aWebServiceCategories); // Scan dictionaries // foreach (glob(APPROOT . $sModulesDir . '/dictionaries/*.dict.php') as $sFilePath) { $sFile = basename($sFilePath); $aDictionaries[] = $sModulesDir . '/dictionaries/' . $sFile; } $this->SetDictionaries($aDictionaries); } }
/** * Helper function to initialize a configuration from the page arguments */ public function UpdateFromParams($aParamValues, $sModulesDir = null, $bPreserveModuleSettings = false) { if (isset($aParamValues['application_path'])) { $this->Set('app_root_url', $aParamValues['application_path']); } if (isset($aParamValues['mode']) && isset($aParamValues['language'])) { if ($aParamValues['mode'] == 'install' || $this->GetDefaultLanguage() == '') { $this->SetDefaultLanguage($aParamValues['language']); } } if (isset($aParamValues['db_server'])) { $this->SetDBHost($aParamValues['db_server']); $this->SetDBUser($aParamValues['db_user']); $this->SetDBPwd($aParamValues['db_pwd']); $sDBName = $aParamValues['db_name']; if ($sDBName == '') { // Todo - obsolete after the transition to the new setup (2.0) is complete (WARNING: used by the designer) $sDBName = $aParamValues['new_db_name']; } $this->SetDBName($sDBName); $this->SetDBSubname($aParamValues['db_prefix']); } if (!is_null($sModulesDir)) { if (isset($aParamValues['selected_modules'])) { $aSelectedModules = explode(',', $aParamValues['selected_modules']); } else { $aSelectedModules = null; } // Initialize the arrays below with default values for the application... $oEmptyConfig = new Config('dummy_file', false); // Do NOT load any config file, just set the default values $aAddOns = $oEmptyConfig->GetAddOns(); $aAppModules = $oEmptyConfig->GetAppModules(); $aDataModels = $oEmptyConfig->GetDataModels(); $aWebServiceCategories = $oEmptyConfig->GetWebServiceCategories(); $aDictionaries = $oEmptyConfig->GetDictionaries(); // Merge the values with the ones provided by the modules // Make sure when don't load the same file twice... $aModules = ModuleDiscovery::GetAvailableModules(array(APPROOT . $sModulesDir)); foreach ($aModules as $sModuleId => $aModuleInfo) { list($sModuleName, $sModuleVersion) = ModuleDiscovery::GetModuleName($sModuleId); if (is_null($aSelectedModules) || in_array($sModuleName, $aSelectedModules)) { if (isset($aModuleInfo['datamodel'])) { $aDataModels = array_unique(array_merge($aDataModels, $aModuleInfo['datamodel'])); } if (isset($aModuleInfo['webservice'])) { $aWebServiceCategories = array_unique(array_merge($aWebServiceCategories, $aModuleInfo['webservice'])); } if (isset($aModuleInfo['settings'])) { list($sName, $sVersion) = ModuleDiscovery::GetModuleName($sModuleId); foreach ($aModuleInfo['settings'] as $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'])) { $sModuleInstallerClass = $aModuleInfo['installer']; if (!class_exists($sModuleInstallerClass)) { throw new Exception("Wrong installer class: '{$sModuleInstallerClass}' is not a PHP class - Module: " . $aModuleInfo['label']); } if (!is_subclass_of($sModuleInstallerClass, 'ModuleInstallerAPI')) { throw new Exception("Wrong installer class: '{$sModuleInstallerClass}' is not derived from 'ModuleInstallerAPI' - Module: " . $aModuleInfo['label']); } $aCallSpec = array($sModuleInstallerClass, 'BeforeWritingConfig'); call_user_func_array($aCallSpec, array($this)); } } } $this->SetAddOns($aAddOns); $this->SetAppModules($aAppModules); $this->SetDataModels($aDataModels); $this->SetWebServiceCategories($aWebServiceCategories); // Scan dictionaries // if (!is_null($sModulesDir)) { foreach (glob(APPROOT . $sModulesDir . '/dictionaries/*.dict.php') as $sFilePath) { $sFile = basename($sFilePath); $aDictionaries[] = $sModulesDir . '/dictionaries/' . $sFile; } } $this->SetDictionaries($aDictionaries); } }
/** * Analyzes the current installation and the possibilities * * @param Config $oConfig Defines the target environment (DB) * @param mixed $modulesPath Either a single string or an array of absolute paths * @param bool $bAbortOnMissingDependency ... * @param hash $aModulesToLoad List of modules to search for, defaults to all if ommitted * @return hash Array with the following format: * array => * 'iTop' => array( * 'version_db' => ... (could be empty in case of a fresh install) * 'version_code => ... * ) * <module_name> => array( * 'version_db' => ... * 'version_code' => ... * 'install' => array( * 'flag' => SETUP_NEVER | SETUP_OPTIONAL | SETUP_MANDATORY * 'message' => ... * ) * 'uninstall' => array( * 'flag' => SETUP_NEVER | SETUP_OPTIONAL | SETUP_MANDATORY * 'message' => ... * ) * 'label' => ... * 'dependencies' => array(<module1>, <module2>, ...) * 'visible' => true | false * ) * ) */ public function AnalyzeInstallation($oConfig, $modulesPath, $bAbortOnMissingDependency = false, $aModulesToLoad = null) { $aRes = array(ROOT_MODULE => array('version_db' => '', 'name_db' => '', 'version_code' => ITOP_VERSION . '.' . ITOP_REVISION, 'name_code' => ITOP_APPLICATION)); $aDirs = is_array($modulesPath) ? $modulesPath : array($modulesPath); $aModules = ModuleDiscovery::GetAvailableModules($aDirs, $bAbortOnMissingDependency, $aModulesToLoad); foreach ($aModules as $sModuleId => $aModuleInfo) { list($sModuleName, $sModuleVersion) = ModuleDiscovery::GetModuleName($sModuleId); if ($sModuleName == '') { throw new Exception("Missing name for the module: '{$sModuleId}'"); } 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'"); $sModuleVersion = '1.0.0'; } $sModuleAppVersion = $aModuleInfo['itop_version']; $aModuleInfo['version_db'] = ''; $aModuleInfo['version_code'] = $sModuleVersion; if (!in_array($sModuleAppVersion, array('1.0.0', '1.0.1', '1.0.2'))) { // This module is NOT compatible with the current version $aModuleInfo['install'] = array('flag' => MODULE_ACTION_IMPOSSIBLE, 'message' => 'the module is not compatible with the current version of the application'); } elseif ($aModuleInfo['mandatory']) { $aModuleInfo['install'] = array('flag' => MODULE_ACTION_MANDATORY, 'message' => 'the module is part of the application'); } else { $aModuleInfo['install'] = array('flag' => MODULE_ACTION_OPTIONAL, 'message' => ''); } $aRes[$sModuleName] = $aModuleInfo; } try { require_once APPROOT . '/core/cmdbsource.class.inc.php'; CMDBSource::Init($oConfig->GetDBHost(), $oConfig->GetDBUser(), $oConfig->GetDBPwd(), $oConfig->GetDBName()); CMDBSource::SetCharacterSet($oConfig->GetDBCharacterSet(), $oConfig->GetDBCollation()); $aSelectInstall = CMDBSource::QueryToArray("SELECT * FROM " . $oConfig->GetDBSubname() . "priv_module_install"); } catch (MySQLException $e) { // No database or erroneous information $aSelectInstall = array(); } // Build the list of installed module (get the latest installation) // $aInstallByModule = array(); // array of <module> => array ('installed' => timestamp, 'version' => <version>) $iRootId = 0; foreach ($aSelectInstall as $aInstall) { if ($aInstall['parent_id'] == 0 && $aInstall['name'] != 'datamodel') { // Root module, what is its ID ? $iId = (int) $aInstall['id']; if ($iId > $iRootId) { $iRootId = $iId; } } } foreach ($aSelectInstall as $aInstall) { //$aInstall['comment']; // unsused $iInstalled = strtotime($aInstall['installed']); $sModuleName = $aInstall['name']; $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) { $sModuleName = ROOT_MODULE; } else { if ($aInstall['parent_id'] != $iRootId) { // Skip all modules belonging to previous installations continue; } } if (array_key_exists($sModuleName, $aInstallByModule)) { if ($iInstalled < $aInstallByModule[$sModuleName]['installed']) { continue; } } if ($aInstall['parent_id'] == 0) { $aRes[$sModuleName]['version_db'] = $sModuleVersion; $aRes[$sModuleName]['name_db'] = $aInstall['name']; } $aInstallByModule[$sModuleName]['installed'] = $iInstalled; $aInstallByModule[$sModuleName]['version'] = $sModuleVersion; } // Adjust the list of proposed modules // foreach ($aInstallByModule as $sModuleName => $aModuleDB) { if ($sModuleName == ROOT_MODULE) { continue; } // Skip the main module if (!array_key_exists($sModuleName, $aRes)) { // A module was installed, it is not proposed in the new build... skip continue; } $aRes[$sModuleName]['version_db'] = $aModuleDB['version']; if ($aRes[$sModuleName]['install']['flag'] == MODULE_ACTION_MANDATORY) { $aRes[$sModuleName]['uninstall'] = array('flag' => MODULE_ACTION_IMPOSSIBLE, 'message' => 'the module is part of the application'); } else { $aRes[$sModuleName]['uninstall'] = array('flag' => MODULE_ACTION_OPTIONAL, 'message' => ''); } } return $aRes; }