*
* @package CRM
* @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
*/
namespace Civi\Api4\Generic;
-use Civi\API\Exception\NotImplementedException;
-use Civi\Api4\Utils\ActionUtil;
-
/**
- * Given a set of records, will appropriately update the database.
+ * Replaces an existing set of $ENTITIES with a new one.
+ *
+ * This will select a group of existing $ENTITIES based on the `where` parameter.
+ * Each will be compared with the $ENTITIES passed in as `records`:
+ *
+ * - $ENTITIES in `records` that don't already exist will be created.
+ * - Existing $ENTITIES that are included in `records` will be updated.
+ * - Existing $ENTITIES that are omitted from `records` will be deleted.
*
- * @method $this setRecords(array $records) Array of records.
+ * @method $this setRecords(array $records) Set array of records.
* @method array getRecords()
- * @method $this setDefaults(array $defaults) Array of defaults.
+ * @method $this setDefaults(array $defaults) Set array of defaults.
* @method array getDefaults()
* @method $this setReload(bool $reload) Specify whether complete objects will be returned after saving.
* @method bool getReload()
class BasicReplaceAction extends AbstractBatchAction {
/**
- * Array of records.
+ * Array of $ENTITY records.
*
- * Should be in the same format as returned by Get.
+ * Should be in the same format as returned by `Get`.
*
* @var array
* @required
/**
* Array of default values.
*
- * Will be merged into $records before saving.
+ * These defaults will be merged into every $ENTITY in `records` before saving.
+ * Values set in `records` will override these defaults if set in both places,
+ * but updating existing $ENTITIES will overwrite current values with these defaults.
+ *
+ * **Note:** Values from the `where` clause that use the `=` operator are _also_ treated as default values;
+ * those do not need to be repeated here.
*
* @var array
*/
protected $defaults = [];
/**
- * Reload records after saving.
+ * Reload $ENTITIES after saving.
*
- * By default this api typically returns partial records containing only the fields
- * that were updated. Set reload to TRUE to do an additional lookup after saving
- * to return complete records.
+ * By default this action typically returns partial records containing only the fields
+ * that were updated. Set `reload` to `true` to do an additional lookup after saving
+ * to return complete values for every $ENTITY.
*
* @var bool
*/
$idField = $this->getSelect()[0];
$toDelete = array_diff_key(array_column($items, NULL, $idField), array_flip(array_filter(\CRM_Utils_Array::collect($idField, $this->records))));
- // Try to delegate to the Save action
- try {
- $saveAction = ActionUtil::getAction($this->getEntityName(), 'save');
- $saveAction
- ->setCheckPermissions($this->getCheckPermissions())
- ->setReload($this->reload)
- ->setRecords($this->records)
- ->setDefaults($this->defaults);
- $result->exchangeArray((array) $saveAction->execute());
- }
- // Fall back on Create/Update if Save doesn't exist
- catch (NotImplementedException $e) {
- foreach ($this->records as $record) {
- $record += $this->defaults;
- if (!empty($record[$idField])) {
- $result[] = civicrm_api4($this->getEntityName(), 'update', [
- 'reload' => $this->reload,
- 'where' => [[$idField, '=', $record[$idField]]],
- 'values' => $record,
- 'checkPermissions' => $this->getCheckPermissions(),
- ])->first();
- }
- else {
- $result[] = civicrm_api4($this->getEntityName(), 'create', [
- 'values' => $record,
- 'checkPermissions' => $this->getCheckPermissions(),
- ])->first();
- }
- }
- }
+ $saveAction = \Civi\API\Request::create($this->getEntityName(), 'save', ['version' => 4]);
+ $saveAction
+ ->setCheckPermissions($this->getCheckPermissions())
+ ->setReload($this->reload)
+ ->setRecords($this->records)
+ ->setDefaults($this->defaults);
+ $result->exchangeArray((array) $saveAction->execute());
if ($toDelete) {
$result->deleted = (array) civicrm_api4($this->getEntityName(), 'delete', [