Merge pull request #14452 from eileenmcnaughton/payment_activity
[civicrm-core.git] / CRM / Core / Form / EntityFormTrait.php
CommitLineData
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 33trait 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}