From 34ce6dec4cf690ad9b27b1a4f16253eefc39cf50 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Mon, 15 Aug 2022 14:27:41 -0400 Subject: [PATCH] Afform - Clean up structure of stored entity ids in submission record This keeps the structure of joined entities consistent with that of the main entities, which makes it eaiser to store other values as well. --- .../core/Civi/Afform/Event/AfformSubmitEvent.php | 3 ++- .../Civi/Api4/Action/Afform/AbstractProcessor.php | 11 ++++++----- ext/afform/core/Civi/Api4/Action/Afform/Submit.php | 7 ++++--- .../core/Civi/Api4/Action/Afform/SubmitFile.php | 7 ++++--- .../tests/phpunit/api/v4/AfformContactUsageTest.php | 11 ++++++++++- 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/ext/afform/core/Civi/Afform/Event/AfformSubmitEvent.php b/ext/afform/core/Civi/Afform/Event/AfformSubmitEvent.php index fa28b3b495..8107e38f3a 100644 --- a/ext/afform/core/Civi/Afform/Event/AfformSubmitEvent.php +++ b/ext/afform/core/Civi/Afform/Event/AfformSubmitEvent.php @@ -148,7 +148,8 @@ class AfformSubmitEvent extends AfformBaseEvent { * @return $this */ public function setJoinIds($index, $joinEntity, $joinIds) { - $this->entityIds[$this->entityName][$index]['joins'][$joinEntity] = $joinIds; + $idField = CoreUtil::getIdFieldName($joinEntity); + $this->entityIds[$this->entityName][$index]['_joins'][$joinEntity] = \CRM_Utils_Array::filterColumns($joinIds, [$idField]); return $this; } diff --git a/ext/afform/core/Civi/Api4/Action/Afform/AbstractProcessor.php b/ext/afform/core/Civi/Api4/Action/Afform/AbstractProcessor.php index fb58a574da..534b4d4903 100644 --- a/ext/afform/core/Civi/Api4/Action/Afform/AbstractProcessor.php +++ b/ext/afform/core/Civi/Api4/Action/Afform/AbstractProcessor.php @@ -52,7 +52,7 @@ abstract class AbstractProcessor extends \Civi\Api4\Generic\AbstractAction { * Each key in the array corresponds to the name of an entity, * and the value is an array of arrays * (because of `` all entities are treated as if they may be multi) - * E.g. $entityIds['Individual1'] = [['id' => 1, 'joins' => ['Email' => [1,2,3]]]; + * E.g. $entityIds['Individual1'] = [['id' => 1, '_joins' => ['Email' => [['id' => 1], ['id' => 2]]]; * * @var array */ @@ -117,19 +117,20 @@ abstract class AbstractProcessor extends \Civi\Api4\Generic\AbstractAction { ])->indexBy($idField); foreach ($ids as $index => $id) { $this->_entityIds[$entity['name']][$index] = [ - 'id' => isset($result[$id]) ? $id : NULL, - 'joins' => [], + $idField => isset($result[$id]) ? $id : NULL, + '_joins' => [], ]; if (isset($result[$id])) { $data = ['fields' => $result[$id]]; foreach ($entity['joins'] ?? [] as $joinEntity => $join) { + $joinIdField = CoreUtil::getIdFieldName($joinEntity); $data['joins'][$joinEntity] = (array) $api4($joinEntity, 'get', [ 'where' => self::getJoinWhereClause($this->_formDataModel, $entity['name'], $joinEntity, $id), 'limit' => !empty($join['af-repeat']) ? $join['max'] ?? 0 : 1, - 'select' => array_keys($join['fields']), + 'select' => array_unique(array_merge([$joinIdField], array_keys($join['fields']))), 'orderBy' => self::getEntityField($joinEntity, 'is_primary') ? ['is_primary' => 'DESC'] : [], ]); - $this->_entityIds[$entity['name']][$index]['joins'][$joinEntity] = array_column($data['joins'][$joinEntity], 'id'); + $this->_entityIds[$entity['name']][$index]['_joins'][$joinEntity] = \CRM_Utils_Array::filterColumns($data['joins'][$joinEntity], [$joinIdField]); } $this->_entityValues[$entity['name']][$index] = $data; } diff --git a/ext/afform/core/Civi/Api4/Action/Afform/Submit.php b/ext/afform/core/Civi/Api4/Action/Afform/Submit.php index 0120e046ae..64f802fbc8 100644 --- a/ext/afform/core/Civi/Api4/Action/Afform/Submit.php +++ b/ext/afform/core/Civi/Api4/Action/Afform/Submit.php @@ -154,9 +154,10 @@ class Submit extends AbstractProcessor { continue; } try { + $idField = CoreUtil::getIdFieldName($event->getEntityType()); $saved = $api4($event->getEntityType(), 'save', ['records' => [$record['fields']]])->first(); - $event->setEntityId($index, $saved['id']); - self::saveJoins($event, $index, $saved['id'], $record['joins'] ?? []); + $event->setEntityId($index, $saved[$idField]); + self::saveJoins($event, $index, $saved[$idField], $record['joins'] ?? []); } catch (\API_Exception $e) { // What to do here? Sometimes we should silently ignore errors, e.g. an optional entity @@ -244,7 +245,7 @@ class Submit extends AbstractProcessor { 'checkPermissions' => FALSE, 'where' => self::getJoinWhereClause($event->getFormDataModel(), $event->getEntityName(), $joinEntityName, $entityId), 'records' => $values, - ], ['id']); + ]); $indexedResult = array_combine(array_keys($values), (array) $result); $event->setJoinIds($index, $joinEntityName, $indexedResult); } diff --git a/ext/afform/core/Civi/Api4/Action/Afform/SubmitFile.php b/ext/afform/core/Civi/Api4/Action/Afform/SubmitFile.php index 5d1f975319..967720fbc2 100644 --- a/ext/afform/core/Civi/Api4/Action/Afform/SubmitFile.php +++ b/ext/afform/core/Civi/Api4/Action/Afform/SubmitFile.php @@ -68,11 +68,12 @@ class SubmitFile extends AbstractProcessor { $apiEntity = $this->joinEntity ?: $afformEntity['type']; $entityIndex = (int) $this->entityIndex; $joinIndex = (int) $this->joinIndex; + $idField = CoreUtil::getIdFieldName($apiEntity); if ($this->joinEntity) { - $entityId = $this->_entityIds[$this->modelName][$entityIndex]['joins'][$this->joinEntity][$joinIndex] ?? NULL; + $entityId = $this->_entityIds[$this->modelName][$entityIndex]['_joins'][$this->joinEntity][$joinIndex][$idField] ?? NULL; } else { - $entityId = $this->_entityIds[$this->modelName][$entityIndex]['id'] ?? NULL; + $entityId = $this->_entityIds[$this->modelName][$entityIndex][$idField] ?? NULL; } if (!$entityId) { @@ -101,7 +102,7 @@ class SubmitFile extends AbstractProcessor { if (strpos($apiEntity, 'Custom_') === 0) { civicrm_api4($apiEntity, 'update', [ 'values' => [ - 'id' => $entityId, + $idField => $entityId, $this->fieldName => $file['id'], ], ]); diff --git a/ext/afform/mock/tests/phpunit/api/v4/AfformContactUsageTest.php b/ext/afform/mock/tests/phpunit/api/v4/AfformContactUsageTest.php index 35d1c2a159..6040704ff6 100644 --- a/ext/afform/mock/tests/phpunit/api/v4/AfformContactUsageTest.php +++ b/ext/afform/mock/tests/phpunit/api/v4/AfformContactUsageTest.php @@ -294,6 +294,7 @@ EOHTML; public function testCreatingContactsWithOnlyEmail(): void { $this->useValues([ 'layout' => self::$layouts['employer'], + 'create_submission' => TRUE, 'permission' => CRM_Core_Permission::ALWAYS_ALLOW_PERMISSION, ]); @@ -331,9 +332,17 @@ EOHTML; $contact = \Civi\Api4\Contact::get() ->addWhere('display_name', '=', $individualEmail) ->addJoin('Contact AS org', 'LEFT', ['employer_id', '=', 'org.id']) - ->addSelect('display_name', 'org.display_name') + ->addSelect('display_name', 'org.display_name', 'org.id', 'email_primary') ->execute()->first(); $this->assertEquals($orgEmail, $contact['org.display_name']); + + $submission = \Civi\Api4\AfformSubmission::get(FALSE) + ->addOrderBy('id', 'DESC') + ->setLimit(1) + ->execute()->single(); + $this->assertEquals($contact['id'], $submission['data']['Individual1'][0]['id']); + $this->assertEquals($contact['org.id'], $submission['data']['Organization1'][0]['id']); + $this->assertEquals($contact['email_primary'], $submission['data']['Individual1'][0]['_joins']['Email'][0]['id']); } } -- 2.25.1