new: [metaTemplate:metaFieldMigration] Added support of force migrate

Remove conflicting meta-fields and migrate non-conflicting ones
develop-unstable
Sami Mokaddem 2023-02-16 13:35:38 +01:00
parent 94509ff5d3
commit 97a151aff5
No known key found for this signature in database
GPG Key ID: 164C473F627A06FA
3 changed files with 76 additions and 16 deletions

View File

@ -247,7 +247,7 @@ class MetaTemplatesController extends AppController
$this->set('movedMetaTemplateFields', $movedMetaTemplateFields); $this->set('movedMetaTemplateFields', $movedMetaTemplateFields);
} }
public function migrateMetafieldsToNewestTemplate(int $template_id) public function migrateMetafieldsToNewestTemplate(int $template_id, $forceMigration=false)
{ {
$oldMetaTemplate = $this->MetaTemplates->find()->where([ $oldMetaTemplate = $this->MetaTemplates->find()->where([
'id' => $template_id 'id' => $template_id
@ -262,7 +262,7 @@ class MetaTemplatesController extends AppController
} }
if ($this->request->is('post')) { if ($this->request->is('post')) {
$result = $this->MetaTemplates->migrateMetafieldsToNewestTemplate($oldMetaTemplate, $newestMetaTemplate); $result = $this->MetaTemplates->migrateMetafieldsToNewestTemplate($oldMetaTemplate, $newestMetaTemplate, !empty($forceMigration));
if ($this->ParamHandler->isRest()) { if ($this->ParamHandler->isRest()) {
return $this->RestResponse->viewData($result, 'json'); return $this->RestResponse->viewData($result, 'json');
} else { } else {

View File

@ -937,7 +937,7 @@ class MetaTemplatesTable extends AppTable
return true; return true;
} }
public function migrateMetafieldsToNewestTemplate(\App\Model\Entity\MetaTemplate $oldMetaTemplate, \App\Model\Entity\MetaTemplate $newestMetaTemplate): array public function migrateMetafieldsToNewestTemplate(\App\Model\Entity\MetaTemplate $oldMetaTemplate, \App\Model\Entity\MetaTemplate $newestMetaTemplate, bool $forceMigration): array
{ {
$result = [ $result = [
'success' => true, 'success' => true,
@ -958,14 +958,26 @@ class MetaTemplatesTable extends AppTable
$conflicts = $this->getMetaFieldsConflictsUnderTemplate($entity->meta_fields, $newestMetaTemplate); $conflicts = $this->getMetaFieldsConflictsUnderTemplate($entity->meta_fields, $newestMetaTemplate);
if (!empty($conflicts)) { if (!empty($conflicts)) {
$conflictingEntities[] = $entity->id; $conflictingEntities[] = $entity->id;
} else { if (!$forceMigration) {
$success = $this->supersedeMetaFieldsWithMetaTemplateField($entity->meta_fields, $newestMetaTemplate); continue;
if ($success) {
$successfullyMigratedEntities += 1;
} else { } else {
$migrationErrors += 1; $conflictingMetafieldIDs = Hash::extract($conflicts, '{n}.id');
$metaFieldsToDelete = [];
foreach ($entity->meta_fields as $i => $metaField) {
if (in_array($metaField->id, $conflictingMetafieldIDs)) {
$metaFieldsToDelete[] = $metaField;
unset($entity->meta_fields[$i]);
}
}
$this->MetaTemplateFields->MetaFields->unlink($entity, $metaFieldsToDelete); // FIXME
} }
} }
$success = $this->supersedeMetaFieldsWithMetaTemplateField($entity->meta_fields, $newestMetaTemplate);
if ($success) {
$successfullyMigratedEntities += 1;
} else {
$migrationErrors += 1;
}
} }
$result['success'] = $migrationErrors == 0; $result['success'] = $migrationErrors == 0;

View File

@ -14,8 +14,6 @@ $bodyHtml .= sprintf('<div><span>%s: </span><span class="font-monospace">%s</spa
$bodyHtml .= sprintf('<div><span>%s: </span><a href="%s" target="_blank" class="font-monospac">%s</a></div>', __('Newest version'), $urlNewestMetaTemplate, h($newestMetaTemplate->version)); $bodyHtml .= sprintf('<div><span>%s: </span><a href="%s" target="_blank" class="font-monospac">%s</a></div>', __('Newest version'), $urlNewestMetaTemplate, h($newestMetaTemplate->version));
$bodyHtml .= sprintf('<h4 class="my-2">%s</h4>', __('{0} Entities with meta-fields for the meta-template version <span class="font-monospace">{1}</span>', h($entityCount), h($oldMetaTemplate->version))); $bodyHtml .= sprintf('<h4 class="my-2">%s</h4>', __('{0} Entities with meta-fields for the meta-template version <span class="font-monospace">{1}</span>', h($entityCount), h($oldMetaTemplate->version)));
// debug($conflictingEntities);
if (empty($conflictingEntities)) { if (empty($conflictingEntities)) {
$bodyHtml .= $this->Bootstrap->alert([ $bodyHtml .= $this->Bootstrap->alert([
'text' => __('All entities can updated automatically', count($conflictingEntities)), 'text' => __('All entities can updated automatically', count($conflictingEntities)),
@ -65,6 +63,19 @@ $form = sprintf(
$this->Form->end() $this->Form->end()
); );
$bodyHtml .= $form; $bodyHtml .= $form;
$form = sprintf(
'<div class="d-none hidden-form-force-container">%s%s</div>',
$this->Form->create(null, [
'url' => [
'controller' => 'MetaTemplates',
'action' => 'migrateMetafieldsToNewestTemplate',
$oldMetaTemplate->id,
1,
]
]),
$this->Form->end()
);
$bodyHtml .= $form;
$title = __('{0} has a new meta-template and meta-fields to be updated', sprintf('<i class="me-1">%s</i>', h($oldMetaTemplate->name))); $title = __('{0} has a new meta-template and meta-fields to be updated', sprintf('<i class="me-1">%s</i>', h($oldMetaTemplate->name)));
if (!empty($ajax)) { if (!empty($ajax)) {
@ -72,16 +83,35 @@ if (!empty($ajax)) {
'titleHtml' => $title, 'titleHtml' => $title,
'bodyHtml' => $bodyHtml, 'bodyHtml' => $bodyHtml,
'size' => 'lg', 'size' => 'lg',
'type' => 'confirm', 'type' => 'custom',
'confirmButton' => [ 'footerButtons' => [
'text' => __('Migrate meta-fields'), [
'variant' => 'success', 'text' => __('Cancel'),
'variant' => 'secondary',
],
[
'text' => __('Force Migrate meta-fields'),
'title' => __('Any meta-field having conflict will be deleted.'),
'variant' => 'danger',
'clickFunction' => 'forceMigrateMetafieldsToNewestTemplate',
],
[
'text' => __('Migrate meta-fields'),
'variant' => 'success',
'clickFunction' => 'migrateMetafieldsToNewestTemplate',
],
], ],
'confirmFunction' => 'migrateMetafieldsToNewestTemplate',
]); ]);
} else { } else {
echo $this->Bootstrap->node('h1', [], $title); echo $this->Bootstrap->node('h1', [], $title);
echo $bodyHtml; echo $bodyHtml;
echo $this->Bootstrap->button([
'text' => __('Force Migrate meta-fields'),
'title' => __('Any meta-field having conflict will be deleted.'),
'variant' => 'danger',
'class' => ['me-2'],
'onclick' => '$(".hidden-form-force-container form").submit()',
]);
echo $this->Bootstrap->button([ echo $this->Bootstrap->button([
'text' => __('Migrate meta-fields'), 'text' => __('Migrate meta-fields'),
'variant' => 'success', 'variant' => 'success',
@ -92,7 +122,25 @@ if (!empty($ajax)) {
<script> <script>
function migrateMetafieldsToNewestTemplate(modalObject, tmpApi) { function migrateMetafieldsToNewestTemplate(modalObject, tmpApi) {
const $form = modalObject.$modal.find('form') const $form = modalObject.$modal.find('.hidden-form-container form')
return doMigration($form, modalObject, tmpApi)
}
function forceMigrateMetafieldsToNewestTemplate(modalObject, tmpApi) {
return UI.quickConfirm(tmpApi.options.statusNode, {
variant: 'danger',
title: '<?= __('Confirm potential deletion of data') ?>',
description: '<?= __('By chosing to force the migration, any meta-fields not satisfying the validation requirements will be deleted.') ?>',
confirmText: '<?= __('Force migration') ?>',
confirm: function() {
const $form = modalObject.$modal.find('.hidden-form-force-container form')
return doMigration($form, modalObject, tmpApi)
}
})
}
function doMigration($form, modalObject, tmpApi) {
return tmpApi.postForm($form[0]).catch((errors) => { return tmpApi.postForm($form[0]).catch((errors) => {
const formHelper = new FormValidationHelper($form[0]) const formHelper = new FormValidationHelper($form[0])
const errorHTMLNode = formHelper.buildValidationMessageNode(errors, true) const errorHTMLNode = formHelper.buildValidationMessageNode(errors, true)