Merge pull request #4607 from samuelsov/CRM-15637
[civicrm-core.git] / CRM / Custom / Form / Option.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
39de6fd5 4 | CiviCRM version 4.6 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
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
06b69b18 31 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
32 * $Id$
33 *
34 */
35
36/**
37 * form to process actions on the field aspect of Custom
38 */
39class CRM_Custom_Form_Option extends CRM_Core_Form {
40
41 /**
100fef9d 42 * The custom field id saved to the session for an update
6a488035
TO
43 *
44 * @var int
6a488035
TO
45 */
46 protected $_fid;
47
48 /**
100fef9d 49 * The custom group id saved to the session for an update
6a488035
TO
50 *
51 * @var int
6a488035
TO
52 */
53 protected $_gid;
54
55 /**
56 * The option group ID
57 */
58 protected $_optionGroupID = NULL;
59
60 /**
61 * The Option id, used when editing the Option
62 *
63 * @var int
6a488035
TO
64 */
65 protected $_id;
66
67 /**
100fef9d 68 * Set variables up before form is built
6a488035
TO
69 *
70 * @param null
71 *
72 * @return void
6a488035
TO
73 */
74 public function preProcess() {
75 $this->_fid = CRM_Utils_Request::retrieve('fid', 'Positive', $this);
76
77 $this->_gid = CRM_Utils_Request::retrieve('gid', 'Positive', $this);
d06700a7 78
6a488035 79 if (!isset($this->_gid) && $this->_fid) {
7688c6be
DL
80 $this->_gid = CRM_Core_DAO::getFieldValue(
81 'CRM_Core_DAO_CustomField',
6a488035
TO
82 $this->_fid,
83 'custom_group_id'
84 );
85 }
7688c6be 86
6a488035 87 if ($this->_fid) {
7688c6be
DL
88 $this->_optionGroupID = CRM_Core_DAO::getFieldValue(
89 'CRM_Core_DAO_CustomField',
6a488035
TO
90 $this->_fid,
91 'option_group_id'
92 );
93 }
94
7688c6be
DL
95 if ($isReserved = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $this->_gid, 'is_reserved', 'id')) {
96 CRM_Core_Error::fatal("You cannot add or edit muliple choice options in a reserved custom field-set.");
97 }
98
6a488035
TO
99 $this->_id = CRM_Utils_Request::retrieve('id', 'Positive', $this);
100 }
101
102 /**
c490a46a 103 * Set default values for the form. Note that in edit/view mode
6a488035
TO
104 * the default values are retrieved from the database
105 *
106 * @param null
107 *
108 * @return array array of default values
6a488035 109 */
00be9182 110 public function setDefaultValues() {
6a488035
TO
111 $defaults = $fieldDefaults = array();
112 if (isset($this->_id)) {
113 $params = array('id' => $this->_id);
114 CRM_Core_BAO_CustomOption::retrieve($params, $defaults);
115
116 $paramsField = array('id' => $this->_fid);
117 CRM_Core_BAO_CustomField::retrieve($paramsField, $fieldDefaults);
118
119 if ($fieldDefaults['html_type'] == 'CheckBox'
120 || $fieldDefaults['html_type'] == 'Multi-Select'
121 || $fieldDefaults['html_type'] == 'AdvMulti-Select'
122 ) {
a7488080 123 if (!empty($fieldDefaults['default_value'])) {
6a488035
TO
124 $defaultCheckValues = explode(CRM_Core_DAO::VALUE_SEPARATOR,
125 substr($fieldDefaults['default_value'], 1, -1)
126 );
127 if (in_array($defaults['value'], $defaultCheckValues)) {
128 $defaults['default_value'] = 1;
129 }
130 }
131 }
132 else {
133 if (CRM_Utils_Array::value('default_value', $fieldDefaults) == CRM_Utils_Array::value('value', $defaults)) {
134 $defaults['default_value'] = 1;
135 }
136 }
137 }
138 else {
139 $defaults['is_active'] = 1;
140 }
141
142 if ($this->_action & CRM_Core_Action::ADD) {
143 $fieldValues = array('option_group_id' => $this->_optionGroupID);
144 $defaults['weight'] = CRM_Utils_Weight::getDefaultWeight('CRM_Core_DAO_OptionValue', $fieldValues);
145 }
146
147 return $defaults;
148 }
149
150 /**
c490a46a 151 * Build the form object
6a488035
TO
152 *
153 * @param null
154 *
155 * @return void
6a488035
TO
156 */
157 public function buildQuickForm() {
158 if ($this->_action == CRM_Core_Action::DELETE) {
c31db174
CW
159 $option = civicrm_api3('option_value', 'getsingle', array('id' => $this->_id));
160 $this->assign('label', $option['label']);
6a488035
TO
161 $this->addButtons(array(
162 array(
163 'type' => 'next',
164 'name' => ts('Delete'),
165 'isDefault' => TRUE,
166 ),
167 array(
168 'type' => 'cancel',
169 'name' => ts('Cancel'),
170 ),
171 )
172 );
173 }
174 else {
175 // lets trim all the whitespace
176 $this->applyFilter('__ALL__', 'trim');
177
178 // hidden Option Id for validation use
179 $this->add('hidden', 'optionId', $this->_id);
180
181 //hidden field ID for validation use
182 $this->add('hidden', 'fieldId', $this->_fid);
183
184 // label
185 $this->add('text', 'label', ts('Option Label'), CRM_Core_DAO::getAttribute('CRM_Core_DAO_OptionValue', 'label'), TRUE);
186
187 $this->add('text', 'value', ts('Option Value'), CRM_Core_DAO::getAttribute('CRM_Core_DAO_OptionValue', 'value'), TRUE);
188
189 // weight
190 $this->add('text', 'weight', ts('Order'), CRM_Core_DAO::getAttribute('CRM_Core_DAO_OptionValue', 'weight'), TRUE);
191 $this->addRule('weight', ts('is a numeric field'), 'numeric');
192
193 // is active ?
194 $this->add('checkbox', 'is_active', ts('Active?'));
195
196 // Set the default value for Custom Field
197 $this->add('checkbox', 'default_value', ts('Default'));
198
199 // add a custom form rule
200 $this->addFormRule(array('CRM_Custom_Form_Option', 'formRule'), $this);
201
202 // add buttons
203 $this->addButtons(array(
204 array(
205 'type' => 'next',
206 'name' => ts('Save'),
207 'isDefault' => TRUE,
208 ),
209 array(
210 'type' => 'next',
211 'name' => ts('Save and New'),
212 'subName' => 'new',
213 ),
214 array(
215 'type' => 'cancel',
216 'name' => ts('Cancel'),
217 ),
218 )
219 );
220
221
222 // if view mode pls freeze it with the done button.
223 if ($this->_action & CRM_Core_Action::VIEW) {
224 $this->freeze();
225 $url = CRM_Utils_System::url('civicrm/admin/custom/group/field/option',
226 'reset=1&action=browse&fid=' . $this->_fid . '&gid=' . $this->_gid,
227 TRUE, NULL, FALSE
228 );
229 $this->addElement('button',
230 'done',
231 ts('Done'),
97e557d7 232 array('onclick' => "location.href='$url'", 'class' => 'crm-form-submit')
6a488035
TO
233 );
234 }
235 }
236 $this->assign('id', $this->_id);
237 }
238
239 /**
100fef9d 240 * Global validation rules for the form
6a488035
TO
241 *
242 * @param array $fields posted values of the form
243 *
fd31fa4c 244 * @param $files
c490a46a 245 * @param CRM_Core_Form $form
fd31fa4c 246 *
6a488035
TO
247 * @return array list of errors to be posted back to the form
248 * @static
6a488035 249 */
00be9182 250 public static function formRule($fields, $files, $form) {
3df236f6
ML
251 $optionLabel = $fields['label'];
252 $optionValue = $fields['value'];
6a488035
TO
253 $fieldId = $form->_fid;
254 $optionGroupId = $form->_optionGroupID;
255
256 $temp = array();
257 if (empty($form->_id)) {
258 $query = "
361fb6c0 259SELECT count(*)
6a488035
TO
260 FROM civicrm_option_value
261 WHERE option_group_id = %1
262 AND label = %2";
3df236f6
ML
263 $params = array(
264 1 => array($optionGroupId, 'Integer'),
6a488035
TO
265 2 => array($optionLabel, 'String'),
266 );
267 if (CRM_Core_DAO::singleValueQuery($query, $params) > 0) {
268 $errors['label'] = ts('There is an entry with the same label.');
269 }
270
271 $query = "
361fb6c0 272SELECT count(*)
6a488035
TO
273 FROM civicrm_option_value
274 WHERE option_group_id = %1
275 AND value = %2";
3df236f6
ML
276 $params = array(
277 1 => array($optionGroupId, 'Integer'),
6a488035
TO
278 2 => array($optionValue, 'String'),
279 );
280 if (CRM_Core_DAO::singleValueQuery($query, $params) > 0) {
281 $errors['value'] = ts('There is an entry with the same value.');
282 }
283 }
284 else {
285 //capture duplicate entries while updating Custom Options
286 $optionId = CRM_Utils_Type::escape($fields['optionId'], 'Integer');
287
288 //check label duplicates within a custom field
289 $query = "
361fb6c0 290SELECT count(*)
6a488035
TO
291 FROM civicrm_option_value
292 WHERE option_group_id = %1
293 AND id != %2
294 AND label = %3";
3df236f6
ML
295 $params = array(
296 1 => array($optionGroupId, 'Integer'),
6a488035
TO
297 2 => array($optionId, 'Integer'),
298 3 => array($optionLabel, 'String'),
299 );
300 if (CRM_Core_DAO::singleValueQuery($query, $params) > 0) {
301 $errors['label'] = ts('There is an entry with the same label.');
302 }
303
304 //check value duplicates within a custom field
305 $query = "
361fb6c0 306SELECT count(*)
6a488035
TO
307 FROM civicrm_option_value
308 WHERE option_group_id = %1
309 AND id != %2
310 AND value = %3";
3df236f6
ML
311 $params = array(
312 1 => array($optionGroupId, 'Integer'),
6a488035
TO
313 2 => array($optionId, 'Integer'),
314 3 => array($optionValue, 'String'),
315 );
316 if (CRM_Core_DAO::singleValueQuery($query, $params) > 0) {
317 $errors['value'] = ts('There is an entry with the same value.');
318 }
319 }
320
321 $query = "
361fb6c0 322SELECT data_type
6a488035
TO
323 FROM civicrm_custom_field
324 WHERE id = %1";
325 $params = array(1 => array($fieldId, 'Integer'));
326 $dao = CRM_Core_DAO::executeQuery($query, $params);
327 if ($dao->fetch()) {
328 switch ($dao->data_type) {
329 case 'Int':
330 if (!CRM_Utils_Rule::integer($fields["value"])) {
331 $errors['value'] = ts('Please enter a valid integer value.');
332 }
333 break;
334
335 case 'Float':
336 // case 'Money':
337 if (!CRM_Utils_Rule::numeric($fields["value"])) {
5ab78070 338 $errors['value'] = ts('Please enter a valid number.');
6a488035
TO
339 }
340 break;
341
342 case 'Money':
343 if (!CRM_Utils_Rule::money($fields["value"])) {
344 $errors['value'] = ts('Please enter a valid value.');
345 }
346 break;
347
348 case 'Date':
349 if (!CRM_Utils_Rule::date($fields["value"])) {
350 $errors['value'] = ts('Please enter a valid date using YYYY-MM-DD format. Example: 2004-12-31.');
351 }
352 break;
353
354 case 'Boolean':
355 if (!CRM_Utils_Rule::integer($fields["value"]) &&
356 ($fields["value"] != '1' || $fields["value"] != '0')
357 ) {
358 $errors['value'] = ts('Please enter 1 or 0 as value.');
359 }
360 break;
361
362 case 'Country':
363 if (!empty($fields["value"])) {
364 $params = array(1 => array($fields['value'], 'String'));
365 $query = "SELECT count(*) FROM civicrm_country WHERE name = %1 OR iso_code = %1";
366 if (CRM_Core_DAO::singleValueQuery($query, $params) <= 0) {
367 $errors['value'] = ts('Invalid default value for country.');
368 }
369 }
370 break;
371
372 case 'StateProvince':
373 if (!empty($fields["value"])) {
374 $params = array(1 => array($fields['value'], 'String'));
375 $query = "
361fb6c0 376SELECT count(*)
6a488035
TO
377 FROM civicrm_state_province
378 WHERE name = %1
379 OR abbreviation = %1";
380 if (CRM_Core_DAO::singleValueQuery($query, $params) <= 0) {
381 $errors['value'] = ts('The invalid value for State/Province data type');
382 }
383 }
384 break;
385 }
386 }
387
388 return empty($errors) ? TRUE : $errors;
389 }
390
391 /**
392 * Process the form
393 *
394 * @param null
395 *
396 * @return void
6a488035
TO
397 */
398 public function postProcess() {
399 // store the submitted values in an array
400 $params = $this->controller->exportValues('Option');
401
402 if ($this->_action == CRM_Core_Action::DELETE) {
c31db174 403 $option = civicrm_api3('option_value', 'getsingle', array('id' => $this->_id));
6a488035 404 $fieldValues = array('option_group_id' => $this->_optionGroupID);
c31db174 405 CRM_Utils_Weight::delWeight('CRM_Core_DAO_OptionValue', $this->_id, $fieldValues);
6a488035 406 CRM_Core_BAO_CustomOption::del($this->_id);
c31db174 407 CRM_Core_Session::setStatus(ts('Option "%1" has been deleted.', array(1 => $option['label'])), ts('Deleted'), 'success');
6a488035
TO
408 return;
409 }
410
411 // set values for custom field properties and save
412 $customOption = new CRM_Core_DAO_OptionValue();
413 $customOption->label = $params['label'];
414 $customOption->name = CRM_Utils_String::titleToVar($params['label']);
415 $customOption->weight = $params['weight'];
416 $customOption->value = $params['value'];
417 $customOption->is_active = CRM_Utils_Array::value('is_active', $params, FALSE);
418
419 $oldWeight = NULL;
420 if ($this->_id) {
421 $customOption->id = $this->_id;
422 CRM_Core_BAO_CustomOption::updateCustomValues($params);
423 $oldWeight = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionValue', $this->_id, 'weight', 'id');
424 }
425
426 $fieldValues = array('option_group_id' => $this->_optionGroupID);
361fb6c0
DL
427 $customOption->weight =
428 CRM_Utils_Weight::updateOtherWeights(
429 'CRM_Core_DAO_OptionValue',
430 $oldWeight,
431 $params['weight'],
432 $fieldValues);
6a488035
TO
433
434 $customOption->option_group_id = $this->_optionGroupID;
435
436 $customField = new CRM_Core_DAO_CustomField();
437 $customField->id = $this->_fid;
361fb6c0
DL
438 if (
439 $customField->find(TRUE) &&
440 (
441 $customField->html_type == 'CheckBox' ||
6a488035
TO
442 $customField->html_type == 'AdvMulti-Select' ||
443 $customField->html_type == 'Multi-Select'
444 )
445 ) {
361fb6c0
DL
446 $defVal = explode(
447 CRM_Core_DAO::VALUE_SEPARATOR,
6a488035
TO
448 substr($customField->default_value, 1, -1)
449 );
a7488080 450 if (!empty($params['default_value'])) {
6a488035
TO
451 if (!in_array($customOption->value, $defVal)) {
452 if (empty($defVal[0])) {
453 $defVal = array($customOption->value);
454 }
455 else {
456 $defVal[] = $customOption->value;
457 }
361fb6c0
DL
458 $customField->default_value =
459 CRM_Core_DAO::VALUE_SEPARATOR .
460 implode(CRM_Core_DAO::VALUE_SEPARATOR, $defVal) .
461 CRM_Core_DAO::VALUE_SEPARATOR;
6a488035
TO
462 $customField->save();
463 }
464 }
465 elseif (in_array($customOption->value, $defVal)) {
466 $tempVal = array();
467 foreach ($defVal as $v) {
468 if ($v != $customOption->value) {
469 $tempVal[] = $v;
470 }
471 }
472
361fb6c0
DL
473 $customField->default_value =
474 CRM_Core_DAO::VALUE_SEPARATOR .
475 implode(CRM_Core_DAO::VALUE_SEPARATOR, $tempVal) .
476 CRM_Core_DAO::VALUE_SEPARATOR;
6a488035
TO
477 $customField->save();
478 }
479 }
480 else {
481 switch ($customField->data_type) {
482 case 'Money':
483 $customOption->value = CRM_Utils_Rule::cleanMoney($customOption->value);
484 break;
485
486 case 'Int':
487 $customOption->value = intval($customOption->value);
488 break;
489
490 case 'Float':
491 $customOption->value = floatval($customOption->value);
492 break;
493 }
494
a7488080 495 if (!empty($params['default_value'])) {
6a488035
TO
496 $customField->default_value = $customOption->value;
497 $customField->save();
498 }
499 elseif ($customField->find(TRUE) && $customField->default_value == $customOption->value) {
500 // this is the case where this option is the current default value and we have been reset
501 $customField->default_value = 'null';
502 $customField->save();
503 }
504 }
505
506 $customOption->save();
507
361fb6c0
DL
508 $msg = ts('Your multiple choice option \'%1\' has been saved', array(1 => $customOption->label));
509 CRM_Core_Session::setStatus($msg, '', 'success');
6a488035
TO
510 $buttonName = $this->controller->getButtonName();
511 $session = CRM_Core_Session::singleton();
512 if ($buttonName == $this->getButtonName('next', 'new')) {
361fb6c0
DL
513 CRM_Core_Session::setStatus(ts('You can add another option.'), '', 'info');
514 $session->replaceUserContext(
515 CRM_Utils_System::url(
516 'civicrm/admin/custom/group/field/option',
6a488035 517 'reset=1&action=add&fid=' . $this->_fid . '&gid=' . $this->_gid
361fb6c0
DL
518 )
519 );
6a488035
TO
520 }
521 }
522}