diff --git a/core/autoload.php b/core/autoload.php new file mode 100644 index 000000000..73c8d8367 --- /dev/null +++ b/core/autoload.php @@ -0,0 +1,37 @@ + + +MetaModel::IncludeModule('application/transaction.class.inc.php'); +MetaModel::IncludeModule('application/menunode.class.inc.php'); +MetaModel::IncludeModule('application/user.preferences.class.inc.php'); +MetaModel::IncludeModule('application/user.dashboard.class.inc.php'); +MetaModel::IncludeModule('application/audit.rule.class.inc.php'); +MetaModel::IncludeModule('application/query.class.inc.php'); + +MetaModel::IncludeModule('core/event.class.inc.php'); +MetaModel::IncludeModule('core/action.class.inc.php'); +MetaModel::IncludeModule('core/trigger.class.inc.php'); +MetaModel::IncludeModule('core/bulkexport.class.inc.php'); +MetaModel::IncludeModule('core/ownershiplock.class.inc.php'); +MetaModel::IncludeModule('synchro/synchrodatasource.class.inc.php'); +MetaModel::IncludeModule('core/backgroundtask.class.inc.php'); +MetaModel::IncludeModule('core/inlineimage.class.inc.php'); + +MetaModel::IncludeModule('webservices/webservices.basic.php'); + +//MetaModel::IncludeModule('addons', 'user rights', 'addons/userrights/userrightsprofile.class.inc.php'); diff --git a/core/config.class.inc.php b/core/config.class.inc.php index 1f59406cb..da53dde75 100644 --- a/core/config.class.inc.php +++ b/core/config.class.inc.php @@ -1022,32 +1022,6 @@ class Config $bLoadConfig = false; } - $this->m_aAppModules = array( - // Some default modules, always present can be move to an official iTop Module later if needed - 'application/transaction.class.inc.php', - 'application/menunode.class.inc.php', - 'application/user.preferences.class.inc.php', - 'application/user.dashboard.class.inc.php', - 'application/audit.rule.class.inc.php', - 'application/query.class.inc.php', -// Romain - That's dirty, because those classes are in fact part of the core -// but I needed those classes to be derived from cmdbAbstractObject -// (to be managed via the GUI) and this class in not really known from -// the core, PLUS I needed the includes to be there also for the setup -// to create the tables. - 'core/event.class.inc.php', - 'core/action.class.inc.php', - 'core/trigger.class.inc.php', - 'core/bulkexport.class.inc.php', - 'core/ownershiplock.class.inc.php', - 'synchro/synchrodatasource.class.inc.php', - 'core/backgroundtask.class.inc.php', - 'core/inlineimage.class.inc.php', - ); - $this->m_aDataModels = array(); - $this->m_aWebServiceCategories = array( - 'webservices/webservices.basic.php', - ); $this->m_aAddons = array( // Default AddOn, always present can be moved to an official iTop Module later if needed 'user rights' => 'addons/userrights/userrightsprofile.class.inc.php', @@ -1150,18 +1124,7 @@ class Config { throw new ConfigException('Missing array in configuration file', array('file' => $sConfigFile, 'expected' => '$MySettings')); } - if (!isset($MyModules) || !is_array($MyModules)) - { - throw new ConfigException('Missing item in configuration file', array('file' => $sConfigFile, 'expected' => '$MyModules')); - } - if (!array_key_exists('application', $MyModules)) - { - throw new ConfigException('Missing item in configuration file', array('file' => $sConfigFile, 'expected' => '$MyModules[\'application\']')); - } - if (!array_key_exists('business', $MyModules)) - { - throw new ConfigException('Missing item in configuration file', array('file' => $sConfigFile, 'expected' => '$MyModules[\'business\']')); - } + if (!array_key_exists('addons', $MyModules)) { throw new ConfigException('Missing item in configuration file', array('file' => $sConfigFile, 'expected' => '$MyModules[\'addons\']')); @@ -1172,12 +1135,6 @@ class Config $MyModules['addons']['user rights'] = '/addons/userrights/userrightsnull.class.inc.php'; } - $this->m_aAppModules = $MyModules['application']; - $this->m_aDataModels = $MyModules['business']; - if (isset($MyModules['webservices'])) - { - $this->m_aWebServiceCategories = $MyModules['webservices']; - } $this->m_aAddons = $MyModules['addons']; foreach($MySettings as $sPropCode => $rawvalue) @@ -1262,33 +1219,6 @@ class Config $this->m_aModuleSettings[$sModule][$sProperty] = $value; } - public function GetAppModules() - { - return $this->m_aAppModules; - } - public function SetAppModules($aAppModules) - { - $this->m_aAppModules = $aAppModules; - } - - public function GetDataModels() - { - return $this->m_aDataModels; - } - public function SetDataModels($aDataModels) - { - $this->m_aDataModels = $aDataModels; - } - - public function GetWebServiceCategories() - { - return $this->m_aWebServiceCategories; - } - public function SetWebServiceCategories($aWebServiceCategories) - { - $this->m_aWebServiceCategories = $aWebServiceCategories; - } - public function GetAddons() { return $this->m_aAddons; @@ -1577,18 +1507,6 @@ class Config $aSettings['module_settings'][$sModule][$sProperty] = $value; } } - foreach($this->m_aAppModules as $sFile) - { - $aSettings['application_list'][] = $sFile; - } - foreach($this->m_aDataModels as $sFile) - { - $aSettings['datamodel_list'][] = $sFile; - } - foreach($this->m_aWebServiceCategories as $sFile) - { - $aSettings['webservice_list'][] = $sFile; - } foreach($this->m_aAddons as $sKey => $sFile) { $aSettings['addon_list'][] = $sFile; @@ -1737,24 +1655,6 @@ class Config fwrite($hFile, " *\n"); fwrite($hFile, " */\n"); fwrite($hFile, "\$MyModules = array(\n"); - fwrite($hFile, "\t'application' => array (\n"); - foreach($this->m_aAppModules as $sFile) - { - fwrite($hFile, "\t\t'$sFile',\n"); - } - fwrite($hFile, "\t),\n"); - fwrite($hFile, "\t'business' => array (\n"); - foreach($this->m_aDataModels as $sFile) - { - fwrite($hFile, "\t\t'$sFile',\n"); - } - fwrite($hFile, "\t),\n"); - fwrite($hFile, "\t'webservices' => array (\n"); - foreach($this->m_aWebServiceCategories as $sFile) - { - fwrite($hFile, "\t\t'$sFile',\n"); - } - fwrite($hFile, "\t),\n"); fwrite($hFile, "\t'addons' => array (\n"); foreach($this->m_aAddons as $sKey => $sFile) { @@ -1830,15 +1730,6 @@ class Config // 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(); - // 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) @@ -1846,14 +1737,6 @@ class Config 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); @@ -1886,9 +1769,6 @@ class Config } } $this->SetAddOns($aAddOns); - $this->SetAppModules($aAppModules); - $this->SetDataModels($aDataModels); - $this->SetWebServiceCategories($aWebServiceCategories); } } @@ -1907,14 +1787,12 @@ class Config } /** - * Quick an dirty way to clone a config file into another environment + * Obsolete: kept only for backward compatibility of the Toolkit + * Quick and dirty way to clone a config file into another environment */ public function ChangeModulesPath($sSourceEnv, $sTargetEnv) { - $sSearchPrefix = 'env-'.$sSourceEnv.'/'; - $sNewPrefix = 'env-'.$sTargetEnv.'/'; - self::ChangePrefix($this->m_aDataModels, $sSearchPrefix, $sNewPrefix); - self::ChangePrefix($this->m_aWebServiceCategories, $sSearchPrefix, $sNewPrefix); + // Now does nothing since the includes are built into the environment itself } /** diff --git a/core/metamodel.class.php b/core/metamodel.class.php index 79e9ed96f..da9706c38 100644 --- a/core/metamodel.class.php +++ b/core/metamodel.class.php @@ -4232,21 +4232,12 @@ abstract class MetaModel // classes have to be derived from cmdbabstract (to be editable in the UI) require_once(APPROOT.'/application/cmdbabstract.class.inc.php'); - foreach (self::$m_oConfig->GetAppModules() as $sModule => $sToInclude) - { - self::IncludeModule('application', $sToInclude); - } - foreach (self::$m_oConfig->GetDataModels() as $sModule => $sToInclude) - { - self::IncludeModule('business', $sToInclude); - } - foreach (self::$m_oConfig->GetWebServiceCategories() as $sModule => $sToInclude) - { - self::IncludeModule('webservice', $sToInclude); - } + require_once(APPROOT.'core/autoload.php'); + require_once(APPROOT.'env-'.utils::GetCurrentEnvironment().'/autoload.php'); + foreach (self::$m_oConfig->GetAddons() as $sModule => $sToInclude) { - self::IncludeModule('addons', $sToInclude); + self::IncludeModule($sToInclude, 'addons'); } $sServer = self::$m_oConfig->GetDBHost(); @@ -4370,7 +4361,7 @@ abstract class MetaModel protected static $m_aExtensionClasses = array(); - protected static function IncludeModule($sModuleType, $sToInclude) + protected static function IncludeModule($sToInclude, $sModuleType = null) { $sFirstChar = substr($sToInclude, 0, 1); $sSecondChar = substr($sToInclude, 1, 1); @@ -4396,14 +4387,21 @@ abstract class MetaModel if (!file_exists($sFile)) { $sConfigFile = self::$m_oConfig->GetLoadedFile(); - if (strlen($sConfigFile) > 0) + if ($sModuleType == null) { - throw new CoreException('Include: wrong file name in configuration file', array('config file' => $sConfigFile, 'section' => $sModuleType, 'filename' => $sFile)); + throw new CoreException("Include: unable to load the file '$sFile'"); } else { - // The configuration is in memory only - throw new CoreException('Include: wrong file name in configuration file (in memory)', array('section' => $sModuleType, 'filename' => $sFile)); + if (strlen($sConfigFile) > 0) + { + throw new CoreException('Include: wrong file name in configuration file', array('config file' => $sConfigFile, 'section' => $sModuleType, 'filename' => $sFile)); + } + else + { + // The configuration is in memory only + throw new CoreException('Include: wrong file name in configuration file (in memory)', array('section' => $sModuleType, 'filename' => $sFile)); + } } } @@ -4419,7 +4417,7 @@ abstract class MetaModel { if ($sPreviousContent != '') { - IssueLog::Error("Spurious characters injected by $sModuleType/$sToInclude"); + IssueLog::Error("Spurious characters injected by '$sFile'"); } } } diff --git a/setup/compiler.class.inc.php b/setup/compiler.class.inc.php index 3b514eae6..0d093c180 100644 --- a/setup/compiler.class.inc.php +++ b/setup/compiler.class.inc.php @@ -181,6 +181,8 @@ class MFCompiler // Compile, module by module // $aModules = $this->oFactory->GetLoadedModules(); + $aDataModelFiles = array(); + $aWebservicesFiles = array(); foreach($aModules as $foo => $oModule) { $sModuleName = $oModule->GetName(); @@ -412,8 +414,19 @@ EOF; { $this->Log("Compilation of module $sModuleName in version $sModuleVersion produced not code at all. No file written."); } + + // files to include (PHP datamodels) + foreach($oModule->GetFilesToInclude('business') as $sRelFileName) + { + $aDataModelFiles[] = "MetaModel::IncludeModule('".basename($sFinalTargetDir).'/'.$sRelativeDir.'/'.$sRelFileName."');"; + } + // files to include (PHP webservices providers) + foreach($oModule->GetFilesToInclude('webservices') as $sRelFileName) + { + $aWebservicesFiles[] = "MetaModel::IncludeModule('".basename($sFinalTargetDir).'/'.$sRelativeDir.'/'.$sRelFileName."');"; + } } // foreach module - + // Compile the dictionaries -out of the modules // $sDictDir = $sTempTargetDir.'/dictionaries'; @@ -484,6 +497,24 @@ EOF; SetupUtils::builddir($sTempTargetDir.'/core'); $sPHPFile = $sTempTargetDir.'/core/main.php'; file_put_contents($sPHPFile, $this->sMainPHPCode); + + + // Autoload + $sPHPFile = $sTempTargetDir.'/autoload.php'; + $sPHPFileContent = +<<sId = $sId; @@ -54,6 +57,9 @@ class MFModule $this->sRootDir = $sRootDir; $this->sLabel = $sLabel; $this->aDataModels = array(); + $this->bAutoSelect = $bAutoSelect; + $this->sAutoSelect = 'false'; + $this->aFilesToInclude = array('addons' => array(), 'business' => array(), 'webservices' => array(),); // Scan the module's root directory to find the datamodel(*).xml files if ($hDir = opendir($sRootDir)) @@ -131,6 +137,38 @@ class MFModule } return $aDictionaries; } + + public function IsAutoSelect() + { + return $this->bAutoSelect; + } + + public function SetAutoSelect($sAutoSelect) + { + $this->sAutoSelect = $sAutoSelect; + } + + public function GetAutoSelect() + { + return $this->sAutoSelect; + } + + public function SetFilesToInclude($aFiles, $sCategory) + { + $sDir = basename($this->sRootDir); + $iLen = strlen($sDir.'/'); + foreach($aFiles as $sFile) + { + $iPos = strpos($sFile, $sDir.'/'); + $this->aFilesToInclude[$sCategory][] = substr($sFile, $iPos+$iLen); + } + } + + public function GetFilesToInclude($sCategory) + { + return $this->aFilesToInclude[$sCategory]; + } + } /** @@ -149,6 +187,7 @@ class MFDeltaModule extends MFModule $this->sRootDir = ''; $this->sLabel = 'Additional Delta'; $this->aDataModels = array($sDeltaFile); + $this->aFilesToInclude = array('addons' => array(), 'business' => array(), 'webservices' => array(),); } public function GetName() @@ -188,6 +227,7 @@ class MFCoreModule extends MFModule $this->sRootDir = ''; $this->sLabel = $sLabel; $this->aDataModels = array($sDeltaFile); + $this->aFilesToInclude = array('addons' => array(), 'business' => array(), 'webservices' => array(),); } public function GetRootDir() @@ -222,6 +262,7 @@ class MFDictModule extends MFModule $this->sRootDir = $sRootDir; $this->sLabel = $sLabel; $this->aDataModels = array(); + $this->aFilesToInclude = array('addons' => array(), 'business' => array(), 'webservices' => array(),); } public function GetRootDir() @@ -1169,7 +1210,24 @@ EOF $aResult = array(); foreach($aAvailableModules as $sId => $aModule) { - $aResult[] = new MFModule($sId, $aModule['root_dir'], $aModule['label']); + $oModule = new MFModule($sId, $aModule['root_dir'], $aModule['label'], isset($aModule['auto_select'])); + if (isset($aModule['auto_select'])) + { + $oModule->SetAutoSelect($aModule['auto_select']); + } + if (isset($aModule['datamodel']) && is_array($aModule['datamodel'])) + { + $oModule->SetFilesToInclude($aModule['datamodel'], 'business'); + } + if (isset($aModule['webservice']) && is_array($aModule['webservice'])) + { + $oModule->SetFilesToInclude($aModule['webservice'], 'webservices'); + } + if (isset($aModule['addons']) && is_array($aModule['addons'])) + { + $oModule->SetFilesToInclude($aModule['addons'], 'addons'); + } + $aResult[] = $oModule; } return $aResult; } diff --git a/setup/runtimeenv.class.inc.php b/setup/runtimeenv.class.inc.php index 7f1c756c3..7bee17869 100644 --- a/setup/runtimeenv.class.inc.php +++ b/setup/runtimeenv.class.inc.php @@ -342,20 +342,20 @@ class RunTimeEnvironment // Do load the required modules // $oDictModule = new MFDictModule('dictionaries', 'iTop Dictionaries', APPROOT.'dictionaries'); - $aRet[] = $oDictModule; + $aRet[$oDictModule->GetName()] = $oDictModule; $oFactory = new ModelFactory($aDirsToCompile); $sDeltaFile = APPROOT.'core/datamodel.core.xml'; if (file_exists($sDeltaFile)) { $oCoreModule = new MFCoreModule('core', 'Core Module', $sDeltaFile); - $aRet[] = $oCoreModule; + $aRet[$oCoreModule->GetName()] = $oCoreModule; } $sDeltaFile = APPROOT.'application/datamodel.application.xml'; if (file_exists($sDeltaFile)) { $oApplicationModule = new MFCoreModule('application', 'Application Module', $sDeltaFile); - $aRet[] = $oApplicationModule; + $aRet[$oApplicationModule->GetName()] = $oApplicationModule; } $aModules = $oFactory->FindModules(); @@ -366,18 +366,47 @@ class RunTimeEnvironment $bIsExtra = (strpos($sModuleRootDir, $sExtraDir) !== false); if (array_key_exists($sModule, $aAvailableModules)) { - if (($aAvailableModules[$sModule]['version_db'] != '') || $bIsExtra) //Extra modules are always selected + if (($aAvailableModules[$sModule]['version_db'] != '') || $bIsExtra && !$oModule->IsAutoSelect()) //Extra modules are always unless they are 'AutoSelect' { - $aRet[] = $oModule; + $aRet[$oModule->GetName()] = $oModule; } } } - + + // Now process the 'AutoSelect' modules + do + { + // Loop while new modules are added... + $bModuleAdded = false; + foreach($aModules as $foo => $oModule) + { + if (!array_key_exists($oModule->GetName(), $aRet) && $oModule->IsAutoSelect()) + { + try + { + $bSelected = false; + SetupInfo::SetSelectedModules($aRet); + eval('$bSelected = ('.$oModule->GetAutoSelect().');'); + } + catch(Exception $e) + { + $bSelected = false; + } + if ($bSelected) + { + $aRet[$oModule->GetName()] = $oModule; // store the Id of the selected module + $bModuleAdded = true; + } + } + } + } + while($bModuleAdded); + $sDeltaFile = APPROOT.'data/'.$this->sTargetEnv.'.delta.xml'; if (file_exists($sDeltaFile)) { $oDelta = new MFDeltaModule($sDeltaFile); - $aRet[] = $oDelta; + $aRet[$oDelta->GetName()] = $oDelta; } return $aRet; diff --git a/setup/wizardsteps.class.inc.php b/setup/wizardsteps.class.inc.php index 701b9a289..d9bf10821 100644 --- a/setup/wizardsteps.class.inc.php +++ b/setup/wizardsteps.class.inc.php @@ -1483,15 +1483,15 @@ EOF // Check once (before recursing) that the hidden modules are selected foreach(SetupUtils::AnalyzeInstallation($this->oWizard) as $sModuleId => $aModule) { - if ($sModuleId != ROOT_MODULE) + if (($sModuleId != ROOT_MODULE) && !isset($aModules[$sModuleId])) { - if (($aModule['category'] == 'authentication') || (!$aModule['visible'])) + 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) @@ -1578,6 +1578,7 @@ EOF if ($bSelected) { $aModules[$sModuleId] = true; // store the Id of the selected module + $sDisplayChoices .= '
  • '.$aModule['label'].' (auto_select)
  • '; $bModuleAdded = true; } } @@ -1659,7 +1660,7 @@ EOF $sModuleLabel = $aModule['label']; $sModuleHelp = $aModule['doc.more_information']; $sMoreInfo = (!empty($aModule['doc.more_information'])) ? "more info": ''; - if (($aModule['category'] != 'authentication') && ($aModule['visible'])) + if (($aModule['category'] != 'authentication') && ($aModule['visible'] && !isset($aModule['auto_select']))) { if (($bAddExtensionsOnly) && (!$this->IsExtension($aModule))) continue;