Merge pull request #13291 from eileenmcnaughton/process_default_active
[civicrm-core.git] / CRM / Core / Form / EntityFormTrait.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
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
31 * @copyright CiviCRM LLC (c) 2004-2019
32 */
33
34 trait CRM_Core_Form_EntityFormTrait {
35
36 /**
37 * The entity subtype ID (eg. for Relationship / Activity)
38 *
39 * @var int
40 */
41 protected $_entitySubTypeId;
42
43 /**
44 * Get entity fields for the entity to be added to the form.
45 *
46 * @return array
47 */
48 public function getEntityFields() {
49 return $this->entityFields;
50 }
51
52 /**
53 * Explicitly declare the form context.
54 */
55 public function getDefaultContext() {
56 return 'create';
57 }
58
59 /**
60 * Get entity fields for the entity to be added to the form.
61 *
62 * @return string
63 */
64 public function getDeleteMessage() {
65 return $this->deleteMessage;
66 }
67
68 /**
69 * Get the entity id being edited.
70 *
71 * @return int|null
72 */
73 public function getEntityId() {
74 return $this->_id;
75 }
76
77 /**
78 * Get the entity subtype ID being edited
79 *
80 * @param $subTypeId
81 *
82 * @return int|null
83 */
84 public function getEntitySubTypeId($subTypeId) {
85 if ($subTypeId) {
86 return $subTypeId;
87 }
88 return $this->_entitySubTypeId;
89 }
90
91 /**
92 * If the custom data is in the submitted data (eg. added via ajax loaded form) add to form.
93 */
94 public function addCustomDataToForm() {
95 $customisableEntities = CRM_Core_SelectValues::customGroupExtends();
96 if (isset($customisableEntities[$this->getDefaultEntity()])) {
97 CRM_Custom_Form_CustomData::addToForm($this);
98 }
99 }
100
101 /**
102 * Build the form object.
103 */
104 public function buildQuickEntityForm() {
105 if ($this->isDeleteContext()) {
106 $this->buildDeleteForm();
107 return;
108 }
109 $this->applyFilter('__ALL__', 'trim');
110 $this->addEntityFieldsToTemplate();
111 $this->assign('entityFields', $this->entityFields);
112 $this->assign('entityID', $this->getEntityId());
113 $this->assign('entityInClassFormat', strtolower(str_replace('_', '-', $this->getDefaultEntity())));
114 $this->assign('entityTable', CRM_Core_DAO_AllCoreTables::getTableForClass(CRM_Core_DAO_AllCoreTables::getFullName($this->getDefaultEntity())));
115 $this->addCustomDataToForm();
116 $this->addFormButtons();
117 }
118
119 /**
120 * Build the form for any deletion.
121 */
122 protected function buildDeleteForm() {
123 $this->assign('deleteMessage', $this->getDeleteMessage());
124 $this->addFormButtons();
125 }
126
127 /**
128 * Add relevant buttons to the form.
129 */
130 protected function addFormButtons() {
131 if ($this->_action & CRM_Core_Action::VIEW || $this->_action & CRM_Core_Action::PREVIEW) {
132 $this->addButtons(array(
133 array(
134 'type' => 'cancel',
135 'name' => ts('Done'),
136 'isDefault' => TRUE,
137 ),
138 )
139 );
140 }
141 else {
142 $this->addButtons(array(
143 array(
144 'type' => 'next',
145 'name' => $this->_action & CRM_Core_Action::DELETE ? ts('Delete') : ts('Save'),
146 'isDefault' => TRUE,
147 ),
148 array(
149 'type' => 'cancel',
150 'name' => ts('Cancel'),
151 ),
152 )
153 );
154 }
155 }
156
157 /**
158 * Get the defaults for the entity.
159 */
160 protected function getEntityDefaults() {
161 $defaults = [];
162 if ($this->_action != CRM_Core_Action::DELETE &&
163 $this->getEntityId()
164 ) {
165 $params = ['id' => $this->getEntityId()];
166 $baoName = $this->_BAOName;
167 $baoName::retrieve($params, $defaults);
168 }
169 foreach ($this->entityFields as $fieldSpec) {
170 $value = CRM_Utils_Request::retrieveValue($fieldSpec['name'], $this->getValidationTypeForField($fieldSpec['name']));
171 if ($value !== FALSE && $value !== NULL) {
172 $defaults[$fieldSpec['name']] = $value;
173 }
174 }
175 return $defaults;
176 }
177
178 /**
179 * Get the validation rule to apply to a function.
180 *
181 * Alphanumeric is designed to always be safe & for now we just return
182 * that but in future we can use tighter rules for types like int, bool etc.
183 *
184 * @param string $fieldName
185 *
186 * @return string|int|bool
187 */
188 protected function getValidationTypeForField($fieldName) {
189 switch ($this->metadata[$fieldName]['type']) {
190 case CRM_Utils_Type::T_BOOLEAN:
191 return 'Boolean';
192
193 default:
194 return 'Alphanumeric';
195 }
196 }
197
198 /**
199 * Set translated fields.
200 *
201 * This function is called from the class constructor, allowing us to set
202 * fields on the class that can't be set as properties due to need for
203 * translation or other non-input specific handling.
204 */
205 protected function setTranslatedFields() {
206 $this->setEntityFields();
207 $this->setDeleteMessage();
208 $metadata = civicrm_api3($this->getDefaultEntity(), 'getfields', ['action' => 'create']);
209 $this->metadata = $metadata['values'];
210 foreach ($this->metadata as $fieldName => $spec) {
211 if (isset($this->entityFields[$fieldName])) {
212 if ($spec['localizable']) {
213 $this->entityFields[$fieldName]['is_add_translate_dialog'] = TRUE;
214 }
215 if (empty($spec['html'])) {
216 $this->entityFields[$fieldName]['not-auto-addable'] = TRUE;
217 }
218 }
219 }
220 }
221
222 /**
223 * Add defined entity field to template.
224 */
225 protected function addEntityFieldsToTemplate() {
226 foreach ($this->getEntityFields() as $fieldSpec) {
227 if (empty($fieldSpec['not-auto-addable'])) {
228 $element = $this->addField($fieldSpec['name'], [], CRM_Utils_Array::value('required', $fieldSpec), FALSE);
229 if (!empty($fieldSpec['is_freeze'])) {
230 $element->freeze();
231 }
232 }
233 }
234 }
235
236 /**
237 * Is the form being used in the context of a deletion.
238 *
239 * (For some reason rather than having separate forms Civi overloads one form).
240 *
241 * @return bool
242 */
243 protected function isDeleteContext() {
244 return ($this->_action & CRM_Core_Action::DELETE);
245 }
246
247 protected function setEntityFieldsMetadata() {
248 foreach ($this->entityFields as $field => &$props) {
249 if (!empty($props['not-auto-addable'])) {
250 // We can't load this field using metadata
251 continue;
252 }
253 // Resolve action.
254 if (empty($props['action'])) {
255 $props['action'] = $this->getApiAction();
256 }
257 $fieldSpec = civicrm_api3($this->getDefaultEntity(), 'getfield', $props);
258 $fieldSpec = $fieldSpec['values'];
259 if (!isset($props['description']) && isset($fieldSpec['description'])) {
260 $props['description'] = $fieldSpec['description'];
261 }
262 }
263 }
264
265 }