mirror of
https://github.com/Combodo/iTop.git
synced 2026-09-15 19:33:51 +02:00
N°10021 Fix handling of removed extension that are also part of product
This commit is contained in:
@@ -526,7 +526,16 @@ class iTopExtensionsMap
|
||||
public function GetAllExtensionsWithPreviouslyInstalled(): array
|
||||
{
|
||||
//Mind the order, local extensions data must overwrite installed extensions data since installed extensions does not have the associated modules.
|
||||
return array_merge($this->aInstalledExtensions ?? [], $this->aExtensions);
|
||||
$aResult = [];
|
||||
foreach ($this->aInstalledExtensions ?? [] as $sKey => $oInstalledExtension) {
|
||||
/** @var \iTopExtension $oInstalledExtension */
|
||||
$aResult[$oInstalledExtension->sSource.'/'.$sKey] = $oInstalledExtension;
|
||||
}
|
||||
foreach ($this->aExtensions as $sKey => $oExtension) {
|
||||
/** @var \iTopExtension $oExtension */
|
||||
$aResult[$oExtension->sSource.'/'.$sKey] = $oExtension;
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -664,7 +673,7 @@ class iTopExtensionsMap
|
||||
return true;
|
||||
}
|
||||
|
||||
public function LoadInstalledExtensionsFromDatabase(Config $oConfig): array|false
|
||||
protected function FetchExtensionInfoFromDatabase(Config $oConfig): array|false
|
||||
{
|
||||
try {
|
||||
if (CMDBSource::DBName() === null) {
|
||||
@@ -672,41 +681,49 @@ class iTopExtensionsMap
|
||||
}
|
||||
$sLatestInstallationDate = CMDBSource::QueryToScalar("SELECT max(installed) FROM ".$oConfig->Get('db_subname')."priv_extension_install");
|
||||
$aDBInfo = CMDBSource::QueryToArray("SELECT * FROM ".$oConfig->Get('db_subname')."priv_extension_install WHERE installed = '".$sLatestInstallationDate."'");
|
||||
|
||||
$this->aInstalledExtensions = [];
|
||||
foreach ($aDBInfo as $aExtensionInfo) {
|
||||
$oExtension = new iTopExtension();
|
||||
$oExtension->sCode = $aExtensionInfo['code'];
|
||||
$oExtension->sLabel = $aExtensionInfo['label'];
|
||||
$oExtension->sDescription = $aExtensionInfo['description'] ?? '';
|
||||
$oExtension->sVersion = $aExtensionInfo['version'];
|
||||
$oExtension->sSource = $aExtensionInfo['source'];
|
||||
$oExtension->bMandatory = false;
|
||||
$oExtension->sMoreInfoUrl = '';
|
||||
$oExtension->aModules = [];
|
||||
$oExtension->aModuleVersion = [];
|
||||
$oExtension->aModuleInfo = [];
|
||||
$oExtension->sSourceDir = '';
|
||||
$oExtension->bVisible = true;
|
||||
$oExtension->bInstalled = true;
|
||||
$oExtension->bCanBeUninstalled = !isset($aExtensionInfo['uninstallable']) || $aExtensionInfo['uninstallable'] === 'yes';
|
||||
$oChoice = $this->GetFromExtensionCode($oExtension->sCode);
|
||||
if ($oChoice) {
|
||||
$oChoice->bInstalled = true;
|
||||
$oExtension->bRemovedFromDisk = $oChoice->bRemovedFromDisk;
|
||||
} else {
|
||||
$oExtension->bRemovedFromDisk = true;
|
||||
$this->aExtensionsByCode[$oExtension->sCode] = $oExtension;
|
||||
}
|
||||
|
||||
$this->aInstalledExtensions[$oExtension->sCode.'/'.$oExtension->sVersion] = $oExtension;
|
||||
}
|
||||
|
||||
return $this->aInstalledExtensions;
|
||||
} catch (MySQLException $e) {
|
||||
// No database or erroneous information
|
||||
return false;
|
||||
}
|
||||
return $aDBInfo;
|
||||
}
|
||||
|
||||
public function LoadInstalledExtensionsFromDatabase(Config $oConfig): array|false
|
||||
{
|
||||
$aDBInfo = $this->FetchExtensionInfoFromDatabase($oConfig);
|
||||
if (false === $aDBInfo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->aInstalledExtensions = [];
|
||||
foreach ($aDBInfo as $aExtensionInfo) {
|
||||
$oExtension = new iTopExtension();
|
||||
$oExtension->sCode = $aExtensionInfo['code'];
|
||||
$oExtension->sLabel = $aExtensionInfo['label'];
|
||||
$oExtension->sDescription = $aExtensionInfo['description'] ?? '';
|
||||
$oExtension->sVersion = $aExtensionInfo['version'];
|
||||
$oExtension->sSource = $aExtensionInfo['source'];
|
||||
$oExtension->bMandatory = false;
|
||||
$oExtension->sMoreInfoUrl = '';
|
||||
$oExtension->aModules = [];
|
||||
$oExtension->aModuleVersion = [];
|
||||
$oExtension->aModuleInfo = [];
|
||||
$oExtension->sSourceDir = '';
|
||||
$oExtension->bVisible = true;
|
||||
$oExtension->bInstalled = true;
|
||||
$oExtension->bCanBeUninstalled = !isset($aExtensionInfo['uninstallable']) || $aExtensionInfo['uninstallable'] === 'yes';
|
||||
$oChoice = $this->GetFromExtensionCode($oExtension->sCode);
|
||||
if ($oChoice) {
|
||||
$oChoice->bInstalled = true;
|
||||
$oExtension->bRemovedFromDisk = $oChoice->bRemovedFromDisk || $oChoice->sSource !== $oExtension->sSource;
|
||||
} else {
|
||||
$oExtension->bRemovedFromDisk = true;
|
||||
$this->aExtensionsByCode[$oExtension->sCode] = $oExtension;
|
||||
}
|
||||
|
||||
$this->aInstalledExtensions[$oExtension->sCode.'/'.$oExtension->sVersion] = $oExtension;
|
||||
}
|
||||
return $this->aInstalledExtensions;
|
||||
}
|
||||
|
||||
public function GetChoicesFromDatabase(Config $oConfig): array|false
|
||||
|
||||
@@ -82,13 +82,14 @@ class WizStepLandingBeforeAudit extends WizStepModulesChoice
|
||||
|
||||
$bForceUninstall = (bool)$this->oWizard->GetParameter('force-uninstall', false);
|
||||
if ($bSkipWizard && !$bForceUninstall) {
|
||||
$oLatestWizardState = $this->oWizard->GetLatestWizardStateFromStepClass(WizStepModulesChoice::class);
|
||||
// Check if the current choices allow going to the data audit step
|
||||
$aOptions = $this->oExtensionsMap->GetAllExtensionsOptionInfo();
|
||||
foreach ($aOptions as $index => $aChoice) {
|
||||
$sChoiceId = self::$SEP.$index;
|
||||
$oLatestWizardState = $this->oWizard->GetLatestWizardStateFromStepClass(WizStepModulesChoice::class);
|
||||
$aFlags = $this->ComputeChoiceFlags($aChoice, $sChoiceId, $aSelectedComponents[$oLatestWizardState->GetState()], false, false);
|
||||
if (!static::CanMoveForwardFromChoiceFlags($aFlags)) {
|
||||
if (!static::CanMoveForwardFromChoiceFlags($aFlags) || $aFlags['missing']) {
|
||||
// If an extension is missing, its uninstallation will be forced. We need to show it to the user
|
||||
// Pop the latest step from the stack, since we are going back to it
|
||||
$this->oWizard->PopStep();
|
||||
|
||||
|
||||
@@ -359,6 +359,40 @@ XML;
|
||||
$oExtensionMap->CheckExtensionsValidity();
|
||||
}
|
||||
|
||||
public function testExtensionsFoundInDBShouldBeMarkedAsInstalled()
|
||||
{
|
||||
$oExtensionsMap = iTopExtensionsMapFake::createFromArray([
|
||||
'itop-installed' => [
|
||||
'installed' => false,
|
||||
],
|
||||
'itop-not-installed' => [
|
||||
'installed' => false,
|
||||
]
|
||||
]);
|
||||
$oExtensionsMap->AddInstalledExtensionInfo('itop-installed');
|
||||
$oExtensionsMap->LoadInstalledExtensionsFromDatabase(new \Config());
|
||||
|
||||
$this->assertTrue($oExtensionsMap->GetFromExtensionCode('itop-installed')->bInstalled);
|
||||
$this->assertFalse($oExtensionsMap->GetFromExtensionCode('itop-not-installed')->bInstalled);
|
||||
}
|
||||
|
||||
public function testExtensionSourceMismatchShouldBeFlaggedAsRemoved()
|
||||
{
|
||||
$sExtensionCode = 'itop-problem-mgmt';
|
||||
$oExtensionsMap = iTopExtensionsMapFake::createFromArray([
|
||||
$sExtensionCode => [
|
||||
'installed' => false,
|
||||
'source' => iTopExtension::SOURCE_WIZARD,
|
||||
]
|
||||
]);
|
||||
$oExtensionsMap->AddInstalledExtensionInfo($sExtensionCode, '6.4.0', iTopExtension::SOURCE_MANUAL);
|
||||
|
||||
$oExtensionsMap->LoadInstalledExtensionsFromDatabase(new \Config());
|
||||
|
||||
$oInstalledExtension = $oExtensionsMap->aInstalledExtensions[$sExtensionCode.'/6.4.0'];
|
||||
$this->assertTrue($oInstalledExtension->bRemovedFromDisk);
|
||||
}
|
||||
|
||||
private function CreateFixtureContext(string $sEnvPrefix): array
|
||||
{
|
||||
$sEnvironment = str_replace('.', '-', uniqid($sEnvPrefix, true));
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
class iTopExtensionsMapFake extends iTopExtensionsMap
|
||||
{
|
||||
public $aInstalledExtensionsInfo = false;
|
||||
public array $aInstalledExtensions;
|
||||
public $aExtensions;
|
||||
|
||||
public function __construct($sFromEnvironment = 'production', $aExtraDirs = [])
|
||||
{
|
||||
$this->aExtensions = [];
|
||||
@@ -33,4 +37,24 @@ class iTopExtensionsMapFake extends iTopExtensionsMap
|
||||
{
|
||||
parent::AddExtension($oNewExtension);
|
||||
}
|
||||
|
||||
protected function FetchExtensionInfoFromDatabase(Config $oConfig): array|false
|
||||
{
|
||||
|
||||
return $this->aInstalledExtensionsInfo;
|
||||
}
|
||||
|
||||
public function AddInstalledExtensionInfo(string $sCode, string $sVersion = '1.0.0', string $sSource = iTopExtension::SOURCE_MANUAL, string $sUninstallable = 'yes'): void
|
||||
{
|
||||
if ($this->aInstalledExtensionsInfo === false) {
|
||||
$this->aInstalledExtensionsInfo = [];
|
||||
}
|
||||
$this->aInstalledExtensionsInfo[] = [
|
||||
'code' => $sCode,
|
||||
'label' => $sCode,
|
||||
'version' => $sVersion,
|
||||
'source' => $sSource,
|
||||
'uninstallable' => $sUninstallable,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user