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