mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
216 lines
6.4 KiB
PHP
216 lines
6.4 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
|
* @license http://opensource.org/licenses/AGPL-3.0
|
|
*/
|
|
|
|
use Combodo\iTop\Setup\ModuleDependency\DependencyExpression;
|
|
|
|
require_once __DIR__.'/ModuleInstallationException.php';
|
|
require_once(APPROOT.'/setup/moduledependency/module.class.inc.php');
|
|
|
|
class InstallationChoicesToModuleConverter
|
|
{
|
|
private static ?InstallationChoicesToModuleConverter $oInstance;
|
|
|
|
protected function __construct()
|
|
{
|
|
}
|
|
|
|
final public static function GetInstance(): InstallationChoicesToModuleConverter
|
|
{
|
|
if (!isset(self::$oInstance)) {
|
|
self::$oInstance = new InstallationChoicesToModuleConverter();
|
|
}
|
|
|
|
return self::$oInstance;
|
|
}
|
|
|
|
final public static function SetInstance(?InstallationChoicesToModuleConverter $oInstance): void
|
|
{
|
|
self::$oInstance = $oInstance;
|
|
}
|
|
|
|
/**
|
|
* @param array $aInstallationChoices
|
|
* @param array $aSearchDirs
|
|
*
|
|
* @return array
|
|
* @throws \ModuleInstallationException
|
|
*/
|
|
public function GetModules(array $aInstallationChoices, array $aSearchDirs, ?string $sInstallationFilePath = null): array
|
|
{
|
|
$aPackageModules = ModuleDiscovery::GetAllModules($aSearchDirs);
|
|
|
|
$bInstallationFileProvided = ! is_null($sInstallationFilePath) && is_file($sInstallationFilePath);
|
|
|
|
if ($bInstallationFileProvided) {
|
|
$oXMLParameters = new XMLParameters($sInstallationFilePath);
|
|
$aSteps = $oXMLParameters->Get('steps', []);
|
|
if (!is_array($aSteps)) {
|
|
return [];
|
|
}
|
|
$aInstalledModuleNames = $this->FindInstalledPackageModules($aPackageModules, $aInstallationChoices, $aSteps);
|
|
} else {
|
|
$aInstalledModuleNames = $this->FindInstalledPackageModules($aPackageModules, $aInstallationChoices);
|
|
}
|
|
|
|
$aInstalledModules = [];
|
|
foreach (array_keys($aPackageModules) as $sModuleId) {
|
|
list($sModuleName) = ModuleDiscovery::GetModuleName($sModuleId);
|
|
if (in_array($sModuleName, $aInstalledModuleNames)) {
|
|
$aInstalledModules[] = $sModuleId;
|
|
}
|
|
}
|
|
|
|
return $aInstalledModules;
|
|
}
|
|
|
|
private function FindInstalledPackageModules(array $aPackageModules, array $aInstallationChoices, array $aInstallationDescription = null): array
|
|
{
|
|
$aInstalledModules = [];
|
|
|
|
$this->ProcessDefaultModules($aPackageModules, $aInstalledModules);
|
|
|
|
if (is_null($aInstallationDescription)) {
|
|
//in legacy usecase: choices are flat modules list already
|
|
foreach ($aInstallationChoices as $sModuleName) {
|
|
$aInstalledModules[$sModuleName] = true;
|
|
}
|
|
} else {
|
|
$this->ProcessInstallationChoices($aInstallationChoices, $aInstallationDescription, $aInstalledModules);
|
|
}
|
|
|
|
$this->ProcessAutoSelectModules($aPackageModules, $aInstalledModules);
|
|
|
|
return array_keys($aInstalledModules);
|
|
}
|
|
|
|
private function IsDefaultModule(string $sModuleId, array $aModule): bool
|
|
{
|
|
if (($sModuleId === ROOT_MODULE)) {
|
|
return false;
|
|
}
|
|
|
|
if (isset($aModule['auto_select'])) {
|
|
return false;
|
|
}
|
|
|
|
if ($aModule['category'] === 'authentication') {
|
|
return true;
|
|
}
|
|
|
|
return !$aModule['visible'];
|
|
}
|
|
|
|
private function ProcessDefaultModules(array &$aPackageModules, array &$aInstalledModules): void
|
|
{
|
|
foreach ($aPackageModules as $sModuleId => $aModule) {
|
|
if ($this->IsDefaultModule($sModuleId, $aModule)) {
|
|
list($sModuleName) = ModuleDiscovery::GetModuleName($sModuleId);
|
|
$aInstalledModules[$sModuleName] = true;
|
|
unset($aPackageModules[$sModuleId]);
|
|
}
|
|
}
|
|
}
|
|
|
|
private function IsAutoSelectedModule(array $aInstalledModules, string $sModuleId, array $aModule): bool
|
|
{
|
|
if (($sModuleId === ROOT_MODULE)) {
|
|
return false;
|
|
}
|
|
|
|
if (!isset($aModule['auto_select'])) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
SetupInfo::SetSelectedModules($aInstalledModules);
|
|
return DependencyExpression::GetPhpExpressionEvaluator()->ParseAndEvaluateBooleanExpression($aModule['auto_select']);
|
|
} catch (Exception $e) {
|
|
IssueLog::Error('Error evaluating module auto-select', null, [
|
|
'module' => $sModuleId,
|
|
'error' => $e->getMessage(),
|
|
'evaluated code' => $aModule['auto_select'],
|
|
'stacktrace' => $e->getTraceAsString(),
|
|
]);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private function ProcessAutoSelectModules(array $aPackageModules, array &$aInstalledModules): void
|
|
{
|
|
foreach ($aPackageModules as $sModuleId => $aModule) {
|
|
if ($this->IsAutoSelectedModule($aInstalledModules, $sModuleId, $aModule)) {
|
|
list($sModuleName) = ModuleDiscovery::GetModuleName($sModuleId);
|
|
$aInstalledModules[$sModuleName] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
private function ProcessInstallationChoices(array $aInstallationChoices, array $aInstallationDescription, array &$aInstalledModules): void
|
|
{
|
|
foreach ($aInstallationDescription as $aStepInfo) {
|
|
$aOptions = $aStepInfo['options'] ?? null;
|
|
if (is_array($aOptions)) {
|
|
foreach ($aOptions as $aChoiceInfo) {
|
|
$this->ProcessSelectedChoice($aInstallationChoices, $aChoiceInfo, $aInstalledModules);
|
|
}
|
|
}
|
|
$aOptions = $aStepInfo['alternatives'] ?? null;
|
|
if (is_array($aOptions)) {
|
|
foreach ($aOptions as $aChoiceInfo) {
|
|
$this->ProcessSelectedChoice($aInstallationChoices, $aChoiceInfo, $aInstalledModules);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private function ProcessSelectedChoice(array $aInstallationChoices, array $aChoiceInfo, array &$aInstalledModules)
|
|
{
|
|
if (!is_array($aChoiceInfo)) {
|
|
return;
|
|
}
|
|
|
|
$sMandatory = $aChoiceInfo['mandatory'] ?? 'false';
|
|
|
|
$aCurrentModules = $aChoiceInfo['modules'] ?? [];
|
|
$sExtensionCode = $aChoiceInfo['extension_code'];
|
|
|
|
$bSelected = ($sMandatory === 'true') || in_array($sExtensionCode, $aInstallationChoices);
|
|
|
|
if (!$bSelected) {
|
|
return;
|
|
}
|
|
|
|
foreach ($aCurrentModules as $sModuleId) {
|
|
$aInstalledModules[$sModuleId] = true;
|
|
}
|
|
|
|
$aAlternatives = $aChoiceInfo['alternatives'] ?? null;
|
|
if (is_array($aAlternatives)) {
|
|
foreach ($aAlternatives as $aSubChoiceInfo) {
|
|
$this->ProcessSelectedChoice($aInstallationChoices, $aSubChoiceInfo, $aInstalledModules);
|
|
}
|
|
}
|
|
|
|
$aSubOptionsChoiceInfo = $aChoiceInfo['sub_options'] ?? null;
|
|
if (is_array($aSubOptionsChoiceInfo)) {
|
|
$aSubOptions = $aSubOptionsChoiceInfo['options'] ?? null;
|
|
if (is_array($aSubOptions)) {
|
|
foreach ($aSubOptions as $aSubChoiceInfo) {
|
|
$this->ProcessSelectedChoice($aInstallationChoices, $aSubChoiceInfo, $aInstalledModules);
|
|
}
|
|
}
|
|
$aSubAlternatives = $aSubOptionsChoiceInfo['alternatives'] ?? null;
|
|
if (is_array($aSubAlternatives)) {
|
|
foreach ($aSubAlternatives as $aSubChoiceInfo) {
|
|
$this->ProcessSelectedChoice($aInstallationChoices, $aSubChoiceInfo, $aInstalledModules);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|