diff --git a/core/dbobject.class.php b/core/dbobject.class.php index 5367f10ff6..5548b4b4d5 100644 --- a/core/dbobject.class.php +++ b/core/dbobject.class.php @@ -5108,8 +5108,8 @@ abstract class DBObject implements iDisplay protected function GetReferencingObjectsForDeletion($bAllowAllData = false) { $aDependentObjects = []; - $aRererencingMe = MetaModel::EnumReferencingClasses(get_class($this)); - foreach ($aRererencingMe as $sRemoteClass => $aExtKeys) { + $aReferencingMe = MetaModel::EnumReferencingClasses(get_class($this)); + foreach ($aReferencingMe as $sRemoteClass => $aExtKeys) { /** @var \AttributeExternalKey $oExtKeyAttDef */ foreach ($aExtKeys as $sExtKeyAttCode => $oExtKeyAttDef) { // skip if external key doesn't require the deletion cascading diff --git a/datamodels/2.x/combodo-data-feature-removal/assets/img/.gitkeep b/datamodels/2.x/combodo-data-feature-removal/assets/img/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/datamodels/2.x/combodo-data-feature-removal/composer.lock b/datamodels/2.x/combodo-data-feature-removal/composer.lock new file mode 100644 index 0000000000..7245f27055 --- /dev/null +++ b/datamodels/2.x/combodo-data-feature-removal/composer.lock @@ -0,0 +1,20 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "b862a55cbf5448fb99f0905a4db6529b", + "packages": [], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": {}, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "composer-runtime-api": "^2.0" + }, + "platform-dev": {}, + "plugin-api-version": "2.6.0" +} diff --git a/datamodels/2.x/combodo-data-feature-removal/datamodel.combodo-data-feature-removal.xml b/datamodels/2.x/combodo-data-feature-removal/datamodel.combodo-data-feature-removal.xml index 20970444fc..f85d4d0103 100644 --- a/datamodels/2.x/combodo-data-feature-removal/datamodel.combodo-data-feature-removal.xml +++ b/datamodels/2.x/combodo-data-feature-removal/datamodel.combodo-data-feature-removal.xml @@ -1,157 +1,5 @@ - - - - grant_by_profile - data_feature_removal_extension - - - - - - - - - - - - - extension_code - false - all - - - label - false - all - - - version - false - all - - - module_names - false - all - - - status - none - true - all - - - - - - - 10 - - - 20 - - - - - - 10 - - - 20 - - -
- - 10 - - - 20 - -
-
- -
- - - grant_by_profile - data_feature_removal_auditrule - - - - - - - - - - - - - - - rule_name - false - all - - - extension_code - false - all - - - class_name - none - true - all - - - count - 0 - all - - - - - - - 10 - - - 20 - - - 30 - - - - - - 10 - - - 20 - - - 30 - - -
- - 10 - - - 20 - - - 30 - -
-
- -
-
30 diff --git a/datamodels/2.x/combodo-data-feature-removal/dictionaries/en.dict.combodo-data-feature-removal.php b/datamodels/2.x/combodo-data-feature-removal/dictionaries/en.dict.combodo-data-feature-removal.php index 6637468489..5a87e5a6af 100644 --- a/datamodels/2.x/combodo-data-feature-removal/dictionaries/en.dict.combodo-data-feature-removal.php +++ b/datamodels/2.x/combodo-data-feature-removal/dictionaries/en.dict.combodo-data-feature-removal.php @@ -16,26 +16,42 @@ Dict::Add('EN US', 'English', 'English', [ 'DataFeatureRemoval:Main:Title' => 'Features Removal', 'DataFeatureRemoval:Main:SubTitle' => 'Prepare features you want to enable/disable in a future setup', 'DataFeatureRemoval:Failure:Title' => 'Feature dry removal errors', - 'DataFeatureRemoval:Helper:Title' => 'This utilitary allows you to enable or disable features that are installed in your iTop.', + 'DataFeatureRemoval:Helper:Title' => 'Enable or disable features that are installed in your iTop.', 'DataFeatureRemoval:Helper:Desc1' => 'It will prepare the setup step that proceeds to feature enabling or disabling.', - 'DataFeatureRemoval:Helper:Desc2' => 'You will need to analyze if there are any data or dependency preventing you from enabling/disabling a feature.', + 'DataFeatureRemoval:Helper:Desc2' => 'Analyze if there are any data or dependency preventing you from enabling/disabling a feature.', 'DataFeatureRemoval:Features:Title' => 'Features', 'DataFeatureRemoval:Analysis:Title' => 'Analysis result', 'DataFeatureRemoval:Analysis:SubTitle' => '%1$s element(s) to clean before continuing', + 'DataFeatureRemoval:DeletionPlan:Title' => 'Deletion plan', + 'DataFeatureRemoval:DeletionPlan:SubTitle' => 'Database tables to clean before continuing', + 'DataFeatureRemoval:DoDeletion:Title' => 'Do deletion', + 'DataFeatureRemoval:DoDeletion:SubTitle' => 'Remove all the entries from the database', + 'DataFeatureRemoval:Table:Analysis:ClassName' => 'Element to remove', - 'DataFeatureRemoval:Table:Analysis:RemovalType' => 'Type of element', 'DataFeatureRemoval:Table:Analysis:FeatureName' => 'Feature name', - 'DataFeatureRemoval:Table:Analysis:Occurence' => 'Occurence', + 'DataFeatureRemoval:Table:Analysis:Module' => 'Module name', + 'DataFeatureRemoval:Table:Analysis:Occurrence' => 'Occurrence', 'UI:Button:Analyze' => 'Analyze', 'UI:Button:ModifyChoices' => 'Modify Choices', 'UI:Button:AnalyzeAndSetup' => 'Analyze and go to setup', + 'UI:Button:PlanDeletion' => 'Prepare deletion plan', + 'UI:Button:DoDeletion' => 'Delete data', + 'UI:Button:BackToMain' => 'Back to Feature Removal', + 'UI:Button:Setup' => 'Back to setup', 'UI:Action:ForceUninstall' => 'Force uninstall', 'UI:Action:MoreInfo' => 'More information', - 'DataFeatureRemoval:Table:Analysis:RemovalType:FINAL_CLASS' => 'Final class', + 'DataFeatureRemoval:Table:Empty' => 'No data to remove', - ]); + 'DataFeatureRemoval:Column:Class' => 'Class', + 'DataFeatureRemoval:Column:DeleteCount' => 'Entries to delete', + 'DataFeatureRemoval:Column:UpdateCount' => 'Entries to update', + 'DataFeatureRemoval:Column:Issue' => 'Issue', + + 'DataFeatureRemoval:Column:DeletedCount' => 'Deleted entries', + 'DataFeatureRemoval:Column:UpdatedCount' => 'Updated entries', +]); diff --git a/datamodels/2.x/combodo-data-feature-removal/dictionaries/fr.dict.combodo-data-feature-removal.php b/datamodels/2.x/combodo-data-feature-removal/dictionaries/fr.dict.combodo-data-feature-removal.php index a722d7d397..ffe23414b4 100644 --- a/datamodels/2.x/combodo-data-feature-removal/dictionaries/fr.dict.combodo-data-feature-removal.php +++ b/datamodels/2.x/combodo-data-feature-removal/dictionaries/fr.dict.combodo-data-feature-removal.php @@ -16,25 +16,42 @@ Dict::Add('FR FR', 'French', 'Français', [ 'DataFeatureRemoval:Main:Title' => 'Features Removal', 'DataFeatureRemoval:Main:SubTitle' => 'Prepare features you want to enable/disable in a future setup', 'DataFeatureRemoval:Failure:Title' => 'Feature dry removal errors', - 'DataFeatureRemoval:Helper:Title' => 'This utilitary allows you to enable or disable features that are installed in your iTop.', + 'DataFeatureRemoval:Helper:Title' => 'Enable or disable features that are installed in your iTop.', 'DataFeatureRemoval:Helper:Desc1' => 'It will prepare the setup step that proceeds to feature enabling or disabling.', - 'DataFeatureRemoval:Helper:Desc2' => 'You will need to analyze if there are any data or dependency preventing you from enabling/disabling a feature.', + 'DataFeatureRemoval:Helper:Desc2' => 'Analyze if there are any data or dependency preventing you from enabling/disabling a feature.', 'DataFeatureRemoval:Features:Title' => 'Features', 'DataFeatureRemoval:Analysis:Title' => 'Analysis result', 'DataFeatureRemoval:Analysis:SubTitle' => '%1$s element(s) to clean before continuing', + 'DataFeatureRemoval:DeletionPlan:Title' => 'Deletion plan', + 'DataFeatureRemoval:DeletionPlan:SubTitle' => 'Database tables to clean before continuing', + 'DataFeatureRemoval:DoDeletion:Title' => 'Do deletion', + 'DataFeatureRemoval:DoDeletion:SubTitle' => 'Remove all the entries from the database', + 'DataFeatureRemoval:Table:Analysis:ClassName' => 'Element to remove', - 'DataFeatureRemoval:Table:Analysis:RemovalType' => 'Type of element', 'DataFeatureRemoval:Table:Analysis:FeatureName' => 'Feature name', - 'DataFeatureRemoval:Table:Analysis:Occurence' => 'Occurence', + 'DataFeatureRemoval:Table:Analysis:Module' => 'Module name', + 'DataFeatureRemoval:Table:Analysis:Occurrence' => 'Occurrence', 'UI:Button:Analyze' => 'Analyze', 'UI:Button:ModifyChoices' => 'Modify Choices', 'UI:Button:AnalyzeAndSetup' => 'Analyze and go to setup', + 'UI:Button:PlanDeletion' => 'Prepare deletion plan', + 'UI:Button:DoDeletion' => 'Delete data', + 'UI:Button:BackToMain' => 'Back to Feature Removal', + 'UI:Button:Setup' => 'Back to setup', 'UI:Action:ForceUninstall' => 'Force uninstall', 'UI:Action:MoreInfo' => 'More information', - 'DataFeatureRemoval:Table:Analysis:RemovalType:FINAL_CLASS' => 'Final class', + 'DataFeatureRemoval:Table:Empty' => 'No data to remove', + + 'DataFeatureRemoval:Column:Class' => 'Class', + 'DataFeatureRemoval:Column:DeleteCount' => 'Entries to delete', + 'DataFeatureRemoval:Column:UpdateCount' => 'Entries to update', + 'DataFeatureRemoval:Column:Issue' => 'Issue', + + 'DataFeatureRemoval:Column:DeletedCount' => 'Deleted entries', + 'DataFeatureRemoval:Column:UpdatedCount' => 'Updated entries', ]); 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 3bc225e1d7..6ad0ed8e16 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 @@ -11,113 +11,161 @@ 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\AuthentToken\Helper\TokenAuthLog; +use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException; use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalHelper; -use Combodo\iTop\DataFeatureRemoval\Model\DataFeatureRemoverAuditRuleService; -use Combodo\iTop\DataFeatureRemoval\Model\DataFeatureRemoverExtensionService; +use Combodo\iTop\DataFeatureRemoval\Service\DataFeatureRemoverExtensionService; +use Combodo\iTop\DataFeatureRemoval\Service\DeletionPlanService; use Combodo\iTop\Setup\FeatureRemoval\DryRemovalRuntimeEnvironment; use Combodo\iTop\Setup\FeatureRemoval\SetupAudit; use Dict; use Exception; +use IssueLog; use MetaModel; use utils; class DataFeatureRemovalController extends Controller { private array $aSelectedExtensionsForCheck = []; + private array $aCountClassesToCleanup = []; + private array $aAnalysisDataTable = []; + private int $iCount = 0; - public function OperationMain($sErrorMessage = null) + public function OperationMain($sErrorMessage = null): void { $aParams = []; + $this->ReadRemovedExtensions(); + $this->AddAnalyzeParams(); + $aParams['sTransactionId'] = utils::GetNewTransactionId(); + $aParams['aExtensions'] = $this->GetExtensionsTable(); + $aParams['aAnalysisDataTable'] = $this->aAnalysisDataTable; + $aParams['aClasses'] = array_keys($this->aCountClassesToCleanup); + $aParams['DataFeatureRemovalErrorMessage'] = $sErrorMessage; + $aParams['bHasData'] = $this->iCount > 0; + $aParams['sSetupUrl'] = utils::GetAbsoluteUrlAppRoot().'setup'; + $aParams['iCount'] = $this->iCount; + $this->AddLinkedStylesheet(utils::GetAbsoluteUrlModulesRoot().DataFeatureRemovalHelper::MODULE_NAME.'/assets/css/DataFeatureRemoval.css'); $this->AddLinkedScript(utils::GetAbsoluteUrlModulesRoot().DataFeatureRemovalHelper::MODULE_NAME.'/assets/js/DataFeatureRemoval.js'); - - $aParams['sTransactionId'] = utils::GetNewTransactionId(); - $this->AddFeatureParams($aParams); - $this->AddAnalyzeParams($aParams); - $aParams['DataFeatureRemovalErrorMessage'] = $sErrorMessage; $this->DisplayPage($aParams); } - public function AddFeatureParams(array &$aParams) + public function AddAnalyzeParams(): void { - $aParams['aExtensions'] = $this->GetExtensionsTable(); - $aParams['sModule'] = DataFeatureRemovalHelper::MODULE_NAME; - } - - public function AddAnalyzeParams(array &$aParams) - { - $iTotalCount = 0; $aData = []; $aColumns = []; - foreach (DataFeatureRemoverAuditRuleService::GetInstance()->ReadCheckRules() as $oRule) { - $sContent = $oRule->Get('class_name'); - $sModuleName = MetaModel::GetModuleName($sContent); + $this->iCount = 0; + foreach ($this->aCountClassesToCleanup as $sClass => $iCount) { + $sModuleName = MetaModel::GetModuleName($sClass); $aExtensions = DataFeatureRemoverExtensionService::GetInstance()->GetIncludingExtensions($sModuleName); $sExtensions = implode(' ', $aExtensions); - $sTypeName = $oRule->Get('rule_name'); - $sTypeDesc = \Dict::S("DataFeatureRemoval:Table:Analysis:RemovalType:$sTypeName"); - $iCount = $oRule->Get('count'); - $iTotalCount += $iCount; - $aColumns = ['ClassName', 'RemovalType','FeatureName','Occurence']; - $aData[] = [ - <<$sContent -HTML, - <<$sTypeDesc -HTML, - <<$sExtensions -HTML, - <<$iCount -HTML, - ]; + $aColumns = ['ClassName','FeatureName','Module','Occurrence']; + $aData[] = [$sClass,$sExtensions,$sModuleName,$iCount]; + $this->iCount += $iCount; } - $aParams['aCheckRules'] = $this->GetTableData('Analysis', $aColumns, $aData); - $aParams['rule_count'] = $iTotalCount; + $this->aAnalysisDataTable = $this->GetTableData('Analysis', $aColumns, $aData); } - public function OperationAnalyze() + public function OperationAnalyze(): void { - $aSelectedExtensionsFromUI = utils::ReadPostedParam('aExtensions', []); - $this->aSelectedExtensionsForCheck = []; - foreach ($aSelectedExtensionsFromUI as $sCode => $aData) { - $sValue = $aData['enable'] ?? 'off'; - if (($sValue) === 'on') { - $this->aSelectedExtensionsForCheck[] = $sCode; - } - } + $this->ReadRemovedExtensions(); $this->m_sOperation = 'Main'; try { - $this->Analyze(); + if (count($this->aSelectedExtensionsForCheck) > 0) { + $this->Analyze(); + } $this->OperationMain(); } catch (Exception $e) { - \IssueLog::Error(__METHOD__, null, ['stack' => $e->getTraceAsString(), 'exception' => $e->getMessage()]); + IssueLog::Error(__METHOD__, null, ['stack' => $e->getTraceAsString(), 'exception' => $e->getMessage()]); $this->OperationMain($e->getMessage()); } } + private function Analyze(): void + { + $sSourceEnv = MetaModel::GetEnvironment(); + $oDryRemovalRuntimeEnvironment = new DryRemovalRuntimeEnvironment(); + $oDryRemovalRuntimeEnvironment->Prepare($sSourceEnv, $this->aSelectedExtensionsForCheck); + $oDryRemovalRuntimeEnvironment->CompileFrom($sSourceEnv); + + $oSetupAudit = new SetupAudit($sSourceEnv, DryRemovalRuntimeEnvironment::DRY_REMOVAL_AUDIT_ENV); + $aGetRemovedClasses = $oSetupAudit->GetIssues(); + IssueLog::Debug(__METHOD__, null, ['aGetRemovedClasses' => $aGetRemovedClasses]); + $this->aCountClassesToCleanup = $aGetRemovedClasses; + } + + public function OperationDeletionPlan(): void + { + $aParams = []; + $this->ValidateTransactionId(); + + $aClasses = utils::ReadPostedParam('classes', null, utils::ENUM_SANITIZATION_FILTER_CLASS); + + $aDeletionPlanSummaryEntities = DeletionPlanService::GetInstance()->GetDeletionPlanSummary($aClasses); + $aColumns = ['Class', 'DeleteCount' , 'UpdateCount', 'Issue']; + $aRows = []; + foreach ($aDeletionPlanSummaryEntities as $oDeletionPlanSummaryEntity) { + $aRows[] = [ + $oDeletionPlanSummaryEntity->sClass, + $oDeletionPlanSummaryEntity->iDeleteCount, + $oDeletionPlanSummaryEntity->iUpdateCount, + $oDeletionPlanSummaryEntity->sIssue ?? '', + ]; + } + + $aParams['sTransactionId'] = utils::GetNewTransactionId(); + $aParams['aDeletionPlanSummary'] = $this->GetTableData('Extensions', $aColumns, $aRows); + $aParams['aClasses'] = $aClasses; + + $this->DisplayPage($aParams); + } + + public function OperationDoDeletion(): void + { + $aParams = []; + $this->ValidateTransactionId(); + + $aClasses = utils::ReadPostedParam('classes', null, utils::ENUM_SANITIZATION_FILTER_CLASS); + + $aDeletionExecutionSummary = DeletionPlanService::GetInstance()->ExecuteDeletionPlan($aClasses); + $aColumns = ['Class', 'DeletedCount' , 'UpdatedCount']; + $aRows = []; + foreach ($aDeletionExecutionSummary as $oDeletionExecutionSummaryEntity) { + $aRows[] = [ + $oDeletionExecutionSummaryEntity->sClass, + $oDeletionExecutionSummaryEntity->iDeleteCount, + $oDeletionExecutionSummaryEntity->iUpdateCount, + ]; + } + + $aParams['sTransactionId'] = utils::GetNewTransactionId(); + $aParams['aDeletionExecutionSummary'] = $this->GetTableData('Extensions', $aColumns, $aRows); + $this->DisplayPage($aParams); + } + + /** + * Get installed extensions from disk + * + * @return array structure for twig datatable + */ private function GetExtensionsTable(): array { $aExtensions = []; $aColumns = ['', 'Version', 'Name', 'Code']; - $this->aSelectedExtensionsForCheck = DataFeatureRemoverExtensionService::GetInstance()->ReadAuditedExtensions(); foreach (DataFeatureRemoverExtensionService::GetInstance()->ReadItopExtensions() as $sCode => $oExtension) { /** @var \iTopExtension $oExtension */ - $sChecked = "checked"; + $sChecked = ''; $sDisabledHtml = ''; if ($oExtension->bRemovedFromDisk) { $sDisabledHtml = 'disabled=""'; - } elseif (! array_key_exists($sCode, $this->aSelectedExtensionsForCheck)) { - $sChecked = ""; + $sChecked = 'checked'; + } elseif (in_array($sCode, $this->aSelectedExtensionsForCheck)) { + $sChecked = 'checked'; } $sLabel = $oExtension->sLabel; @@ -128,35 +176,28 @@ HTML, << HTML, - <<$sVersion -HTML, - <<$sLabel -HTML, - <<$sCode -HTML, + $sVersion, + $sLabel, + $sCode, ]; } return $this->GetTableData('Extensions', $aColumns, $aExtensions); - } - public function GetTableData(string $sTableName, array $aColumns, array $aData): array + private function GetTableData(string $sTableName, array $aColumns, array $aData): array { if (empty($aData)) { return [ 'Type' => 'Table', 'Columns' => [['label' => '']], - 'Data' => [[ Dict::S('DbCleaner:Table:Empty')]], + 'Data' => [[ Dict::S('DataFeatureRemoval:Table:Empty')]], ]; } $aNewColumns = []; foreach ($aColumns as $sColumn) { - $aNewColumns[] = ['label' => Dict::S("DataFeatureRemoval:Table:$sTableName:$sColumn", $sColumn)]; + $aNewColumns[] = ['label' => Dict::S("DataFeatureRemoval:Table:$sTableName:$sColumn", Dict::S("DataFeatureRemoval:Column:$sColumn", $sColumn))]; } $aColumns = $aNewColumns; @@ -167,23 +208,45 @@ HTML, ]; } - private function Analyze() + /** + * @return void + * @throws \Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException + */ + private function ValidateTransactionId(): void { - DataFeatureRemoverExtensionService::GetInstance()->SaveExtensions($this->aSelectedExtensionsForCheck); + if (empty($_POST)) { + return; + } - $sSourceEnvt = \MetaModel::GetEnvironment(); - $oDryRemovalRuntimeEnvironment = new DryRemovalRuntimeEnvironment(); - $oDryRemovalRuntimeEnvironment->Prepare($sSourceEnvt, $this->aSelectedExtensionsForCheck); - $oDryRemovalRuntimeEnvironment->CompileFrom($sSourceEnvt); - - $oSetupAudit = new SetupAudit($sSourceEnvt, DryRemovalRuntimeEnvironment::DRY_REMOVAL_AUDIT_ENV); - $this->Save($oSetupAudit->GetIssues()); + $sTransactionId = utils::ReadPostedParam('transaction_id', null, utils::ENUM_SANITIZATION_FILTER_TRANSACTION_ID); + IssueLog::Debug(__FUNCTION__.": Transaction [$sTransactionId]"); + if (empty($sTransactionId) || !utils::IsTransactionValid($sTransactionId, false)) { + throw new DataFeatureRemovalException(Dict::S("iTopUpdate:Error:InvalidToken")); + } } - private function Save(array $aGetRemovedClasses) + /** + * @return void + */ + public function ReadRemovedExtensions(): void { - \IssueLog::Debug(__METHOD__, null, ['aGetRemovedClasses' => $aGetRemovedClasses]); + if (count($this->aSelectedExtensionsForCheck) > 0) { + return; + } - DataFeatureRemoverAuditRuleService::GetInstance()->SaveChecks($aGetRemovedClasses); + $aSelectedExtensionsFromUI = utils::ReadPostedParam('aExtensions', []); + foreach ($aSelectedExtensionsFromUI as $sCode => $aData) { + $sValue = $aData['enable'] ?? 'off'; + if (($sValue) === 'on') { + $this->aSelectedExtensionsForCheck[] = $sCode; + } + } + + // Add source removed to check + foreach (DataFeatureRemoverExtensionService::GetInstance()->ReadItopExtensions() as $sCode => $oExtension) { + if ($oExtension->bRemovedFromDisk) { + $this->aSelectedExtensionsForCheck[] = $sCode; + } + } } } diff --git a/datamodels/2.x/combodo-data-feature-removal/src/Entity/DeletionPlanSummaryEntity.php b/datamodels/2.x/combodo-data-feature-removal/src/Entity/DeletionPlanSummaryEntity.php new file mode 100644 index 0000000000..b477827741 --- /dev/null +++ b/datamodels/2.x/combodo-data-feature-removal/src/Entity/DeletionPlanSummaryEntity.php @@ -0,0 +1,25 @@ +sClass = $sClass; + } +} diff --git a/datamodels/2.x/combodo-data-feature-removal/src/Hook/.gitkeep b/datamodels/2.x/combodo-data-feature-removal/src/Hook/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/datamodels/2.x/combodo-data-feature-removal/src/Model/DataFeatureRemoverAuditRuleService.php b/datamodels/2.x/combodo-data-feature-removal/src/Model/DataFeatureRemoverAuditRuleService.php deleted file mode 100644 index 16f64684ee..0000000000 --- a/datamodels/2.x/combodo-data-feature-removal/src/Model/DataFeatureRemoverAuditRuleService.php +++ /dev/null @@ -1,70 +0,0 @@ -AllowAllData(); - $oSet = new DBObjectSet($oSearch); - - while (null != ($oObj = $oSet->Fetch())) { - $oObj->DBDelete(); - } - - foreach ($aGetRemovedClasses as $sClass => $iCount) { - $oObj = new DataFeatureRemoverAuditRule(); - $oObj->Set('rule_name', 'FINAL_CLASS'); - $oObj->Set('extension_code', $sClass); - $oObj->Set('class_name', $sClass); - $oObj->Set('count', $iCount); - $oObj->DBWrite(); - } - } - - public function ReadCheckRules(): array - { - try { - $oSearch = DBObjectSearch::FromOQL('SELECT DataFeatureRemoverAuditRule', []); - $oSearch->AllowAllData(); - $oSet = new DBObjectSet($oSearch); - - $aRes = []; - while (null != ($oObj = $oSet->Fetch())) { - $aRes[] = $oObj; - } - - return $aRes; - } catch (Exception $e) { - throw new DataFeatureRemovalException(__FUNCTION__.' failed', 0, $e); - } - } -} diff --git a/datamodels/2.x/combodo-data-feature-removal/src/Model/DataFeatureRemoverExtensionService.php b/datamodels/2.x/combodo-data-feature-removal/src/Model/DataFeatureRemoverExtensionService.php deleted file mode 100644 index 79e053a10d..0000000000 --- a/datamodels/2.x/combodo-data-feature-removal/src/Model/DataFeatureRemoverExtensionService.php +++ /dev/null @@ -1,122 +0,0 @@ -ReadItopExtensions(); - - $oSearch = DBObjectSearch::FromOQL('SELECT DataFeatureRemoverExtension', []); - $oSearch->AllowAllData(); - $oSet = new DBObjectSet($oSearch); - - while (null != ($oObj = $oSet->Fetch())) { - $oObj->DBDelete(); - } - - foreach ($aSelectedExtensionsForCheck as $i => $sCode) { - $oObj = new DataFeatureRemoverExtension(); - $oObj->Set('extension_code', $sCode); - /** @var iTopExtension $oExtension */ - $oExtension = $this->aItopExtensions[$sCode]; - $oObj->Set('module_names', json_encode($oExtension->aModules)); - $oObj->Set('label', $oExtension->sLabel); - $oObj->Set('version', $oExtension->sVersion); - $oObj->DBWrite(); - } - } - - private array $aSelectedExtensions = []; - private array $aItopExtensions = []; - private array $aIncludingExtensionsByModuleName = []; - public function ReadAuditedExtensions(): array - { - if (count($this->aSelectedExtensions) == 0) { - try { - $oSearch = DBObjectSearch::FromOQL('SELECT DataFeatureRemoverExtension', []); - $oSearch->AllowAllData(); - $oSet = new DBObjectSet($oSearch); - - while (null != ($oObj = $oSet->Fetch())) { - $sCode = $oObj->Get('extension_code'); - $sLabel = $oObj->Get('label'); - $sVersion = $oObj->Get('version'); - - $sModuleNames = $oObj->Get('module_names'); - $aModuleNames = json_decode($sModuleNames, true); - if (is_array($aModuleNames) && count($aModuleNames) > 0) { - foreach ($aModuleNames as $sModuleName) { - $aExtensions = $this->aIncludingExtensionsByModuleName[$sModuleName] ?? []; - $aExtensions[] = "$sLabel / $sVersion"; - $this->aIncludingExtensionsByModuleName[$sModuleName] = $aExtensions; - - } - } - $this->aSelectedExtensions[$sCode] = $oObj; - } - } catch (Exception $e) { - throw new DataFeatureRemovalException(__FUNCTION__.' failed', 0, $e); - } - } - - \IssueLog::Debug(__METHOD__, null, ['aSelectedExtensionsForCheck' => $this->aSelectedExtensions]); - \IssueLog::Debug(__METHOD__, null, ['aIncludingExtensionsByModuleName' => $this->aIncludingExtensionsByModuleName]); - - return $this->aSelectedExtensions; - } - - public function GetIncludingExtensions(string $sModuleName): array - { - $this->ReadAuditedExtensions(); - return $this->aIncludingExtensionsByModuleName[$sModuleName] ?? []; - } - - /** - * @return iTopExtension[] - */ - public function ReadItopExtensions(): array - { - if (count($this->aItopExtensions) == 0) { - $oExtensionsMap = new iTopExtensionsMap(); - $oExtensionsMap->LoadInstalledExtensionsFromDatabase(MetaModel::GetConfig()); - $this->aItopExtensions = $oExtensionsMap->GetAllExtensionsToDisplayInSetup(true); - - uasort($this->aItopExtensions, function (iTopExtension $oiTopExtension1, iTopExtension $oiTopExtension2) { - return strcmp($oiTopExtension1->sLabel, $oiTopExtension2->sLabel); - }); - } - - return $this->aItopExtensions; - } -} diff --git a/datamodels/2.x/combodo-data-feature-removal/src/Service/DataFeatureRemoverExtensionService.php b/datamodels/2.x/combodo-data-feature-removal/src/Service/DataFeatureRemoverExtensionService.php new file mode 100644 index 0000000000..5dcdaa4169 --- /dev/null +++ b/datamodels/2.x/combodo-data-feature-removal/src/Service/DataFeatureRemoverExtensionService.php @@ -0,0 +1,80 @@ +aIncludingExtensionsByModuleName) === 0) { + foreach ($this->ReadItopExtensions() as $oExtension) { + $aModuleNames = $oExtension->aModules; + if (is_array($aModuleNames) && count($aModuleNames) > 0) { + foreach ($aModuleNames as $sModule) { + $aExtensions = $this->aIncludingExtensionsByModuleName[$sModule] ?? []; + $aExtensions[] = $oExtension->sLabel.'/'.$oExtension->sVersion; + $this->aIncludingExtensionsByModuleName[$sModule] = $aExtensions; + } + } + } + } + + return $this->aIncludingExtensionsByModuleName[$sModuleName] ?? []; + } + + /** + * @return iTopExtension[] + */ + public function ReadItopExtensions(): array + { + if (count($this->aItopExtensions) === 0) { + $oExtensionsMap = new iTopExtensionsMap(); + $oExtensionsMap->LoadInstalledExtensionsFromDatabase(MetaModel::GetConfig()); + $this->aItopExtensions = $oExtensionsMap->GetAllExtensionsToDisplayInSetup(true); + + uasort($this->aItopExtensions, function (iTopExtension $oiTopExtension1, iTopExtension $oiTopExtension2) { + return strcmp($oiTopExtension1->sLabel, $oiTopExtension2->sLabel); + }); + } + + return $this->aItopExtensions; + } +} diff --git a/datamodels/2.x/combodo-data-feature-removal/src/Service/DeletionPlanService.php b/datamodels/2.x/combodo-data-feature-removal/src/Service/DeletionPlanService.php new file mode 100644 index 0000000000..bce90b8bfd --- /dev/null +++ b/datamodels/2.x/combodo-data-feature-removal/src/Service/DeletionPlanService.php @@ -0,0 +1,174 @@ + + * @throws \CoreException + * @throws \CoreUnexpectedValue + * @throws \MySQLException + */ + public function GetDeletionPlanSummary(?array $aClasses): array + { + $aSummary = []; + if (is_null($aClasses)) { + return $aSummary; + } + + $oDeletionPlan = $this->GetDeletionPlan($aClasses); + + foreach ($oDeletionPlan->ListUpdates() as $sClass => $aUpdates) { + $oDeletionPlanSummaryEntity = new DeletionPlanSummaryEntity($sClass); + $oDeletionPlanSummaryEntity->iUpdateCount = count($aUpdates); + $aSummary[$sClass] = $oDeletionPlanSummaryEntity; + } + + foreach ($oDeletionPlan->ListDeletes() as $sClass => $aDeletes) { + $oDeletionPlanSummaryEntity = $aSummary[$sClass] ?? new DeletionPlanSummaryEntity($sClass); + $oDeletionPlanSummaryEntity->iDeleteCount = count($aDeletes); + + $aDelete = array_shift($aDeletes); + $oDeletionPlanSummaryEntity->iMode = $aDelete['mode']; + $oDeletionPlanSummaryEntity->sIssue = $aDelete['issue'] ?? null; + + $aSummary[$sClass] = $oDeletionPlanSummaryEntity; + } + + return $aSummary; + } + + /** + * @param string $sClass + * + * @return \DBObject[] + * @throws \CoreException + * @throws \CoreUnexpectedValue + * @throws \MySQLException + * @throws \Exception + */ + private function GetAllObjects(string $sClass): array + { + $oFilter = new DBObjectSearch($sClass); + $oFilter->AllowAllData(); + $oSet = new \DBObjectSet($oFilter); + return $oSet->ToArray(); + } + + /** + * @param array $aClasses + * + * @return array<\Combodo\iTop\DataFeatureRemoval\Entity\DeletionPlanSummaryEntity> + * @throws \Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException + * @throws \CoreException + * @throws \CoreUnexpectedValue + * @throws \MySQLException + */ + public function ExecuteDeletionPlan(array $aClasses): array + { + $oDeletionPlan = $this->GetDeletionPlan($aClasses); + + if (count($oDeletionPlan->GetIssues()) > 0) { + throw new DataFeatureRemovalException("Deletion Plan cannot be executed due to issues"); + } + + $aSummary = []; + foreach ($oDeletionPlan->ListUpdates() as $sClass => $aToUpdate) { + $oDeletionPlanSummaryEntity = $aSummary[$sClass] ?? new DeletionPlanSummaryEntity($sClass); + + foreach ($aToUpdate as $aData) { + $oToUpdate = $aData['to_reset']; + /** @var \DBObject $oToUpdate */ + foreach ($aData['attributes'] as $sRemoteExtKey => $aRemoteAttDef) { + $oToUpdate->Set($sRemoteExtKey, $aData['values'][$sRemoteExtKey]); + } + $oToUpdate->DBUpdate(); + $oDeletionPlanSummaryEntity->iUpdateCount++; + } + + $aSummary[$sClass] = $oDeletionPlanSummaryEntity; + } + + foreach ($oDeletionPlan->ListDeletes() as $sClass => $aDeletes) { + $oDeletionPlanSummaryEntity = $aSummary[$sClass] ?? new DeletionPlanSummaryEntity($sClass); + + foreach ($aDeletes as $sId => $aDelete) { + // Delete any existing change tracking about the current object + $oFilter = new DBObjectSearch('CMDBChangeOp'); + $oFilter->AddCondition('objclass', $sClass, '='); + $oFilter->AddCondition('objkey', $sId, '='); + MetaModel::PurgeData($oFilter); + + // Delete the entry + $aClassesToRemove = array_merge(MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL), MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_EXCLUDELEAF, false)); + foreach ($aClassesToRemove as $sParentClass) { + $oFilter = DBObjectSearch::FromOQL_AllData("SELECT $sParentClass WHERE id=:id"); + $sQuery = $oFilter->MakeDeleteQuery(['id' => $sId]); + CMDBSource::DeleteFrom($sQuery); + } + + $oDeletionPlanSummaryEntity->iDeleteCount++; + } + + $aSummary[$sClass] = $oDeletionPlanSummaryEntity; + } + + return $aSummary; + } + + /** + * Get a deletion plan for all the objects of the classes + * + * @param array $aClasses array of class names to clean + * + * @return \DeletionPlan + * @throws \CoreException + * @throws \CoreUnexpectedValue + * @throws \MySQLException + */ + public function GetDeletionPlan(array $aClasses): DeletionPlan + { + $oDeletionPlan = new DeletionPlan(); + foreach ($aClasses as $sClass) { + $aObjects = $this->GetAllObjects($sClass); + foreach ($aObjects as $oObject) { + $oObject->CheckToDelete($oDeletionPlan); + } + } + + return $oDeletionPlan; + } +} diff --git a/datamodels/2.x/combodo-data-feature-removal/templates/DeletionPlan.html.twig b/datamodels/2.x/combodo-data-feature-removal/templates/DeletionPlan.html.twig new file mode 100644 index 0000000000..d4edc84fc5 --- /dev/null +++ b/datamodels/2.x/combodo-data-feature-removal/templates/DeletionPlan.html.twig @@ -0,0 +1,25 @@ +{# @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_s } %} + {% UIDataTable ForForm { sRef:'aDeletionPlanSummary', aColumns:aDeletionPlanSummary.Columns, aData:aDeletionPlanSummary.Data} %}{% EndUIDataTable %} +{% EndUIPanel %} + +{% 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 %} + +{% 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 %} \ No newline at end of file diff --git a/datamodels/2.x/combodo-data-feature-removal/templates/DoDeletion.html.twig b/datamodels/2.x/combodo-data-feature-removal/templates/DoDeletion.html.twig new file mode 100644 index 0000000000..3deadb13b2 --- /dev/null +++ b/datamodels/2.x/combodo-data-feature-removal/templates/DoDeletion.html.twig @@ -0,0 +1,14 @@ +{# @copyright Copyright (C) 2010-2026 Combodo SARL #} +{# @license http://opensource.org/licenses/AGPL-3.0 #} + +{% UIPanel ForInformation { sTitle:'DataFeatureRemoval:DoDeletion:Title'|dict_s, sSubTitle: 'DataFeatureRemoval:DoDeletion:SubTitle'|dict_s } %} + {% UIDataTable ForForm { sRef:'aDeletionExecutionSummary', aColumns:aDeletionExecutionSummary.Columns, aData:aDeletionExecutionSummary.Data} %}{% EndUIDataTable %} +{% EndUIPanel %} + +{% 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_to_main', sId:'btn_back_to_main', bIsSubmit:true} %} + {% EndUIToolbar %} +{% EndUIForm %} \ No newline at end of file diff --git a/datamodels/2.x/combodo-data-feature-removal/templates/ExtensionRemovalData.html.twig b/datamodels/2.x/combodo-data-feature-removal/templates/ExtensionRemovalData.html.twig new file mode 100644 index 0000000000..2cce0e9ff4 --- /dev/null +++ b/datamodels/2.x/combodo-data-feature-removal/templates/ExtensionRemovalData.html.twig @@ -0,0 +1,19 @@ +{# @copyright Copyright (C) 2010-2024 Combodo SAS #} +{# @license http://opensource.org/licenses/AGPL-3.0 #} + +{% if bHasData %} + {% UIPanel Neutral { sTitle:'DataFeatureRemoval:Analysis:Title'|dict_s, sSubTitle: 'DataFeatureRemoval:Analysis:SubTitle'|dict_format(iCount) } %} + {% UIDataTable ForForm { sRef:'aAnalysisDataTable', aColumns:aAnalysisDataTable.Columns, aData:aAnalysisDataTable.Data} %}{% EndUIDataTable %} + {% EndUIPanel %} + + {% UIForm Standard {} %} + {% UIInput ForHidden { sName:'transaction_id', sValue:sTransactionId} %} + {% UIInput ForHidden { sName:'operation', sValue:'DeletionPlan'} %} + {% for sKey, sClass in aClasses %} + {% UIInput ForHidden { sName:"classes[" ~ sKey ~ "]", sValue:sClass } %} + {% endfor %} + {% UIToolbar ForButton {} %} + {% UIButton ForPrimaryAction {sLabel:'UI:Button:PlanDeletion'|dict_s, sName:'btn_plandeletion', sId:'btn_plandeletion', bIsSubmit:true} %} + {% EndUIToolbar %} + {% EndUIForm %} +{% endif %} diff --git a/datamodels/2.x/combodo-data-feature-removal/templates/ExtensionRemovalDataTab.html.twig b/datamodels/2.x/combodo-data-feature-removal/templates/ExtensionRemovalDataTab.html.twig deleted file mode 100644 index dbe39a956a..0000000000 --- a/datamodels/2.x/combodo-data-feature-removal/templates/ExtensionRemovalDataTab.html.twig +++ /dev/null @@ -1,8 +0,0 @@ -{# @copyright Copyright (C) 2010-2024 Combodo SAS #} -{# @license http://opensource.org/licenses/AGPL-3.0 #} - -{% UIForm Standard {} %} - {% UIPanel Neutral { sTitle:'DataFeatureRemoval:Analysis:Title'|dict_s, sSubTitle: 'DataFeatureRemoval:Analysis:SubTitle'|dict_format(rule_count) } %} - {% UIDataTable ForForm { sRef:'aCheckRules', aColumns:aCheckRules.Columns, aData:aCheckRules.Data} %}{% EndUIDataTable %} - {% EndUIPanel %} -{% EndUIForm %} diff --git a/datamodels/2.x/combodo-data-feature-removal/templates/FeaturesTab.html.twig b/datamodels/2.x/combodo-data-feature-removal/templates/Features.html.twig similarity index 99% rename from datamodels/2.x/combodo-data-feature-removal/templates/FeaturesTab.html.twig rename to datamodels/2.x/combodo-data-feature-removal/templates/Features.html.twig index 6e1e9c8e13..26c3f15a10 100644 --- a/datamodels/2.x/combodo-data-feature-removal/templates/FeaturesTab.html.twig +++ b/datamodels/2.x/combodo-data-feature-removal/templates/Features.html.twig @@ -10,9 +10,7 @@ {% UIDataTable ForForm { sRef:'aExtensions', aColumns:aExtensions.Columns, aData:aExtensions.Data} %}{% EndUIDataTable %} {% EndUIFieldSet %} - {% UIToolbar ForButton {} %} {% UIButton ForPrimaryAction {sLabel:'UI:Button:Analyze'|dict_s, sName:'btn_apply', sId:'btn_apply', bIsSubmit:true} %} {% EndUIToolbar %} - {% EndUIForm %} diff --git a/datamodels/2.x/combodo-data-feature-removal/templates/Main.html.twig b/datamodels/2.x/combodo-data-feature-removal/templates/Main.html.twig index d1552287f9..89c6fa5798 100644 --- a/datamodels/2.x/combodo-data-feature-removal/templates/Main.html.twig +++ b/datamodels/2.x/combodo-data-feature-removal/templates/Main.html.twig @@ -8,21 +8,28 @@ {# DataFeatureRemoval #} -{% UIPanel Neutral { sTitle:'DataFeatureRemoval:Main:Title'|dict_s, sSubTitle: 'DataFeatureRemoval:Main:SubTitle'|dict_s } %} +{% UIPanel ForInformation { sTitle:'DataFeatureRemoval:Main:Title'|dict_s, sSubTitle: 'DataFeatureRemoval:Main:SubTitle'|dict_s } %} {% UIAlert ForInformation { sTitle:'DataFeatureRemoval:Helper:Title'|dict_s } %} {{ 'DataFeatureRemoval:Helper:Desc1'|dict_s }}
{{ 'DataFeatureRemoval:Helper:Desc2'|dict_s }} {% EndUIAlert %} + {% if null != DataFeatureRemovalErrorMessage %} +
+ {% UIAlert ForFailure { sTitle:'DataFeatureRemoval:Failure:Title'|dict_s, sId: 'feature_removal_error_msg', sContent:DataFeatureRemovalErrorMessage } %} + {% EndUIAlert %} +
+ {% endif %} -{% if null != DataFeatureRemovalErrorMessage %} -
- {% UIAlert ForFailure { sTitle:'DataFeatureRemoval:Failure:Title'|dict_s, sId: 'feature_removal_error_msg', sContent:DataFeatureRemovalErrorMessage } %} - {% EndUIAlert %} -
-{% endif %} + {% include 'Features.html.twig' %} + {% include 'ExtensionRemovalData.html.twig' %} - {% include 'FeaturesTab.html.twig' %} - {% include 'ExtensionRemovalDataTab.html.twig' %} + {% if not bHasData %} + {% UIToolbar ForButton {} %} + + {% UIButton ForPrimaryAction {sLabel:'UI:Button:Setup'|dict_s, sName:'btn_setup', sId:'btn_setup', bIsSubmit:false} %} + + {% EndUIToolbar %} + {% endif %} {% EndUIPanel %} diff --git a/datamodels/2.x/combodo-data-feature-removal/templates/Main.js.twig b/datamodels/2.x/combodo-data-feature-removal/templates/Main.js.twig deleted file mode 100644 index a99810a517..0000000000 --- a/datamodels/2.x/combodo-data-feature-removal/templates/Main.js.twig +++ /dev/null @@ -1,9 +0,0 @@ -{# @copyright Copyright (C) 2010-2024 Combodo SAS #} -{# @license http://opensource.org/licenses/AGPL-3.0 #} - -$(document).on('click', '#checkAllExtensions', function() { - var bChecked = this.checked; - $('.extension_check').each( function() { this.checked = bChecked }); -}); - - diff --git a/datamodels/2.x/combodo-data-feature-removal/templates/Main.ready.js.twig b/datamodels/2.x/combodo-data-feature-removal/templates/Main.ready.js.twig deleted file mode 100644 index 375c45499a..0000000000 --- a/datamodels/2.x/combodo-data-feature-removal/templates/Main.ready.js.twig +++ /dev/null @@ -1,2 +0,0 @@ -{# @copyright Copyright (C) 2010-2024 Combodo SAS #} -{# @license http://opensource.org/licenses/AGPL-3.0 #} diff --git a/datamodels/2.x/combodo-data-feature-removal/vendor/autoload.php b/datamodels/2.x/combodo-data-feature-removal/vendor/autoload.php index 43b68436c8..a18424e39d 100644 --- a/datamodels/2.x/combodo-data-feature-removal/vendor/autoload.php +++ b/datamodels/2.x/combodo-data-feature-removal/vendor/autoload.php @@ -14,10 +14,7 @@ if (PHP_VERSION_ID < 50600) { echo $err; } } - trigger_error( - $err, - E_USER_ERROR - ); + throw new RuntimeException($err); } require_once __DIR__ . '/composer/autoload_real.php'; diff --git a/datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_classmap.php b/datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_classmap.php index a3e67ca36b..e47194c953 100644 --- a/datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_classmap.php +++ b/datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_classmap.php @@ -7,11 +7,11 @@ $baseDir = dirname($vendorDir); return array( 'Combodo\\iTop\\DataFeatureRemoval\\Controller\\DataFeatureRemovalController' => $baseDir . '/src/Controller/DataFeatureRemovalController.php', + 'Combodo\\iTop\\DataFeatureRemoval\\Entity\\DeletionPlanSummaryEntity' => $baseDir . '/src/Entity/DeletionPlanSummaryEntity.php', 'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalException' => $baseDir . '/src/Helper/DataFeatureRemovalException.php', 'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalHelper' => $baseDir . '/src/Helper/DataFeatureRemovalHelper.php', 'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalLog' => $baseDir . '/src/Helper/DataFeatureRemovalLog.php', - 'Combodo\\iTop\\DataFeatureRemoval\\Model\\DataFeatureRemoverAuditRuleService' => $baseDir . '/src/Model/DataFeatureRemoverAuditRuleService.php', - 'Combodo\\iTop\\DataFeatureRemoval\\Model\\DataFeatureRemoverExtensionService' => $baseDir . '/src/Model/DataFeatureRemoverExtensionService.php', - 'Combodo\\iTop\\DataFeatureRemoval\\Service\\SetupAudit' => $baseDir . '/src/Service/SetupAudit.php', + 'Combodo\\iTop\\DataFeatureRemoval\\Service\\DataFeatureRemoverExtensionService' => $baseDir . '/src/Service/DataFeatureRemoverExtensionService.php', + 'Combodo\\iTop\\DataFeatureRemoval\\Service\\DeletionPlanService' => $baseDir . '/src/Service/DeletionPlanService.php', 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', ); diff --git a/datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_static.php b/datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_static.php index 046440b0f3..8f127af07c 100644 --- a/datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_static.php +++ b/datamodels/2.x/combodo-data-feature-removal/vendor/composer/autoload_static.php @@ -26,12 +26,12 @@ class ComposerStaticInit4f96a7199e2c0d90e547333758b26464 public static $classMap = array ( 'Combodo\\iTop\\DataFeatureRemoval\\Controller\\DataFeatureRemovalController' => __DIR__ . '/../..' . '/src/Controller/DataFeatureRemovalController.php', + 'Combodo\\iTop\\DataFeatureRemoval\\Entity\\DeletionPlanSummaryEntity' => __DIR__ . '/../..' . '/src/Entity/DeletionPlanSummaryEntity.php', 'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalException' => __DIR__ . '/../..' . '/src/Helper/DataFeatureRemovalException.php', 'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalHelper' => __DIR__ . '/../..' . '/src/Helper/DataFeatureRemovalHelper.php', 'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalLog' => __DIR__ . '/../..' . '/src/Helper/DataFeatureRemovalLog.php', - 'Combodo\\iTop\\DataFeatureRemoval\\Model\\DataFeatureRemoverAuditRuleService' => __DIR__ . '/../..' . '/src/Model/DataFeatureRemoverAuditRuleService.php', - 'Combodo\\iTop\\DataFeatureRemoval\\Model\\DataFeatureRemoverExtensionService' => __DIR__ . '/../..' . '/src/Model/DataFeatureRemoverExtensionService.php', - 'Combodo\\iTop\\DataFeatureRemoval\\Service\\SetupAudit' => __DIR__ . '/../..' . '/src/Service/SetupAudit.php', + 'Combodo\\iTop\\DataFeatureRemoval\\Service\\DataFeatureRemoverExtensionService' => __DIR__ . '/../..' . '/src/Service/DataFeatureRemoverExtensionService.php', + 'Combodo\\iTop\\DataFeatureRemoval\\Service\\DeletionPlanService' => __DIR__ . '/../..' . '/src/Service/DeletionPlanService.php', 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', ); diff --git a/setup/wizardcontroller.class.inc.php b/setup/wizardcontroller.class.inc.php index 0eb73c597f..6eb2076e8a 100644 --- a/setup/wizardcontroller.class.inc.php +++ b/setup/wizardcontroller.class.inc.php @@ -16,7 +16,6 @@ // // You should have received a copy of the GNU Affero General Public License // along with iTop. If not, see -use Combodo\iTop\Application\WebPage\WebPage; require_once(APPROOT.'setup/setuputils.class.inc.php'); require_once(APPROOT.'setup/parameters.class.inc.php'); @@ -243,6 +242,7 @@ HTML; } $oPage->add(''); $oPage->add(""); + $oStep->PostFormDisplay($oPage); $oPage->add(''); // The div may become visible in case of error // Hack to have the "Next >>" button, be the default button, since the first submit button in the form is the default one diff --git a/setup/wizardsteps/WizStepDataAudit.php b/setup/wizardsteps/WizStepDataAudit.php index a7f6d2b60c..95e312400d 100644 --- a/setup/wizardsteps/WizStepDataAudit.php +++ b/setup/wizardsteps/WizStepDataAudit.php @@ -17,6 +17,7 @@ * * You should have received a copy of the GNU Affero General Public License */ + use Combodo\iTop\Application\WebPage\WebPage; require_once(APPROOT.'setup/sequencers/DataAuditSequencer.php'); @@ -51,7 +52,6 @@ class WizStepDataAudit extends WizStepInstall } else { return false; } - } public function UpdateWizardStateAndGetNextStep($bMoveForward = true): WizardState @@ -76,8 +76,6 @@ class WizStepDataAudit extends WizStepInstall $sAuthentToken = $this->oWizard->GetParameter('authent', ''); $oPage->add(''); - $sApplicationUrl = $this->oWizard->GetParameter('application_url').'pages/exec.php?exec_module=combodo-data-feature-removal&exec_page=index.php'; - $oPage->add(''); if (!$this->CheckDependencies()) { $oPage->error($this->sDependencyIssue); $oPage->add_ready_script(<<oWizard->GetParameter('removed_extensions', "[]"), true); + $aHiddenRemovedExtensionInputs = ""; + if (!is_array($aRemovedExtensions)) { + IssueLog::Warning('Posted removed_extensions is not an array'); + $aRemovedExtensions = []; + } + foreach ($aRemovedExtensions as $sExtCode => $sExtLabel) { + $sSafeExtCode = utils::HtmlEntities($sExtCode); + $aHiddenRemovedExtensionInputs .= << +INPUT; + } + + $oPage->add( + << + + $aHiddenRemovedExtensionInputs + +HTML + ); } protected function AddProgressErrorScript($oPage, $aRes) @@ -101,8 +131,13 @@ JS); <<'); - $('.ibo-setup--wizard--buttons-container tr td:nth-child(2)').after(''); - + $('.ibo-setup--wizard--buttons-container tr td:nth-child(2)').after(' '); + $('#goto-data-feature-removal').on("click", function() { + $('#goto-data-feature-removal').prop('disabled', true); + $('#submit-wait').removeClass("ibo-is-hidden"); + $('#data-feature-removal').submit(); + }) + $("#wiz_form").data("installation_status", "cleanup_needed"); $('#btn_next').hide(); EOF diff --git a/setup/wizardsteps/WizardStep.php b/setup/wizardsteps/WizardStep.php index dd34d10a95..2e3f2cf2fd 100644 --- a/setup/wizardsteps/WizardStep.php +++ b/setup/wizardsteps/WizardStep.php @@ -66,6 +66,16 @@ abstract class WizardStep protected $bDependencyCheck = null; protected $sDependencyIssue = null; + /** + * Add post display stuff to the setup screen + * @param \SetupPage $oPage + * + * @return void + */ + public function PostFormDisplay(SetupPage $oPage) + { + } + protected function CheckDependencies() { if (is_null($this->bDependencyCheck)) {