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