mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
@@ -23,6 +23,10 @@
|
|||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
class MissingDependencyException extends Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
class ModuleDiscovery
|
class ModuleDiscovery
|
||||||
{
|
{
|
||||||
static $m_aModuleArgs = array(
|
static $m_aModuleArgs = array(
|
||||||
@@ -106,13 +110,22 @@ class ModuleDiscovery
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function GetModules($oP = null)
|
/**
|
||||||
|
*
|
||||||
|
* @param bool $bAbortOnMissingDependency ...
|
||||||
|
* @param hash $aModulesToLoad List of modules to search for, defaults to all if ommitted
|
||||||
|
*/
|
||||||
|
protected static function GetModules($bAbortOnMissingDependency = false, $aModulesToLoad = null)
|
||||||
{
|
{
|
||||||
// Order the modules to take into account their inter-dependencies
|
// Order the modules to take into account their inter-dependencies
|
||||||
$aDependencies = array();
|
$aDependencies = array();
|
||||||
foreach(self::$m_aModules as $sId => $aModule)
|
foreach(self::$m_aModules as $sId => $aModule)
|
||||||
{
|
{
|
||||||
$aDependencies[$sId] = $aModule['dependencies'];
|
list($sModuleName, $sModuleVersion) = self::GetModuleName($sId);
|
||||||
|
if (is_null($aModulesToLoad) || in_array($sModuleName, $aModulesToLoad))
|
||||||
|
{
|
||||||
|
$aDependencies[$sId] = $aModule['dependencies'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ksort($aDependencies);
|
ksort($aDependencies);
|
||||||
$aOrderedModules = array();
|
$aOrderedModules = array();
|
||||||
@@ -137,27 +150,16 @@ class ModuleDiscovery
|
|||||||
}
|
}
|
||||||
$iLoopCount++;
|
$iLoopCount++;
|
||||||
}
|
}
|
||||||
if (count($aDependencies) >0)
|
if ($bAbortOnMissingDependency && count($aDependencies) > 0)
|
||||||
{
|
{
|
||||||
$sHtml = "<ul><b>Warning: the following modules have unmet dependencies, and have been ignored:</b>\n";
|
$aModuleDeps = array();
|
||||||
foreach($aDependencies as $sId => $aDeps)
|
foreach($aDependencies as $sId => $aDeps)
|
||||||
{
|
{
|
||||||
$aModule = self::$m_aModules[$sId];
|
$aModule = self::$m_aModules[$sId];
|
||||||
$sHtml.= "<li>{$aModule['label']} (id: $sId), depends on: ".implode(', ', $aDeps)."</li>";
|
$aModuleDeps[] = "{$aModule['label']} (id: $sId) depends on ".implode(' + ', $aDeps);
|
||||||
}
|
|
||||||
$sHtml .= "</ul>\n";
|
|
||||||
if ($oP instanceof SetupPage)
|
|
||||||
{
|
|
||||||
$oP->warning($sHtml); // used in the context of the installation
|
|
||||||
}
|
|
||||||
elseif (class_exists('SetupPage'))
|
|
||||||
{
|
|
||||||
SetupPage::log_warning($sHtml); // used in the context of ?
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
echo $sHtml; // used in the context of the compiler
|
|
||||||
}
|
}
|
||||||
|
$sMessage = "The following modules have unmet dependencies: ".implode(', ', $aModuleDeps);
|
||||||
|
throw new MissingDependencyException($sMessage);
|
||||||
}
|
}
|
||||||
// Return the ordered list, so that the dependencies are met...
|
// Return the ordered list, so that the dependencies are met...
|
||||||
$aResult = array();
|
$aResult = array();
|
||||||
@@ -207,9 +209,11 @@ class ModuleDiscovery
|
|||||||
* Search (on the disk) for all defined iTop modules, load them and returns the list (as an array)
|
* 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
|
* of the possible iTop modules to install
|
||||||
* @param aSearchDirs Array of directories to search (absolute paths)
|
* @param aSearchDirs Array of directories to search (absolute paths)
|
||||||
|
* @param bool $bAbortOnMissingDependency ...
|
||||||
|
* @param hash $aModulesToLoad List of modules to search for, defaults to all if ommitted
|
||||||
* @return Hash A big array moduleID => ModuleData
|
* @return Hash A big array moduleID => ModuleData
|
||||||
*/
|
*/
|
||||||
public static function GetAvailableModules($aSearchDirs, $oP = null)
|
public static function GetAvailableModules($aSearchDirs, $bAbortOnMissingDependency = false, $aModulesToLoad = null)
|
||||||
{
|
{
|
||||||
if (self::$m_aSearchDirs != $aSearchDirs)
|
if (self::$m_aSearchDirs != $aSearchDirs)
|
||||||
{
|
{
|
||||||
@@ -232,12 +236,12 @@ class ModuleDiscovery
|
|||||||
clearstatcache();
|
clearstatcache();
|
||||||
self::ListModuleFiles(basename($sSearchDir), dirname($sSearchDir));
|
self::ListModuleFiles(basename($sSearchDir), dirname($sSearchDir));
|
||||||
}
|
}
|
||||||
return self::GetModules($oP);
|
return self::GetModules($bAbortOnMissingDependency, $aModulesToLoad);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Reuse the previous results
|
// Reuse the previous results
|
||||||
return self::GetModules($oP);
|
return self::GetModules($bAbortOnMissingDependency, $aModulesToLoad);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ class RunTimeEnvironment
|
|||||||
*
|
*
|
||||||
* @param Config $oConfig 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
|
* @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:
|
* @return hash Array with the following format:
|
||||||
* array =>
|
* array =>
|
||||||
* 'iTop' => array(
|
* 'iTop' => array(
|
||||||
@@ -118,7 +120,7 @@ class RunTimeEnvironment
|
|||||||
* )
|
* )
|
||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
public function AnalyzeInstallation($oConfig, $modulesPath)
|
public function AnalyzeInstallation($oConfig, $modulesPath, $bAbortOnMissingDependency = false, $aModulesToLoad = null)
|
||||||
{
|
{
|
||||||
$aRes = array(
|
$aRes = array(
|
||||||
ROOT_MODULE => array(
|
ROOT_MODULE => array(
|
||||||
@@ -130,7 +132,7 @@ class RunTimeEnvironment
|
|||||||
);
|
);
|
||||||
|
|
||||||
$aDirs = is_array($modulesPath) ? $modulesPath : array($modulesPath);
|
$aDirs = is_array($modulesPath) ? $modulesPath : array($modulesPath);
|
||||||
$aModules = ModuleDiscovery::GetAvailableModules($aDirs);
|
$aModules = ModuleDiscovery::GetAvailableModules($aDirs, $bAbortOnMissingDependency, $aModulesToLoad);
|
||||||
foreach($aModules as $sModuleId => $aModuleInfo)
|
foreach($aModules as $sModuleId => $aModuleInfo)
|
||||||
{
|
{
|
||||||
list($sModuleName, $sModuleVersion) = ModuleDiscovery::GetModuleName($sModuleId);
|
list($sModuleName, $sModuleVersion) = ModuleDiscovery::GetModuleName($sModuleId);
|
||||||
|
|||||||
@@ -336,6 +336,33 @@ class SetupUtils
|
|||||||
return $aResult;
|
return $aResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that the selected modules meet their dependencies
|
||||||
|
*/
|
||||||
|
static function CheckSelectedModules($sSourceDir, $sExtensionDir, $aSelectedModules)
|
||||||
|
{
|
||||||
|
$aResult = array();
|
||||||
|
SetupPage::log('Info - CheckSelectedModules');
|
||||||
|
|
||||||
|
$aDirsToScan = array(APPROOT.$sSourceDir);
|
||||||
|
$sExtensionsPath = APPROOT.$sExtensionDir;
|
||||||
|
if (is_dir($sExtensionsPath))
|
||||||
|
{
|
||||||
|
// if the extensions dir exists, scan it for additional modules as well
|
||||||
|
$aDirsToScan[] = $sExtensionsPath;
|
||||||
|
}
|
||||||
|
require_once(APPROOT.'setup/modulediscovery.class.inc.php');
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ModuleDiscovery::GetAvailableModules($aDirsToScan, true, $aSelectedModules);
|
||||||
|
}
|
||||||
|
catch(MissingDependencyException $e)
|
||||||
|
{
|
||||||
|
$aResult[] = new CheckResult(CheckResult::ERROR, $e->getMessage());
|
||||||
|
}
|
||||||
|
return $aResult;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that the backup could be executed
|
* Check that the backup could be executed
|
||||||
* @param Page $oP The page used only for its 'log' method
|
* @param Page $oP The page used only for its 'log' method
|
||||||
@@ -1008,7 +1035,12 @@ EOF
|
|||||||
return $sHtml;
|
return $sHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function AnalyzeInstallation($oWizard)
|
/**
|
||||||
|
*
|
||||||
|
* @param bool $bAbortOnMissingDependency ...
|
||||||
|
* @param array $aModulesToLoad List of modules to search for, defaults to all if ommitted
|
||||||
|
*/
|
||||||
|
public static function AnalyzeInstallation($oWizard, $bAbortOnMissingDependency = false, $aModulesToLoad = null)
|
||||||
{
|
{
|
||||||
require_once(APPROOT.'/setup/moduleinstaller.class.inc.php');
|
require_once(APPROOT.'/setup/moduleinstaller.class.inc.php');
|
||||||
$oConfig = new Config();
|
$oConfig = new Config();
|
||||||
@@ -1048,7 +1080,7 @@ EOF
|
|||||||
$aDirsToScan[] = $oWizard->GetParameter('copy_extensions_from');
|
$aDirsToScan[] = $oWizard->GetParameter('copy_extensions_from');
|
||||||
}
|
}
|
||||||
$oProductionEnv = new RunTimeEnvironment();
|
$oProductionEnv = new RunTimeEnvironment();
|
||||||
$aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, $aDirsToScan);
|
$aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, $aDirsToScan, $bAbortOnMissingDependency, $aModulesToLoad);
|
||||||
|
|
||||||
return $aAvailableModules;
|
return $aAvailableModules;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1095,6 +1095,16 @@ class WizStepModulesChoice extends WizardStep
|
|||||||
|
|
||||||
protected function DisplayStep($oPage)
|
protected function DisplayStep($oPage)
|
||||||
{
|
{
|
||||||
|
// Sanity check (not stopper, to let developpers go further...)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SetupUtils::AnalyzeInstallation($this->oWizard, true);
|
||||||
|
}
|
||||||
|
catch(MissingDependencyException $e)
|
||||||
|
{
|
||||||
|
$oPage->warning($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
$this->bUpgrade = ($this->oWizard->GetParameter('install_mode') != 'install');
|
$this->bUpgrade = ($this->oWizard->GetParameter('install_mode') != 'install');
|
||||||
$aStepInfo = $this->GetStepInfo();
|
$aStepInfo = $this->GetStepInfo();
|
||||||
$oPage->add_style("div.choice { margin: 0.5em;}");
|
$oPage->add_style("div.choice { margin: 0.5em;}");
|
||||||
@@ -1657,6 +1667,28 @@ EOF
|
|||||||
*/
|
*/
|
||||||
class WizStepSummary extends WizardStep
|
class WizStepSummary extends WizardStep
|
||||||
{
|
{
|
||||||
|
protected $bDependencyCheck = null;
|
||||||
|
protected $sDependencyIssue = null;
|
||||||
|
|
||||||
|
protected function CheckDependencies()
|
||||||
|
{
|
||||||
|
if (is_null($this->bDependencyCheck))
|
||||||
|
{
|
||||||
|
$aSelectedModules = json_decode($this->oWizard->GetParameter('selected_modules'), true);
|
||||||
|
$this->bDependencyCheck = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SetupUtils::AnalyzeInstallation($this->oWizard, true, $aSelectedModules);
|
||||||
|
}
|
||||||
|
catch(MissingDependencyException $e)
|
||||||
|
{
|
||||||
|
$this->bDependencyCheck = false;
|
||||||
|
$this->sDependencyIssue = $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $this->bDependencyCheck;
|
||||||
|
}
|
||||||
|
|
||||||
public function GetTitle()
|
public function GetTitle()
|
||||||
{
|
{
|
||||||
$sMode = $this->oWizard->GetParameter('mode', 'install');
|
$sMode = $this->oWizard->GetParameter('mode', 'install');
|
||||||
@@ -1684,7 +1716,19 @@ class WizStepSummary extends WizardStep
|
|||||||
{
|
{
|
||||||
return ' Install ! ';
|
return ' Install ! ';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function CanMoveForward()
|
||||||
|
{
|
||||||
|
if ($this->CheckDependencies())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function ProcessParams($bMoveForward = true)
|
public function ProcessParams($bMoveForward = true)
|
||||||
{
|
{
|
||||||
return array('class' => 'WizStepDone', 'state' => '');
|
return array('class' => 'WizStepDone', 'state' => '');
|
||||||
@@ -1736,7 +1780,7 @@ class WizStepSummary extends WizardStep
|
|||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
|
|
||||||
$aInstallParams = $this->BuildConfig();
|
$aInstallParams = $this->BuildConfig();
|
||||||
|
|
||||||
$sMode = $aInstallParams['mode'];
|
$sMode = $aInstallParams['mode'];
|
||||||
@@ -1847,6 +1891,11 @@ EOF
|
|||||||
$sJSONData = json_encode($aInstallParams);
|
$sJSONData = json_encode($aInstallParams);
|
||||||
$oPage->add('<input type="hidden" id="installer_parameters" value="'.htmlentities($sJSONData, ENT_QUOTES, 'UTF-8').'"/>');
|
$oPage->add('<input type="hidden" id="installer_parameters" value="'.htmlentities($sJSONData, ENT_QUOTES, 'UTF-8').'"/>');
|
||||||
|
|
||||||
|
if (!$this->CheckDependencies())
|
||||||
|
{
|
||||||
|
$oPage->error($this->sDependencyIssue);
|
||||||
|
}
|
||||||
|
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
$("#params_summary div").addClass('closed');
|
$("#params_summary div").addClass('closed');
|
||||||
|
|||||||
Reference in New Issue
Block a user