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'; require_once APPROOT.'setup/feature_removal/DryRemovalRuntimeEnvironment.php';
use Combodo\iTop\Application\TwigBase\Controller\Controller; use Combodo\iTop\Application\TwigBase\Controller\Controller;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalConfig;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException; use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException;
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalHelper; use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalHelper;
use Combodo\iTop\DataFeatureRemoval\Service\DataCleanupService; use Combodo\iTop\DataFeatureRemoval\Service\DataCleanupService;
@@ -39,7 +38,7 @@ class DataFeatureRemovalController extends Controller
$this->ReadRemovedExtensions(); $this->ReadRemovedExtensions();
$this->AddAnalyzeParams(); $this->AddAnalyzeParams();
$aParams['sTransactionId'] = utils::GetNewTransactionId(); $aParams['sTransactionId'] = utils::GetNewTransactionId();
$aParams['aExtensions'] = $this->GetExtensionsTable(); $aParams['aExtensions'] = $this->GetExtensionsTableToSelect();
$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;
@@ -110,6 +109,12 @@ class DataFeatureRemovalController extends Controller
$this->ValidateTransactionId(); $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(); $sSourceEnv = MetaModel::GetEnvironment();
$oSetupAudit = new SetupAudit($sSourceEnv); $oSetupAudit = new SetupAudit($sSourceEnv);
$aGetRemovedClasses = array_keys($oSetupAudit->RunDataAudit()); $aGetRemovedClasses = array_keys($oSetupAudit->RunDataAudit());
@@ -138,6 +143,9 @@ class DataFeatureRemovalController extends Controller
$aParams['aClasses'] = $aGetRemovedClasses; $aParams['aClasses'] = $aGetRemovedClasses;
$aParams['iQueryCount'] = $iQueryCount; $aParams['iQueryCount'] = $iQueryCount;
$aParams['bDeletionPossible'] = !$bHasIssues; $aParams['bDeletionPossible'] = !$bHasIssues;
$aParams['aAddedExtensions'] = $aAddedExtensions;
$aParams['aRemovedExtensions'] = $aRemovedExtensions;
$aParams['aExtensions'] = $this->GetExtensionsTableDiff($aAddedExtensions, $aRemovedExtensions);
$this->DisplayPage($aParams); $this->DisplayPage($aParams);
} }
@@ -201,12 +209,41 @@ class DataFeatureRemovalController extends Controller
$this->DisplayPage($aParams); $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 * Get installed extensions from disk
* *
* @return array structure for twig datatable * @return array structure for twig datatable
*/ */
private function GetExtensionsTable(): array private function GetExtensionsTableToSelect(): array
{ {
$aExtensions = []; $aExtensions = [];
$aColumns = ['', 'Version', 'Name', 'Code']; $aColumns = ['', 'Version', 'Name', 'Code'];

View File

@@ -23,7 +23,7 @@ class ObjectServiceSummary implements iObjectService
public function Update(DBObject $oToUpdate, string $sAttCode, $value): void public function Update(DBObject $oToUpdate, string $sAttCode, $value): void
{ {
$sClass = get_class($oToUpdate); $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)) { if (! array_key_exists($sClass, $this->aSummary)) {
$this->aSummary[$sClass] = new DataCleanupSummaryEntity($sClass); $this->aSummary[$sClass] = new DataCleanupSummaryEntity($sClass);
} }
@@ -33,7 +33,7 @@ class ObjectServiceSummary implements iObjectService
public function Delete(string $sClass, string $sId): void 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)) { if (!array_key_exists($sClass, $this->aSummary)) {
$this->aSummary[$sClass] = new DataCleanupSummaryEntity($sClass); $this->aSummary[$sClass] = new DataCleanupSummaryEntity($sClass);
} }

View File

@@ -1,29 +1,38 @@
{# @copyright Copyright (C) 2010-2026 Combodo SARL #} {# @copyright Copyright (C) 2010-2026 Combodo SARL #}
{# @license http://opensource.org/licenses/AGPL-3.0 #} {# @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 {} %} {% UIForm Standard {} %}
{% UIInput ForHidden { sName:'transaction_id', sValue:sTransactionId} %} {% UIInput ForHidden { sName:'transaction_id', sValue:sTransactionId} %}
{% UIInput ForHidden { sName:'operation', sValue:'DoDeletion'} %} {% UIInput ForHidden { sName:'operation', sValue:'Main'} %}
{% for sKey, sClass in aClasses %}
{% UIInput ForHidden { sName:"classes[" ~ sKey ~ "]", sValue:sClass } %}
{% endfor %}
{% UIToolbar ForButton {} %} {% 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 %} {% EndUIToolbar %}
{% EndUIForm %} {% EndUIForm %}
{% else %} {% EndUIPanel %}
{{ '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 %}

View File

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