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