N°9412 - Analysis results screen wip

This commit is contained in:
Eric Espie
2026-05-11 11:47:47 +02:00
parent e50319043c
commit ed814c1439
6 changed files with 103 additions and 42 deletions

View File

@@ -126,13 +126,14 @@ class DataFeatureRemovalController extends Controller
$aParams['sTransactionId'] = utils::GetNewTransactionId(); $aParams['sTransactionId'] = utils::GetNewTransactionId();
$aParams['aClasses'] = $aGetRemovedClasses; $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['aAddedExtensions'] = $aAddedExtensions;
$aParams['aRemovedExtensions'] = $aRemovedExtensions; $aParams['aRemovedExtensions'] = $aRemovedExtensions;
$aParams['aExtensions'] = $this->GetExtensionsTableDiff($aAddedExtensions, $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'); $this->DisplayPage($aParams, 'AnalysisResult');
} }
@@ -244,21 +245,7 @@ class DataFeatureRemovalController extends Controller
$aClasses = utils::ReadPostedParam('classes', null, utils::ENUM_SANITIZATION_FILTER_CLASS); $aClasses = utils::ReadPostedParam('classes', null, utils::ENUM_SANITIZATION_FILTER_CLASS);
$oDataCleanupService = new DataCleanupService(); $oDataCleanupService = new DataCleanupService();
$aDeletionExecutionSummary = $oDataCleanupService->ExecuteCleanup($aClasses); $this->aDeletionExecutionSummary = $oDataCleanupService->ExecuteCleanup($aClasses, $this->aDeletionExecutionSummary);
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->OperationAnalysisResult(); $this->OperationAnalysisResult();
} }

View File

@@ -35,7 +35,7 @@ class DataCleanupService
*/ */
public function GetCleanupSummary(?array $aClasses): array 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 private function GetNextObjectToDelete(array $aClasses): ?DBObject
@@ -56,6 +56,7 @@ class DataCleanupService
/** /**
* @param array $aClasses * @param array $aClasses
* @param array $aPreviousExecutionSummary
* @param \Combodo\iTop\DataFeatureRemoval\Service\iObjectService|null $oObjectService * @param \Combodo\iTop\DataFeatureRemoval\Service\iObjectService|null $oObjectService
* *
* @return array execution summary * @return array execution summary
@@ -65,9 +66,10 @@ class DataCleanupService
* @throws \CoreUnexpectedValue * @throws \CoreUnexpectedValue
* @throws \MySQLException * @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 = $oObjectService ?? new ObjectService();
$this->oObjectService->SetSummary($aPreviousExecutionSummary);
$this->aVisited = []; $this->aVisited = [];

View File

@@ -29,6 +29,7 @@ class ObjectServiceSummary implements iObjectService
} }
$oDeletionPlanSummaryEntity = $this->aSummary[$sClass]; $oDeletionPlanSummaryEntity = $this->aSummary[$sClass];
$oDeletionPlanSummaryEntity->iUpdateCount++; $oDeletionPlanSummaryEntity->iUpdateCount++;
$oDeletionPlanSummaryEntity->iTotalUpdateCount++;
} }
public function Delete(string $sClass, string $sId): void public function Delete(string $sClass, string $sId): void
@@ -39,6 +40,7 @@ class ObjectServiceSummary implements iObjectService
} }
$oDeletionPlanSummaryEntity = $this->aSummary[$sClass]; $oDeletionPlanSummaryEntity = $this->aSummary[$sClass];
$oDeletionPlanSummaryEntity->iDeleteCount++; $oDeletionPlanSummaryEntity->iDeleteCount++;
$oDeletionPlanSummaryEntity->iTotalDeleteCount++;
} }
public function SetIssue(string $sClass): void public function SetIssue(string $sClass): void
@@ -55,4 +57,16 @@ class ObjectServiceSummary implements iObjectService
{ {
return $this->aSummary; 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;
}
}
} }

View File

@@ -40,5 +40,5 @@
</selected_modules> </selected_modules>
<selected_extensions type="array"> <selected_extensions type="array">
</selected_extensions> </selected_extensions>
<use_symbolic_links>on</use_symbolic_links> <use_symbolic_links>off</use_symbolic_links>
</installation> </installation>

View File

@@ -69,7 +69,7 @@ class DataCleanupServiceTest extends ItopCustomDatamodelTestCase
$aClasses = [ 'DFRToRemoveLeaf' ]; $aClasses = [ 'DFRToRemoveLeaf' ];
$oService = new DataCleanupService(); $oService = new DataCleanupService();
$aRes = $oService->ExecuteCleanup($aClasses); $aRes = $oService->ExecuteCleanup($aClasses, []);
$aExpected = [ $aExpected = [
['DFRToUpdate', 1, 0 ], ['DFRToUpdate', 1, 0 ],
['DFRToRemoveLeaf', 0, 1 ], ['DFRToRemoveLeaf', 0, 1 ],
@@ -97,7 +97,7 @@ class DataCleanupServiceTest extends ItopCustomDatamodelTestCase
$aClasses = [ 'DFRToRemoveLeaf' ]; $aClasses = [ 'DFRToRemoveLeaf' ];
$oService = new DataCleanupService(); $oService = new DataCleanupService();
$aRes = $oService->ExecuteCleanup($aClasses); $aRes = $oService->ExecuteCleanup($aClasses, []);
$aExpected = [ $aExpected = [
['DFRToUpdate', 3, 0 ], ['DFRToUpdate', 3, 0 ],
['DFRToRemoveLeaf', 0, 3 ], ['DFRToRemoveLeaf', 0, 3 ],
@@ -107,6 +107,59 @@ class DataCleanupServiceTest extends ItopCustomDatamodelTestCase
$this->AssertSummaryEquals($aExpected, $aRes); $this->AssertSummaryEquals($aExpected, $aRes);
} }
public function testExecuteCleanup_CheckSummaryIsEnrichedAfterEachPass()
{
$aExecutionSummary = [];
$this->GivenDFRTreeInDB(
<<<EOF
DFRToRemoveLeaf_1 <- DFRToUpdate_1
DFRToRemoveLeaf_1 <- DFRRemovedCollateral_1
DFRRemovedCollateral_1 <- DFRRemovedCollateralCascade_1
DFRToRemoveLeaf_2 <- DFRToUpdate_2
DFRToRemoveLeaf_2 <- DFRRemovedCollateral_2
DFRRemovedCollateral_2 <- DFRRemovedCollateralCascade_2
DFRToRemoveLeaf_3 <- DFRToUpdate_3
DFRToRemoveLeaf_3 <- DFRRemovedCollateral_3
DFRRemovedCollateral_3 <- DFRRemovedCollateralCascade_3
EOF
);
$aClasses = ['DFRToRemoveLeaf'];
$oService = new DataCleanupService();
$aExecutionSummary = $oService->ExecuteCleanup($aClasses, $aExecutionSummary);
$aExpected = [
['DFRToUpdate', 3, 0 ],
['DFRToRemoveLeaf', 0, 3 ],
['DFRRemovedCollateral', 0, 3 ],
['DFRRemovedCollateralCascade', 0, 3 ],
];
$this->AssertSummaryEquals($aExpected, $aExecutionSummary);
$this->GivenDFRTreeInDB(
<<<EOF
DFRToRemoveLeaf_4 <- DFRToUpdate_4
DFRToRemoveLeaf_4 <- DFRRemovedCollateral_4
DFRRemovedCollateral_4 <- DFRRemovedCollateralCascade_4
EOF
);
$aClasses = ['DFRToRemoveLeaf'];
$oService = new DataCleanupService();
$aExecutionSummary = $oService->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() public function testGetCleanupSummary_DeleteManyObjPerClassWithoutLimit()
{ {
$this->GivenDFRTreeInDB(<<<EOF $this->GivenDFRTreeInDB(<<<EOF
@@ -145,7 +198,7 @@ class DataCleanupServiceTest extends ItopCustomDatamodelTestCase
$this->expectException(DataFeatureRemovalException::class); $this->expectException(DataFeatureRemovalException::class);
$this->expectExceptionMessage('Deletion Plan cannot be executed due to issues'); $this->expectExceptionMessage('Deletion Plan cannot be executed due to issues');
$oService = new DataCleanupService(); $oService = new DataCleanupService();
$oService->ExecuteCleanup($aClasses); $oService->ExecuteCleanup($aClasses, []);
} }
public function testGetCleanupSummary_ManualDeleteShouldFail() public function testGetCleanupSummary_ManualDeleteShouldFail()
@@ -174,11 +227,16 @@ class DataCleanupServiceTest extends ItopCustomDatamodelTestCase
$iUpdate = $line[1]; $iUpdate = $line[1];
$iDelete = $line[2]; $iDelete = $line[2];
$iIssue = $line[3] ?? 0; $iIssue = $line[3] ?? 0;
$iTotalUpdate = $line[4] ?? $iUpdate;
$iTotalDelete = $line[5] ?? $iDelete;
$oCleanupSummaryEntity = new DataCleanupSummaryEntity($sClass); $oCleanupSummaryEntity = new DataCleanupSummaryEntity($sClass);
$oCleanupSummaryEntity->iUpdateCount = $iUpdate; $oCleanupSummaryEntity->iUpdateCount = $iUpdate;
$oCleanupSummaryEntity->iDeleteCount = $iDelete; $oCleanupSummaryEntity->iDeleteCount = $iDelete;
$oCleanupSummaryEntity->iIssueCount = $iIssue; $oCleanupSummaryEntity->iIssueCount = $iIssue;
$oCleanupSummaryEntity->iTotalUpdateCount = $iTotalUpdate;
$oCleanupSummaryEntity->iTotalDeleteCount = $iTotalDelete;
$aExpected[$sClass] = $oCleanupSummaryEntity; $aExpected[$sClass] = $oCleanupSummaryEntity;
} }
$this->assertEquals($aExpected, $actual, $sMessage); $this->assertEquals($aExpected, $actual, $sMessage);
@@ -252,7 +310,7 @@ class DataCleanupServiceTest extends ItopCustomDatamodelTestCase
$oDeletionPlaService = new DataCleanupService(); $oDeletionPlaService = new DataCleanupService();
$this->GivenExecutionLimits($iExecutionCount); $this->GivenExecutionLimits($iExecutionCount);
$this->SetNonPublicProperty($oDeletionPlaService, 'oExecutionLimits', $this->oExecutionLimits); $this->SetNonPublicProperty($oDeletionPlaService, 'oExecutionLimits', $this->oExecutionLimits);
$aRes = $oDeletionPlaService->ExecuteCleanup($aClasses); $aRes = $oDeletionPlaService->ExecuteCleanup($aClasses, []);
$this->AssertSummaryEquals($aExpected, $aRes); $this->AssertSummaryEquals($aExpected, $aRes);
} }
@@ -270,18 +328,18 @@ class DataCleanupServiceTest extends ItopCustomDatamodelTestCase
private array $aIdByObjectName = []; private array $aIdByObjectName = [];
private function GivenDFRTreeLineInDB(string $sLine) private function GivenDFRTreeLineInDB(string $sLine)
{ {
list($sLeft, $sRight) = explode('<-', $sLine); [$sLeft, $sRight] = explode('<-', $sLine);
$sLeft = trim($sLeft); $sLeft = trim($sLeft);
$iLeftId = $this->aIdByObjectName[$sLeft] ?? 0; $iLeftId = $this->aIdByObjectName[$sLeft] ?? 0;
if ($iLeftId === 0) { if ($iLeftId === 0) {
list($sChildClass, ) = explode('_', $sLeft, 2); [$sChildClass, ] = explode('_', $sLeft, 2);
$iLeftId = $this->GivenObjectInDB($sChildClass, ['name' => $sLeft]); $iLeftId = $this->GivenObjectInDB($sChildClass, ['name' => $sLeft]);
$this->aIdByObjectName[$sLeft] = $iLeftId; $this->aIdByObjectName[$sLeft] = $iLeftId;
} }
$sRight = trim($sRight); $sRight = trim($sRight);
list($sChildClass, ) = explode('_', $sRight, 2); [$sChildClass, ] = explode('_', $sRight, 2);
$iRightId = $this->GivenObjectInDB($sChildClass, ['name' => $sRight, 'extkey_id' => $iLeftId]); $iRightId = $this->GivenObjectInDB($sChildClass, ['name' => $sRight, 'extkey_id' => $iLeftId]);
$this->aIdByObjectName[$sRight] = $iRightId; $this->aIdByObjectName[$sRight] = $iRightId;
} }