Merge pull request #1176 from pratik-joshi/CRM-13025
[civicrm-core.git] / CRM / Custom / Form / Field.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.3 |
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 */
39class CRM_Custom_Form_Field extends CRM_Core_Form {
40
41 /**
42 * Constants for number of options for data types of multiple option.
43 */
44 CONST NUM_OPTION = 11;
45
46 /**
47 * the custom group id saved to the session for an update
48 *
49 * @var int
50 * @access protected
51 */
52 protected $_gid;
53
54 /**
55 * The field id, used when editing the field
56 *
57 * @var int
58 * @access protected
59 */
60 protected $_id;
61
62 /**
63 * The default custom data/input types, when editing the field
64 *
65 * @var array
66 * @access protected
67 */
68 protected $_defaultDataType;
69
70 /**
71 * array of custom field values if update mode
72 */
73 protected $_values;
74
75 /**
76 * Array for valid combinations of data_type & html_type
77 *
78 * @var array
79 * @static
80 */
81 private static $_dataTypeValues = NULL;
82 private static $_dataTypeKeys = NULL;
83
84 private static $_dataToHTML = NULL;
85
86 private static $_dataToLabels = NULL;
87
88 /**
89 * Function to set variables up before form is built
90 *
91 * @param null
92 *
93 * @return void
94 * @access public
95 */
96 public function preProcess() {
97 if (!(self::$_dataTypeKeys)) {
98 self::$_dataTypeKeys = array_keys(CRM_Core_BAO_CustomField::dataType());
99 self::$_dataTypeValues = array_values(CRM_Core_BAO_CustomField::dataType());
100 }
101
102 if (!self::$_dataToHTML) {
103 self::$_dataToHTML = CRM_Core_BAO_CustomField::dataToHtml();
104 }
105
106 //custom group id
107 $this->_gid = CRM_Utils_Request::retrieve('gid', 'Positive', $this);
108
d06700a7 109 if ($isReserved = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $this->_gid, 'is_reserved', 'id')) {
e89941dc 110 CRM_Core_Error::fatal("You cannot add or edit fields in a reserved custom field-set.");
d06700a7
RN
111 }
112
6a488035
TO
113 if ($this->_gid) {
114 $url = CRM_Utils_System::url('civicrm/admin/custom/group/field',
115 "reset=1&action=browse&gid={$this->_gid}"
116 );
117
118 $session = CRM_Core_Session::singleton();
119 $session->pushUserContext($url);
120 }
121
122 //custom field id
123 $this->_id = CRM_Utils_Request::retrieve('id', 'Positive', $this);
124
125 //get the values form db if update.
126 $this->_values = array();
127 if ($this->_id) {
128 $params = array('id' => $this->_id);
129 CRM_Core_BAO_CustomField::retrieve($params, $this->_values);
2f940a36
NG
130 // note_length is an alias for the text_length field
131 $this->_values['note_length'] = CRM_Utils_Array::value('text_length', $this->_values);
6a488035
TO
132 }
133
134 if (self::$_dataToLabels == NULL) {
135 self::$_dataToLabels = array(
136 array('Text' => ts('Text'), 'Select' => ts('Select'),
137 'Radio' => ts('Radio'), 'CheckBox' => ts('CheckBox'), 'Multi-Select' => ts('Multi-Select'),
138 'AdvMulti-Select' => ts('Advanced Multi-Select'),
139 'Autocomplete-Select' => ts('Autocomplete Select'),
140 ),
141 array('Text' => ts('Text'), 'Select' => ts('Select'),
142 'Radio' => ts('Radio'),
143 ),
144 array('Text' => ts('Text'), 'Select' => ts('Select'),
145 'Radio' => ts('Radio'),
146 ),
147 array('Text' => ts('Text'), 'Select' => ts('Select'),
148 'Radio' => ts('Radio'),
149 ),
150 array('TextArea' => ts('TextArea'), 'RichTextEditor' => 'RichTextEditor'),
151 array('Date' => ts('Select Date')),
152 array('Radio' => ts('Radio')),
153 array('StateProvince' => ts('Select State/Province'), 'Multi-Select' => ts('Multi-Select State/Province')),
154 array('Country' => ts('Select Country'), 'Multi-Select' => ts('Multi-Select Country ')),
155 array('File' => ts('Select File')),
156 array('Link' => ts('Link')),
157 array('ContactReference' => ts('Autocomplete Select')),
158 );
159 }
160 }
161
162 /**
163 * This function sets the default values for the form. Note that in edit/view mode
164 * the default values are retrieved from the database
165 *
166 * @param null
167 *
168 * @return array array of default values
169 * @access public
170 */
171 function setDefaultValues() {
172 $defaults = $this->_values;
173
174 if ($this->_id) {
175 $this->assign('id', $this->_id);
176 $this->_gid = $defaults['custom_group_id'];
177
178 //get the value for state or country
179 if ($defaults['data_type'] == 'StateProvince' &&
180 $stateId = CRM_Utils_Array::value('default_value', $defaults)
181 ) {
182 $defaults['default_value'] = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_StateProvince', $stateId);
183 }
184 elseif ($defaults['data_type'] == 'Country' &&
185 $countryId = CRM_Utils_Array::value('default_value', $defaults)
186 ) {
187 $defaults['default_value'] = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Country', $countryId);
188 }
189
190 if ($defaults['data_type'] == 'ContactReference' && CRM_Utils_Array::value('filter', $defaults)) {
191 $contactRefFilter = 'Advance';
192 if (strpos($defaults['filter'], 'action=lookup') !== FALSE &&
193 strpos($defaults['filter'], 'group=') !== FALSE
194 ) {
195 $filterParts = explode('&', $defaults['filter']);
196
197 if (count($filterParts) == 2) {
198 $contactRefFilter = 'Group';
199 foreach ($filterParts as $part) {
200 if (strpos($part, 'group=') === FALSE) {
201 continue;
202 }
203 $groups = substr($part, strpos($part, '=') + 1);
204 foreach (explode(',', $groups) as $grp) {
205 if (CRM_Utils_Rule::positiveInteger($grp)) {
206 $defaults['group_id'][] = $grp;
207 }
208 }
209 }
210 }
211 }
212 $defaults['filter_selected'] = $contactRefFilter;
213 }
214
215 if (CRM_Utils_Array::value('data_type', $defaults)) {
216 $defaultDataType = array_search($defaults['data_type'],
217 self::$_dataTypeKeys
218 );
219 $defaultHTMLType = array_search($defaults['html_type'],
220 self::$_dataToHTML[$defaultDataType]
221 );
222 $defaults['data_type'] = array(
223 '0' => $defaultDataType,
224 '1' => $defaultHTMLType,
225 );
226 $this->_defaultDataType = $defaults['data_type'];
227 }
228
229 $defaults['option_type'] = 2;
230
231 $this->assign('changeFieldType', CRM_Custom_Form_ChangeFieldType::fieldTypeTransitions($this->_values['data_type'], $this->_values['html_type']));
232 }
233 else {
234 $defaults['is_active'] = 1;
235 $defaults['option_type'] = 1;
236 }
237
238 // set defaults for weight.
239 for ($i = 1; $i <= self::NUM_OPTION; $i++) {
240 $defaults['option_status[' . $i . ']'] = 1;
241 $defaults['option_weight[' . $i . ']'] = $i;
242 }
243
244 if ($this->_action & CRM_Core_Action::ADD) {
245 $fieldValues = array('custom_group_id' => $this->_gid);
246 $defaults['weight'] = CRM_Utils_Weight::getDefaultWeight('CRM_Core_DAO_CustomField', $fieldValues);
247
248 $defaults['text_length'] = 255;
249 $defaults['note_columns'] = 60;
250 $defaults['note_rows'] = 4;
251 $defaults['is_view'] = 0;
252 }
253
254 if (CRM_Utils_Array::value('html_type', $defaults)) {
255 $dontShowLink = substr($defaults['html_type'], -14) == 'State/Province' || substr($defaults['html_type'], -7) == 'Country' ? 1 : 0;
256 }
257
258 if (isset($dontShowLink)) {
259 $this->assign('dontShowLink', $dontShowLink);
260 }
261 return $defaults;
262 }
263
264 /**
265 * Function to actually build the form
266 *
267 * @param null
268 *
269 * @return void
270 * @access public
271 */
272 public function buildQuickForm() {
273 if ($this->_gid) {
274 $this->_title = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $this->_gid, 'title');
275 CRM_Utils_System::setTitle($this->_title . ' - ' . ts('Custom Fields'));
276 }
277
278 // lets trim all the whitespace
279 $this->applyFilter('__ALL__', 'trim');
280
281 $attributes = CRM_Core_DAO::getAttribute('CRM_Core_DAO_CustomField');
282
283 // label
284 $this->add('text',
285 'label',
286 ts('Field Label'),
287 $attributes['label'],
288 TRUE
289 );
290
291 $dt = &self::$_dataTypeValues;
292 $it = array();
293 foreach ($dt as $key => $value) {
294 $it[$key] = self::$_dataToLabels[$key];
295 }
296 $sel = &$this->addElement('hierselect',
297 'data_type',
298 ts('Data and Input Field Type'),
299 'onclick="clearSearchBoxes();custom_option_html_type(this.form)"; onBlur="custom_option_html_type(this.form)";',
300 '&nbsp;&nbsp;&nbsp;'
301 );
302 $sel->setOptions(array($dt, $it));
303 if ($this->_action == CRM_Core_Action::UPDATE) {
304 $this->freeze('data_type');
305 }
306 $includeFieldIds = NULL;
307 if ($this->_action == CRM_Core_Action::UPDATE) {
308 $includeFieldIds = $this->_values['id'];
309 }
310 $optionGroups = CRM_Core_BAO_CustomField::customOptionGroup($includeFieldIds);
311 $emptyOptGroup = FALSE;
312 if (empty($optionGroups)) {
313 $emptyOptGroup = TRUE;
314 $optionTypes = array('1' => ts('Create a new set of options'));
315 }
316 else {
317 $optionTypes = array('1' => ts('Create a new set of options'),
318 '2' => ts('Reuse an existing set'),
319 );
320
321 $this->add('select',
322 'option_group_id',
323 ts('Multiple Choice Option Sets'),
324 array(
325 '' => ts('- select -')) + $optionGroups
326 );
327 }
328
329 $element = &$this->addRadio('option_type',
330 ts('Option Type'),
331 $optionTypes,
332 array(
333 'onclick' => "showOptionSelect();"), '<br/>'
334 );
335
336
337 $contactGroups = CRM_Core_PseudoConstant::group();
338 asort($contactGroups);
339
340 $this->add('select',
341 'group_id',
342 ts('Limit List to Group'),
343 $contactGroups,
344 FALSE,
345 array('multiple' => 'multiple')
346 );
347
348 $this->add('text',
349 'filter',
350 ts('Advanced Filter'),
351 $attributes['filter']
352 );
353
354 $this->add('hidden', 'filter_selected', 'Group', array('id' => 'filter_selected'));
355
356 //if empty option group freeze the option type.
357 if ($emptyOptGroup) {
358 $element->freeze();
359 }
360
361 // form fields of Custom Option rows
362 $defaultOption = array();
363 $_showHide = new CRM_Core_ShowHideBlocks('', '');
364 for ($i = 1; $i <= self::NUM_OPTION; $i++) {
365
366 //the show hide blocks
367 $showBlocks = 'optionField_' . $i;
368 if ($i > 2) {
369 $_showHide->addHide($showBlocks);
370 if ($i == self::NUM_OPTION) {
371 $_showHide->addHide('additionalOption');
372 }
373 }
374 else {
375 $_showHide->addShow($showBlocks);
376 }
377
378 $optionAttributes = CRM_Core_DAO::getAttribute('CRM_Core_DAO_OptionValue');
379 // label
380 $this->add('text', 'option_label[' . $i . ']', ts('Label'),
381 $optionAttributes['label']
382 );
383
384 // value
385 $this->add('text', 'option_value[' . $i . ']', ts('Value'),
386 $optionAttributes['value']
387 );
388
389 // weight
390 $this->add('text', "option_weight[$i]", ts('Order'),
391 $optionAttributes['weight']
392 );
393
394 // is active ?
395 $this->add('checkbox', "option_status[$i]", ts('Active?'));
396
397 $defaultOption[$i] = $this->createElement('radio', NULL, NULL, NULL, $i);
398
399 //for checkbox handling of default option
400 $this->add('checkbox', "default_checkbox_option[$i]", NULL);
401 }
402
403 //default option selection
404 $this->addGroup($defaultOption, 'default_option');
405
406 $_showHide->addToTemplate();
407
408 // text length for alpha numeric data types
409 $this->add('text',
410 'text_length',
411 ts('Database field length'),
412 $attributes['text_length'],
413 FALSE
414 );
415 $this->addRule('text_length', ts('Value should be a positive number'), 'integer');
416
417 $this->add('text',
418 'start_date_years',
419 ts('Dates may be up to'),
420 $attributes['start_date_years'],
421 FALSE
422 );
423 $this->add('text',
424 'end_date_years',
425 ts('Dates may be up to'),
426 $attributes['end_date_years'],
427 FALSE
428 );
429
430 $this->addRule('start_date_years', ts('Value should be a positive number'), 'integer');
431 $this->addRule('end_date_years', ts('Value should be a positive number'), 'integer');
432
433 $this->add('select', 'date_format', ts('Date Format'),
434 array('' => ts('- select -')) + CRM_Core_SelectValues::getDatePluginInputFormats()
435 );
436
437 $this->add('select', 'time_format', ts('Time'),
438 array('' => ts('- none -')) + CRM_Core_SelectValues::getTimeFormats()
439 );
440
441 // for Note field
442 $this->add('text',
443 'note_columns',
444 ts('Width (columns)') . ' ',
445 $attributes['note_columns'],
446 FALSE
447 );
448 $this->add('text',
449 'note_rows',
450 ts('Height (rows)') . ' ',
451 $attributes['note_rows'],
452 FALSE
453 );
2f940a36
NG
454 $this->add('text',
455 'note_length',
456 ts('Maximum length') . ' ',
457 $attributes['text_length'], // note_length is an alias for the text-length field
458 FALSE
459 );
6a488035
TO
460
461 $this->addRule('note_columns', ts('Value should be a positive number'), 'positiveInteger');
462 $this->addRule('note_rows', ts('Value should be a positive number'), 'positiveInteger');
2f940a36 463 $this->addRule('note_length', ts('Value should be a positive number'), 'positiveInteger');
6a488035
TO
464
465 // weight
466 $this->add('text', 'weight', ts('Order'),
467 $attributes['weight'],
468 TRUE
469 );
470 $this->addRule('weight', ts('is a numeric field'), 'numeric');
471
472 // is required ?
473 $this->add('checkbox', 'is_required', ts('Required?'));
474
475 // checkbox / radio options per line
476 $this->add('text', 'options_per_line', ts('Options Per Line'));
477 $this->addRule('options_per_line', ts('must be a numeric value'), 'numeric');
478
479 // default value, help pre, help post, mask, attributes, javascript ?
480 $this->add('text', 'default_value', ts('Default Value'),
481 $attributes['default_value']
482 );
483 $this->add('textarea', 'help_pre', ts('Field Pre Help'),
484 $attributes['help_pre']
485 );
486 $this->add('textarea', 'help_post', ts('Field Post Help'),
487 $attributes['help_post']
488 );
489 $this->add('text', 'mask', ts('Mask'),
490 $attributes['mask']
491 );
492
493 // is active ?
494 $this->add('checkbox', 'is_active', ts('Active?'));
495
496 // is active ?
497 $this->add('checkbox', 'is_view', ts('View Only?'));
498
499 // is searchable ?
500 $this->addElement('checkbox',
501 'is_searchable',
502 ts('Is this Field Searchable?'),
503 NULL, array('onclick' => "showSearchRange(this)")
504 );
505
506 // is searchable by range?
507 $searchRange = array();
508 $searchRange[] = $this->createElement('radio', NULL, NULL, ts('Yes'), '1');
509 $searchRange[] = $this->createElement('radio', NULL, NULL, ts('No'), '0');
510
511 $this->addGroup($searchRange, 'is_search_range', ts('Search by Range?'));
512
513 // add buttons
514 $this->addButtons(array(
515 array(
516 'type' => 'next',
517 'name' => ts('Save'),
518 'isDefault' => TRUE,
519 ),
520 array(
521 'type' => 'next',
522 'name' => ts('Save and New'),
523 'subName' => 'new',
524 ),
525 array(
526 'type' => 'cancel',
527 'name' => ts('Cancel'),
528 ),
529 )
530 );
531
532 // add a form rule to check default value
533 $this->addFormRule(array('CRM_Custom_Form_Field', 'formRule'), $this);
534
535 // if view mode pls freeze it with the done button.
536 if ($this->_action & CRM_Core_Action::VIEW) {
537 $this->freeze();
538 $url = CRM_Utils_System::url('civicrm/admin/custom/group/field', 'reset=1&action=browse&gid=' . $this->_gid);
539 $this->addElement('button',
540 'done',
541 ts('Done'),
542 array('onclick' => "location.href='$url'")
543 );
544 }
545 }
546
547 /**
548 * global validation rules for the form
549 *
550 * @param array $fields (referance) posted values of the form
551 *
552 * @return array if errors then list of errors to be posted back to the form,
553 * true otherwise
554 * @static
555 * @access public
556 */
557 static function formRule($fields, $files, $self) {
558 $default = CRM_Utils_Array::value('default_value', $fields);
559
560 $errors = array();
561
562 //validate field label as well as name.
563 $title = $fields['label'];
564 $name = CRM_Utils_String::munge($title, '_', 64);
e1069955 565 $gId = $self->_gid; // CRM-7564
8ef12e64 566 $query = 'select count(*) from civicrm_custom_field where ( name like %1 OR label like %2 ) and id != %3 and custom_group_id = %4';
6a488035
TO
567 $fldCnt = CRM_Core_DAO::singleValueQuery($query, array(1 => array($name, 'String'),
568 2 => array($title, 'String'),
569 3 => array((int)$self->_id, 'Integer'),
e1069955 570 4 => array($gId, 'Integer'),
6a488035
TO
571 ));
572 if ($fldCnt) {
573 $errors['label'] = ts('Custom field \'%1\' already exists in Database.', array(1 => $title));
574 }
575
576 //checks the given custom field name doesnot start with digit
577 if (!empty($title)) {
578 // gives the ascii value
579 $asciiValue = ord($title{0});
580 if ($asciiValue >= 48 && $asciiValue <= 57) {
581 $errors['label'] = ts("Field's Name should not start with digit");
582 }
583 }
584
585 // ensure that the label is not 'id'
586 if (strtolower($title) == 'id') {
587 $errors['label'] = ts("You cannot use 'id' as a field label.");
588 }
589
590 if (!isset($fields['data_type'][0]) || !isset($fields['data_type'][1])) {
591 $errors['_qf_default'] = ts('Please enter valid - Data and Input Field Type.');
592 }
593
594 $dataType = self::$_dataTypeKeys[$fields['data_type'][0]];
595
596 if ($default || $dataType == 'ContactReference') {
597 switch ($dataType) {
598 case 'Int':
599 if (!CRM_Utils_Rule::integer($default)) {
600 $errors['default_value'] = ts('Please enter a valid integer as default value.');
601 }
602 break;
603
604 case 'Float':
605 if (!CRM_Utils_Rule::numeric($default)) {
606 $errors['default_value'] = ts('Please enter a valid number as default value.');
607 }
608 break;
609
610 case 'Money':
611 if (!CRM_Utils_Rule::money($default)) {
612 $errors['default_value'] = ts('Please enter a valid number value.');
613 }
614 break;
615
616 case 'Link':
617 if (!CRM_Utils_Rule::url($default)) {
618 $errors['default_value'] = ts('Please enter a valid link.');
619 }
620 break;
621
622 case 'Date':
623 if (!CRM_Utils_Rule::date($default)) {
624 $errors['default_value'] = ts('Please enter a valid date as default value using YYYY-MM-DD format. Example: 2004-12-31.');
625 }
626 break;
627
628 case 'Boolean':
629 if ($default != '1' && $default != '0') {
630 $errors['default_value'] = ts('Please enter 1 (for Yes) or 0 (for No) if you want to set a default value.');
631 }
632 break;
633
634 case 'Country':
635 if (!empty($default)) {
636 $query = "SELECT count(*) FROM civicrm_country WHERE name = %1 OR iso_code = %1";
637 $params = array(1 => array($fields['default_value'], 'String'));
638 if (CRM_Core_DAO::singleValueQuery($query, $params) <= 0) {
639 $errors['default_value'] = ts('Invalid default value for country.');
640 }
641 }
642 break;
643
644 case 'StateProvince':
645 if (!empty($default)) {
646 $query = "
8ef12e64 647SELECT count(*)
6a488035
TO
648 FROM civicrm_state_province
649 WHERE name = %1
650 OR abbreviation = %1";
651 $params = array(1 => array($fields['default_value'], 'String'));
652 if (CRM_Core_DAO::singleValueQuery($query, $params) <= 0) {
653 $errors['default_value'] = ts('The invalid default value for State/Province data type');
654 }
655 }
656 break;
657
658 case 'ContactReference':
659 if ($fields['filter_selected'] == 'Advance' &&
660 CRM_Utils_Array::value('filter', $fields)
661 ) {
662 if (strpos($fields['filter'], 'entity=') !== FALSE) {
663 $errors['filter'] = ts("Please do not include entity parameter (entity is always 'contact')");
664 }
665 elseif (strpos($fields['filter'], 'action=') === FALSE) {
666 $errors['filter'] = ts("Please specify 'action' parameter, it should be 'lookup' or 'get'");
667 }
668 elseif (strpos($fields['filter'], 'action=get') === FALSE &&
669 strpos($fields['filter'], 'action=lookup') === FALSE
670 ) {
671 $errors['filter'] = ts("Only 'get' and 'lookup' actions are supported.");
672 }
673 }
674 $self->setDefaults(array('filter_selected', $fields['filter_selected']));
675 break;
676 }
677 }
678
679 if (self::$_dataTypeKeys[$fields['data_type'][0]] == 'Date') {
680 if (!$fields['date_format']) {
681 $errors['date_format'] = ts('Please select a date format.');
682 }
683 }
684
685 /** Check the option values entered
686 * Appropriate values are required for the selected datatype
687 * Incomplete row checking is also required.
688 */
689 $_flagOption = $_rowError = 0;
690 $_showHide = new CRM_Core_ShowHideBlocks('', '');
691 $dataType = self::$_dataTypeKeys[$fields['data_type'][0]];
692 if (isset($fields['data_type'][1])) {
693 $dataField = $fields['data_type'][1];
694 }
695 $optionFields = array('Select', 'Multi-Select', 'CheckBox', 'Radio', 'AdvMulti-Select');
696
697 if ($fields['option_type'] == 1) {
698 //capture duplicate Custom option values
699 if (!empty($fields['option_value'])) {
700 $countValue = count($fields['option_value']);
701 $uniqueCount = count(array_unique($fields['option_value']));
702
703 if ($countValue > $uniqueCount) {
704
705 $start = 1;
706 while ($start < self::NUM_OPTION) {
707 $nextIndex = $start + 1;
708 while ($nextIndex <= self::NUM_OPTION) {
709 if ($fields['option_value'][$start] == $fields['option_value'][$nextIndex] &&
710 !empty($fields['option_value'][$nextIndex])
711 ) {
712 $errors['option_value[' . $start . ']'] = ts('Duplicate Option values');
713 $errors['option_value[' . $nextIndex . ']'] = ts('Duplicate Option values');
714 $_flagOption = 1;
715 }
716 $nextIndex++;
717 }
718 $start++;
719 }
720 }
721 }
722
723 //capture duplicate Custom Option label
724 if (!empty($fields['option_label'])) {
725 $countValue = count($fields['option_label']);
726 $uniqueCount = count(array_unique($fields['option_label']));
727
728 if ($countValue > $uniqueCount) {
729 $start = 1;
730 while ($start < self::NUM_OPTION) {
731 $nextIndex = $start + 1;
732 while ($nextIndex <= self::NUM_OPTION) {
733 if ($fields['option_label'][$start] == $fields['option_label'][$nextIndex] &&
734 !empty($fields['option_label'][$nextIndex])
735 ) {
736 $errors['option_label[' . $start . ']'] = ts('Duplicate Option label');
737 $errors['option_label[' . $nextIndex . ']'] = ts('Duplicate Option label');
738 $_flagOption = 1;
739 }
740 $nextIndex++;
741 }
742 $start++;
743 }
744 }
745 }
746
747 for ($i = 1; $i <= self::NUM_OPTION; $i++) {
748 if (!$fields['option_label'][$i]) {
749 if ($fields['option_value'][$i]) {
750 $errors['option_label[' . $i . ']'] = ts('Option label cannot be empty');
751 $_flagOption = 1;
752 }
753 else {
754 $_emptyRow = 1;
755 }
756 }
757 else {
758 if (!strlen(trim($fields['option_value'][$i]))) {
759 if (!$fields['option_value'][$i]) {
760 $errors['option_value[' . $i . ']'] = ts('Option value cannot be empty');
761 $_flagOption = 1;
762 }
763 }
764 }
765
766 if ($fields['option_value'][$i] && $dataType != 'String') {
767 if ($dataType == 'Int') {
768 if (!CRM_Utils_Rule::integer($fields['option_value'][$i])) {
769 $_flagOption = 1;
770 $errors['option_value[' . $i . ']'] = ts('Please enter a valid integer.');
771 }
772 }
773 elseif ($dataType == 'Money') {
774 if (!CRM_Utils_Rule::money($fields['option_value'][$i])) {
775 $_flagOption = 1;
776 $errors['option_value[' . $i . ']'] = ts('Please enter a valid money value.');
777 }
778 }
779 else {
780 if (!CRM_Utils_Rule::numeric($fields['option_value'][$i])) {
781 $_flagOption = 1;
782 $errors['option_value[' . $i . ']'] = ts('Please enter a valid number.');
783 }
784 }
785 }
786
787 $showBlocks = 'optionField_' . $i;
788 if ($_flagOption) {
789 $_showHide->addShow($showBlocks);
790 $_rowError = 1;
791 }
792
793 if (!empty($_emptyRow)) {
794 $_showHide->addHide($showBlocks);
795 }
796 else {
797 $_showHide->addShow($showBlocks);
798 }
799 if ($i == self::NUM_OPTION) {
800 $hideBlock = 'additionalOption';
801 $_showHide->addHide($hideBlock);
802 }
803
804 $_flagOption = $_emptyRow = 0;
805 }
806 }
807 elseif (isset($dataField) &&
808 in_array($dataField, $optionFields) &&
809 !in_array($dataType, array('Boolean', 'Country', 'StateProvince'))
810 ) {
811 if (!$fields['option_group_id']) {
812 $errors['option_group_id'] = ts('You must select a Multiple Choice Option set if you chose Reuse an existing set.');
813 }
814 else {
815 $query = "
816SELECT count(*)
817FROM civicrm_custom_field
818WHERE data_type != %1
819AND option_group_id = %2";
820 $params = array(
821 1 => array(self::$_dataTypeKeys[$fields['data_type'][0]],
822 'String',
823 ),
824 2 => array($fields['option_group_id'], 'Integer'),
825 );
826 $count = CRM_Core_DAO::singleValueQuery($query, $params);
827 if ($count > 0) {
828 $errors['option_group_id'] = ts('The data type of the multiple choice option set you\'ve selected does not match the data type assigned to this field.');
829 }
830 }
831 }
832
833 $assignError = new CRM_Core_Page();
834 if ($_rowError) {
835 $_showHide->addToTemplate();
836 $assignError->assign('optionRowError', $_rowError);
837 }
838 else {
839 if (isset($fields['data_type'][1])) {
840 switch (self::$_dataToHTML[$fields['data_type'][0]][$fields['data_type'][1]]) {
841 case 'Radio':
842 $_fieldError = 1;
843 $assignError->assign('fieldError', $_fieldError);
844 break;
845
846 case 'Checkbox':
847 $_fieldError = 1;
848 $assignError->assign('fieldError', $_fieldError);
849 break;
850
851 case 'Select':
852 $_fieldError = 1;
853 $assignError->assign('fieldError', $_fieldError);
854 break;
855
856 default:
857 $_fieldError = 0;
858 $assignError->assign('fieldError', $_fieldError);
859 }
860 }
861
862 for ($idx = 1; $idx <= self::NUM_OPTION; $idx++) {
863 $showBlocks = 'optionField_' . $idx;
864 if (!empty($fields['option_label'][$idx])) {
865 $_showHide->addShow($showBlocks);
866 }
867 else {
868 $_showHide->addHide($showBlocks);
869 }
870 }
871 $_showHide->addToTemplate();
872 }
873
874 // we can not set require and view at the same time.
875 if (CRM_Utils_Array::value('is_required', $fields) &&
876 CRM_Utils_Array::value('is_view', $fields)
877 ) {
878 $errors['is_view'] = ts('Can not set this field Required and View Only at the same time.');
879 }
880
881 return empty($errors) ? TRUE : $errors;
882 }
883
884 /**
885 * Process the form
886 *
887 * @param null
888 *
889 * @return void
890 * @access public
891 */
892 public function postProcess() {
893 // store the submitted values in an array
894 $params = $this->controller->exportValues($this->_name);
895 if ($this->_action == CRM_Core_Action::UPDATE) {
896 $dataTypeKey = $this->_defaultDataType[0];
897 $params['data_type'] = self::$_dataTypeKeys[$this->_defaultDataType[0]];
898 $params['html_type'] = self::$_dataToHTML[$this->_defaultDataType[0]][$this->_defaultDataType[1]];
899 }
900 else {
901 $dataTypeKey = $params['data_type'][0];
902 $params['html_type'] = self::$_dataToHTML[$params['data_type'][0]][$params['data_type'][1]];
903 $params['data_type'] = self::$_dataTypeKeys[$params['data_type'][0]];
904 }
905
906 //fix for 'is_search_range' field.
907 if (in_array($dataTypeKey, array(
908 1, 2, 3, 5))) {
909 if (!CRM_Utils_Array::value('is_searchable', $params)) {
910 $params['is_search_range'] = 0;
911 }
912 }
913 else {
914 $params['is_search_range'] = 0;
915 }
916
917 $filter = 'null';
918 if ($dataTypeKey == 11 && CRM_Utils_Array::value('filter_selected', $params)) {
919 if ($params['filter_selected'] == 'Advance' && trim(CRM_Utils_Array::value('filter', $params))) {
920 $filter = trim($params['filter']);
921 }
922 elseif ($params['filter_selected'] == 'Group' && CRM_Utils_Array::value('group_id', $params)) {
923
924 $filter = 'action=lookup&group=' . implode(',', $params['group_id']);
925 }
926 }
927 $params['filter'] = $filter;
928
929 // fix for CRM-316
930 $oldWeight = NULL;
931 if ($this->_action & (CRM_Core_Action::UPDATE | CRM_Core_Action::ADD)) {
932 $fieldValues = array('custom_group_id' => $this->_gid);
933 if ($this->_id) {
934 $oldWeight = $this->_values['weight'];
935 }
936 $params['weight'] = CRM_Utils_Weight::updateOtherWeights('CRM_Core_DAO_CustomField', $oldWeight, $params['weight'], $fieldValues);
937 }
938
939 $strtolower = function_exists('mb_strtolower') ? 'mb_strtolower' : 'strtolower';
940
941 //store the primary key for State/Province or Country as default value.
942 if (strlen(trim($params['default_value']))) {
943 switch ($params['data_type']) {
944 case 'StateProvince':
945 $fieldStateProvince = $strtolower($params['default_value']);
946 $query = "
947SELECT id
8ef12e64 948 FROM civicrm_state_province
949 WHERE LOWER(name) = '$fieldStateProvince'
6a488035
TO
950 OR abbreviation = '$fieldStateProvince'";
951 $dao = CRM_Core_DAO::executeQuery($query, CRM_Core_DAO::$_nullArray);
952 if ($dao->fetch()) {
953 $params['default_value'] = $dao->id;
954 }
955 break;
956
957 case 'Country':
958 $fieldCountry = $strtolower($params['default_value']);
959 $query = "
960SELECT id
961 FROM civicrm_country
8ef12e64 962 WHERE LOWER(name) = '$fieldCountry'
6a488035
TO
963 OR iso_code = '$fieldCountry'";
964 $dao = CRM_Core_DAO::executeQuery($query, CRM_Core_DAO::$_nullArray);
965 if ($dao->fetch()) {
966 $params['default_value'] = $dao->id;
967 }
968 break;
969 }
970 }
971
2f940a36
NG
972 // The text_length attribute for Memo fields is in a different input as there
973 // are different label, help text and default value than for other type fields
974 if ($params['data_type'] == "Memo") {
975 $params['text_length'] = $params['note_length'];
976 }
977
6a488035
TO
978 // need the FKEY - custom group id
979 $params['custom_group_id'] = $this->_gid;
980
981 if ($this->_action & CRM_Core_Action::UPDATE) {
982 $params['id'] = $this->_id;
983 }
984
985 $customField = CRM_Core_BAO_CustomField::create($params);
986
987 // reset the cache
988 CRM_Core_BAO_Cache::deleteGroup('contact fields');
989
990 CRM_Core_Session::setStatus(ts('Your custom field \'%1\' has been saved.',
991 array(1 => $customField->label)
992 ), ts('Saved'), 'success');
993
994 $buttonName = $this->controller->getButtonName();
995 $session = CRM_Core_Session::singleton();
996 if ($buttonName == $this->getButtonName('next', 'new')) {
997 CRM_Core_Session::setStatus(ts(' You can add another custom field.'), '', 'info');
998 $session->replaceUserContext(CRM_Utils_System::url('civicrm/admin/custom/group/field/add',
999 'reset=1&action=add&gid=' . $this->_gid
1000 ));
1001 }
1002 else {
1003 $session->replaceUserContext(CRM_Utils_System::url('civicrm/admin/custom/group/field',
1004 'reset=1&action=browse&gid=' . $this->_gid
1005 ));
1006 }
1007 }
1008}
1009