Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion css/backoffice/layout/extension/_extension-details.scss
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,15 @@ $ibo-extension-details--actions--button--padding-x: $ibo-button--padding-x !defa

.ibo-extension-details--actions:has(.toggler-install:not(:disabled)) .ibo-popover-menu--section a[data-resource-id="force_uninstall"] {
display: none;
}
}

.ibo-extension-details .ibo-popover-menu ~ .ibo-button{
visibility: hidden;
}
.ibo-extension-details .ibo-popover-menu:has(.ibo-popover-menu--item) ~ .ibo-button{
visibility: visible;
}

.ibo-extension-details .ibo-toggler--wrapper:has(.ibo-toggler.ibo-is-hidden){
visibility: hidden;
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,23 @@
class DataFeatureRemovalController extends Controller
{
private array $aRemovedExtensionsForCheck = [];
private ?array $aExtensionsToCheck = null;
private bool $bForcedUninstallation = false;
private array $aCountClassesToCleanup = [];
private array $aAnalysisDataTable = [];
private array $aDeletionExecutionSummary = [];

private int $iCount = 0;
private int $iColumnCount = 2;

public function OperationMain($sErrorMessage = null): void
{
$aParams = [];

$this->ReadRemovedExtensions();
$this->AddAnalyzeParams();
$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['aClasses'] = array_keys($this->aCountClassesToCleanup);
$aParams['DataFeatureRemovalErrorMessage'] = $sErrorMessage;
Expand Down Expand Up @@ -76,12 +79,11 @@ public function AddAnalyzeParams(): void

public function OperationAnalyze(): void
{
$this->ReadRemovedExtensions();
$iCount = $this->ReadExtensionsDiff();

$this->m_sOperation = 'Main';

try {
if (count($this->aRemovedExtensionsForCheck) > 0) {
if ($iCount > 0) {
$this->Analyze();
}
$this->OperationMain();
Expand All @@ -93,7 +95,8 @@ public function OperationAnalyze(): 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();
$oSetupAudit = new SetupAudit($sSourceEnv);
$aGetRemovedClasses = $oSetupAudit->RunDataAudit();
Expand Down Expand Up @@ -148,7 +151,8 @@ public function OperationAnalysisResult(): void

$aParams['sTransactionId'] = utils::GetNewTransactionId();
$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);
$aParams['sLaunchSetupUrl'] = utils::GetAbsoluteUrlAppRoot().'setup/wizard.php';
Expand Down Expand Up @@ -261,72 +265,51 @@ public function OperationDoDeletion(): void
$this->OperationAnalysisResult();
}

private function GetExtensionsTableDiff(array $aAddedExtensions, array $aRemovedExtensions): array
private function GetAvailableExtensions(bool $bIncludePackageExtensions = false): array
{
$aExtensions = [];
$aColumns = ['', 'Name', 'code', 'Badge' ];

foreach ($aAddedExtensions as $sAddedExtensionCode => $sAddedExtensionLabel) {
$aExtensions[] = [
<<<HTML
<input type="checkbox" disabled class="extension_check" checked/>
HTML,
$sAddedExtensionLabel,
$sAddedExtensionCode,
Dict::S('UI:Layout:ExtensionsDetails:BadgeToBeInstalled'),
];
$aExtensionsData = [];
if ($bIncludePackageExtensions) {
$aExtensionsRef = DataFeatureRemoverExtensionService::GetInstance()->GetExtensionMap()->GetAllExtensionsWithPreviouslyInstalled();
} else {
$aExtensionsRef = DataFeatureRemoverExtensionService::GetInstance()->ReadItopExtensions();
}
foreach ($aRemovedExtensions as $sAddedExtensionCode => $sAddedExtensionLabel) {
$aExtensions[] = [
<<<HTML
<input type="checkbox" disabled class="extension_check"/>
HTML,
$sAddedExtensionLabel,
$sAddedExtensionCode,
Dict::S('UI:Layout:ExtensionsDetails:BadgeToBeUninstalled'),

foreach ($aExtensionsRef as $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,
],
Comment thread
Timmy38 marked this conversation as resolved.

];
}

return $this->GetTableData('Extensions', $aColumns, $aExtensions);
return $aExtensionsData;
}

/**
* Get installed extensions from disk
*
* @return array structure for twig datatable
*/
private function GetExtensionsTableToSelect(): array
private function GetExtensionsDiff(array $aAddedExtensions, array $aRemovedExtensions): array
{
$aExtensions = [];
$aColumns = ['', 'Version', 'Name', 'Code'];

foreach (DataFeatureRemoverExtensionService::GetInstance()->ReadItopExtensions() as $sCode => $oExtension) {
/** @var \iTopExtension $oExtension */

$sChecked = '';
$sDisabledHtml = '';
if ($oExtension->bRemovedFromDisk) {
$sDisabledHtml = 'disabled=""';
$sChecked = 'checked';
} elseif (in_array($sCode, $this->aRemovedExtensionsForCheck)) {
$sChecked = 'checked';
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;
}

$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 $aExtensions;
}

private function GetTableData(string $sTableName, array $aColumns, array $aData): array
Expand Down Expand Up @@ -370,27 +353,56 @@ private function ValidateTransactionId(): void
}

/**
* @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) {
return;
if (!is_null($this->aExtensionsToCheck)) {
return count($this->aExtensionsToCheck['to_be_installed']) + count($this->aExtensionsToCheck['to_be_removed']);
}

$aSelectedExtensionsFromUI = utils::ReadPostedParam('aExtensions', []);
foreach ($aSelectedExtensionsFromUI as $sCode => $aData) {
$sValue = $aData['enable'] ?? 'off';
if (($sValue) === 'on') {
$this->aRemovedExtensionsForCheck[] = $sCode;
$aAvailableExtensions = $this->GetAvailableExtensions();
$aSelectedExtensionsFromUI = utils::ReadPostedParam('aSelectedExtensions', []);
$this->aExtensionsToCheck = [
'to_be_installed' => [],
'to_be_removed' => [],
];
foreach ($aAvailableExtensions as $sCode => &$aExtensionData) {
if (!isset($aSelectedExtensionsFromUI[$sCode])) {
continue;
}
}

// Add source removed to check
foreach (DataFeatureRemoverExtensionService::GetInstance()->ReadItopExtensions() as $sCode => $oExtension) {
if ($oExtension->bRemovedFromDisk) {
$this->aRemovedExtensionsForCheck[] = $sCode;
if ($aExtensionData['installed'] && $aSelectedExtensionsFromUI[$sCode] !== 'on') {
$aExtensionData['extra_flags']['selected'] = false;
$this->aExtensionsToCheck['to_be_removed'][] = $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) {
Comment thread
Timmy38 marked this conversation as resolved.
//Split extensions in $iColNumber columns
$aOutput[$iIndex % $this->iColumnCount][] = $mItem;
$iIndex++;
}
return $aOutput;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
class DataFeatureRemoverExtensionService
{
private static DataFeatureRemoverExtensionService $oInstance;

private ?iTopExtensionsMap $oMap = null;
private array $aItopExtensions = [];
private array $aIncludingExtensionsByModuleName = [];

Expand Down Expand Up @@ -60,15 +60,25 @@ public function GetIncludingExtensions(string $sModuleName): array
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[]
*/
public function ReadItopExtensions(): array
{
if (count($this->aItopExtensions) === 0) {
$oExtensionsMap = new iTopExtensionsMap();
$oExtensionsMap->LoadInstalledExtensionsFromDatabase(MetaModel::GetConfig());
$this->aItopExtensions = $oExtensionsMap->GetAllExtensionsToDisplayInSetup(true);
$this->aItopExtensions = $this->GetExtensionMap()->GetAllExtensionsToDisplayInSetup(true);

uasort($this->aItopExtensions, function (iTopExtension $oiTopExtension1, iTopExtension $oiTopExtension2) {
return strcmp($oiTopExtension1->sLabel, $oiTopExtension2->sLabel);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,21 @@


{% UIPanel ForInformation { sTitle:'DataFeatureRemoval:Analysis:Title'|dict_s} %}

{% UIFieldSet Standard {sLegend:'DataFeatureRemoval:Features:Title'|dict_s} %}
{% UIDataTable ForForm { sRef:'aExtensions', aColumns:aExtensions.Columns, aData:aExtensions.Data} %}{% EndUIDataTable %}
{% EndUIFieldSet %}
{% UIPanel Neutral { sTitle:'DataFeatureRemoval:Features:Title'|dict_s, sSubTitle: '' } %}
{% UIMultiColumn Standard {} %}
{% for iColumnIndex in 0..iColumnCount-1 %}
{% UIColumn Standard {} %}
{% for aExtension in aAvailableExtensions[iColumnIndex] %}
{% if aExtension['installed'] %}
{% UIExtensionDetails Installed { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : [aExtension['version'], aExtension['source']], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %}
{% else %}
{% UIExtensionDetails NotInstalled { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : [aExtension['version'], aExtension['source']], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %}
{% endif %}
{% endfor %}
{% EndUIColumn %}
{% endfor %}
{% EndUIMultiColumn %}
{% EndUIPanel %}

{% if bDeletionNeeded %}
{% UIFieldSet Standard {sLegend:'DataFeatureRemoval:DeletionPlan:Title'|dict_s} %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,21 @@
{% UIInput ForHidden {sName:'operation', sValue:'Analyze'} %}
{% UIInput ForHidden {sName:'transaction_id', sValue:sTransactionId} %}

{% UIFieldSet Standard {sLegend:'DataFeatureRemoval:Features:Title'|dict_s} %}
{% UIDataTable ForForm { sRef:'aExtensions', aColumns:aExtensions.Columns, aData:aExtensions.Data} %}{% EndUIDataTable %}
{% EndUIFieldSet %}
{% UIPanel Neutral { sTitle:'DataFeatureRemoval:Features:Title'|dict_s, sSubTitle: '' } %}
{% UIMultiColumn Standard {} %}
{% for iColumnIndex in 0..iColumnCount-1 %}
{% UIColumn Standard {} %}
{% for aExtension in aAvailableExtensions[iColumnIndex] %}
{% if aExtension['installed'] %}
{% UIExtensionDetails Installed { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : [aExtension['version'], aExtension['source']], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %}
{% else %}
{% UIExtensionDetails NotInstalled { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : [aExtension['version'], aExtension['source']], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %}
{% endif %}
{% endfor %}
{% EndUIColumn %}
{% endfor %}
{% EndUIMultiColumn %}
{% EndUIPanel %}

{% UIToolbar ForButton {} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:Analyze'|dict_s, sName:'btn_apply', sId:'btn_apply', bIsSubmit:true} %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
'UI:Layout:ExtensionsDetails:MoreActions' => 'Show more actions~~',
]);
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
'UI:Layout:ExtensionsDetails:MoreActions' => 'Show more actions~~',
]);
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
'UI:Layout:ExtensionsDetails:MoreActions' => 'Show more actions~~',
]);
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s',
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations',
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall',
'UI:Layout:ExtensionsDetails:MoreActions' => 'Show more actions',
]);
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
'UI:Layout:ExtensionsDetails:MoreActions' => 'Show more actions~~',
]);
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'À propos de %1$s',
'UI:Layout:ExtensionsDetails:MenuAbout' => 'Plus d\'informations',
'UI:Layout:ExtensionsDetails:MenuForce' => 'Forcer la désinstallation',
'UI:Layout:ExtensionsDetails:MoreActions' => 'Plus d\'actions',
]);
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
'UI:Layout:ExtensionsDetails:MoreActions' => 'Show more actions~~',
]);
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
'UI:Layout:ExtensionsDetails:MoreActions' => 'Show more actions~~',
]);
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'About %1$s~~',
'UI:Layout:ExtensionsDetails:MenuAbout' => 'More informations~~',
'UI:Layout:ExtensionsDetails:MenuForce' => 'Force uninstall~~',
'UI:Layout:ExtensionsDetails:MoreActions' => 'Show more actions~~',
]);
Loading