mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-21 08:12:26 +02:00
N°9167 Use ExtensionDetails UIBlocks instead of table
This commit is contained in:
@@ -31,20 +31,23 @@ use utils;
|
|||||||
class DataFeatureRemovalController extends Controller
|
class DataFeatureRemovalController extends Controller
|
||||||
{
|
{
|
||||||
private array $aRemovedExtensionsForCheck = [];
|
private array $aRemovedExtensionsForCheck = [];
|
||||||
|
private ?array $aExtensionsToCheck = null;
|
||||||
|
private bool $bForcedUninstallation = false;
|
||||||
private array $aCountClassesToCleanup = [];
|
private array $aCountClassesToCleanup = [];
|
||||||
private array $aAnalysisDataTable = [];
|
private array $aAnalysisDataTable = [];
|
||||||
private array $aDeletionExecutionSummary = [];
|
private array $aDeletionExecutionSummary = [];
|
||||||
|
|
||||||
private int $iCount = 0;
|
private int $iCount = 0;
|
||||||
|
private int $iColumnCount = 2;
|
||||||
|
|
||||||
public function OperationMain($sErrorMessage = null): void
|
public function OperationMain($sErrorMessage = null): void
|
||||||
{
|
{
|
||||||
$aParams = [];
|
$aParams = [];
|
||||||
|
|
||||||
$this->ReadRemovedExtensions();
|
|
||||||
$this->AddAnalyzeParams();
|
$this->AddAnalyzeParams();
|
||||||
$aParams['sTransactionId'] = utils::GetNewTransactionId();
|
$aParams['sTransactionId'] = utils::GetNewTransactionId();
|
||||||
$aParams['aExtensions'] = $this->GetExtensionsTableToSelect();
|
$aParams['iColumnCount'] = $this->iColumnCount;
|
||||||
|
$aParams['aAvailableExtensions'] = $this->SplitArrayIntoColumns($this->GetAvailableExtensions(), $this->iColumnCount);
|
||||||
$aParams['aAnalysisDataTable'] = $this->aAnalysisDataTable;
|
$aParams['aAnalysisDataTable'] = $this->aAnalysisDataTable;
|
||||||
$aParams['aClasses'] = array_keys($this->aCountClassesToCleanup);
|
$aParams['aClasses'] = array_keys($this->aCountClassesToCleanup);
|
||||||
$aParams['DataFeatureRemovalErrorMessage'] = $sErrorMessage;
|
$aParams['DataFeatureRemovalErrorMessage'] = $sErrorMessage;
|
||||||
@@ -76,12 +79,11 @@ class DataFeatureRemovalController extends Controller
|
|||||||
|
|
||||||
public function OperationAnalyze(): void
|
public function OperationAnalyze(): void
|
||||||
{
|
{
|
||||||
$this->ReadRemovedExtensions();
|
$iCount = $this->ReadExtensionsDiff();
|
||||||
|
|
||||||
$this->m_sOperation = 'Main';
|
$this->m_sOperation = 'Main';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (count($this->aRemovedExtensionsForCheck) > 0) {
|
if ($iCount > 0) {
|
||||||
$this->Analyze();
|
$this->Analyze();
|
||||||
}
|
}
|
||||||
$this->OperationMain();
|
$this->OperationMain();
|
||||||
@@ -93,7 +95,8 @@ class DataFeatureRemovalController extends Controller
|
|||||||
|
|
||||||
private function Analyze(): void
|
private function Analyze(): void
|
||||||
{
|
{
|
||||||
$this->Compile($this->aRemovedExtensionsForCheck);
|
//TODO : Run data audit with added extension too, not just removed ones
|
||||||
|
$this->Compile($this->aExtensionsToCheck['to_be_removed']);
|
||||||
$sSourceEnv = MetaModel::GetEnvironment();
|
$sSourceEnv = MetaModel::GetEnvironment();
|
||||||
$oSetupAudit = new SetupAudit($sSourceEnv);
|
$oSetupAudit = new SetupAudit($sSourceEnv);
|
||||||
$aGetRemovedClasses = $oSetupAudit->RunDataAudit();
|
$aGetRemovedClasses = $oSetupAudit->RunDataAudit();
|
||||||
@@ -148,7 +151,8 @@ class DataFeatureRemovalController extends Controller
|
|||||||
|
|
||||||
$aParams['sTransactionId'] = utils::GetNewTransactionId();
|
$aParams['sTransactionId'] = utils::GetNewTransactionId();
|
||||||
$aParams['aClasses'] = $aGetRemovedClasses;
|
$aParams['aClasses'] = $aGetRemovedClasses;
|
||||||
$aParams['aExtensions'] = $this->GetExtensionsTableDiff($aAddedExtensions, $aRemovedExtensions);
|
$aParams['iColumnCount'] = $this->iColumnCount;
|
||||||
|
$aParams['aAvailableExtensions'] = $this->SplitArrayIntoColumns($this->GetExtensionsDiff($aAddedExtensions, $aRemovedExtensions), $this->iColumnCount);
|
||||||
|
|
||||||
new ContextTag(ContextTag::TAG_SETUP);
|
new ContextTag(ContextTag::TAG_SETUP);
|
||||||
$aParams['sLaunchSetupUrl'] = utils::GetAbsoluteUrlAppRoot().'setup/wizard.php';
|
$aParams['sLaunchSetupUrl'] = utils::GetAbsoluteUrlAppRoot().'setup/wizard.php';
|
||||||
@@ -261,72 +265,52 @@ class DataFeatureRemovalController extends Controller
|
|||||||
$this->OperationAnalysisResult();
|
$this->OperationAnalysisResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function GetExtensionsTableDiff(array $aAddedExtensions, array $aRemovedExtensions): array
|
private function GetAvailableExtensions(bool $bIncludePackageExtensions = false): array
|
||||||
{
|
{
|
||||||
$aExtensions = [];
|
$aExtensionsData = [];
|
||||||
$aColumns = ['', 'Name', 'code', 'Badge' ];
|
if ($bIncludePackageExtensions) {
|
||||||
|
$aExtensionsRef = DataFeatureRemoverExtensionService::GetInstance()->GetExtensionMap()->GetAllExtensionsWithPreviouslyInstalled();
|
||||||
foreach ($aAddedExtensions as $sAddedExtensionCode => $sAddedExtensionLabel) {
|
|
||||||
$aExtensions[] = [
|
|
||||||
<<<HTML
|
|
||||||
<input type="checkbox" disabled class="extension_check" checked/>
|
|
||||||
HTML,
|
|
||||||
$sAddedExtensionLabel,
|
|
||||||
$sAddedExtensionCode,
|
|
||||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeToBeInstalled'),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
foreach ($aRemovedExtensions as $sAddedExtensionCode => $sAddedExtensionLabel) {
|
else {
|
||||||
$aExtensions[] = [
|
$aExtensionsRef = DataFeatureRemoverExtensionService::GetInstance()->ReadItopExtensions();
|
||||||
<<<HTML
|
|
||||||
<input type="checkbox" disabled class="extension_check"/>
|
|
||||||
HTML,
|
|
||||||
$sAddedExtensionLabel,
|
|
||||||
$sAddedExtensionCode,
|
|
||||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeToBeUninstalled'),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->GetTableData('Extensions', $aColumns, $aExtensions);
|
foreach ($aExtensionsRef as $oExtension) {
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get installed extensions from disk
|
|
||||||
*
|
|
||||||
* @return array structure for twig datatable
|
|
||||||
*/
|
|
||||||
private function GetExtensionsTableToSelect(): array
|
|
||||||
{
|
|
||||||
$aExtensions = [];
|
|
||||||
$aColumns = ['', 'Version', 'Name', 'Code'];
|
|
||||||
|
|
||||||
foreach (DataFeatureRemoverExtensionService::GetInstance()->ReadItopExtensions() as $sCode => $oExtension) {
|
|
||||||
/** @var \iTopExtension $oExtension */
|
/** @var \iTopExtension $oExtension */
|
||||||
|
$aExtensionsData[$oExtension->sCode] = [
|
||||||
|
'version' => $oExtension->sVersion,
|
||||||
|
'label' => $oExtension->sLabel,
|
||||||
|
'code' => $oExtension->sCode,
|
||||||
|
'description' => $oExtension->sDescription,
|
||||||
|
'source' => $oExtension->GetExtensionSourceLabel(),
|
||||||
|
'installed' => $oExtension->bInstalled,
|
||||||
|
'extra_flags' => [
|
||||||
|
'uninstallable' => $oExtension->CanBeUninstalled(),
|
||||||
|
'remote' => $oExtension->IsRemote(),
|
||||||
|
'missing' => $oExtension->bRemovedFromDisk,
|
||||||
|
],
|
||||||
|
|
||||||
$sChecked = '';
|
|
||||||
$sDisabledHtml = '';
|
|
||||||
if ($oExtension->bRemovedFromDisk) {
|
|
||||||
$sDisabledHtml = 'disabled=""';
|
|
||||||
$sChecked = 'checked';
|
|
||||||
} elseif (in_array($sCode, $this->aRemovedExtensionsForCheck)) {
|
|
||||||
$sChecked = 'checked';
|
|
||||||
}
|
|
||||||
|
|
||||||
$sLabel = $oExtension->sLabel;
|
|
||||||
$sVersion = $oExtension->sVersion;
|
|
||||||
$sIdEnable = "aExtensions[$sCode][enable]";
|
|
||||||
|
|
||||||
$aExtensions[] = [
|
|
||||||
<<<HTML
|
|
||||||
<input type="checkbox" $sDisabledHtml class="extension_check" $sChecked id="$sIdEnable" name="$sIdEnable"/>
|
|
||||||
HTML,
|
|
||||||
$sVersion,
|
|
||||||
$sLabel,
|
|
||||||
$sCode,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->GetTableData('Extensions', $aColumns, $aExtensions);
|
return $aExtensionsData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function GetExtensionsDiff(array $aAddedExtensions, array $aRemovedExtensions): array
|
||||||
|
{
|
||||||
|
$aExtensions = [];
|
||||||
|
foreach ($this->GetAvailableExtensions(true) as $sCode => $aExtension) {
|
||||||
|
$aExtension['extra_flags']['disabled'] = true;
|
||||||
|
if (isset($aAddedExtensions[$sCode])) {
|
||||||
|
$aExtension['extra_flags']['selected'] = true;
|
||||||
|
$aExtensions[$sCode] = $aExtension;
|
||||||
|
} elseif (isset($aRemovedExtensions[$sCode])) {
|
||||||
|
$aExtension['extra_flags']['selected'] = false;
|
||||||
|
$aExtensions[$sCode] = $aExtension;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $aExtensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function GetTableData(string $sTableName, array $aColumns, array $aData): array
|
private function GetTableData(string $sTableName, array $aColumns, array $aData): array
|
||||||
@@ -370,27 +354,56 @@ HTML,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return void
|
* Read extensions selected from posted parameters
|
||||||
|
* @return int Number of extensions to be added or removed
|
||||||
*/
|
*/
|
||||||
public function ReadRemovedExtensions(): void
|
public function ReadExtensionsDiff(): int
|
||||||
{
|
{
|
||||||
if (count($this->aRemovedExtensionsForCheck) > 0) {
|
if (!is_null($this->aExtensionsToCheck)) {
|
||||||
return;
|
return count($this->aExtensionsToCheck['to_be_installed']) + count($this->aExtensionsToCheck['to_be_removed']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$aSelectedExtensionsFromUI = utils::ReadPostedParam('aExtensions', []);
|
$aAvailableExtensions = $this->GetAvailableExtensions();
|
||||||
foreach ($aSelectedExtensionsFromUI as $sCode => $aData) {
|
$aSelectedExtensionsFromUI = utils::ReadPostedParam('aSelectedExtensions', []);
|
||||||
$sValue = $aData['enable'] ?? 'off';
|
$this->aExtensionsToCheck = [
|
||||||
if (($sValue) === 'on') {
|
'to_be_installed' => [],
|
||||||
$this->aRemovedExtensionsForCheck[] = $sCode;
|
'to_be_removed' => [],
|
||||||
}
|
];
|
||||||
|
foreach ($aAvailableExtensions as $sCode => &$aExtensionData) {
|
||||||
|
if (!isset($aSelectedExtensionsFromUI[$sCode])) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add source removed to check
|
if ($aExtensionData['installed'] && $aSelectedExtensionsFromUI[$sCode] !== 'on') {
|
||||||
foreach (DataFeatureRemoverExtensionService::GetInstance()->ReadItopExtensions() as $sCode => $oExtension) {
|
$aExtensionData['extra_flags']['selected'] = false;
|
||||||
if ($oExtension->bRemovedFromDisk) {
|
$this->aExtensionsToCheck['to_be_removed'][] = $sCode;
|
||||||
$this->aRemovedExtensionsForCheck[] = $sCode;
|
if (!$aExtensionData['extra_flags']['uninstallable'] || $aExtensionData['extra_flags']['remote']) {
|
||||||
|
$this->bForcedUninstallation = true;
|
||||||
|
}
|
||||||
|
} elseif (!$aExtensionData['installed'] && $aSelectedExtensionsFromUI[$sCode] === 'on') {
|
||||||
|
$aExtensionData['extra_flags']['selected'] = true;
|
||||||
|
$this->aExtensionsToCheck['to_be_installed'][] = $sCode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return count($this->aExtensionsToCheck['to_be_installed']) + count($this->aExtensionsToCheck['to_be_removed']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Divide an array into several sub arrays, distributing elements so that every sub array has an equal amount of elements
|
||||||
|
* @param mixed[] $aInput
|
||||||
|
* @param int $iColNumber
|
||||||
|
*
|
||||||
|
* @return array[]
|
||||||
|
*/
|
||||||
|
private function SplitArrayIntoColumns(array $aInput, int $iColNumber)
|
||||||
|
{
|
||||||
|
$aOutput = array_fill(0, $iColNumber, []);
|
||||||
|
$iIndex = 0;
|
||||||
|
foreach ($aInput as $mItem) {
|
||||||
|
//Split extensions in $iColNumber columns
|
||||||
|
$aOutput[$iIndex % $this->iColumnCount][] = $mItem;
|
||||||
|
$iIndex++;
|
||||||
|
}
|
||||||
|
return $aOutput;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use MetaModel;
|
|||||||
class DataFeatureRemoverExtensionService
|
class DataFeatureRemoverExtensionService
|
||||||
{
|
{
|
||||||
private static DataFeatureRemoverExtensionService $oInstance;
|
private static DataFeatureRemoverExtensionService $oInstance;
|
||||||
|
private ?iTopExtensionsMap $oMap = null;
|
||||||
private array $aItopExtensions = [];
|
private array $aItopExtensions = [];
|
||||||
private array $aIncludingExtensionsByModuleName = [];
|
private array $aIncludingExtensionsByModuleName = [];
|
||||||
|
|
||||||
@@ -60,15 +60,25 @@ class DataFeatureRemoverExtensionService
|
|||||||
return $this->aIncludingExtensionsByModuleName[$sModuleName] ?? [];
|
return $this->aIncludingExtensionsByModuleName[$sModuleName] ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \iTopExtensionsMap
|
||||||
|
*/
|
||||||
|
public function GetExtensionMap(): iTopExtensionsMap
|
||||||
|
{
|
||||||
|
if (is_null($this->oMap)) {
|
||||||
|
$this->oMap = new iTopExtensionsMap();
|
||||||
|
$this->oMap->LoadInstalledExtensionsFromDatabase(MetaModel::GetConfig());
|
||||||
|
}
|
||||||
|
return $this->oMap;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return iTopExtension[]
|
* @return iTopExtension[]
|
||||||
*/
|
*/
|
||||||
public function ReadItopExtensions(): array
|
public function ReadItopExtensions(): array
|
||||||
{
|
{
|
||||||
if (count($this->aItopExtensions) === 0) {
|
if (count($this->aItopExtensions) === 0) {
|
||||||
$oExtensionsMap = new iTopExtensionsMap();
|
$this->aItopExtensions = $this->GetExtensionMap()->GetAllExtensionsToDisplayInSetup(true);
|
||||||
$oExtensionsMap->LoadInstalledExtensionsFromDatabase(MetaModel::GetConfig());
|
|
||||||
$this->aItopExtensions = $oExtensionsMap->GetAllExtensionsToDisplayInSetup(true);
|
|
||||||
|
|
||||||
uasort($this->aItopExtensions, function (iTopExtension $oiTopExtension1, iTopExtension $oiTopExtension2) {
|
uasort($this->aItopExtensions, function (iTopExtension $oiTopExtension1, iTopExtension $oiTopExtension2) {
|
||||||
return strcmp($oiTopExtension1->sLabel, $oiTopExtension2->sLabel);
|
return strcmp($oiTopExtension1->sLabel, $oiTopExtension2->sLabel);
|
||||||
|
|||||||
@@ -174,6 +174,7 @@ class iTopExtension
|
|||||||
return match ($this->sSource) {
|
return match ($this->sSource) {
|
||||||
self::SOURCE_MANUAL => 'Local extensions folder',
|
self::SOURCE_MANUAL => 'Local extensions folder',
|
||||||
self::SOURCE_REMOTE => (ITOP_APPLICATION == 'iTop') ? 'iTop Hub' : 'ITSM Designer',
|
self::SOURCE_REMOTE => (ITOP_APPLICATION == 'iTop') ? 'iTop Hub' : 'ITSM Designer',
|
||||||
|
self::SOURCE_WIZARD => 'iTop package',
|
||||||
default => '',
|
default => '',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class ExtensionDetails extends UIContentBlock
|
|||||||
$this->sCode = $sCode;
|
$this->sCode = $sCode;
|
||||||
$this->sLabel = $sLabel;
|
$this->sLabel = $sLabel;
|
||||||
$this->sDescription = $sDescription;
|
$this->sDescription = $sDescription;
|
||||||
$this->aMetaData = $aMetaData;
|
$this->aMetaData = array_filter($aMetaData);
|
||||||
$this->aBadges = $aBadges;
|
$this->aBadges = $aBadges;
|
||||||
$this->sAbout = $sAbout;
|
$this->sAbout = $sAbout;
|
||||||
$this->InitializeToggler();
|
$this->InitializeToggler();
|
||||||
@@ -105,7 +105,7 @@ class ExtensionDetails extends UIContentBlock
|
|||||||
*/
|
*/
|
||||||
public function SetMetaData(array $aMetaData): static
|
public function SetMetaData(array $aMetaData): static
|
||||||
{
|
{
|
||||||
$this->aMetaData = $aMetaData;
|
$this->aMetaData = array_filter($aMetaData);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user