YOU MUST RUN THE SETUP AFTER PERFORMING THIS UPDATE !!

- Better handling of  'auto_select' modules
- New way of implementing the "includes" of modules, now completely out of the configuration file !

SVN:trunk[3989]
This commit is contained in:
Denis Flaven
2016-04-07 16:00:01 +00:00
parent e9f57fd9e2
commit ed035b3699
7 changed files with 191 additions and 159 deletions

37
core/autoload.php Normal file
View File

@@ -0,0 +1,37 @@
<?php
// Copyright (C) 2016 Combodo SARL
//
// This file is part of iTop.
//
// iTop is free software; you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// iTop is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
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');

View File

@@ -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
}
/**

View File

@@ -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'");
}
}
}

View File

@@ -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 =
<<<EOF
<?php
//
// File generated on $sCurrDate
// Please do not edit manually
//
EOF
;
$sPHPFileContent .= "\nMetaModel::IncludeModule('".basename($sFinalTargetDir)."/core/main.php');\n";
$sPHPFileContent .= implode("\n", $aDataModelFiles);
$sPHPFileContent .= implode("\n", $aWebservicesFiles);
file_put_contents($sPHPFile, $sPHPFileContent);
} // DoCompile()

View File

@@ -40,8 +40,11 @@ class MFModule
protected $sRootDir;
protected $sLabel;
protected $aDataModels;
protected $bAutoSelect;
protected $sAutoSelect;
protected $aFilesToInclude;
public function __construct($sId, $sRootDir, $sLabel)
public function __construct($sId, $sRootDir, $sLabel, $bAutoSelect = false)
{
$this->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;
}

View File

@@ -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;

View File

@@ -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 .= '<li><i>'.$aModule['label'].' (hidden)</i></li>';
}
}
}
}
$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 .= '<li><b>'.$aModule['label'].' (auto_select)</b></li>';
$bModuleAdded = true;
}
}
@@ -1659,7 +1660,7 @@ EOF
$sModuleLabel = $aModule['label'];
$sModuleHelp = $aModule['doc.more_information'];
$sMoreInfo = (!empty($aModule['doc.more_information'])) ? "<a href=\"$sDefaultAppPath{$aModule['doc.more_information']}\" target=\"_blank\">more info</a>": '';
if (($aModule['category'] != 'authentication') && ($aModule['visible']))
if (($aModule['category'] != 'authentication') && ($aModule['visible'] && !isset($aModule['auto_select'])))
{
if (($bAddExtensionsOnly) && (!$this->IsExtension($aModule))) continue;