| 1 | <?php |
| 2 | |
| 3 | /* |
| 4 | +--------------------------------------------------------------------+ |
| 5 | | Copyright CiviCRM LLC. All rights reserved. | |
| 6 | | | |
| 7 | | This work is published under the GNU AGPLv3 license with some | |
| 8 | | permitted exceptions and without any warranty. For full license | |
| 9 | | and copyright information, see https://civicrm.org/licensing | |
| 10 | +--------------------------------------------------------------------+ |
| 11 | */ |
| 12 | |
| 13 | namespace Civi\Api4\Generic; |
| 14 | |
| 15 | /** |
| 16 | * Replaces an existing set of $ENTITIES with a new one. |
| 17 | * |
| 18 | * This will select a group of existing $ENTITIES based on the `where` parameter. |
| 19 | * Each will be compared with the $ENTITIES passed in as `records`: |
| 20 | * |
| 21 | * - $ENTITIES in `records` that don't already exist will be created. |
| 22 | * - Existing $ENTITIES that are included in `records` will be updated. |
| 23 | * - Existing $ENTITIES that are omitted from `records` will be deleted. |
| 24 | * |
| 25 | * @method $this setRecords(array $records) Set array of records. |
| 26 | * @method array getRecords() |
| 27 | * @method $this setDefaults(array $defaults) Set array of defaults. |
| 28 | * @method array getDefaults() |
| 29 | * @method $this setReload(bool $reload) Specify whether complete objects will be returned after saving. |
| 30 | * @method bool getReload() |
| 31 | */ |
| 32 | class BasicReplaceAction extends AbstractBatchAction { |
| 33 | |
| 34 | /** |
| 35 | * Array of $ENTITY records. |
| 36 | * |
| 37 | * Should be in the same format as returned by `Get`. |
| 38 | * |
| 39 | * @var array |
| 40 | * @required |
| 41 | */ |
| 42 | protected $records = []; |
| 43 | |
| 44 | /** |
| 45 | * Array of default values. |
| 46 | * |
| 47 | * These defaults will be merged into every $ENTITY in `records` before saving. |
| 48 | * Values set in `records` will override these defaults if set in both places, |
| 49 | * but updating existing $ENTITIES will overwrite current values with these defaults. |
| 50 | * |
| 51 | * **Note:** Values from the `where` clause that use the `=` operator are _also_ treated as default values; |
| 52 | * those do not need to be repeated here. |
| 53 | * |
| 54 | * @var array |
| 55 | */ |
| 56 | protected $defaults = []; |
| 57 | |
| 58 | /** |
| 59 | * Reload $ENTITIES after saving. |
| 60 | * |
| 61 | * By default this action typically returns partial records containing only the fields |
| 62 | * that were updated. Set `reload` to `true` to do an additional lookup after saving |
| 63 | * to return complete values for every $ENTITY. |
| 64 | * |
| 65 | * @var bool |
| 66 | */ |
| 67 | protected $reload = FALSE; |
| 68 | |
| 69 | /** |
| 70 | * @return \Civi\Api4\Result\ReplaceResult |
| 71 | */ |
| 72 | public function execute() { |
| 73 | return parent::execute(); |
| 74 | } |
| 75 | |
| 76 | /** |
| 77 | * @inheritDoc |
| 78 | */ |
| 79 | public function _run(Result $result) { |
| 80 | $items = $this->getBatchRecords(); |
| 81 | |
| 82 | // Copy defaults from where clause if the operator is = |
| 83 | foreach ($this->where as $clause) { |
| 84 | if (is_array($clause) && $clause[1] === '=') { |
| 85 | $this->defaults[$clause[0]] = $clause[2]; |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | $idField = $this->getSelect()[0]; |
| 90 | $toDelete = array_diff_key(array_column($items, NULL, $idField), array_flip(array_filter(\CRM_Utils_Array::collect($idField, $this->records)))); |
| 91 | |
| 92 | $saveAction = \Civi\API\Request::create($this->getEntityName(), 'save', ['version' => 4]); |
| 93 | $saveAction |
| 94 | ->setCheckPermissions($this->getCheckPermissions()) |
| 95 | ->setReload($this->reload) |
| 96 | ->setRecords($this->records) |
| 97 | ->setDefaults($this->defaults); |
| 98 | $result->exchangeArray((array) $saveAction->execute()); |
| 99 | |
| 100 | if ($toDelete) { |
| 101 | $result->deleted = (array) civicrm_api4($this->getEntityName(), 'delete', [ |
| 102 | 'where' => [[$idField, 'IN', array_keys($toDelete)]], |
| 103 | 'checkPermissions' => $this->getCheckPermissions(), |
| 104 | ]); |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | /** |
| 109 | * Set default value for a field. |
| 110 | * @param string $fieldName |
| 111 | * @param mixed $defaultValue |
| 112 | * @return $this |
| 113 | */ |
| 114 | public function addDefault(string $fieldName, $defaultValue) { |
| 115 | $this->defaults[$fieldName] = $defaultValue; |
| 116 | return $this; |
| 117 | } |
| 118 | |
| 119 | /** |
| 120 | * Add one or more records |
| 121 | * @param array ...$records |
| 122 | * @return $this |
| 123 | */ |
| 124 | public function addRecord(array ...$records) { |
| 125 | $this->records = array_merge($this->records, $records); |
| 126 | return $this; |
| 127 | } |
| 128 | |
| 129 | } |