From ed814c1439be281edec78ba78b691035800bb6d7 Mon Sep 17 00:00:00 2001 From: Eric Espie Date: Mon, 11 May 2026 11:47:47 +0200 Subject: [PATCH] =?UTF-8?q?N=C2=B09412=20-=20Analysis=20results=20screen?= =?UTF-8?q?=20wip?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DataFeatureRemovalController.php | 23 ++---- .../src/Service/DataCleanupService.php | 6 +- .../src/Service/ObjectServiceSummary.php | 14 ++++ .../templates/AnalysisResult.html.twig | 28 ++++---- .../unattended-install/xml_setup/upgrade.xml | 2 +- .../DataCleanupServiceTest.php | 72 +++++++++++++++++-- 6 files changed, 103 insertions(+), 42 deletions(-) diff --git a/datamodels/2.x/combodo-data-feature-removal/src/Controller/DataFeatureRemovalController.php b/datamodels/2.x/combodo-data-feature-removal/src/Controller/DataFeatureRemovalController.php index dd60db17a8..8e6854fdf8 100644 --- a/datamodels/2.x/combodo-data-feature-removal/src/Controller/DataFeatureRemovalController.php +++ b/datamodels/2.x/combodo-data-feature-removal/src/Controller/DataFeatureRemovalController.php @@ -126,13 +126,14 @@ class DataFeatureRemovalController extends Controller $aParams['sTransactionId'] = utils::GetNewTransactionId(); $aParams['aClasses'] = $aGetRemovedClasses; - [$aParams['aDeletionPlanSummary'], $aParams['iQueryCount'], $aParams['bDeletionPossible']] = $this->GetDeletionPlanSummaryTable($aGetRemovedClasses); - [$aParams['aDeletionExecutionSummary'], $aParams['bHasDeletionExecution']] = $this->GetExecutionSummaryTable(); - $aParams['bDeletionNeeded'] = ($aParams['iQueryCount'] > 0); $aParams['aAddedExtensions'] = $aAddedExtensions; $aParams['aRemovedExtensions'] = $aRemovedExtensions; $aParams['aExtensions'] = $this->GetExtensionsTableDiff($aAddedExtensions, $aRemovedExtensions); + [$aParams['aDeletionPlanSummary'], $aParams['iQueryCount'], $aParams['bDeletionPossible']] = $this->GetDeletionPlanSummaryTable($aGetRemovedClasses); + [$aParams['aDeletionExecutionSummary'], $aParams['bHasDeletionExecution']] = $this->GetExecutionSummaryTable(); + $aParams['bDeletionNeeded'] = ($aParams['iQueryCount'] > 0); + $this->DisplayPage($aParams, 'AnalysisResult'); } @@ -244,21 +245,7 @@ class DataFeatureRemovalController extends Controller $aClasses = utils::ReadPostedParam('classes', null, utils::ENUM_SANITIZATION_FILTER_CLASS); $oDataCleanupService = new DataCleanupService(); - $aDeletionExecutionSummary = $oDataCleanupService->ExecuteCleanup($aClasses); - - foreach ($aDeletionExecutionSummary as $oDeletionExecutionSummaryEntity) { - if (isset($this->aDeletionExecutionSummary[$oDeletionExecutionSummaryEntity->sClass])) { - /** @var \Combodo\iTop\DataFeatureRemoval\Entity\DataCleanupSummaryEntity $oTotal */ - $oTotal = $this->aDeletionExecutionSummary[$oDeletionExecutionSummaryEntity->sClass]; - $oTotal->iTotalUpdateCount += $oDeletionExecutionSummaryEntity->iUpdateCount; - $oTotal->iTotalDeleteCount += $oDeletionExecutionSummaryEntity->iDeleteCount; - $oTotal->iUpdateCount = $oDeletionExecutionSummaryEntity->iUpdateCount; - $oTotal->iDeleteCount = $oDeletionExecutionSummaryEntity->iDeleteCount; - } else { - $oTotal = $oDeletionExecutionSummaryEntity; - } - $this->aDeletionExecutionSummary[$oDeletionExecutionSummaryEntity->sClass] = $oTotal; - } + $this->aDeletionExecutionSummary = $oDataCleanupService->ExecuteCleanup($aClasses, $this->aDeletionExecutionSummary); $this->OperationAnalysisResult(); } diff --git a/datamodels/2.x/combodo-data-feature-removal/src/Service/DataCleanupService.php b/datamodels/2.x/combodo-data-feature-removal/src/Service/DataCleanupService.php index e2d3956b7a..800b7ce18b 100644 --- a/datamodels/2.x/combodo-data-feature-removal/src/Service/DataCleanupService.php +++ b/datamodels/2.x/combodo-data-feature-removal/src/Service/DataCleanupService.php @@ -35,7 +35,7 @@ class DataCleanupService */ public function GetCleanupSummary(?array $aClasses): array { - return $this->ExecuteCleanup($aClasses ?? [], oObjectService: new ObjectServiceSummary()); + return $this->ExecuteCleanup($aClasses ?? [], [], oObjectService: new ObjectServiceSummary()); } private function GetNextObjectToDelete(array $aClasses): ?DBObject @@ -56,6 +56,7 @@ class DataCleanupService /** * @param array $aClasses + * @param array $aPreviousExecutionSummary * @param \Combodo\iTop\DataFeatureRemoval\Service\iObjectService|null $oObjectService * * @return array execution summary @@ -65,9 +66,10 @@ class DataCleanupService * @throws \CoreUnexpectedValue * @throws \MySQLException */ - public function ExecuteCleanup(array $aClasses, ?iObjectService $oObjectService = null): array + public function ExecuteCleanup(array $aClasses, array $aPreviousExecutionSummary, ?iObjectService $oObjectService = null): array { $this->oObjectService = $oObjectService ?? new ObjectService(); + $this->oObjectService->SetSummary($aPreviousExecutionSummary); $this->aVisited = []; diff --git a/datamodels/2.x/combodo-data-feature-removal/src/Service/ObjectServiceSummary.php b/datamodels/2.x/combodo-data-feature-removal/src/Service/ObjectServiceSummary.php index 27635136fc..577ee53c73 100644 --- a/datamodels/2.x/combodo-data-feature-removal/src/Service/ObjectServiceSummary.php +++ b/datamodels/2.x/combodo-data-feature-removal/src/Service/ObjectServiceSummary.php @@ -29,6 +29,7 @@ class ObjectServiceSummary implements iObjectService } $oDeletionPlanSummaryEntity = $this->aSummary[$sClass]; $oDeletionPlanSummaryEntity->iUpdateCount++; + $oDeletionPlanSummaryEntity->iTotalUpdateCount++; } public function Delete(string $sClass, string $sId): void @@ -39,6 +40,7 @@ class ObjectServiceSummary implements iObjectService } $oDeletionPlanSummaryEntity = $this->aSummary[$sClass]; $oDeletionPlanSummaryEntity->iDeleteCount++; + $oDeletionPlanSummaryEntity->iTotalDeleteCount++; } public function SetIssue(string $sClass): void @@ -55,4 +57,16 @@ class ObjectServiceSummary implements iObjectService { return $this->aSummary; } + + public function SetSummary(array $aSummary): void + { + $this->aSummary = []; + foreach ($aSummary as $sClass => $oPreviousSummaryEntity) { + $oSummaryEntity = new DataCleanupSummaryEntity($sClass); + $oSummaryEntity->iTotalUpdateCount = $oPreviousSummaryEntity->iTotalUpdateCount; + $oSummaryEntity->iTotalDeleteCount = $oPreviousSummaryEntity->iTotalDeleteCount; + + $this->aSummary[$sClass] = $oSummaryEntity; + } + } } diff --git a/datamodels/2.x/combodo-data-feature-removal/templates/AnalysisResult.html.twig b/datamodels/2.x/combodo-data-feature-removal/templates/AnalysisResult.html.twig index f6d4f515bd..61a4847ac2 100644 --- a/datamodels/2.x/combodo-data-feature-removal/templates/AnalysisResult.html.twig +++ b/datamodels/2.x/combodo-data-feature-removal/templates/AnalysisResult.html.twig @@ -15,20 +15,20 @@ {% 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 %} - {% for sCode, sLabel in aAddedExtensions %} - {% UIInput ForHidden { sName:"aAddedExtensions[" ~ sCode ~ "]", sValue:sLabel } %} - {% endfor %} - {% for sCode, sLabel in aRemovedExtensions %} - {% UIInput ForHidden { sName:"aRemovedExtensions[" ~ sCode ~ "]", sValue:sLabel } %} - {% endfor %} - {% UIToolbar ForButton {} %} - {% UIButton ForPrimaryAction {sLabel:'UI:Button:DoDeletion'|dict_s, sName:'btn_deletion', sId:'btn_deletion', bIsSubmit:true} %} - {% EndUIToolbar %} + {% 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 %} + {% for sCode, sLabel in aAddedExtensions %} + {% UIInput ForHidden { sName:"aAddedExtensions[" ~ sCode ~ "]", sValue:sLabel } %} + {% endfor %} + {% for sCode, sLabel in aRemovedExtensions %} + {% UIInput ForHidden { sName:"aRemovedExtensions[" ~ sCode ~ "]", sValue:sLabel } %} + {% endfor %} + {% UIToolbar ForButton {} %} + {% UIButton ForPrimaryAction {sLabel:'UI:Button:DoDeletion'|dict_s, sName:'btn_deletion', sId:'btn_deletion', bIsSubmit:true} %} + {% EndUIToolbar %} {% EndUIForm %} {% else %} {% UIAlert ForFailure { sContent: 'DataFeatureRemoval:DeletionPlan:Error:Issues'|dict_s } %}{% EndUIAlert %} diff --git a/setup/unattended-install/xml_setup/upgrade.xml b/setup/unattended-install/xml_setup/upgrade.xml index adf49e1ac7..deb1ce314c 100644 --- a/setup/unattended-install/xml_setup/upgrade.xml +++ b/setup/unattended-install/xml_setup/upgrade.xml @@ -40,5 +40,5 @@ - on + off diff --git a/tests/php-unit-tests/unitary-tests/datamodels/2.x/combodo-data-feature-removal/DataCleanupServiceTest.php b/tests/php-unit-tests/unitary-tests/datamodels/2.x/combodo-data-feature-removal/DataCleanupServiceTest.php index 5418d5881b..832360c587 100644 --- a/tests/php-unit-tests/unitary-tests/datamodels/2.x/combodo-data-feature-removal/DataCleanupServiceTest.php +++ b/tests/php-unit-tests/unitary-tests/datamodels/2.x/combodo-data-feature-removal/DataCleanupServiceTest.php @@ -69,7 +69,7 @@ class DataCleanupServiceTest extends ItopCustomDatamodelTestCase $aClasses = [ 'DFRToRemoveLeaf' ]; $oService = new DataCleanupService(); - $aRes = $oService->ExecuteCleanup($aClasses); + $aRes = $oService->ExecuteCleanup($aClasses, []); $aExpected = [ ['DFRToUpdate', 1, 0 ], ['DFRToRemoveLeaf', 0, 1 ], @@ -97,7 +97,7 @@ class DataCleanupServiceTest extends ItopCustomDatamodelTestCase $aClasses = [ 'DFRToRemoveLeaf' ]; $oService = new DataCleanupService(); - $aRes = $oService->ExecuteCleanup($aClasses); + $aRes = $oService->ExecuteCleanup($aClasses, []); $aExpected = [ ['DFRToUpdate', 3, 0 ], ['DFRToRemoveLeaf', 0, 3 ], @@ -107,6 +107,59 @@ class DataCleanupServiceTest extends ItopCustomDatamodelTestCase $this->AssertSummaryEquals($aExpected, $aRes); } + public function testExecuteCleanup_CheckSummaryIsEnrichedAfterEachPass() + { + $aExecutionSummary = []; + + $this->GivenDFRTreeInDB( + <<ExecuteCleanup($aClasses, $aExecutionSummary); + + $aExpected = [ + ['DFRToUpdate', 3, 0 ], + ['DFRToRemoveLeaf', 0, 3 ], + ['DFRRemovedCollateral', 0, 3 ], + ['DFRRemovedCollateralCascade', 0, 3 ], + ]; + $this->AssertSummaryEquals($aExpected, $aExecutionSummary); + + $this->GivenDFRTreeInDB( + <<ExecuteCleanup($aClasses, $aExecutionSummary); + + $aExpected = [ + ['DFRToUpdate', 1, 0, 0, 4 ], + ['DFRToRemoveLeaf', 0, 1, 0, 0, 4 ], + ['DFRRemovedCollateral', 0, 1, 0, 0, 4 ], + ['DFRRemovedCollateralCascade', 0, 1, 0, 0, 4 ], + ]; + $this->AssertSummaryEquals($aExpected, $aExecutionSummary); + } + public function testGetCleanupSummary_DeleteManyObjPerClassWithoutLimit() { $this->GivenDFRTreeInDB(<<expectException(DataFeatureRemovalException::class); $this->expectExceptionMessage('Deletion Plan cannot be executed due to issues'); $oService = new DataCleanupService(); - $oService->ExecuteCleanup($aClasses); + $oService->ExecuteCleanup($aClasses, []); } public function testGetCleanupSummary_ManualDeleteShouldFail() @@ -174,11 +227,16 @@ class DataCleanupServiceTest extends ItopCustomDatamodelTestCase $iUpdate = $line[1]; $iDelete = $line[2]; $iIssue = $line[3] ?? 0; + $iTotalUpdate = $line[4] ?? $iUpdate; + $iTotalDelete = $line[5] ?? $iDelete; $oCleanupSummaryEntity = new DataCleanupSummaryEntity($sClass); $oCleanupSummaryEntity->iUpdateCount = $iUpdate; $oCleanupSummaryEntity->iDeleteCount = $iDelete; $oCleanupSummaryEntity->iIssueCount = $iIssue; + $oCleanupSummaryEntity->iTotalUpdateCount = $iTotalUpdate; + $oCleanupSummaryEntity->iTotalDeleteCount = $iTotalDelete; + $aExpected[$sClass] = $oCleanupSummaryEntity; } $this->assertEquals($aExpected, $actual, $sMessage); @@ -252,7 +310,7 @@ class DataCleanupServiceTest extends ItopCustomDatamodelTestCase $oDeletionPlaService = new DataCleanupService(); $this->GivenExecutionLimits($iExecutionCount); $this->SetNonPublicProperty($oDeletionPlaService, 'oExecutionLimits', $this->oExecutionLimits); - $aRes = $oDeletionPlaService->ExecuteCleanup($aClasses); + $aRes = $oDeletionPlaService->ExecuteCleanup($aClasses, []); $this->AssertSummaryEquals($aExpected, $aRes); } @@ -270,18 +328,18 @@ class DataCleanupServiceTest extends ItopCustomDatamodelTestCase private array $aIdByObjectName = []; private function GivenDFRTreeLineInDB(string $sLine) { - list($sLeft, $sRight) = explode('<-', $sLine); + [$sLeft, $sRight] = explode('<-', $sLine); $sLeft = trim($sLeft); $iLeftId = $this->aIdByObjectName[$sLeft] ?? 0; if ($iLeftId === 0) { - list($sChildClass, ) = explode('_', $sLeft, 2); + [$sChildClass, ] = explode('_', $sLeft, 2); $iLeftId = $this->GivenObjectInDB($sChildClass, ['name' => $sLeft]); $this->aIdByObjectName[$sLeft] = $iLeftId; } $sRight = trim($sRight); - list($sChildClass, ) = explode('_', $sRight, 2); + [$sChildClass, ] = explode('_', $sRight, 2); $iRightId = $this->GivenObjectInDB($sChildClass, ['name' => $sRight, 'extkey_id' => $iLeftId]); $this->aIdByObjectName[$sRight] = $iRightId; }