From e39ece57c53fa6c0142c6f5e20627948ee34693f Mon Sep 17 00:00:00 2001 From: iglocska Date: Wed, 28 Aug 2024 15:39:46 +0200 Subject: [PATCH] new: [meta_field] API improved - simple way to add metafields added - simply pass a list of meta_fields to the object about to be saved - the only fields required are: template_uuid, template_version, field, value Example for an individual: ``` { "first_name": "Andras", "last_name": "Iklody", "email": "andras.iklody@circl.lu", "alignments": { "organisation": [ { "uuid": "9d4d7913-2602-4333-8440-c78b7f92eca3", "name": "Iglocska.eu" } ] }, "meta_fields": [ { "field": "perm_mattermost", "value": true, "template_uuid": "447ded8b-314b-41c7-a913-4ce32535b28d", "template_version": 2 } ] } ``` --- src/Controller/Component/CRUDComponent.php | 59 ++++++++++++++++++++-- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/src/Controller/Component/CRUDComponent.php b/src/Controller/Component/CRUDComponent.php index 7d87fd5..441a5e7 100644 --- a/src/Controller/Component/CRUDComponent.php +++ b/src/Controller/Component/CRUDComponent.php @@ -458,6 +458,9 @@ class CRUDComponent extends Component $massagedData = $this->massageMetaFields($data, $input, $metaTemplates); unset($input['MetaTemplates']); // Avoid MetaTemplates to be overriden when patching entity $data = $massagedData['entity']; + if (isset($input['meta_fields'])) { + unset($input['meta_fields']); + } } $data = $this->Table->patchEntity($data, $input, $patchEntityParams); if (isset($params['beforeSave'])) { @@ -568,10 +571,35 @@ class CRUDComponent extends Component $this->Table->saveMetaFields($id, $input, $this->Table); } - // prune empty values and marshall fields - public function massageMetaFields($entity, $input, $allMetaTemplates = []) + private function handleSimpleMetaFieldInput($allMetaTemplates, $input, &$cleanupMetaFields) { - if (empty($input['MetaTemplates']) || !$this->metaFieldsSupported()) { + $input['MetaTemplates'] = []; + foreach ($input['meta_fields'] as $metaField) { + foreach ($allMetaTemplates as $metaTemplate) { + if ($metaTemplate->uuid != $metaField['template_uuid'] || $metaTemplate->version != $metaField['template_version']) { + continue; + } + foreach ($metaTemplate['meta_template_fields'] as $mtp) { + if ($mtp->field == $metaField['field']) { + // I feel dirty. I'm sorry. + $input['MetaTemplates'][$metaTemplate->id]['meta_template_fields'][$mtp->id]['metaFields']['new'][] = $metaField['value']; + $cleanupMetaFields[] = [ + 'scope' => $this->Table->getBehavior('MetaFields')->getScope(), + 'field' => $mtp->field, + 'meta_template_field_id' => $mtp->id, + 'meta_template_id' => $metaTemplate->id + ]; + } + } + } + } + return $input; + } + + // prune empty values and marshall fields + public function massageMetaFields($entity, $input, $allMetaTemplates = [], &$cleanupMetaFields = []) + { + if ((empty($input['MetaTemplates']) && !isset($input['meta_fields'])) || !$this->metaFieldsSupported()) { return ['entity' => $entity, 'metafields_to_delete' => []]; } @@ -580,6 +608,12 @@ class CRUDComponent extends Component if (empty($metaTemplates)) { $allMetaTemplates = $this->getMetaTemplates()->toArray(); } + // handle simpler format of meta_templates via the API + // the idea is that integrators shouldn't have to mimic the complex format used by the UI. + if (isset($input['meta_fields'])) { + $input = $this->handleSimpleMetaFieldInput($allMetaTemplates, $input, $cleanupMetaFields); + $entity->cleanupMetaFields = $cleanupMetaFields; + } if (!empty($entity->meta_fields)) { foreach ($entity->meta_fields as $i => $metaField) { $metaFieldsIndex[$metaField->id] = $i; @@ -738,11 +772,28 @@ class CRUDComponent extends Component throw new NotFoundException(__('Could not save {0} due to the marshaling failing. Your input is bad and you should feel bad.', $this->ObjectAlias)); } } + $cleanupMetaFields = []; if ($metaFieldsEnabled) { - $massagedData = $this->massageMetaFields($data, $input, $metaTemplates); + $massagedData = $this->massageMetaFields($data, $input, $metaTemplates, $cleanupMetaFields); + if (!empty($cleanupMetaFields)) { + foreach ($cleanupMetaFields as $cleanupMetaField) { + $this->Table->MetaFields->deleteAll([ + 'AND' => [ + 'scope' => $cleanupMetaField['scope'], + 'field' => $cleanupMetaField['field'], + 'meta_template_field_id' => $cleanupMetaField['meta_template_field_id'], + 'meta_template_id' => $cleanupMetaField['meta_template_id'], + 'parent_id' => $id + ] + ]); + } + } unset($input['MetaTemplates']); // Avoid MetaTemplates to be overriden when patching entity $data = $massagedData['entity']; $metaFieldsToDelete = $massagedData['metafields_to_delete']; + if (isset($input['meta_fields'])) { + unset($input['meta_fields']); + } } $data = $this->Table->patchEntity($data, $input, $patchEntityParams); if (isset($params['beforeSave'])) {