Merge pull request #16629 from WeMoveEU/core-1620
[civicrm-core.git] / Civi / Api4 / Generic / AbstractSaveAction.php
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 /**
14 *
15 * @package CRM
16 * @copyright CiviCRM LLC https://civicrm.org/licensing
17 */
18
19
20 namespace Civi\Api4\Generic;
21
22 /**
23 * Base class for all `Save` api actions.
24 *
25 * @method $this setRecords(array $records) Set array of records to be saved.
26 * @method array getRecords()
27 * @method $this setDefaults(array $defaults) 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 * @package Civi\Api4\Generic
33 */
34 abstract class AbstractSaveAction extends AbstractAction {
35
36 /**
37 * Array of $ENTITIES to save.
38 *
39 * Should be in the same format as returned by `Get`.
40 *
41 * @var array
42 * @required
43 */
44 protected $records = [];
45
46 /**
47 * Array of default values.
48 *
49 * These defaults will be merged into every $ENTITY in `records` before saving.
50 * Values set in `records` will override these defaults if set in both places,
51 * but updating existing $ENTITIES will overwrite current values with these defaults.
52 *
53 * @var array
54 */
55 protected $defaults = [];
56
57 /**
58 * Reload $ENTITIES after saving.
59 *
60 * By default this action typically returns partial records containing only the fields
61 * that were updated. Set `reload` to `true` to do an additional lookup after saving
62 * to return complete values for every $ENTITY.
63 *
64 * @var bool
65 */
66 protected $reload = FALSE;
67
68 /**
69 * @var string
70 */
71 private $idField;
72
73 /**
74 * BatchAction constructor.
75 * @param string $entityName
76 * @param string $actionName
77 * @param string $idField
78 */
79 public function __construct($entityName, $actionName, $idField = 'id') {
80 // $idField should be a string but some apis (e.g. CustomValue) give us an array
81 $this->idField = array_values((array) $idField)[0];
82 parent::__construct($entityName, $actionName);
83 }
84
85 /**
86 * @throws \API_Exception
87 */
88 protected function validateValues() {
89 $unmatched = [];
90 foreach ($this->records as $record) {
91 if (empty($record[$this->idField])) {
92 $unmatched = array_unique(array_merge($unmatched, $this->checkRequiredFields($record)));
93 }
94 }
95 if ($unmatched) {
96 throw new \API_Exception("Mandatory values missing from Api4 {$this->getEntityName()}::{$this->getActionName()}: " . implode(", ", $unmatched), "mandatory_missing", ["fields" => $unmatched]);
97 }
98 }
99
100 /**
101 * @return string
102 */
103 protected function getIdField() {
104 return $this->idField;
105 }
106
107 /**
108 * Add one or more records to be saved.
109 * @param array ...$records
110 * @return $this
111 */
112 public function addRecord(array ...$records) {
113 $this->records = array_merge($this->records, $records);
114 return $this;
115 }
116
117 /**
118 * Set default value for a field.
119 * @param string $fieldName
120 * @param mixed $defaultValue
121 * @return $this
122 */
123 public function addDefault(string $fieldName, $defaultValue) {
124 $this->defaults[$fieldName] = $defaultValue;
125 return $this;
126 }
127
128 }