From e2f66e4815f9ac1d78f456cd55fb11a5713c615f Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Sun, 7 Aug 2022 17:50:50 -0400 Subject: [PATCH] Afform - Ensure correct existing email,phone,address is chosen to update, and prevent deletion of other records when updating a single one (primary or by location type). --- .../Api4/Action/Afform/AbstractProcessor.php | 28 +++++++++++++------ .../core/Civi/Api4/Action/Afform/Submit.php | 4 +-- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/ext/afform/core/Civi/Api4/Action/Afform/AbstractProcessor.php b/ext/afform/core/Civi/Api4/Action/Afform/AbstractProcessor.php index 3fcde4e9c4..870254d1c1 100644 --- a/ext/afform/core/Civi/Api4/Action/Afform/AbstractProcessor.php +++ b/ext/afform/core/Civi/Api4/Action/Afform/AbstractProcessor.php @@ -103,7 +103,7 @@ abstract class AbstractProcessor extends \Civi\Api4\Generic\AbstractAction { $data = ['fields' => $result[$id]]; foreach ($entity['joins'] ?? [] as $joinEntity => $join) { $data['joins'][$joinEntity] = (array) $api4($joinEntity, 'get', [ - 'where' => self::getJoinWhereClause($entity['type'], $joinEntity, $id), + 'where' => self::getJoinWhereClause($this->_formDataModel, $entity['name'], $joinEntity, $id), 'limit' => !empty($join['af-repeat']) ? $join['max'] ?? 0 : 1, 'select' => array_keys($join['fields']), 'orderBy' => self::getEntityField($joinEntity, 'is_primary') ? ['is_primary' => 'DESC'] : [], @@ -139,22 +139,32 @@ abstract class AbstractProcessor extends \Civi\Api4\Generic\AbstractAction { abstract protected function processForm(); /** - * @param $mainEntityName - * @param $joinEntityName - * @param $mainEntityId + * @param \Civi\Afform\FormDataModel $formDataModel + * @param string $mainEntityName + * @param string $joinEntityType + * @param int|string $mainEntityId * @return array * @throws \API_Exception */ - protected static function getJoinWhereClause($mainEntityName, $joinEntityName, $mainEntityId) { + protected static function getJoinWhereClause(FormDataModel $formDataModel, string $mainEntityName, string $joinEntityType, $mainEntityId) { + $entity = $formDataModel->getEntity($mainEntityName); + $mainEntityType = $entity['type']; $params = []; - if (self::getEntityField($joinEntityName, 'entity_id')) { + + // Add data as clauses e.g. `is_primary: true` + foreach ($entity['joins'][$joinEntityType]['data'] ?? [] as $key => $val) { + $params[] = [$key, '=', $val]; + } + + // Figure out the FK field between the join entity and the main entity + if (self::getEntityField($joinEntityType, 'entity_id')) { $params[] = ['entity_id', '=', $mainEntityId]; - if (self::getEntityField($joinEntityName, 'entity_table')) { - $params[] = ['entity_table', '=', CoreUtil::getTableName($mainEntityName)]; + if (self::getEntityField($joinEntityType, 'entity_table')) { + $params[] = ['entity_table', '=', CoreUtil::getTableName($mainEntityType)]; } } else { - $mainEntityField = \CRM_Core_DAO_AllCoreTables::convertEntityNameToLower($mainEntityName) . '_id'; + $mainEntityField = \CRM_Core_DAO_AllCoreTables::convertEntityNameToLower($mainEntityType) . '_id'; $params[] = [$mainEntityField, '=', $mainEntityId]; } return $params; diff --git a/ext/afform/core/Civi/Api4/Action/Afform/Submit.php b/ext/afform/core/Civi/Api4/Action/Afform/Submit.php index 3e453c52ea..0120e046ae 100644 --- a/ext/afform/core/Civi/Api4/Action/Afform/Submit.php +++ b/ext/afform/core/Civi/Api4/Action/Afform/Submit.php @@ -242,7 +242,7 @@ class Submit extends AbstractProcessor { $result = civicrm_api4($joinEntityName, 'replace', [ // Disable permission checks because the main entity has already been vetted 'checkPermissions' => FALSE, - 'where' => self::getJoinWhereClause($event->getEntityType(), $joinEntityName, $entityId), + 'where' => self::getJoinWhereClause($event->getFormDataModel(), $event->getEntityName(), $joinEntityName, $entityId), 'records' => $values, ], ['id']); $indexedResult = array_combine(array_keys($values), (array) $result); @@ -254,7 +254,7 @@ class Submit extends AbstractProcessor { civicrm_api4($joinEntityName, 'delete', [ // Disable permission checks because the main entity has already been vetted 'checkPermissions' => FALSE, - 'where' => self::getJoinWhereClause($event->getEntityType(), $joinEntityName, $entityId), + 'where' => self::getJoinWhereClause($event->getFormDataModel(), $event->getEntityName(), $joinEntityName, $entityId), ]); } catch (\API_Exception $e) { -- 2.25.1