chg: [metaTemplate] Major refactoring and documentation - WiP

pull/93/head
Sami Mokaddem 2021-12-14 15:09:40 +01:00
parent f7ae58a22d
commit 02cc0c30a3
No known key found for this signature in database
GPG Key ID: 164C473F627A06FA
9 changed files with 920 additions and 420 deletions

View File

@ -37,9 +37,10 @@ class MoreMetaFieldColumns extends AbstractMigration
$metaTemplate = $this->table('meta_templates') $metaTemplate = $this->table('meta_templates')
->removeIndex(['uuid']) ->removeIndex(['uuid'])
->addIndex(['uuid']) ->addIndex(['uuid', 'version'])
->update(); ->update();
// TODO: Make sure FK constraints are set between meta_field, meta_template and meta_template_fields // TODO: Make sure FK constraints are set between meta_field, meta_template and meta_template_fields
// TODO: Make sure to add constraints on meta_template `uuid` and `version`
} }
} }

View File

@ -24,15 +24,15 @@ class MetaTemplatesNavigation extends BaseNavigation
]); ]);
$totalUpdateCount = 0; $totalUpdateCount = 0;
if (!empty($this->viewVars['updateableTemplate']['updateable']) && !empty($this->viewVars['updateableTemplate']['new'])) { if (!empty($this->viewVars['updateableTemplates']['automatically-updateable']) && !empty($this->viewVars['updateableTemplates']['new'])) {
$udpateCount = count($this->viewVars['updateableTemplate']['updateable']) ?? 0; $udpateCount = count($this->viewVars['updateableTemplates']['automatically-updateable']) ?? 0;
$newCount = count($this->viewVars['updateableTemplate']['new']) ?? 0; $newCount = count($this->viewVars['updateableTemplates']['new']) ?? 0;
$totalUpdateCount = $udpateCount + $newCount; $totalUpdateCount = $udpateCount + $newCount;
} }
$updateRouteConfig = [ $updateRouteConfig = [
'label' => __('Update all templates'), 'label' => __('Update all templates'),
'icon' => 'download', 'icon' => 'download',
'url' => '/metaTemplates/update', 'url' => '/metaTemplates/updateAllTemplates',
]; ];
if ($totalUpdateCount > 0) { if ($totalUpdateCount > 0) {
$updateRouteConfig['badge'] = [ $updateRouteConfig['badge'] = [
@ -41,7 +41,17 @@ class MetaTemplatesNavigation extends BaseNavigation
'title' => __('There are {0} new meta-template(s) and {1} update(s) available', h($newCount), h($udpateCount)), 'title' => __('There are {0} new meta-template(s) and {1} update(s) available', h($newCount), h($udpateCount)),
]; ];
} }
$this->bcf->addRoute('MetaTemplates', 'update', $updateRouteConfig); $this->bcf->addRoute('MetaTemplates', 'update_all_templates', $updateRouteConfig);
$this->bcf->addRoute('MetaTemplates', 'update', [
'label' => __('Update template'),
'icon' => 'download',
'url' => '/metaTemplates/update',
]);
$this->bcf->addRoute('MetaTemplates', 'prune_outdated_template', [
'label' => __('Prune outdated template'),
'icon' => 'trash',
'url' => '/metaTemplates/prune_outdated_template',
]);
} }
public function addParents() public function addParents()
@ -58,30 +68,34 @@ class MetaTemplatesNavigation extends BaseNavigation
public function addActions() public function addActions()
{ {
$totalUpdateCount = 0; $totalUpdateCount = 0;
if (!empty($this->viewVars['updateableTemplate']['not_up_to_date']) && !empty($this->viewVars['updateableTemplate']['new'])) { if (!empty($this->viewVars['updateableTemplates']['not-up-to-date']) && !empty($this->viewVars['updateableTemplates']['new'])) {
$udpateCount = count($this->viewVars['updateableTemplate']['not_up_to_date']) ?? 0; $udpateCount = count($this->viewVars['updateableTemplates']['not-up-to-date']) ?? 0;
$newCount = count($this->viewVars['updateableTemplate']['new']) ?? 0; $newCount = count($this->viewVars['updateableTemplates']['new']) ?? 0;
$totalUpdateCount = $udpateCount + $newCount; $totalUpdateCount = $udpateCount + $newCount;
} }
$updateActionConfig = [ $updateAllActionConfig = [
'label' => __('Update template'), 'label' => __('Update template'),
'url' => '/metaTemplates/update/{{id}}', 'url' => '/metaTemplates/updateAllTemplates',
'url_vars' => ['id' => 'id'], 'url_vars' => ['id' => 'id'],
]; ];
if ($totalUpdateCount > 0) { if ($totalUpdateCount > 0) {
$updateActionConfig['badge'] = [ $updateAllActionConfig['badge'] = [
'text' => h($totalUpdateCount), 'text' => h($totalUpdateCount),
'variant' => 'warning', 'variant' => 'warning',
'title' => __('There are {0} new meta-template(s) and {1} update(s) available', h($newCount), h($udpateCount)), 'title' => __('There are {0} new meta-template(s) and {1} update(s) available', h($newCount), h($udpateCount)),
]; ];
} }
$this->bcf->addAction('MetaTemplates', 'index', 'MetaTemplates', 'update', $updateActionConfig); $this->bcf->addAction('MetaTemplates', 'index', 'MetaTemplates', 'update_all_templates', $updateAllActionConfig);
$this->bcf->addAction('MetaTemplates', 'index', 'MetaTemplates', 'prune_outdated_template', [
'label' => __('Prune outdated template'),
'url' => '/metaTemplates/prune_outdated_template',
]);
if (empty($this->viewVars['updateableTemplate']['up-to-date'])) { if (empty($this->viewVars['updateableTemplates']['up-to-date'])) {
$this->bcf->addAction('MetaTemplates', 'view', 'MetaTemplates', 'update', [ $this->bcf->addAction('MetaTemplates', 'view', 'MetaTemplates', 'update', [
'label' => __('Update template'), 'label' => __('Update template'),
'url' => '/metaTemplates/update/{{uuid}}', 'url' => '/metaTemplates/update/{{id}}',
'url_vars' => ['uuid' => 'uuid'], 'url_vars' => ['id' => 'id'],
'variant' => 'warning', 'variant' => 'warning',
'badge' => [ 'badge' => [
'variant' => 'warning', 'variant' => 'warning',

View File

@ -17,27 +17,78 @@ class MetaTemplatesController extends AppController
public $filterFields = ['name', 'uuid', 'scope', 'namespace']; public $filterFields = ['name', 'uuid', 'scope', 'namespace'];
public $containFields = ['MetaTemplateFields']; public $containFields = ['MetaTemplateFields'];
public function update($template_uuid=null) // public function update($template_uuid=null)
// {
// $metaTemplate = false;
// if (!is_null($template_uuid)) {
// $metaTemplate = $this->MetaTemplates->find()->where([
// 'uuid' => $template_uuid
// ])->first();
// if (empty($metaTemplate)) {
// throw new NotFoundException(__('Invalid {0}.', $this->MetaTemplates->getAlias()));
// }
// }
// if ($this->request->is('post')) {
// $updateStrategy = $this->request->getData('update_strategy', null);
// $result = $this->MetaTemplates->update($template_uuid, $updateStrategy);
// if ($this->ParamHandler->isRest()) {
// return $this->RestResponse->viewData($result, 'json');
// } else {
// if ($result['success']) {
// $message = __n('{0} templates updated.', 'The template has been updated.', empty($template_uuid), $result['files_processed']);
// } else {
// $message = __n('{0} templates could not be updated.', 'The template could not be updated.', empty($template_uuid), $result['files_processed']);
// }
// $this->CRUD->setResponseForController('update', $result['success'], $message, $result['files_processed'], $result['update_errors'], ['redirect' => $this->referer()]);
// $responsePayload = $this->CRUD->getResponsePayload();
// if (!empty($responsePayload)) {
// return $responsePayload;
// }
// }
// } else {
// if (!$this->ParamHandler->isRest()) {
// if (!is_null($template_uuid)) {
// $this->set('metaTemplate', $metaTemplate);
// $this->setUpdateStatus($metaTemplate->id);
// } else {
// $this->set('title', __('Update Meta Templates'));
// $this->set('question', __('Are you sure you wish to update the Meta Template definitions'));
// $templatesUpdateStatus = $this->MetaTemplates->getUpdateStatusForTemplates();
// $this->set('templatesUpdateStatus', $templatesUpdateStatus);
// $this->render('updateAll');
// }
// }
// }
// }
/**
* Update the provided template or all templates
*
* @param int|null $template_id
*/
public function update($template_id=null)
{ {
$metaTemplate = false; $metaTemplate = false;
if (!is_null($template_uuid)) { if (!is_null($template_id)) {
$metaTemplate = $this->MetaTemplates->find()->where([ if (!is_numeric($template_id)) {
'uuid' => $template_uuid throw new NotFoundException(__('Invalid {0} for provided ID.', $this->MetaTemplates->getAlias(), $template_id));
])->first(); }
$metaTemplate = $this->MetaTemplates->get($template_id);
if (empty($metaTemplate)) { if (empty($metaTemplate)) {
throw new NotFoundException(__('Invalid {0}.', $this->MetaTemplates->getAlias())); throw new NotFoundException(__('Invalid {0} {1}.', $this->MetaTemplates->getAlias(), $template_id));
} }
} }
if ($this->request->is('post')) { if ($this->request->is('post')) {
$updateStrategy = $this->request->getData('update_strategy', null); $params = $this->ParamHandler->harvestParams(['update_strategy']);
$result = $this->MetaTemplates->update($template_uuid, $updateStrategy); $updateStrategy = $params['update_strategy'] ?? null;
$result = $this->MetaTemplates->update($metaTemplate, $updateStrategy);
if ($this->ParamHandler->isRest()) { if ($this->ParamHandler->isRest()) {
return $this->RestResponse->viewData($result, 'json'); return $this->RestResponse->viewData($result, 'json');
} else { } else {
if ($result['success']) { if ($result['success']) {
$message = __n('{0} templates updated.', 'The template has been updated.', empty($template_uuid), $result['files_processed']); $message = __n('{0} templates updated.', 'The template has been updated.', empty($template_id), $result['files_processed']);
} else { } else {
$message = __n('{0} templates could not be updated.', 'The template could not be updated.', empty($template_uuid), $result['files_processed']); $message = __n('{0} templates could not be updated.', 'The template could not be updated.', empty($template_id), $result['files_processed']);
} }
$this->CRUD->setResponseForController('update', $result['success'], $message, $result['files_processed'], $result['update_errors'], ['redirect' => $this->referer()]); $this->CRUD->setResponseForController('update', $result['success'], $message, $result['files_processed'], $result['update_errors'], ['redirect' => $this->referer()]);
$responsePayload = $this->CRUD->getResponsePayload(); $responsePayload = $this->CRUD->getResponsePayload();
@ -47,14 +98,15 @@ class MetaTemplatesController extends AppController
} }
} else { } else {
if (!$this->ParamHandler->isRest()) { if (!$this->ParamHandler->isRest()) {
if (!is_null($template_uuid)) { if (!empty($metaTemplate)) {
$this->set('metaTemplate', $metaTemplate); $this->set('metaTemplate', $metaTemplate);
$this->setUpdateStatus($metaTemplate->id); $statuses = $this->setUpdateStatus($metaTemplate->id);
$this->set('updateStatus', $this->MetaTemplates->computeFullUpdateStatusForMetaTemplate($statuses['templateStatus'], $metaTemplate));
} else { } else {
$this->set('title', __('Update Meta Templates')); $this->set('title', __('Update All Meta Templates'));
$this->set('question', __('Are you sure you wish to update the Meta Template definitions')); $this->set('question', __('Are you sure you wish to update all the Meta Template definitions'));
$updateableTemplates = $this->MetaTemplates->checkForUpdates(); $templatesUpdateStatus = $this->MetaTemplates->getUpdateStatusForTemplates();
$this->set('updateableTemplates', $updateableTemplates); $this->set('templatesUpdateStatus', $templatesUpdateStatus);
$this->render('updateAll'); $this->render('updateAll');
} }
} }
@ -65,7 +117,7 @@ class MetaTemplatesController extends AppController
{ {
$metaTemplate = $this->MetaTemplates->get($template_id); $metaTemplate = $this->MetaTemplates->get($template_id);
$newestMetaTemplate = $this->MetaTemplates->getNewestVersion($metaTemplate); $newestMetaTemplate = $this->MetaTemplates->getNewestVersion($metaTemplate);
$entities = $this->MetaTemplates->getEntitiesWithMetaFieldsToUpdate($template_id); $entities = $this->MetaTemplates->getEntitiesHavingMetaFieldsFromTemplate($template_id);
$this->set('metaTemplate', $metaTemplate); $this->set('metaTemplate', $metaTemplate);
$this->set('newestMetaTemplate', $newestMetaTemplate); $this->set('newestMetaTemplate', $newestMetaTemplate);
$this->set('entities', $entities); $this->set('entities', $entities);
@ -77,15 +129,16 @@ class MetaTemplatesController extends AppController
'contain' => ['MetaTemplateFields'] 'contain' => ['MetaTemplateFields']
]); ]);
$newestMetaTemplate = $this->MetaTemplates->getNewestVersion($metaTemplate, true); $newestMetaTemplate = $this->MetaTemplates->getNewestVersion($metaTemplate, true);
$entity = $this->MetaTemplates->migrateMetaTemplateToNewVersion($metaTemplate, $newestMetaTemplate, $entity_id); $entity = $this->MetaTemplates->getEntity($metaTemplate, $entity_id);
$conditions = [ $conditions = [
'MetaFields.meta_template_id IN' => [$metaTemplate->id, $newestMetaTemplate->id] 'MetaFields.meta_template_id IN' => [$metaTemplate->id, $newestMetaTemplate->id],
'MetaFields.scope' => $metaTemplate->scope,
]; ];
$keyedMetaFields = $this->MetaTemplates->getKeyedMetaFields($metaTemplate->scope, $entity_id, $conditions); $keyedMetaFields = $this->MetaTemplates->getKeyedMetaFieldsForEntity($entity_id, $conditions);
if (empty($keyedMetaFields[$metaTemplate->id])) { if (empty($keyedMetaFields[$metaTemplate->id])) {
throw new NotFoundException(__('Invalid {0}. This entities does not have meta-fields to be moved to a newer template.', $this->MetaTemplates->getAlias())); throw new NotFoundException(__('Invalid {0}. This entities does not have meta-fields to be moved to a newer template.', $this->MetaTemplates->getAlias()));
} }
$mergedMetaFields = $this->MetaTemplates->mergeMetaFieldsInMetaTemplate($keyedMetaFields, [$metaTemplate, $newestMetaTemplate]); $mergedMetaFields = $this->MetaTemplates->insertMetaFieldsInMetaTemplates($keyedMetaFields, [$metaTemplate, $newestMetaTemplate]);
$entity['MetaTemplates'] = $mergedMetaFields; $entity['MetaTemplates'] = $mergedMetaFields;
if ($this->request->is('post') || $this->request->is('put')) { if ($this->request->is('post') || $this->request->is('put')) {
$className = Inflector::camelize(Inflector::pluralize($newestMetaTemplate->scope)); $className = Inflector::camelize(Inflector::pluralize($newestMetaTemplate->scope));
@ -126,11 +179,13 @@ class MetaTemplatesController extends AppController
return $responsePayload; return $responsePayload;
} }
} }
$conflicts = $this->MetaTemplates->checkForMetaTemplateConflicts($metaTemplate, $newestMetaTemplate); $conflicts = $this->MetaTemplates->getMetaTemplateConflictsForMetaTemplate($metaTemplate, $newestMetaTemplate);
foreach ($conflicts as $conflict) { foreach ($conflicts as $conflict) {
$existingMetaTemplateField = $conflict['existing_meta_template_field']; if (!empty($conflict['existing_meta_template_field'])) {
foreach ($existingMetaTemplateField->metaFields as $metafield_id => $metaField) { $existingMetaTemplateField = $conflict['existing_meta_template_field'];
$metaField->setError('value', implode(', ', $existingMetaTemplateField->conflicts)); foreach ($existingMetaTemplateField->metaFields as $metaField) {
$metaField->setError('value', implode(', ', $existingMetaTemplateField->conflicts));
}
} }
} }
// automatically convert non-conflicting fields to new meta-template // automatically convert non-conflicting fields to new meta-template
@ -162,25 +217,29 @@ class MetaTemplatesController extends AppController
public function index() public function index()
{ {
$updateableTemplate = $this->MetaTemplates->checkForUpdates(); $templatesUpdateStatus = $this->MetaTemplates->getUpdateStatusForTemplates();
$this->CRUD->index([ $this->CRUD->index([
'filters' => $this->filterFields, 'filters' => $this->filterFields,
'quickFilters' => $this->quickFilterFields, 'quickFilters' => $this->quickFilterFields,
'contextFilters' => [ 'contextFilters' => [
'fields' => ['scope'],
'custom' => [ 'custom' => [
[ [
'label' => __('Default Templates'), 'default' => true,
'filterCondition' => ['is_default' => true] 'label' => __('Newest Templates'),
'filterConditionFunction' => function ($query) {
return $query->where([
'id IN' => $this->MetaTemplates->genQueryForAllNewestVersionIDs()
]);
}
], ],
] ]
], ],
'contain' => $this->containFields, 'contain' => $this->containFields,
'afterFind' => function($data) use ($updateableTemplate) { 'afterFind' => function($data) use ($templatesUpdateStatus) {
foreach ($data as $i => $metaTemplate) { foreach ($data as $i => $metaTemplate) {
if (!empty($updateableTemplate[$metaTemplate->uuid])) { if (!empty($templatesUpdateStatus[$metaTemplate->uuid])) {
$updateStatusForTemplate = $this->MetaTemplates->checkUpdateForMetaTemplate($updateableTemplate[$metaTemplate->uuid]['template'], $metaTemplate); $templateStatus = $this->MetaTemplates->getStatusForMetaTemplate($templatesUpdateStatus[$metaTemplate->uuid]['template'], $metaTemplate);
$metaTemplate->set('status', $this->MetaTemplates->getTemplateStatus($updateStatusForTemplate, $metaTemplate)); $metaTemplate->set('updateStatus', $this->MetaTemplates->computeFullUpdateStatusForMetaTemplate($templateStatus, $metaTemplate));
} }
} }
return $data; return $data;
@ -190,14 +249,14 @@ class MetaTemplatesController extends AppController
if (!empty($responsePayload)) { if (!empty($responsePayload)) {
return $responsePayload; return $responsePayload;
} }
$updateableTemplate = [ $updateableTemplates = [
'not_up_to_date' => $this->MetaTemplates->getNotUpToDateTemplates(), 'not-up-to-date' => $this->MetaTemplates->getNotUpToDateTemplates(),
'can_be_removed' => $this->MetaTemplates->getCanBeRemovedTemplates(), 'can-be-removed' => $this->MetaTemplates->getCanBeRemovedTemplates(),
'new' => $this->MetaTemplates->getNewTemplates(), 'new' => $this->MetaTemplates->getNewTemplates(),
]; ];
$this->set('defaultTemplatePerScope', $this->MetaTemplates->getDefaultTemplatePerScope()); $this->set('defaultTemplatePerScope', $this->MetaTemplates->getDefaultTemplatePerScope());
$this->set('alignmentScope', 'individuals'); $this->set('alignmentScope', 'individuals');
$this->set('updateableTemplate', $updateableTemplate); $this->set('updateableTemplates', $updateableTemplates);
} }
public function view($id) public function view($id)
@ -215,7 +274,7 @@ class MetaTemplatesController extends AppController
public function delete($id) public function delete($id)
{ {
$updateableTemplate = $this->getUpdateStatus($id); $updateableTemplate = $this->getUpdateStatus($id);
if (empty($updateableTemplate['can_be_removed'])) { if (empty($updateableTemplate['can-be-removed'])) {
throw MethodNotAllowedException(__('This meta-template cannot be removed')); throw MethodNotAllowedException(__('This meta-template cannot be removed'));
} }
$this->set('deletionText', __('The meta-template "{0}" has no meta-field and can be safely removed.', h($updateableTemplate['existing_template']->name))); $this->set('deletionText', __('The meta-template "{0}" has no meta-field and can be safely removed.', h($updateableTemplate['existing_template']->name)));
@ -247,18 +306,28 @@ class MetaTemplatesController extends AppController
'contain' => ['MetaTemplateFields'] 'contain' => ['MetaTemplateFields']
]); ]);
$templateOnDisk = $this->MetaTemplates->readTemplateFromDisk($metaTemplate->uuid); $templateOnDisk = $this->MetaTemplates->readTemplateFromDisk($metaTemplate->uuid);
$updateableTemplate = $this->MetaTemplates->checkUpdateForMetaTemplate($templateOnDisk, $metaTemplate); $templateStatus = $this->MetaTemplates->getStatusForMetaTemplate($templateOnDisk, $metaTemplate);
return $updateableTemplate; return $templateStatus;
} }
public function setUpdateStatus($id) /**
* Retreive the template stored on disk and compute the status for the provided template id.
*
* @param [type] $id
* @return array
*/
private function setUpdateStatus($template_id): array
{ {
$metaTemplate = $this->MetaTemplates->get($id, [ $metaTemplate = $this->MetaTemplates->get($template_id, [
'contain' => ['MetaTemplateFields'] 'contain' => ['MetaTemplateFields']
]); ]);
$templateOnDisk = $this->MetaTemplates->readTemplateFromDisk($metaTemplate->uuid); $templateOnDisk = $this->MetaTemplates->readTemplateFromDisk($metaTemplate->uuid);
$updateableTemplate = $this->MetaTemplates->checkUpdateForMetaTemplate($templateOnDisk, $metaTemplate); $templateStatus = $this->MetaTemplates->getStatusForMetaTemplate($templateOnDisk, $metaTemplate);
$this->set('updateableTemplate', $updateableTemplate);
$this->set('templateOnDisk', $templateOnDisk); $this->set('templateOnDisk', $templateOnDisk);
$this->set('templateStatus', $templateStatus);
return [
'templateOnDisk' => $templateOnDisk,
'templateStatus' => $templateStatus,
];
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
<?php <?php
use Cake\Utility\Hash; use Cake\Utility\Hash;
if (!empty($updateableTemplate)) { if (!empty($updateableTemplates['new'])) {
$alertHtml = sprintf('<strong>%s</strong> %s', __('New meta-templates available!'), __n('There is one new template on disk that can be loaded in the database', 'There are {0} new templates on disk that can be loaded in the database:', count($updateableTemplate['new']))); $alertHtml = sprintf('<strong>%s</strong> %s', __('New meta-templates available!'), __n('There is one new template on disk that can be loaded in the database', 'There are {0} new templates on disk that can be loaded in the database:', count($updateableTemplates['new'])));
$alertList = Hash::combine( $alertList = Hash::combine(
$updateableTemplate, $updateableTemplates,
null, null,
['%s :: %s', 'new.{s}.template.namespace', 'new.{s}.template.name'], ['%s :: %s', 'new.{s}.template.namespace', 'new.{s}.template.name'],
'new.{n}.template.namespace' 'new.{n}.template.namespace'
@ -171,12 +171,12 @@ echo $this->element('genericElements/IndexTable/index_table', [
], ],
[ [
'open_modal' => '/metaTemplates/update/[onclick_params_data_path]', 'open_modal' => '/metaTemplates/update/[onclick_params_data_path]',
'modal_params_data_path' => 'uuid', 'modal_params_data_path' => 'id',
'title' => __('Update Meta-Template'), 'title' => __('Update Meta-Template'),
'icon' => 'download', 'icon' => 'download',
'complex_requirement' => [ 'complex_requirement' => [
'function' => function ($row, $options) { 'function' => function ($row, $options) {
return empty($row['status']['up_to_date']) && empty($row['status']['to_existing']); return empty($row['updateStatus']['up-to-date']) && empty($row['updateStatus']['to-existing']);
} }
] ]
], ],
@ -188,7 +188,7 @@ echo $this->element('genericElements/IndexTable/index_table', [
'variant' => 'warning', 'variant' => 'warning',
'complex_requirement' => [ 'complex_requirement' => [
'function' => function ($row, $options) { 'function' => function ($row, $options) {
return !empty($row['status']['to_existing']) && empty($row['status']['can_be_removed']); return !empty($row['updateStatus']['to-existing']) && empty($row['updateStatus']['can-be-removed']);
} }
] ]
], ],
@ -200,7 +200,7 @@ echo $this->element('genericElements/IndexTable/index_table', [
'variant' => 'success', 'variant' => 'success',
'complex_requirement' => [ 'complex_requirement' => [
'function' => function ($row, $options) { 'function' => function ($row, $options) {
return !empty($row['status']['to_existing']) && !empty($row['status']['can_be_removed']); return !empty($row['updateStatus']['to-existing']) && !empty($row['updateStatus']['can-be-removed']);
} }
] ]
], ],

View File

@ -3,7 +3,7 @@
$bodyHtml = ''; $bodyHtml = '';
$modalType = 'confirm'; $modalType = 'confirm';
$modalSize = 'lg'; $modalSize = 'lg';
if ($updateableTemplate['up-to-date']) { if ($updateStatus['up-to-date']) {
$bodyHtml .= $this->Bootstrap->alert([ $bodyHtml .= $this->Bootstrap->alert([
'variant' => 'success', 'variant' => 'success',
'text' => __('This meta-template is already up-to-date!'), 'text' => __('This meta-template is already up-to-date!'),
@ -11,7 +11,7 @@ if ($updateableTemplate['up-to-date']) {
]); ]);
$modalType = 'ok-only'; $modalType = 'ok-only';
} else { } else {
if ($updateableTemplate['updateable']) { if ($updateStatus['automatically-updateable']) {
$bodyHtml .= $this->Bootstrap->alert([ $bodyHtml .= $this->Bootstrap->alert([
'variant' => 'success', 'variant' => 'success',
'html' => __('This meta-template can be updated to version {0} (current: {1}).', sprintf('<strong>%s</strong>', h($templateOnDisk['version'])), h($metaTemplate->version)), 'html' => __('This meta-template can be updated to version {0} (current: {1}).', sprintf('<strong>%s</strong>', h($templateOnDisk['version'])), h($metaTemplate->version)),
@ -45,7 +45,7 @@ if ($updateableTemplate['up-to-date']) {
'dismissible' => false, 'dismissible' => false,
]); ]);
$conflictTable = $this->element('MetaTemplates/conflictTable', [ $conflictTable = $this->element('MetaTemplates/conflictTable', [
'updateableTemplate' => $updateableTemplate, 'templateStatus' => $templateStatus,
'metaTemplate' => $metaTemplate, 'metaTemplate' => $metaTemplate,
'templateOnDisk' => $templateOnDisk, 'templateOnDisk' => $templateOnDisk,
]); ]);
@ -54,7 +54,7 @@ if ($updateableTemplate['up-to-date']) {
'open' => false 'open' => false
], $conflictTable); ], $conflictTable);
$bodyHtml .= $this->element('MetaTemplates/conflictResolution', [ $bodyHtml .= $this->element('MetaTemplates/conflictResolution', [
'updateableTemplate' => $updateableTemplate, 'templateStatus' => $templateStatus,
'metaTemplate' => $metaTemplate, 'metaTemplate' => $metaTemplate,
'templateOnDisk' => $templateOnDisk, 'templateOnDisk' => $templateOnDisk,
]); ]);

View File

@ -15,7 +15,7 @@ $tableHtml .= sprintf('<th class="text-nowrap">%s</th>', __('Will be updated'));
$tableHtml .= '</tr></thead><tbody>'; $tableHtml .= '</tr></thead><tbody>';
$numberOfUpdates = 0; $numberOfUpdates = 0;
$numberOfSkippedUpdates = 0; $numberOfSkippedUpdates = 0;
foreach ($updateableTemplates as $uuid => $status) { foreach ($templatesUpdateStatus as $uuid => $status) {
$tableHtml .= '<tr>'; $tableHtml .= '<tr>';
if (!empty($status['new'])) { if (!empty($status['new'])) {
$tableHtml .= sprintf('<td>%s</td>', h($uuid)); $tableHtml .= sprintf('<td>%s</td>', h($uuid));
@ -53,7 +53,7 @@ foreach ($updateableTemplates as $uuid => $status) {
if (!empty($status['new'])) { if (!empty($status['new'])) {
$tableHtml .= sprintf('<td>%s</td>', $this->Bootstrap->icon('check', ['class' => 'text-success'])); $tableHtml .= sprintf('<td>%s</td>', $this->Bootstrap->icon('check', ['class' => 'text-success']));
} else { } else {
if (!empty($status['new']) || !empty($status['updateable'])) { if (!empty($status['new']) || !empty($status['automatically-updateable'])) {
$numberOfUpdates += 1; $numberOfUpdates += 1;
$tableHtml .= sprintf('<td>%s</td>', $this->Bootstrap->icon('check', ['class' => 'text-success'])); $tableHtml .= sprintf('<td>%s</td>', $this->Bootstrap->icon('check', ['class' => 'text-success']));
} else { } else {

View File

@ -1,4 +1,10 @@
<?php <?php
$create_new_allowed = true;
$keep_all_allowed = false;
$delete_all_allowed = false;
$totalAllowed = $create_new_allowed + $keep_all_allowed + $delete_all_allowed;
$maxWidth = 99 - ($create_new_allowed ? 33 : 0) - ($keep_all_allowed ? 33 : 0) - ($delete_all_allowed ? 33 : 0);
$form = $this->element('genericElements/Form/genericForm', [ $form = $this->element('genericElements/Form/genericForm', [
'entity' => null, 'entity' => null,
'ajax' => false, 'ajax' => false,
@ -10,6 +16,7 @@ $form = $this->element('genericElements/Form/genericForm', [
'field' => 'update_strategy', 'field' => 'update_strategy',
'type' => 'radio', 'type' => 'radio',
'options' => [ 'options' => [
['value' => 'create_new', 'text' => 'create_new', 'id' => 'radio_create_new'],
['value' => 'keep_both', 'text' => 'keep_both', 'id' => 'radio_keep_both'], ['value' => 'keep_both', 'text' => 'keep_both', 'id' => 'radio_keep_both'],
['value' => 'delete', 'text' => 'delete', 'id' => 'radio_delete'], ['value' => 'delete', 'text' => 'delete', 'id' => 'radio_delete'],
], ],
@ -25,28 +32,46 @@ $form = $this->element('genericElements/Form/genericForm', [
<div class="conflict-resolution-picker"> <div class="conflict-resolution-picker">
<div class="mt-3 d-flex justify-content-center"> <div class="mt-3 d-flex justify-content-center">
<div class="btn-group justify-content-center" role="group" aria-label="Basic radio toggle button group"> <div class="btn-group justify-content-center" role="group" aria-label="Basic radio toggle button group">
<input type="radio" class="btn-check" name="btnradio" id="btnradio1" autocomplete="off" value="keep_both" checked> <?php if ($create_new_allowed) : ?>
<label class="btn btn-outline-primary mw-33" for="btnradio1"> <input type="radio" class="btn-check" name="btnradio" id="btnradio1" autocomplete="off" value="create_new" checked>
<div> <label class="btn btn-outline-primary mw-<?= $maxWidth ?>" for="btnradio1">
<h5 class="mb-3"><?= __('Keep both template') ?></h5> <div>
<ul class="text-start fs-7"> <h5 class="mb-3"><?= __('Create new template') ?></h5>
<li><?= __('Meta-fields not having conflicts will be migrated to the new meta-template.') ?></li> <ul class="text-start fs-7">
<li><?= __('Meta-fields having a conflicts will stay on their current meta-template.') ?></li> <li><?= __('A new meta-template will be created and made default.') ?></li>
<li><?= __('Conflicts can be taken care of manually via the UI.') ?></li> <li><?= __('The old meta-template will remain untouched.') ?></li>
</ul> <li><?= __('Migration of meta-fields to this newer template can be done manually via the UI.') ?></li>
</div> </ul>
</label> </div>
</label>
<?php endif; ?>
<input type="radio" class="btn-check" name="btnradio" id="btnradio3" autocomplete="off" value="delete"> <?php if ($keep_all_allowed) : ?>
<label class="btn btn-outline-danger mw-33" for="btnradio3"> <input type="radio" class="btn-check" name="btnradio" id="btnradio2" autocomplete="off" value="keep_both">
<div> <label class="btn btn-outline-warning mw-<?= $maxWidth ?>" for="btnradio2">
<h5 class="mb-3"><?= __('Delete conflicting fields') ?></h5> <div>
<ul class="text-start fs-7"> <h5 class="mb-3"><?= __('Update non-conflicting') ?></h5>
<li><?= __('Meta-fields not satisfying the new meta-template definition will be deleted.') ?></li> <ul class="text-start fs-7">
<li><?= __('All other meta-fields will be upgraded to the new meta-template.') ?></li> <li><?= __('Meta-fields not having conflicts will be migrated to the new meta-template.') ?></li>
</ul> <li><?= __('Meta-fields having a conflicts will stay on their current meta-template.') ?></li>
</div> <li><?= __('Conflicts can be taken care of manually via the UI.') ?></li>
</label> </ul>
</div>
</label>
<?php endif; ?>
<?php if ($delete_all_allowed) : ?>
<input type="radio" class="btn-check" name="btnradio" id="btnradio3" autocomplete="off" value="delete">
<label class="btn btn-outline-danger mw-<?= $maxWidth ?>" for="btnradio3">
<div>
<h5 class="mb-3"><?= __('Delete conflicting fields') ?></h5>
<ul class="text-start fs-7">
<li><?= __('Meta-fields not satisfying the new meta-template definition will be deleted.') ?></li>
<li><?= __('All other meta-fields will be upgraded to the new meta-template.') ?></li>
</ul>
</div>
</label>
<?php endif; ?>
</div> </div>
</div> </div>
</div> </div>
@ -58,6 +83,7 @@ $form = $this->element('genericElements/Form/genericForm', [
<script> <script>
(function() { (function() {
const $form = $('.conflict-resolution-form-container form') const $form = $('.conflict-resolution-form-container form')
const $create = $form.find('input#radio_create_new')
const $keep = $form.find('input#radio_keep_both') const $keep = $form.find('input#radio_keep_both')
const $delete = $form.find('input#radio_delete') const $delete = $form.find('input#radio_delete')
@ -65,7 +91,7 @@ $form = $this->element('genericElements/Form/genericForm', [
$('.conflict-resolution-picker').find('input[type="radio"]').change(function() { $('.conflict-resolution-picker').find('input[type="radio"]').change(function() {
updateSelected($(this).val()) updateSelected($(this).val())
}) })
updateSelected('keep_both') updateSelected('create_new')
}) })
function updateSelected(choice) { function updateSelected(choice) {
@ -73,6 +99,8 @@ $form = $this->element('genericElements/Form/genericForm', [
$keep.prop('checked', true) $keep.prop('checked', true)
} else if (choice == 'delete') { } else if (choice == 'delete') {
$delete.prop('checked', true) $delete.prop('checked', true)
} else if (choice == 'create_new') {
$create.prop('checked', true)
} }
} }
}()) }())

View File

@ -12,7 +12,7 @@ use Cake\Routing\Router;
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<?php foreach ($updateableTemplate['conflicts'] as $fieldName => $fieldConflict) : ?> <?php foreach ($templateStatus['conflicts'] as $fieldName => $fieldConflict) : ?>
<?php foreach ($fieldConflict['conflicts'] as $conflict) : ?> <?php foreach ($fieldConflict['conflicts'] as $conflict) : ?>
<tr> <tr>
<th scope="row"><?= h($fieldName) ?></th> <th scope="row"><?= h($fieldName) ?></th>
@ -30,11 +30,11 @@ use Cake\Routing\Router;
break; break;
} }
$url = Router::url([ $url = Router::url([
'controller' => Inflector::pluralize($updateableTemplate['existing_template']->scope), 'controller' => Inflector::pluralize($templateStatus['existing_template']->scope),
'action' => 'view', 'action' => 'view',
$id $id
]); ]);
echo sprintf('<a href="%s" target="_blank">%s</a>', $url, __('{0} #{1}', h(Inflector::humanize($updateableTemplate['existing_template']->scope)), h($id))); echo sprintf('<a href="%s" target="_blank">%s</a>', $url, __('{0} #{1}', h(Inflector::humanize($templateStatus['existing_template']->scope)), h($id)));
} }
?> ?>
</td> </td>