Merge pull request #16149 from seamuslee001/dev_core_1489
[civicrm-core.git] / Civi / Api4 / Generic / BasicGetFieldsAction.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 * $Id$
18 *
19 */
20
21
22 namespace Civi\Api4\Generic;
23
24 use Civi\API\Exception\NotImplementedException;
25 use Civi\Api4\Utils\ActionUtil;
26
27 /**
28 * Get fields for an entity.
29 *
30 * @method $this setLoadOptions(bool $value)
31 * @method bool getLoadOptions()
32 * @method $this setAction(string $value)
33 * @method $this addValue(string $value)
34 * @method $this setValues(array $values)
35 * @method array getValues()
36 */
37 class BasicGetFieldsAction extends BasicGetAction {
38
39 /**
40 * Fetch option lists for fields?
41 *
42 * @var bool
43 */
44 protected $loadOptions = FALSE;
45
46 /**
47 * Fields will be returned appropriate to the specified action (get, create, delete, etc.)
48 *
49 * @var string
50 */
51 protected $action = 'get';
52
53 /**
54 * Fields will be returned appropriate to the specified values (e.g. ['contact_type' => 'Individual'])
55 *
56 * @var array
57 */
58 protected $values = [];
59
60 /**
61 * To implement getFields for your own entity:
62 *
63 * 1. From your entity class add a static getFields method.
64 * 2. That method should construct and return this class.
65 * 3. The 3rd argument passed to this constructor should be a function that returns an
66 * array of fields for your entity's CRUD actions.
67 * 4. For non-crud actions that need a different set of fields, you can override the
68 * list from step 3 on a per-action basis by defining a fields() method in that action.
69 * See for example BasicGetFieldsAction::fields() or GetActions::fields().
70 *
71 * @param Result $result
72 * @throws \Civi\API\Exception\NotImplementedException
73 */
74 public function _run(Result $result) {
75 try {
76 $actionClass = ActionUtil::getAction($this->getEntityName(), $this->getAction());
77 }
78 catch (NotImplementedException $e) {
79 }
80 if (isset($actionClass) && method_exists($actionClass, 'fields')) {
81 $values = $actionClass->fields();
82 }
83 else {
84 $values = $this->getRecords();
85 }
86 $this->padResults($values);
87 $result->exchangeArray($this->queryArray($values));
88 }
89
90 /**
91 * Ensure every result contains, at minimum, the array keys as defined in $this->fields.
92 *
93 * Attempt to set some sensible defaults for some fields.
94 *
95 * In most cases it's not necessary to override this function, even if your entity is really weird.
96 * Instead just override $this->fields and thes function will respect that.
97 *
98 * @param array $values
99 */
100 protected function padResults(&$values) {
101 $fields = array_column($this->fields(), 'name');
102 foreach ($values as &$field) {
103 $defaults = array_intersect_key([
104 'title' => empty($field['name']) ? NULL : ucwords(str_replace('_', ' ', $field['name'])),
105 'entity' => $this->getEntityName(),
106 'required' => FALSE,
107 'options' => !empty($field['pseudoconstant']),
108 'data_type' => \CRM_Utils_Array::value('type', $field, 'String'),
109 ], array_flip($fields));
110 $field += $defaults;
111 if (!$this->loadOptions && isset($defaults['options'])) {
112 $field['options'] = (bool) $field['options'];
113 }
114 $field += array_fill_keys($fields, NULL);
115 }
116 }
117
118 /**
119 * @return string
120 */
121 public function getAction() {
122 // For actions that build on top of other actions, return fields for the simpler action
123 $sub = [
124 'save' => 'create',
125 'replace' => 'create',
126 ];
127 return $sub[$this->action] ?? $this->action;
128 }
129
130 public function fields() {
131 return [
132 [
133 'name' => 'name',
134 'data_type' => 'String',
135 ],
136 [
137 'name' => 'title',
138 'data_type' => 'String',
139 ],
140 [
141 'name' => 'description',
142 'data_type' => 'String',
143 ],
144 [
145 'name' => 'default_value',
146 'data_type' => 'String',
147 ],
148 [
149 'name' => 'required',
150 'data_type' => 'Boolean',
151 ],
152 [
153 'name' => 'required_if',
154 'data_type' => 'String',
155 ],
156 [
157 'name' => 'options',
158 'data_type' => 'Array',
159 ],
160 [
161 'name' => 'data_type',
162 'data_type' => 'String',
163 ],
164 [
165 'name' => 'input_type',
166 'data_type' => 'String',
167 ],
168 [
169 'name' => 'input_attrs',
170 'data_type' => 'Array',
171 ],
172 [
173 'name' => 'fk_entity',
174 'data_type' => 'String',
175 ],
176 [
177 'name' => 'serialize',
178 'data_type' => 'Integer',
179 ],
180 [
181 'name' => 'entity',
182 'data_type' => 'String',
183 ],
184 ];
185 }
186
187 }