Merge branch 'feature/uninstallation' into feature/9567-runsetup-from-ext-mgt

This commit is contained in:
Eric Espie
2026-05-06 18:04:43 +02:00
4 changed files with 88 additions and 29 deletions

View File

@@ -11,7 +11,6 @@ require_once APPROOT.'setup/feature_removal/SetupAudit.php';
require_once APPROOT.'setup/feature_removal/DryRemovalRuntimeEnvironment.php';
use Combodo\iTop\Application\TwigBase\Controller\Controller;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalConfig;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalHelper;
use Combodo\iTop\DataFeatureRemoval\Service\DataCleanupService;
@@ -39,7 +38,7 @@ class DataFeatureRemovalController extends Controller
$this->ReadRemovedExtensions();
$this->AddAnalyzeParams();
$aParams['sTransactionId'] = utils::GetNewTransactionId();
$aParams['aExtensions'] = $this->GetExtensionsTable();
$aParams['aExtensions'] = $this->GetExtensionsTableToSelect();
$aParams['aAnalysisDataTable'] = $this->aAnalysisDataTable;
$aParams['aClasses'] = array_keys($this->aCountClassesToCleanup);
$aParams['DataFeatureRemovalErrorMessage'] = $sErrorMessage;
@@ -110,6 +109,12 @@ class DataFeatureRemovalController extends Controller
$this->ValidateTransactionId();
}
// Display changed extensions
$aAddedExtensions = utils::ReadPostedParam('aAddedExtensions', []);
$aRemovedExtensions = utils::ReadPostedParam('aRemovedExtensions', []);
IssueLog::Info(__METHOD__.' Extensions given in parameter', null, ['aAddedExtensions' => $aAddedExtensions, 'aRemovedExtensions' => $aRemovedExtensions]);
$sSourceEnv = MetaModel::GetEnvironment();
$oSetupAudit = new SetupAudit($sSourceEnv);
$aGetRemovedClasses = array_keys($oSetupAudit->RunDataAudit());
@@ -138,6 +143,9 @@ class DataFeatureRemovalController extends Controller
$aParams['aClasses'] = $aGetRemovedClasses;
$aParams['iQueryCount'] = $iQueryCount;
$aParams['bDeletionPossible'] = !$bHasIssues;
$aParams['aAddedExtensions'] = $aAddedExtensions;
$aParams['aRemovedExtensions'] = $aRemovedExtensions;
$aParams['aExtensions'] = $this->GetExtensionsTableDiff($aAddedExtensions, $aRemovedExtensions);
$this->DisplayPage($aParams);
}
@@ -201,12 +209,41 @@ class DataFeatureRemovalController extends Controller
$this->DisplayPage($aParams);
}
private function GetExtensionsTableDiff(array $aAddedExtensions, array $aRemovedExtensions): 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'),
];
}
foreach ($aRemovedExtensions as $sAddedExtensionCode => $sAddedExtensionLabel) {
$aExtensions[] = [
<<<HTML
<input type="checkbox" disabled class="extension_check"/>
HTML,
$sAddedExtensionLabel,
$sAddedExtensionCode,
Dict::S('UI:Layout:ExtensionsDetails:BadgeToBeUninstalled'),
];
}
return $this->GetTableData('Extensions', $aColumns, $aExtensions);
}
/**
* Get installed extensions from disk
*
* @return array structure for twig datatable
*/
private function GetExtensionsTable(): array
private function GetExtensionsTableToSelect(): array
{
$aExtensions = [];
$aColumns = ['', 'Version', 'Name', 'Code'];

View File

@@ -23,7 +23,7 @@ class ObjectServiceSummary implements iObjectService
public function Update(DBObject $oToUpdate, string $sAttCode, $value): void
{
$sClass = get_class($oToUpdate);
DataFeatureRemovalLog::Info('Update object', null, ['class' => $sClass, 'id' => $oToUpdate->GetKey(), 'code' => $sAttCode, 'value' => "$value"]);
DataFeatureRemovalLog::Info('Object to update', null, ['class' => $sClass, 'id' => $oToUpdate->GetKey(), 'code' => $sAttCode, 'value' => "$value"]);
if (! array_key_exists($sClass, $this->aSummary)) {
$this->aSummary[$sClass] = new DataCleanupSummaryEntity($sClass);
}
@@ -33,7 +33,7 @@ class ObjectServiceSummary implements iObjectService
public function Delete(string $sClass, string $sId): void
{
DataFeatureRemovalLog::Info('Delete object', null, ['class' => $sClass, 'id' => $sId]);
DataFeatureRemovalLog::Info('Object to delete', null, ['class' => $sClass, 'id' => $sId]);
if (!array_key_exists($sClass, $this->aSummary)) {
$this->aSummary[$sClass] = new DataCleanupSummaryEntity($sClass);
}

View File

@@ -1,29 +1,38 @@
{# @copyright Copyright (C) 2010-2026 Combodo SARL #}
{# @license http://opensource.org/licenses/AGPL-3.0 #}
{% UIPanel ForInformation { sTitle:'DataFeatureRemoval:DeletionPlan:Title'|dict_s, sSubTitle: 'DataFeatureRemoval:DeletionPlan:SubTitle'|dict_format(iQueryCount) } %}
{% UIDataTable ForForm { sRef:'aDeletionPlanSummary', aColumns:aDeletionPlanSummary.Columns, aData:aDeletionPlanSummary.Data} %}{% EndUIDataTable %}
{% EndUIPanel %}
{% if bDeletionPossible %}
{% 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 %}
{% UIFieldSet Standard {sLegend:'DataFeatureRemoval:DeletionPlan:Title'|dict_s} %}
{% UIDataTable ForForm { sRef:'aDeletionPlanSummary', aColumns:aDeletionPlanSummary.Columns, aData:aDeletionPlanSummary.Data} %}{% EndUIDataTable %}
{% EndUIFieldSet %}
{% if bDeletionPossible %}
{% UIForm Standard {} %}
{% UIInput ForHidden { sName:'transaction_id', sValue:sTransactionId} %}
{% UIInput ForHidden { sName:'operation', sValue:'DoDeletion'} %}
{% for sKey, sClass in aClasses %}
{% UIInput ForHidden { sName:"classes[" ~ sKey ~ "]", sValue:sClass } %}
{% endfor %}
{% UIToolbar ForButton {} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:DoDeletion'|dict_s, sName:'btn_deletion', sId:'btn_deletion', bIsSubmit:true} %}
{% EndUIToolbar %}
{% EndUIForm %}
{% else %}
{{ 'DataFeatureRemoval:DeletionPlan:Error:Issues'|dict_s }}
{% endif %}
{% UIForm Standard {} %}
{% UIInput ForHidden { sName:'transaction_id', sValue:sTransactionId} %}
{% UIInput ForHidden { sName:'operation', sValue:'DoDeletion'} %}
{% for sKey, sClass in aClasses %}
{% UIInput ForHidden { sName:"classes[" ~ sKey ~ "]", sValue:sClass } %}
{% endfor %}
{% UIInput ForHidden { sName:'operation', sValue:'Main'} %}
{% UIToolbar ForButton {} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:DoDeletion'|dict_s, sName:'btn_deletion', sId:'btn_deletion', bIsSubmit:true} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:BackToMain'|dict_s, sName:'btn_back', sId:'btn_back', bIsSubmit:true} %}
{% EndUIToolbar %}
{% EndUIForm %}
{% else %}
{{ 'DataFeatureRemoval:DeletionPlan:Error:Issues'|dict_s }}
{% endif %}
{% UIForm Standard {} %}
{% UIInput ForHidden { sName:'transaction_id', sValue:sTransactionId} %}
{% UIInput ForHidden { sName:'operation', sValue:'Main'} %}
{% UIToolbar ForButton {} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:BackToMain'|dict_s, sName:'btn_back', sId:'btn_back', bIsSubmit:true} %}
{% EndUIToolbar %}
{% EndUIForm %}
{% EndUIPanel %}

View File

@@ -19,7 +19,6 @@
*/
use Combodo\iTop\Application\Helper\Session;
use Combodo\iTop\Application\WebPage\WebPage;
require_once(APPROOT.'setup/sequencers/DataAuditSequencer.php');
@@ -101,8 +100,8 @@ JS);
{
$sApplicationUrl = utils::GetAbsoluteUrlModulePage('combodo-data-feature-removal', 'index.php');
$aRemovedExtensions = json_decode($this->oWizard->GetParameter('removed_extensions', "[]"), true);
$aHiddenRemovedExtensionInputs = "";
$aRemovedExtensions = json_decode($this->oWizard->GetParameter('removed_extensions', '[]'), true);
$aHiddenRemovedExtensionInputs = '';
if (!is_array($aRemovedExtensions)) {
IssueLog::Warning('Posted removed_extensions is not an array');
$aRemovedExtensions = [];
@@ -110,7 +109,20 @@ JS);
foreach ($aRemovedExtensions as $sExtCode => $sExtLabel) {
$sSafeExtCode = utils::HtmlEntities($sExtCode);
$aHiddenRemovedExtensionInputs .= <<<INPUT
<input type="hidden" name="aExtensions[$sSafeExtCode][enable]" value="on"/>
<input type="hidden" name="aRemovedExtensions[$sSafeExtCode]" value="$sExtLabel"/>
INPUT;
}
$aAddedExtensions = json_decode($this->oWizard->GetParameter('extensions_added', "[]"), true);
$aHiddenAddedExtensionInputs = "";
if (!is_array($aAddedExtensions)) {
IssueLog::Warning('Posted extensions_added is not an array');
$aAddedExtensions = [];
}
foreach ($aAddedExtensions as $sExtCode => $sExtLabel) {
$sSafeExtCode = utils::HtmlEntities($sExtCode);
$aHiddenAddedExtensionInputs .= <<<INPUT
<input type="hidden" name="aAddedExtensions[$sSafeExtCode]" value="$sExtLabel"/>
INPUT;
}
$sUID = Session::Get('setup_token');
@@ -120,6 +132,7 @@ INPUT;
<input type="hidden" name="operation" value="AnalysisResult"/>
<input type="hidden" name="setup_token" value="$sUID"/>
$aHiddenRemovedExtensionInputs
$aHiddenAddedExtensionInputs
</form>
HTML
);