3 +--------------------------------------------------------------------+
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2019
34 trait CRM_Core_Form_EntityFormTrait
{
37 * The entity subtype ID (eg. for Relationship / Activity)
41 protected $_entitySubTypeId;
44 * Get entity fields for the entity to be added to the form.
48 public function getEntityFields() {
49 return $this->entityFields
;
53 * Explicitly declare the form context.
55 public function getDefaultContext() {
60 * Get entity fields for the entity to be added to the form.
64 public function getDeleteMessage() {
65 return $this->deleteMessage
;
69 * Get the entity id being edited.
73 public function getEntityId() {
78 * Get the entity subtype ID being edited
84 public function getEntitySubTypeId($subTypeId) {
88 return $this->_entitySubTypeId
;
92 * If the custom data is in the submitted data (eg. added via ajax loaded form) add to form.
94 public function addCustomDataToForm() {
95 $customisableEntities = CRM_Core_SelectValues
::customGroupExtends();
96 if (isset($customisableEntities[$this->getDefaultEntity()])) {
97 CRM_Custom_Form_CustomData
::addToForm($this);
102 * Build the form object.
104 public function buildQuickEntityForm() {
105 if ($this->isDeleteContext()) {
106 $this->buildDeleteForm();
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();
118 if ($this->isViewContext()) {
124 * Build the form for any deletion.
126 protected function buildDeleteForm() {
127 $this->assign('deleteMessage', $this->getDeleteMessage());
128 $this->addFormButtons();
132 * Add relevant buttons to the form.
134 protected function addFormButtons() {
135 if ($this->isViewContext() ||
$this->_action
& CRM_Core_Action
::PREVIEW
) {
136 $this->addButtons(array(
139 'name' => ts('Done'),
146 $this->addButtons(array(
149 'name' => $this->isDeleteContext() ?
ts('Delete') : ts('Save'),
154 'name' => ts('Cancel'),
162 * Get the defaults for the entity.
164 protected function getEntityDefaults() {
165 $defaults = $moneyFields = [];
167 if (!$this->isDeleteContext() &&
170 $params = ['id' => $this->getEntityId()];
171 $baoName = $this->_BAOName
;
172 $baoName::retrieve($params, $defaults);
174 foreach ($this->entityFields
as $entityFieldName => $fieldSpec) {
175 $value = CRM_Utils_Request
::retrieveValue($fieldSpec['name'], $this->getValidationTypeForField($fieldSpec['name']));
176 if ($value !== FALSE && $value !== NULL) {
177 $defaults[$fieldSpec['name']] = $value;
179 // Store a list of fields with money formatters
180 if (CRM_Utils_Array
::value('formatter', $fieldSpec) == 'crmMoney') {
181 $moneyFields[] = $entityFieldName;
184 if (!empty($defaults['currency'])) {
185 // If we have a money formatter we need to pass the specified currency or it will render as the default
186 foreach ($moneyFields as $entityFieldName) {
187 $this->entityFields
[$entityFieldName]['formatterParam'] = $defaults['currency'];
191 // Assign again as we may have modified above
192 $this->assign('entityFields', $this->entityFields
);
197 * Get the validation rule to apply to a function.
199 * Alphanumeric is designed to always be safe & for now we just return
200 * that but in future we can use tighter rules for types like int, bool etc.
202 * @param string $fieldName
204 * @return string|int|bool
206 protected function getValidationTypeForField($fieldName) {
207 switch ($this->metadata
[$fieldName]['type']) {
208 case CRM_Utils_Type
::T_BOOLEAN
:
212 return 'Alphanumeric';
217 * Set translated fields.
219 * This function is called from the class constructor, allowing us to set
220 * fields on the class that can't be set as properties due to need for
221 * translation or other non-input specific handling.
223 protected function setTranslatedFields() {
224 $this->setEntityFields();
225 $this->setDeleteMessage();
226 $metadata = civicrm_api3($this->getDefaultEntity(), 'getfields', ['action' => 'create']);
227 $this->metadata
= $metadata['values'];
228 foreach ($this->metadata
as $fieldName => $spec) {
229 if (isset($this->entityFields
[$fieldName])) {
230 if ($spec['localizable']) {
231 $this->entityFields
[$fieldName]['is_add_translate_dialog'] = TRUE;
233 if (empty($spec['html'])) {
234 $this->entityFields
[$fieldName]['not-auto-addable'] = TRUE;
241 * Add defined entity field to template.
243 protected function addEntityFieldsToTemplate() {
244 foreach ($this->getEntityFields() as $fieldSpec) {
245 if (empty($fieldSpec['not-auto-addable'])) {
246 $element = $this->addField($fieldSpec['name'], [], CRM_Utils_Array
::value('required', $fieldSpec), FALSE);
247 if (!empty($fieldSpec['is_freeze'])) {
255 * Is the form being used in the context of a deletion.
257 * (For some reason rather than having separate forms Civi overloads one form).
261 protected function isDeleteContext() {
262 return ($this->_action
& CRM_Core_Action
::DELETE
);
266 * Is the form being used in the context of a view.
270 protected function isViewContext() {
271 return ($this->_action
& CRM_Core_Action
::VIEW
);
274 protected function setEntityFieldsMetadata() {
275 foreach ($this->entityFields
as $field => &$props) {
276 if (!empty($props['not-auto-addable'])) {
277 // We can't load this field using metadata
280 if ($field != 'id' && $this->isDeleteContext()) {
281 // Delete forms don't generally present any fields to edit
285 if (empty($props['action'])) {
286 $props['action'] = $this->getApiAction();
288 $fieldSpec = civicrm_api3($this->getDefaultEntity(), 'getfield', $props);
289 $fieldSpec = $fieldSpec['values'];
290 if (!isset($props['description']) && isset($fieldSpec['description'])) {
291 $props['description'] = $fieldSpec['description'];