diff --git a/setup/setuputils.class.inc.php b/setup/setuputils.class.inc.php index 6378f4179..8c40c9a3c 100644 --- a/setup/setuputils.class.inc.php +++ b/setup/setuputils.class.inc.php @@ -2150,7 +2150,7 @@ class SetupInfo /** * Called by the setup process to initializes the list of selected modules. Do not call this method * from an 'auto_select' rule - * @param hash $aModules + * @param array $aModules * @return void */ public static function SetSelectedModules($aModules) diff --git a/setup/wizardsteps/WizStepModulesChoice.php b/setup/wizardsteps/WizStepModulesChoice.php index 0a0f6b875..5cb90bd01 100644 --- a/setup/wizardsteps/WizStepModulesChoice.php +++ b/setup/wizardsteps/WizStepModulesChoice.php @@ -48,7 +48,7 @@ class WizStepModulesChoice extends WizardStep */ protected bool $bChoicesFromDatabase; - private array $aAnalyzeInstallationModules; + private array $aAnalyzeInstallationModules = []; private ?MissingDependencyException $oMissingDependencyException = null; public function __construct(WizardController $oWizard, $sCurrentState) @@ -488,7 +488,7 @@ EOF * * @return string A text representation of what will be installed */ - protected function GetSelectedModules($aInfo, $aSelectedChoices, &$aModules, $sParentId = '', $sDisplayChoices = '', &$aSelectedExtensions = null) + public function GetSelectedModules($aInfo, $aSelectedChoices, &$aModules, $sParentId = '', $sDisplayChoices = '', &$aSelectedExtensions = null) { if ($sParentId == '') { // Check once (before recursing) that the hidden modules are selected @@ -501,7 +501,7 @@ EOF } } } - $aOptions = isset($aInfo['options']) ? $aInfo['options'] : []; + $aOptions = $aInfo['options'] ?? []; foreach ($aOptions as $index => $aChoice) { $sChoiceId = $sParentId.self::$SEP.$index; $aModuleInfo = []; @@ -516,16 +516,19 @@ EOF (isset($aSelectedChoices[$sChoiceId]) && ($aSelectedChoices[$sChoiceId] == $sChoiceId))) { $sDisplayChoices .= '
  • '.$aChoice['title'].'
  • '; if (isset($aChoice['modules'])) { + if (count($aChoice['modules']) === 0) { + throw new Exception('Extension '.$aChoice['extension_code'].' does not have any module associated'); + } foreach ($aChoice['modules'] as $sModuleId) { $bSelected = true; if (isset($aModuleInfo[$sModuleId])) { // Test if module has 'auto_select' - $aInfo = $aModuleInfo[$sModuleId]; - if (isset($aInfo['auto_select'])) { + $aCurrentModuleInfo = $aModuleInfo[$sModuleId]; + if (isset($aCurrentModuleInfo['auto_select'])) { // Check the module selection try { SetupInfo::SetSelectedModules($aModules); - $bSelected = $this->GetPhpExpressionEvaluator()->ParseAndEvaluateBooleanExpression($aInfo['auto_select']); + $bSelected = $this->GetPhpExpressionEvaluator()->ParseAndEvaluateBooleanExpression($aCurrentModuleInfo['auto_select']); } catch (ModuleFileReaderException $e) { //logged already $bSelected = false; @@ -538,7 +541,6 @@ EOF } } } - $sChoiceType = isset($aChoice['type']) ? $aChoice['type'] : 'wizard_option'; if ($aSelectedExtensions !== null) { $aSelectedExtensions[] = $aChoice['extension_code']; } @@ -552,7 +554,7 @@ EOF } } - $aAlternatives = isset($aInfo['alternatives']) ? $aInfo['alternatives'] : []; + $aAlternatives = $aInfo['alternatives'] ?? []; $sChoiceName = null; foreach ($aAlternatives as $index => $aChoice) { $sChoiceId = $sParentId.self::$SEP.$index; diff --git a/tests/php-unit-tests/unitary-tests/setup/WizStepModulesChoiceTest.php b/tests/php-unit-tests/unitary-tests/setup/WizStepModulesChoiceTest.php index 039215a8c..8c4d74edb 100644 --- a/tests/php-unit-tests/unitary-tests/setup/WizStepModulesChoiceTest.php +++ b/tests/php-unit-tests/unitary-tests/setup/WizStepModulesChoiceTest.php @@ -613,4 +613,279 @@ class WizStepModulesChoiceTest extends ItopTestCase return $aSteps[$index] ?? null; } + + public function ProviderGetSelectedModules() + { + return [ + 'No extension selected' => [ + 'aSelected' => [], + 'aExpectedModules' => [], + 'aExpectedExtensions' => [], + ], + 'One extension selected' => [ + 'aSelected' => ['_0' => '_0'], + 'aExpectedModules' => ['combodo-sample-module' => true], + 'aExpectedExtensions' => ['combodo-sample'], + ], + 'More extensions selected' => [ + 'aSelected' => ['_0' => '_0', '_1' => '_1'], + 'aExpectedModules' => ['combodo-sample-module' => true, 'combodo-test-moduleA' => true, 'combodo-test-moduleB' => true], + 'aExpectedExtensions' => ['combodo-sample', 'combodo-test'], + ], + ]; + } + + /** + * @dataProvider ProviderGetSelectedModules + */ + public function testGetSelectedModules($aSelectedExtensions, $aExpectedModules, $aExpectedExtensions) + { + $aExtensionsMapData = [ + 'combodo-sample' => [ + 'installed' => false, + ], + 'combodo-test' => [ + 'installed' => false, + ], + ]; + $this->oStep->setExtensionMap(iTopExtensionsMapFake::createFromArray($aExtensionsMapData)); + + $aStepInfo = [ + 'title' => 'Extensions', + 'description' => '', + 'banner' => '', + 'options' => [ + [ + 'extension_code' => 'combodo-sample', + 'title' => 'Sample extension', + 'description' => '', + 'more_info' => '', + 'default' => true, + 'modules' => [ + 'combodo-sample-module', + ], + 'mandatory' => false, + 'source_label' => '', + 'uninstallable' => true, + 'missing' => false, + ], + [ + 'extension_code' => 'combodo-test', + 'title' => 'Test extension', + 'description' => '', + 'more_info' => '', + 'default' => true, + 'modules' => [ + 'combodo-test-moduleA', + 'combodo-test-moduleB', + ], + 'mandatory' => false, + 'source_label' => '', + 'uninstallable' => true, + 'missing' => false, + ], + ], + ]; + + $aModules = []; + $aExtensions = []; + $this->oStep->GetSelectedModules($aStepInfo, $aSelectedExtensions, $aModules, '', '', $aExtensions); + $this->assertEquals($aExpectedModules, $aModules); + $this->assertEquals($aExpectedExtensions, $aExtensions); + } + + public function testGetSelectedModulesShouldAlwaysSelectMandatoryExtension() + { + + $aSelectedExtensions = ['_0' => '_0']; + + $aExtensionsMapData = [ + 'combodo-sample' => [ + 'installed' => true, + ], + ]; + + $this->oStep->setExtensionMap(iTopExtensionsMapFake::createFromArray($aExtensionsMapData)); + + $aStepInfo = [ + 'title' => 'Extensions', + 'description' => '', + 'banner' => '', + 'options' => [ + [ + 'extension_code' => 'combodo-sample', + 'title' => 'Sample extension', + 'description' => '', + 'more_info' => '', + 'default' => true, + 'modules' => [ + 'combodo-sample-module', + ], + 'mandatory' => false, + 'source_label' => '', + 'uninstallable' => true, + 'missing' => true, + ], + ], + ]; + + $aExpectedModules = ['combodo-sample-module' => true]; + $aExpectedExtensions = ['combodo-sample']; + + $aModules = []; + $aExtensions = []; + $this->oStep->GetSelectedModules($aStepInfo, $aSelectedExtensions, $aModules, '', '', $aExtensions); + $this->assertEquals($aExpectedModules, $aModules); + $this->assertEquals($aExpectedExtensions, $aExtensions); + } + + public function testGetSelectedModulesShouldShouldParseAutoSelectCondition() + { + //the 'auto_select' parameter, contrary to its name, deselect the module if its result is false + + $aSelectedExtensions = ['_0' => '_0']; + + $aExtensionsMapData = [ + 'combodo-sample' => [ + 'installed' => true, + 'module_info' => [ + 'combodo-sample-module' => [ + 'auto_select' => 'true && false', + ], + ], + ], + ]; + $this->oStep->setExtensionMap(iTopExtensionsMapFake::createFromArray($aExtensionsMapData)); + + $aStepInfo = [ + 'title' => 'Extensions', + 'description' => '', + 'banner' => '', + 'options' => [ + [ + 'extension_code' => 'combodo-sample', + 'title' => 'Sample extension', + 'description' => '', + 'more_info' => '', + 'default' => true, + 'modules' => [ + 'combodo-sample-module', + ], + 'mandatory' => false, + 'source_label' => '', + 'uninstallable' => true, + 'missing' => true, + ], + ], + ]; + + $aExpectedModules = []; + $aExpectedExtensions = ['combodo-sample']; + + $aModules = []; + $aExtensions = []; + $this->oStep->GetSelectedModules($aStepInfo, $aSelectedExtensions, $aModules, '', '', $aExtensions); + $this->assertEquals($aExpectedModules, $aModules); + $this->assertEquals($aExpectedExtensions, $aExtensions); + } + + public function testGetSelectedModulesWithSubOptions() + { + + $aSelectedExtensions = ['_0' => '_0', '_0_0' => '_0_0']; + + $aExtensionsMapData = [ + 'combodo-sample' => [ + 'installed' => false, + ], + 'combodo-sub-sample' => [ + 'installed' => false, + ], + ]; + $this->oStep->setExtensionMap(iTopExtensionsMapFake::createFromArray($aExtensionsMapData)); + + $aStepInfo = [ + 'options' => [ + [ + 'extension_code' => 'combodo-sample', + 'title' => 'Sample extension', + 'description' => '', + 'more_info' => '', + 'default' => true, + 'modules' => [ + 'combodo-sample-module', + ], + 'mandatory' => false, + 'source_label' => '', + 'uninstallable' => true, + 'missing' => false, + 'sub_options' => [ + 'options' => [ + [ + 'extension_code' => 'combodo-sub-sample', + 'title' => 'Sample sub extension', + 'description' => '', + 'more_info' => '', + 'default' => true, + 'modules' => [ + 'combodo-sub-sample-module', + ], + 'mandatory' => false, + 'source_label' => '', + 'uninstallable' => true, + 'missing' => false, + ], + ], + ], + ], + ], + ]; + + $aExpectedModules = ['combodo-sample-module' => true, 'combodo-sub-sample-module' => true]; + $aExpectedExtensions = ['combodo-sample', 'combodo-sub-sample']; + + $aModules = []; + $aExtensions = []; + $this->oStep->GetSelectedModules($aStepInfo, $aSelectedExtensions, $aModules, '', '', $aExtensions); + $this->assertEquals($aExpectedModules, $aModules); + $this->assertEquals($aExpectedExtensions, $aExtensions); + } + + public function testGetSelectedModulesShouldThrowAnExceptionWhenAnySelectedExtensionDoesNotHaveAnyAssociatedModules() + { + $aExtensionsMapData = [ + 'combodo-sample' => [ + 'installed' => false, + ], + ]; + $this->oStep->setExtensionMap(iTopExtensionsMapFake::createFromArray($aExtensionsMapData)); + + //GetSelectedModules + $aStepInfo = [ + 'title' => 'Extensions', + 'description' => '', + 'banner' => '', + 'options' => [ + [ + 'extension_code' => 'combodo-sample', + 'title' => 'Sample extension', + 'description' => '', + 'more_info' => '', + 'default' => true, + 'modules' => [], + 'mandatory' => false, + 'source_label' => '', + 'uninstallable' => true, + 'missing' => false, + ], + ], + ]; + + $aModules = []; + $aExtensions = []; + $this->expectException('Exception'); + $this->expectExceptionMessage('Extension combodo-sample does not have any module associated'); + $this->oStep->GetSelectedModules($aStepInfo, ['_0' => '_0'], $aModules, '', '', $aExtensions); + } + } diff --git a/tests/php-unit-tests/unitary-tests/setup/iTopExtensionsMapFake.php b/tests/php-unit-tests/unitary-tests/setup/iTopExtensionsMapFake.php index ff1a204af..f53eb84c7 100644 --- a/tests/php-unit-tests/unitary-tests/setup/iTopExtensionsMapFake.php +++ b/tests/php-unit-tests/unitary-tests/setup/iTopExtensionsMapFake.php @@ -21,7 +21,7 @@ class iTopExtensionsMapFake extends iTopExtensionsMap $oExtension->aModules = $aExtension['modules'] ?? []; $oExtension->bCanBeUninstalled = $aExtension['uninstallable'] ?? null; $oExtension->sVersion = $aExtension['version'] ?? '1.0.0'; - $oExtension->aModuleInfo = []; + $oExtension->aModuleInfo = $aExtension['module_info'] ?? []; $oMap->AddExtension($oExtension); } return $oMap;