From: Coleman Watts Date: Tue, 11 May 2021 16:34:05 +0000 (-0400) Subject: APIv4 - Use bulk method for saving custom fields X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=bfa91094338f7d75e1e24ec9b1125ee4f97274cd;p=civicrm-core.git APIv4 - Use bulk method for saving custom fields Renames the prototype bulkSave => writeRecords to follow the convention now in APIv4 and CRM_Core_DAO --- diff --git a/CRM/Core/BAO/CustomField.php b/CRM/Core/BAO/CustomField.php index 323b9ce9cd..dc0a3f5cc8 100644 --- a/CRM/Core/BAO/CustomField.php +++ b/CRM/Core/BAO/CustomField.php @@ -109,11 +109,9 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField { } /** - * Create/ update several fields at once in a mysql efficient way. - * + * Save multiple fields, now deprecated in favor of self::writeRecords. * https://lab.civicrm.org/dev/core/issues/1093 - * - * The intention is that apiv4 would expose any BAO with bulkSave as a new action. + * @deprecated * * @param array $bulkParams * Array of arrays as would be passed into create @@ -123,9 +121,25 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField { * @throws \CiviCRM_API3_Exception */ public static function bulkSave($bulkParams, $defaults = []) { - $addedColumns = $sql = $customFields = $pre = $post = []; foreach ($bulkParams as $index => $fieldParams) { - $params = array_merge($defaults, $fieldParams); + $bulkParams[$index] = array_merge($defaults, $fieldParams); + } + self::writeRecords($bulkParams); + } + + /** + * Create/update several fields at once in a mysql efficient way. + * + * @param array $records + * @return CRM_Core_DAO_CustomField[] + * @throws CRM_Core_Exception + * @throws CiviCRM_API3_Exception + */ + public static function writeRecords(array $records) { + $addedColumns = $sql = $customFields = $pre = $post = []; + foreach ($records as $index => $params) { + CRM_Utils_Hook::pre(empty($params['id']) ? 'create' : 'edit', 'CustomField', $params['id'] ?? NULL, $params); + $changeSerialize = self::getChangeSerialize($params); $customField = self::createCustomFieldRecord($params); // Serialize/deserialize sql must run after/before the table is altered @@ -136,9 +150,7 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField { $post[] = self::getAlterSerializeSQL($customField); } $fieldSQL = self::getAlterFieldSQL($customField, empty($params['id']) ? 'add' : 'modify'); - if (!isset($params['custom_group_id'])) { - $params['custom_group_id'] = civicrm_api3('CustomField', 'getvalue', ['id' => $customField->id, 'return' => 'custom_group_id']); - } + $tableName = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $customField->custom_group_id, 'table_name'); $sql[$tableName][] = $fieldSQL; $addedColumns[$tableName][] = $customField->name; @@ -166,9 +178,12 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField { } CRM_Utils_System::flushCache(); + Civi::cache('metadata')->clear(); + foreach ($customFields as $index => $customField) { - CRM_Utils_Hook::post(empty($bulkParams[$index]['id']) ? 'create' : 'edit', 'CustomField', $customField->id, $customField); + CRM_Utils_Hook::post(empty($records[$index]['id']) ? 'create' : 'edit', 'CustomField', $customField->id, $customField); } + return $customFields; } /** diff --git a/Civi/Api4/Generic/Traits/DAOActionTrait.php b/Civi/Api4/Generic/Traits/DAOActionTrait.php index c06475ce8e..88d1a612cd 100644 --- a/Civi/Api4/Generic/Traits/DAOActionTrait.php +++ b/Civi/Api4/Generic/Traits/DAOActionTrait.php @@ -106,15 +106,16 @@ trait DAOActionTrait { protected function writeObjects(&$items) { $baoName = $this->getBaoName(); - // Some BAOs are weird and don't support a straightforward "create" method. - $oddballs = [ + // TODO: Opt-in more entities to use the new writeRecords BAO method. + $functionNames = [ 'Address' => 'add', + 'CustomField' => 'writeRecords', 'EntityTag' => 'add', 'GroupContact' => 'add', ]; - $method = $oddballs[$this->getEntityName()] ?? 'create'; - if (!method_exists($baoName, $method)) { - $method = method_exists($baoName, 'add') ? 'add' : FALSE; + $method = $functionNames[$this->getEntityName()] ?? NULL; + if (!isset($method)) { + $method = method_exists($baoName, 'create') ? 'create' : (method_exists($baoName, 'add') ? 'add' : 'writeRecords'); } $result = []; @@ -124,8 +125,8 @@ trait DAOActionTrait { FormattingUtil::formatWriteParams($item, $this->entityFields()); $this->formatCustomParams($item, $entityId); - // Skip to writeRecords if not using legacy method - if (!$method) { + // Skip individual processing if using writeRecords + if ($method === 'writeRecords') { continue; } $item['check_permissions'] = $this->getCheckPermissions(); @@ -156,7 +157,7 @@ trait DAOActionTrait { // Use bulk `writeRecords` method if the BAO doesn't have a create or add method // TODO: reverse this from opt-in to opt-out and default to using `writeRecords` for all BAOs - if (!$method) { + if ($method === 'writeRecords') { $items = array_values($items); foreach ($baoName::writeRecords($items) as $i => $createResult) { $result[] = $this->baoToArray($createResult, $items[$i]);