Commit | Line | Data |
---|---|---|
d84ae5f6 | 1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
775788cf | 4 | | CiviCRM version 5 | |
d84ae5f6 | 5 | +--------------------------------------------------------------------+ |
6b83d5bd | 6 | | Copyright CiviCRM LLC (c) 2004-2019 | |
d84ae5f6 | 7 | +--------------------------------------------------------------------+ |
8 | | This file is a part of CiviCRM. | | |
9 | | | | |
10 | | CiviCRM is free software; you can copy, modify, and distribute it | | |
11 | | under the terms of the GNU Affero General Public License | | |
12 | | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | | |
13 | | | | |
14 | | CiviCRM is distributed in the hope that it will be useful, but | | |
15 | | WITHOUT ANY WARRANTY; without even the implied warranty of | | |
16 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | | |
17 | | See the GNU Affero General Public License for more details. | | |
18 | | | | |
19 | | You should have received a copy of the GNU Affero General Public | | |
20 | | License and the CiviCRM Licensing Exception along | | |
21 | | with this program; if not, contact CiviCRM LLC | | |
22 | | at info[AT]civicrm[DOT]org. If you have questions about the | | |
23 | | GNU Affero General Public License or the licensing of CiviCRM, | | |
24 | | see the CiviCRM license FAQ at http://civicrm.org/licensing | | |
25 | +--------------------------------------------------------------------+ | |
26 | */ | |
27 | ||
28 | /** | |
29 | * | |
30 | * @package CRM | |
6b83d5bd | 31 | * @copyright CiviCRM LLC (c) 2004-2019 |
d84ae5f6 | 32 | */ |
d84ae5f6 | 33 | trait CRM_Core_Form_EntityFormTrait { |
d5e4784e | 34 | |
9f1073d2 MWMC |
35 | /** |
36 | * The entity subtype ID (eg. for Relationship / Activity) | |
37 | * | |
38 | * @var int | |
39 | */ | |
40 | protected $_entitySubTypeId; | |
41 | ||
d84ae5f6 | 42 | /** |
43 | * Get entity fields for the entity to be added to the form. | |
44 | * | |
d5e4784e | 45 | * @return array |
d84ae5f6 | 46 | */ |
47 | public function getEntityFields() { | |
48 | return $this->entityFields; | |
49 | } | |
50 | ||
51 | /** | |
52 | * Explicitly declare the form context. | |
53 | */ | |
54 | public function getDefaultContext() { | |
55 | return 'create'; | |
56 | } | |
57 | ||
58 | /** | |
59 | * Get entity fields for the entity to be added to the form. | |
60 | * | |
d5e4784e | 61 | * @return string |
d84ae5f6 | 62 | */ |
63 | public function getDeleteMessage() { | |
64 | return $this->deleteMessage; | |
65 | } | |
66 | ||
379d6cd7 | 67 | /** |
68 | * Set the delete message. | |
69 | * | |
70 | * We do this from the constructor in order to do a translation. | |
71 | */ | |
72 | public function setDeleteMessage() { | |
73 | } | |
74 | ||
75 | /** | |
76 | * Set entity fields to be assigned to the form. | |
77 | */ | |
78 | protected function setEntityFields() { | |
79 | } | |
80 | ||
d84ae5f6 | 81 | /** |
82 | * Get the entity id being edited. | |
83 | * | |
84 | * @return int|null | |
85 | */ | |
86 | public function getEntityId() { | |
87 | return $this->_id; | |
88 | } | |
9f1073d2 | 89 | |
f1105edc | 90 | /** |
91 | * Should custom data be suppressed on this form. | |
92 | * | |
93 | * @return bool | |
94 | */ | |
95 | protected function isSuppressCustomData() { | |
96 | return FALSE; | |
97 | } | |
98 | ||
9f1073d2 MWMC |
99 | /** |
100 | * Get the entity subtype ID being edited | |
101 | * | |
102 | * @param $subTypeId | |
103 | * | |
104 | * @return int|null | |
105 | */ | |
106 | public function getEntitySubTypeId($subTypeId) { | |
107 | if ($subTypeId) { | |
108 | return $subTypeId; | |
109 | } | |
110 | return $this->_entitySubTypeId; | |
111 | } | |
112 | ||
d84ae5f6 | 113 | /** |
114 | * If the custom data is in the submitted data (eg. added via ajax loaded form) add to form. | |
115 | */ | |
116 | public function addCustomDataToForm() { | |
f1105edc | 117 | if ($this->isSuppressCustomData()) { |
118 | return TRUE; | |
119 | } | |
d84ae5f6 | 120 | $customisableEntities = CRM_Core_SelectValues::customGroupExtends(); |
121 | if (isset($customisableEntities[$this->getDefaultEntity()])) { | |
122 | CRM_Custom_Form_CustomData::addToForm($this); | |
123 | } | |
124 | } | |
125 | ||
126 | /** | |
127 | * Build the form object. | |
128 | */ | |
129 | public function buildQuickEntityForm() { | |
59c798c9 | 130 | if ($this->isDeleteContext()) { |
d84ae5f6 | 131 | $this->buildDeleteForm(); |
132 | return; | |
133 | } | |
134 | $this->applyFilter('__ALL__', 'trim'); | |
135 | $this->addEntityFieldsToTemplate(); | |
136 | $this->assign('entityFields', $this->entityFields); | |
137 | $this->assign('entityID', $this->getEntityId()); | |
138 | $this->assign('entityInClassFormat', strtolower(str_replace('_', '-', $this->getDefaultEntity()))); | |
139 | $this->assign('entityTable', CRM_Core_DAO_AllCoreTables::getTableForClass(CRM_Core_DAO_AllCoreTables::getFullName($this->getDefaultEntity()))); | |
140 | $this->addCustomDataToForm(); | |
141 | $this->addFormButtons(); | |
48c242dc MWMC |
142 | |
143 | if ($this->isViewContext()) { | |
144 | $this->freeze(); | |
145 | } | |
d84ae5f6 | 146 | } |
147 | ||
148 | /** | |
149 | * Build the form for any deletion. | |
150 | */ | |
151 | protected function buildDeleteForm() { | |
152 | $this->assign('deleteMessage', $this->getDeleteMessage()); | |
153 | $this->addFormButtons(); | |
154 | } | |
155 | ||
156 | /** | |
157 | * Add relevant buttons to the form. | |
158 | */ | |
159 | protected function addFormButtons() { | |
48c242dc | 160 | if ($this->isViewContext() || $this->_action & CRM_Core_Action::PREVIEW) { |
be2fb01f | 161 | $this->addButtons([ |
518fa0ee SL |
162 | [ |
163 | 'type' => 'cancel', | |
164 | 'name' => ts('Done'), | |
165 | 'isDefault' => TRUE, | |
166 | ], | |
167 | ]); | |
d84ae5f6 | 168 | } |
169 | else { | |
be2fb01f | 170 | $this->addButtons([ |
518fa0ee SL |
171 | [ |
172 | 'type' => 'next', | |
173 | 'name' => $this->isDeleteContext() ? ts('Delete') : ts('Save'), | |
174 | 'isDefault' => TRUE, | |
175 | ], | |
176 | [ | |
177 | 'type' => 'cancel', | |
178 | 'name' => ts('Cancel'), | |
179 | ], | |
180 | ]); | |
d84ae5f6 | 181 | } |
182 | } | |
183 | ||
612215eb | 184 | /** |
185 | * Get the defaults for the entity. | |
186 | */ | |
187 | protected function getEntityDefaults() { | |
99e201e8 MWMC |
188 | $defaults = $moneyFields = []; |
189 | ||
48c242dc | 190 | if (!$this->isDeleteContext() && |
518fa0ee | 191 | $this->getEntityId()) { |
612215eb | 192 | $params = ['id' => $this->getEntityId()]; |
193 | $baoName = $this->_BAOName; | |
194 | $baoName::retrieve($params, $defaults); | |
195 | } | |
99e201e8 | 196 | foreach ($this->entityFields as $entityFieldName => $fieldSpec) { |
612215eb | 197 | $value = CRM_Utils_Request::retrieveValue($fieldSpec['name'], $this->getValidationTypeForField($fieldSpec['name'])); |
ea1cafad | 198 | if ($value !== FALSE && $value !== NULL) { |
612215eb | 199 | $defaults[$fieldSpec['name']] = $value; |
200 | } | |
99e201e8 | 201 | // Store a list of fields with money formatters |
48c242dc | 202 | if (CRM_Utils_Array::value('formatter', $fieldSpec) == 'crmMoney') { |
99e201e8 MWMC |
203 | $moneyFields[] = $entityFieldName; |
204 | } | |
205 | } | |
206 | if (!empty($defaults['currency'])) { | |
207 | // If we have a money formatter we need to pass the specified currency or it will render as the default | |
208 | foreach ($moneyFields as $entityFieldName) { | |
209 | $this->entityFields[$entityFieldName]['formatterParam'] = $defaults['currency']; | |
48c242dc | 210 | } |
612215eb | 211 | } |
99e201e8 | 212 | |
48c242dc MWMC |
213 | // Assign again as we may have modified above |
214 | $this->assign('entityFields', $this->entityFields); | |
612215eb | 215 | return $defaults; |
216 | } | |
217 | ||
218 | /** | |
219 | * Get the validation rule to apply to a function. | |
220 | * | |
221 | * Alphanumeric is designed to always be safe & for now we just return | |
222 | * that but in future we can use tighter rules for types like int, bool etc. | |
223 | * | |
224 | * @param string $fieldName | |
225 | * | |
226 | * @return string|int|bool | |
227 | */ | |
228 | protected function getValidationTypeForField($fieldName) { | |
229 | switch ($this->metadata[$fieldName]['type']) { | |
230 | case CRM_Utils_Type::T_BOOLEAN: | |
231 | return 'Boolean'; | |
232 | ||
233 | default: | |
234 | return 'Alphanumeric'; | |
235 | } | |
236 | } | |
237 | ||
d84ae5f6 | 238 | /** |
239 | * Set translated fields. | |
240 | * | |
241 | * This function is called from the class constructor, allowing us to set | |
242 | * fields on the class that can't be set as properties due to need for | |
243 | * translation or other non-input specific handling. | |
244 | */ | |
245 | protected function setTranslatedFields() { | |
246 | $this->setEntityFields(); | |
247 | $this->setDeleteMessage(); | |
248 | $metadata = civicrm_api3($this->getDefaultEntity(), 'getfields', ['action' => 'create']); | |
249 | $this->metadata = $metadata['values']; | |
250 | foreach ($this->metadata as $fieldName => $spec) { | |
251 | if (isset($this->entityFields[$fieldName])) { | |
252 | if ($spec['localizable']) { | |
253 | $this->entityFields[$fieldName]['is_add_translate_dialog'] = TRUE; | |
254 | } | |
255 | if (empty($spec['html'])) { | |
256 | $this->entityFields[$fieldName]['not-auto-addable'] = TRUE; | |
257 | } | |
258 | } | |
259 | } | |
260 | } | |
261 | ||
262 | /** | |
263 | * Add defined entity field to template. | |
264 | */ | |
265 | protected function addEntityFieldsToTemplate() { | |
266 | foreach ($this->getEntityFields() as $fieldSpec) { | |
267 | if (empty($fieldSpec['not-auto-addable'])) { | |
59c798c9 | 268 | $element = $this->addField($fieldSpec['name'], [], CRM_Utils_Array::value('required', $fieldSpec), FALSE); |
4d876348 | 269 | if (!empty($fieldSpec['is_freeze'])) { |
270 | $element->freeze(); | |
271 | } | |
d84ae5f6 | 272 | } |
273 | } | |
274 | } | |
275 | ||
59c798c9 | 276 | /** |
277 | * Is the form being used in the context of a deletion. | |
278 | * | |
279 | * (For some reason rather than having separate forms Civi overloads one form). | |
280 | * | |
281 | * @return bool | |
282 | */ | |
283 | protected function isDeleteContext() { | |
284 | return ($this->_action & CRM_Core_Action::DELETE); | |
285 | } | |
286 | ||
48c242dc MWMC |
287 | /** |
288 | * Is the form being used in the context of a view. | |
289 | * | |
290 | * @return bool | |
291 | */ | |
292 | protected function isViewContext() { | |
293 | return ($this->_action & CRM_Core_Action::VIEW); | |
294 | } | |
295 | ||
d5e4784e MWMC |
296 | protected function setEntityFieldsMetadata() { |
297 | foreach ($this->entityFields as $field => &$props) { | |
298 | if (!empty($props['not-auto-addable'])) { | |
299 | // We can't load this field using metadata | |
300 | continue; | |
301 | } | |
079c7954 CW |
302 | if ($field != 'id' && $this->isDeleteContext()) { |
303 | // Delete forms don't generally present any fields to edit | |
304 | continue; | |
305 | } | |
d5e4784e MWMC |
306 | // Resolve action. |
307 | if (empty($props['action'])) { | |
308 | $props['action'] = $this->getApiAction(); | |
309 | } | |
310 | $fieldSpec = civicrm_api3($this->getDefaultEntity(), 'getfield', $props); | |
311 | $fieldSpec = $fieldSpec['values']; | |
312 | if (!isset($props['description']) && isset($fieldSpec['description'])) { | |
313 | $props['description'] = $fieldSpec['description']; | |
314 | } | |
315 | } | |
316 | } | |
317 | ||
d84ae5f6 | 318 | } |