/** * Validate a value against a CustomField type. * * @param string $type * The type of the data. * @param string $value * The data to be validated. * * @return bool * True if the value is of the specified type */ public static function typecheck($type, $value) { switch ($type) { case 'Memo': return TRUE; case 'String': return CRM_Utils_Rule::string($value); case 'Int': return CRM_Utils_Rule::integer($value); case 'Float': case 'Money': return CRM_Utils_Rule::numeric($value); case 'Date': if (is_numeric($value)) { return CRM_Utils_Rule::dateTime($value); } else { return CRM_Utils_Rule::date($value); } case 'Boolean': return CRM_Utils_Rule::boolean($value); case 'ContactReference': return CRM_Utils_Rule::validContact($value); case 'StateProvince': //fix for multi select state, CRM-3437 $valid = FALSE; $mulValues = explode(',', $value); foreach ($mulValues as $key => $state) { $valid = array_key_exists(strtolower(trim($state)), array_change_key_case(array_flip(CRM_Core_PseudoConstant::stateProvinceAbbreviation()), CASE_LOWER)) || array_key_exists(strtolower(trim($state)), array_change_key_case(array_flip(CRM_Core_PseudoConstant::stateProvince()), CASE_LOWER)); if (!$valid) { break; } } return $valid; case 'Country': //fix multi select country, CRM-3437 $valid = FALSE; $mulValues = explode(',', $value); foreach ($mulValues as $key => $country) { $valid = array_key_exists(strtolower(trim($country)), array_change_key_case(array_flip(CRM_Core_PseudoConstant::countryIsoCode()), CASE_LOWER)) || array_key_exists(strtolower(trim($country)), array_change_key_case(array_flip(CRM_Core_PseudoConstant::country()), CASE_LOWER)); if (!$valid) { break; } } return $valid; case 'Link': return CRM_Utils_Rule::url($value); } return FALSE; }
/** * Validate a value against a CustomField type * * @param string $type The type of the data * @param string $value The data to be validated * * @return boolean True if the value is of the specified type * @access public * @static */ function typecheck($type, $value) { switch ($type) { case 'Memo': return true; case 'String': return CRM_Utils_Rule::string($value); case 'Int': return CRM_Utils_Rule::integer($value); case 'Float': case 'Money': return CRM_Utils_Rule::numeric($value); case 'Date': return CRM_Utils_Rule::date($value); case 'Boolean': return CRM_Utils_Rule::boolean($value); case 'StateProvince': return array_key_exists(strtolower($value), array_change_key_case(array_flip(CRM_Core_PseudoConstant::stateProvinceAbbreviation()), CASE_LOWER)) || array_key_exists(strtolower($value), array_change_key_case(array_flip(CRM_Core_PseudoConstant::stateProvince()), CASE_LOWER)); case 'Country': return array_key_exists(strtolower($value), array_change_key_case(array_flip(CRM_Core_PseudoConstant::countryIsoCode()), CASE_LOWER)) || array_key_exists(strtolower($value), array_change_key_case(array_flip(CRM_Core_PseudoConstant::country()), CASE_LOWER)); } return false; }
/** * function to check if an error in Core( non-custom fields ) field * * @param String $errorMessage A string containing all the error-fields. * * @access public */ function isErrorInCoreData($params, &$errorMessage) { require_once 'CRM/Core/OptionGroup.php'; foreach ($params as $key => $value) { if ($value) { $session =& CRM_Core_Session::singleton(); $dateType = $session->get("dateTypes"); switch ($key) { case 'birth_date': if (CRM_Utils_Date::convertToDefaultDate($params, $dateType, $key)) { if (!CRM_Utils_Rule::date($params[$key])) { self::addToErrorMsg(ts('Birth Date'), $errorMessage); } } else { self::addToErrorMsg(ts('Birth-Date'), $errorMessage); } break; case 'deceased_date': if (CRM_Utils_Date::convertToDefaultDate($params, $dateType, $key)) { if (!CRM_Utils_Rule::date($params[$key])) { self::addToErrorMsg(ts('Deceased Date'), $errorMessage); } } else { self::addToErrorMsg(ts('Deceased Date'), $errorMessage); } break; case 'is_deceased': if (CRM_Utils_String::strtoboolstr($value) === false) { self::addToErrorMsg(ts('Is Deceased'), $errorMessage); } break; case 'gender': if (!self::checkGender($value)) { self::addToErrorMsg(ts('Gender'), $errorMessage); } break; case 'preferred_communication_method': $preffComm = array(); $preffComm = explode(',', $value); foreach ($preffComm as $v) { if (!self::in_value(trim($v), CRM_Core_PseudoConstant::pcm())) { self::addToErrorMsg(ts('Preferred Communication Method'), $errorMessage); } } break; case 'preferred_mail_format': if (!array_key_exists(strtolower($value), array_change_key_case(CRM_Core_SelectValues::pmf(), CASE_LOWER))) { self::addToErrorMsg(ts('Preferred Mail Format'), $errorMessage); } break; case 'individual_prefix': if (!self::in_value($value, CRM_Core_PseudoConstant::individualPrefix())) { self::addToErrorMsg(ts('Individual Prefix'), $errorMessage); } break; case 'individual_suffix': if (!self::in_value($value, CRM_Core_PseudoConstant::individualSuffix())) { self::addToErrorMsg(ts('Individual Suffix'), $errorMessage); } break; case 'state_province': if (!empty($value)) { foreach ($value as $stateValue) { if ($stateValue['state_province']) { if (self::in_value($stateValue['state_province'], CRM_Core_PseudoConstant::stateProvinceAbbreviation()) || self::in_value($stateValue['state_province'], CRM_Core_PseudoConstant::stateProvince())) { continue; } else { self::addToErrorMsg(ts('State / Province'), $errorMessage); } } } } break; case 'country': if (!empty($value)) { foreach ($value as $stateValue) { if ($stateValue['country']) { CRM_Core_PseudoConstant::populate($countryNames, 'CRM_Core_DAO_Country', true, 'name', 'is_active'); CRM_Core_PseudoConstant::populate($countryIsoCodes, 'CRM_Core_DAO_Country', true, 'iso_code'); $config =& CRM_Core_Config::singleton(); $limitCodes = $config->countryLimit(); //If no country is selected in //localization then take all countries if (empty($limitCodes)) { $limitCodes = $countryIsoCodes; } if (self::in_value($stateValue['country'], $limitCodes) || self::in_value($stateValue['country'], CRM_Core_PseudoConstant::country())) { continue; } else { if (self::in_value($stateValue['country'], $countryIsoCodes) || self::in_value($stateValue['country'], $countryNames)) { self::addToErrorMsg(ts('Country input value is in table but not "available": "This Country is valid but is NOT in the list of Available Countries currently configured for your site. This can be viewed and modifed from Global Settings >> Localization." '), $errorMessage); } else { self::addToErrorMsg(ts('Country input value not in country table: "The Country value appears to be invalid. It does not match any value in CiviCRM table of countries."'), $errorMessage); } } } } } break; case 'geo_code_1': if (!empty($value)) { foreach ($value as $codeValue) { if ($codeValue['geo_code_1']) { if (CRM_Utils_Rule::numeric($codeValue['geo_code_1'])) { continue; } else { self::addToErrorMsg(ts('Geo code 1'), $errorMessage); } } } } break; case 'geo_code_2': if (!empty($value)) { foreach ($value as $codeValue) { if ($codeValue['geo_code_2']) { if (CRM_Utils_Rule::numeric($codeValue['geo_code_2'])) { continue; } else { self::addToErrorMsg(ts('Geo code 2'), $errorMessage); } } } } break; //check for any error in email/postal greeting, addressee, //custom email/postal greeting, custom addressee, CRM-4575 //check for any error in email/postal greeting, addressee, //custom email/postal greeting, custom addressee, CRM-4575 case 'email_greeting': $emailGreetingFilter = array('contact_type' => $this->_contactType, 'greeting_type' => 'email_greeting'); if (!self::in_value($value, CRM_Core_PseudoConstant::greeting($emailGreetingFilter))) { self::addToErrorMsg(ts('Email Greeting must be one of the configured format options. Check Administer >> Option Lists >> Email Greetings for valid values'), $errorMessage); } break; case 'postal_greeting': $postalGreetingFilter = array('contact_type' => $this->_contactType, 'greeting_type' => 'postal_greeting'); if (!self::in_value($value, CRM_Core_PseudoConstant::greeting($postalGreetingFilter))) { self::addToErrorMsg(ts('Postal Greeting must be one of the configured format options. Check Administer >> Option Lists >> Postal Greetings for valid values'), $errorMessage); } break; case 'addressee': $addresseeFilter = array('contact_type' => $this->_contactType, 'greeting_type' => 'addressee'); if (!self::in_value($value, CRM_Core_PseudoConstant::greeting($addresseeFilter))) { self::addToErrorMsg(ts('Addressee must be one of the configured format options. Check Administer >> Option Lists >> Addressee for valid values'), $errorMessage); } break; case 'email_greeting_custom': if (array_key_exists('email_greeting', $params)) { $emailGreetingLabel = key(CRM_Core_OptionGroup::values('email_greeting', true, null, null, 'AND v.name = "Customized"')); if (CRM_Utils_Array::value('email_greeting', $params) != $emailGreetingLabel) { self::addToErrorMsg(ts('Email Greeting - Custom'), $errorMessage); } } break; case 'postal_greeting_custom': if (array_key_exists('postal_greeting', $params)) { $postalGreetingLabel = key(CRM_Core_OptionGroup::values('postal_greeting', true, null, null, 'AND v.name = "Customized"')); if (CRM_Utils_Array::value('postal_greeting', $params) != $postalGreetingLabel) { self::addToErrorMsg(ts('Postal Greeting - Custom'), $errorMessage); } } break; case 'addressee_custom': if (array_key_exists('addressee', $params)) { $addresseeLabel = key(CRM_Core_OptionGroup::values('addressee', true, null, null, 'AND v.name = "Customized"')); if (CRM_Utils_Array::value('addressee', $params) != $addresseeLabel) { self::addToErrorMsg(ts('Addressee - Custom'), $errorMessage); } } break; case 'home_URL': if (CRM_Utils_Rule::url($value) === false) { self::addToErrorMsg(ts('Website'), $errorMessage); } break; case 'do_not_email': case 'do_not_phone': case 'do_not_mail': case 'do_not_sms': case 'do_not_trade': if (CRM_Utils_Rule::boolean($value) == false) { $key = ucwords(str_replace("_", " ", $key)); self::addToErrorMsg($key, $errorMessage); } break; case 'email': if (is_array($value)) { foreach ($value as $values) { if (CRM_Utils_Array::value('email', $values) && !CRM_Utils_Rule::email($values['email'])) { self::addToErrorMsg($key, $errorMessage); break; } } } break; default: if (is_array($params[$key]) && isset($params[$key]["contact_type"])) { //check for any relationship data ,FIX ME self::isErrorInCoreData($params[$key], $errorMessage); } } } } }
/** * global validation rules for the form * * @param array $fields (referance) posted values of the form * * @return array if errors then list of errors to be posted back to the form, * true otherwise * @static * @access public */ static function formRule($fields, $files, $self) { $default = CRM_Utils_Array::value('default_value', $fields); $errors = array(); //validate field label as well as name. $title = $fields['label']; $name = CRM_Utils_String::munge($title, '_', 64); $gId = $self->_gid; // CRM-7564 $query = 'select count(*) from civicrm_custom_field where ( name like %1 OR label like %2 ) and id != %3 and custom_group_id = %4'; $fldCnt = CRM_Core_DAO::singleValueQuery($query, array(1 => array($name, 'String'), 2 => array($title, 'String'), 3 => array((int) $self->_id, 'Integer'), 4 => array($gId, 'Integer'))); if ($fldCnt) { $errors['label'] = ts('Custom field \'%1\' already exists in Database.', array(1 => $title)); } //checks the given custom field name doesnot start with digit if (!empty($title)) { // gives the ascii value $asciiValue = ord($title[0]); if ($asciiValue >= 48 && $asciiValue <= 57) { $errors['label'] = ts("Field's Name should not start with digit"); } } // ensure that the label is not 'id' if (strtolower($title) == 'id') { $errors['label'] = ts("You cannot use 'id' as a field label."); } if (!isset($fields['data_type'][0]) || !isset($fields['data_type'][1])) { $errors['_qf_default'] = ts('Please enter valid - Data and Input Field Type.'); } $dataType = self::$_dataTypeKeys[$fields['data_type'][0]]; if ($default || $dataType == 'ContactReference') { switch ($dataType) { case 'Int': if (!CRM_Utils_Rule::integer($default)) { $errors['default_value'] = ts('Please enter a valid integer as default value.'); } break; case 'Float': if (!CRM_Utils_Rule::numeric($default)) { $errors['default_value'] = ts('Please enter a valid number as default value.'); } break; case 'Money': if (!CRM_Utils_Rule::money($default)) { $errors['default_value'] = ts('Please enter a valid number value.'); } break; case 'Link': if (!CRM_Utils_Rule::url($default)) { $errors['default_value'] = ts('Please enter a valid link.'); } break; case 'Date': if (!CRM_Utils_Rule::date($default)) { $errors['default_value'] = ts('Please enter a valid date as default value using YYYY-MM-DD format. Example: 2004-12-31.'); } break; case 'Boolean': if ($default != '1' && $default != '0') { $errors['default_value'] = ts('Please enter 1 (for Yes) or 0 (for No) if you want to set a default value.'); } break; case 'Country': if (!empty($default)) { $query = "SELECT count(*) FROM civicrm_country WHERE name = %1 OR iso_code = %1"; $params = array(1 => array($fields['default_value'], 'String')); if (CRM_Core_DAO::singleValueQuery($query, $params) <= 0) { $errors['default_value'] = ts('Invalid default value for country.'); } } break; case 'StateProvince': if (!empty($default)) { $query = "\nSELECT count(*)\n FROM civicrm_state_province\n WHERE name = %1\n OR abbreviation = %1"; $params = array(1 => array($fields['default_value'], 'String')); if (CRM_Core_DAO::singleValueQuery($query, $params) <= 0) { $errors['default_value'] = ts('The invalid default value for State/Province data type'); } } break; case 'ContactReference': if ($fields['filter_selected'] == 'Advance' && CRM_Utils_Array::value('filter', $fields)) { if (strpos($fields['filter'], 'entity=') !== FALSE) { $errors['filter'] = ts("Please do not include entity parameter (entity is always 'contact')"); } elseif (strpos($fields['filter'], 'action=') === FALSE) { $errors['filter'] = ts("Please specify 'action' parameter, it should be 'lookup' or 'get'"); } elseif (strpos($fields['filter'], 'action=get') === FALSE && strpos($fields['filter'], 'action=lookup') === FALSE) { $errors['filter'] = ts("Only 'get' and 'lookup' actions are supported."); } } $self->setDefaults(array('filter_selected', $fields['filter_selected'])); break; } } if (self::$_dataTypeKeys[$fields['data_type'][0]] == 'Date') { if (!$fields['date_format']) { $errors['date_format'] = ts('Please select a date format.'); } } /** Check the option values entered * Appropriate values are required for the selected datatype * Incomplete row checking is also required. */ $_flagOption = $_rowError = 0; $_showHide = new CRM_Core_ShowHideBlocks('', ''); $dataType = self::$_dataTypeKeys[$fields['data_type'][0]]; if (isset($fields['data_type'][1])) { $dataField = $fields['data_type'][1]; } $optionFields = array('Select', 'Multi-Select', 'CheckBox', 'Radio', 'AdvMulti-Select'); if (isset($fields['option_type']) && $fields['option_type'] == 1) { //capture duplicate Custom option values if (!empty($fields['option_value'])) { $countValue = count($fields['option_value']); $uniqueCount = count(array_unique($fields['option_value'])); if ($countValue > $uniqueCount) { $start = 1; while ($start < self::NUM_OPTION) { $nextIndex = $start + 1; while ($nextIndex <= self::NUM_OPTION) { if ($fields['option_value'][$start] == $fields['option_value'][$nextIndex] && !empty($fields['option_value'][$nextIndex])) { $errors['option_value[' . $start . ']'] = ts('Duplicate Option values'); $errors['option_value[' . $nextIndex . ']'] = ts('Duplicate Option values'); $_flagOption = 1; } $nextIndex++; } $start++; } } } //capture duplicate Custom Option label if (!empty($fields['option_label'])) { $countValue = count($fields['option_label']); $uniqueCount = count(array_unique($fields['option_label'])); if ($countValue > $uniqueCount) { $start = 1; while ($start < self::NUM_OPTION) { $nextIndex = $start + 1; while ($nextIndex <= self::NUM_OPTION) { if ($fields['option_label'][$start] == $fields['option_label'][$nextIndex] && !empty($fields['option_label'][$nextIndex])) { $errors['option_label[' . $start . ']'] = ts('Duplicate Option label'); $errors['option_label[' . $nextIndex . ']'] = ts('Duplicate Option label'); $_flagOption = 1; } $nextIndex++; } $start++; } } } for ($i = 1; $i <= self::NUM_OPTION; $i++) { if (!$fields['option_label'][$i]) { if ($fields['option_value'][$i]) { $errors['option_label[' . $i . ']'] = ts('Option label cannot be empty'); $_flagOption = 1; } else { $_emptyRow = 1; } } else { if (!strlen(trim($fields['option_value'][$i]))) { if (!$fields['option_value'][$i]) { $errors['option_value[' . $i . ']'] = ts('Option value cannot be empty'); $_flagOption = 1; } } } if ($fields['option_value'][$i] && $dataType != 'String') { if ($dataType == 'Int') { if (!CRM_Utils_Rule::integer($fields['option_value'][$i])) { $_flagOption = 1; $errors['option_value[' . $i . ']'] = ts('Please enter a valid integer.'); } } elseif ($dataType == 'Money') { if (!CRM_Utils_Rule::money($fields['option_value'][$i])) { $_flagOption = 1; $errors['option_value[' . $i . ']'] = ts('Please enter a valid money value.'); } } else { if (!CRM_Utils_Rule::numeric($fields['option_value'][$i])) { $_flagOption = 1; $errors['option_value[' . $i . ']'] = ts('Please enter a valid number.'); } } } $showBlocks = 'optionField_' . $i; if ($_flagOption) { $_showHide->addShow($showBlocks); $_rowError = 1; } if (!empty($_emptyRow)) { $_showHide->addHide($showBlocks); } else { $_showHide->addShow($showBlocks); } if ($i == self::NUM_OPTION) { $hideBlock = 'additionalOption'; $_showHide->addHide($hideBlock); } $_flagOption = $_emptyRow = 0; } } elseif (isset($dataField) && in_array($dataField, $optionFields) && !in_array($dataType, array('Boolean', 'Country', 'StateProvince'))) { if (!$fields['option_group_id']) { $errors['option_group_id'] = ts('You must select a Multiple Choice Option set if you chose Reuse an existing set.'); } else { $query = "\nSELECT count(*)\nFROM civicrm_custom_field\nWHERE data_type != %1\nAND option_group_id = %2"; $params = array(1 => array(self::$_dataTypeKeys[$fields['data_type'][0]], 'String'), 2 => array($fields['option_group_id'], 'Integer')); $count = CRM_Core_DAO::singleValueQuery($query, $params); if ($count > 0) { $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.'); } } } $assignError = new CRM_Core_Page(); if ($_rowError) { $_showHide->addToTemplate(); $assignError->assign('optionRowError', $_rowError); } else { if (isset($fields['data_type'][1])) { switch (self::$_dataToHTML[$fields['data_type'][0]][$fields['data_type'][1]]) { case 'Radio': $_fieldError = 1; $assignError->assign('fieldError', $_fieldError); break; case 'Checkbox': $_fieldError = 1; $assignError->assign('fieldError', $_fieldError); break; case 'Select': $_fieldError = 1; $assignError->assign('fieldError', $_fieldError); break; default: $_fieldError = 0; $assignError->assign('fieldError', $_fieldError); } } for ($idx = 1; $idx <= self::NUM_OPTION; $idx++) { $showBlocks = 'optionField_' . $idx; if (!empty($fields['option_label'][$idx])) { $_showHide->addShow($showBlocks); } else { $_showHide->addHide($showBlocks); } } $_showHide->addToTemplate(); } // we can not set require and view at the same time. if (CRM_Utils_Array::value('is_required', $fields) && CRM_Utils_Array::value('is_view', $fields)) { $errors['is_view'] = ts('Can not set this field Required and View Only at the same time.'); } return empty($errors) ? TRUE : $errors; }
/** * @dataProvider numericDataProvider */ function testNumeric($inputData, $expectedResult) { $this->assertEquals($expectedResult, CRM_Utils_Rule::numeric($inputData)); }
/** * global validation rules for the form * * @param array $fields posted values of the form * * @return array list of errors to be posted back to the form * @static * @access public */ static function formRule(&$fields, &$files, &$form) { $optionLabel = CRM_Utils_Type::escape($fields['label'], 'String'); $optionValue = CRM_Utils_Type::escape($fields['value'], 'String'); $fieldId = $form->_fid; $optionGroupId = $form->_optionGroupID; $temp = array(); if (empty($form->_id)) { $query = "\nSELECT count(*) \n FROM civicrm_option_value\n WHERE option_group_id = %1\n AND label = %2"; $params = array(1 => array($optionGroupId, 'Integer'), 2 => array($optionLabel, 'String')); if (CRM_Core_DAO::singleValueQuery($query, $params) > 0) { $errors['label'] = ts('There is an entry with the same label.'); } $query = "\nSELECT count(*) \n FROM civicrm_option_value\n WHERE option_group_id = %1\n AND value = %2"; $params = array(1 => array($optionGroupId, 'Integer'), 2 => array($optionValue, 'String')); if (CRM_Core_DAO::singleValueQuery($query, $params) > 0) { $errors['value'] = ts('There is an entry with the same value.'); } } else { //capture duplicate entries while updating Custom Options $optionId = CRM_Utils_Type::escape($fields['optionId'], 'Integer'); //check label duplicates within a custom field $query = "\nSELECT count(*) \n FROM civicrm_option_value\n WHERE option_group_id = %1\n AND id != %2\n AND label = %3"; $params = array(1 => array($optionGroupId, 'Integer'), 2 => array($optionId, 'Integer'), 3 => array($optionLabel, 'String')); if (CRM_Core_DAO::singleValueQuery($query, $params) > 0) { $errors['label'] = ts('There is an entry with the same label.'); } //check value duplicates within a custom field $query = "\nSELECT count(*) \n FROM civicrm_option_value\n WHERE option_group_id = %1\n AND id != %2\n AND value = %3"; $params = array(1 => array($optionGroupId, 'Integer'), 2 => array($optionId, 'Integer'), 3 => array($optionValue, 'String')); if (CRM_Core_DAO::singleValueQuery($query, $params) > 0) { $errors['value'] = ts('There is an entry with the same value.'); } } $query = "\nSELECT data_type \n FROM civicrm_custom_field\n WHERE id = %1"; $params = array(1 => array($fieldId, 'Integer')); $dao =& CRM_Core_DAO::executeQuery($query, $params); if ($dao->fetch()) { switch ($dao->data_type) { case 'Int': if (!CRM_Utils_Rule::integer($fields["value"])) { $errors['value'] = ts('Please enter a valid integer value.'); } break; case 'Float': // case 'Money': if (!CRM_Utils_Rule::numeric($fields["value"])) { $errors['value'] = ts('Please enter a valid number value.'); } break; case 'Money': if (!CRM_Utils_Rule::money($fields["value"])) { $errors['value'] = ts('Please enter a valid value.'); } break; case 'Date': if (!CRM_Utils_Rule::date($fields["value"])) { $errors['value'] = ts('Please enter a valid date using YYYY-MM-DD format. Example: 2004-12-31.'); } break; case 'Boolean': if (!CRM_Utils_Rule::integer($fields["value"]) && ($fields["value"] != '1' || $fields["value"] != '0')) { $errors['value'] = ts('Please enter 1 or 0 as value.'); } break; case 'Country': if (!empty($fields["value"])) { $params = array(1 => array($fields['value'], 'String')); $query = "SELECT count(*) FROM civicrm_country WHERE name = %1 OR iso_code = %1"; if (CRM_Core_DAO::singleValueQuery($query, $params) <= 0) { $errors['value'] = ts('Invalid default value for country.'); } } break; case 'StateProvince': if (!empty($fields["value"])) { $params = array(1 => array($fields['value'], 'String')); $query = "\nSELECT count(*) \n FROM civicrm_state_province\n WHERE name = %1\n OR abbreviation = %1"; if (CRM_Core_DAO::singleValueQuery($query, $params) <= 0) { $errors['value'] = ts('The invalid value for State/Province data type'); } } break; } } return empty($errors) ? true : $errors; }
/** * Helper function to validate custom field value * * @params String $fieldName Custom field name (eg: custom_8 ) * @params Mixed $value Field value to be validate * @params Array $fieldDetails Field Details * @params Array $errors Collect validation errors * * @param $fieldName * @param $value * @param $fieldDetails * @param array $errors * * @return Array Validation errors * @todo remove this function - not in use but need to review functionality before * removing as it might be useful in wrapper layer */ function _civicrm_api3_custom_field_validate_field($fieldName, $value, $fieldDetails, &$errors = array()) { return; //see comment block if (!$value) { return $errors; } $dataType = $fieldDetails['data_type']; $htmlType = $fieldDetails['html_type']; switch ($dataType) { case 'Int': if (!CRM_Utils_Rule::integer($value)) { $errors[$fieldName] = 'Invalid integer value for ' . $fieldName; } break; case 'Float': if (!CRM_Utils_Rule::numeric($value)) { $errors[$fieldName] = 'Invalid numeric value for ' . $fieldName; } break; case 'Money': if (!CRM_Utils_Rule::money($value)) { $errors[$fieldName] = 'Invalid numeric value for ' . $fieldName; } break; case 'Link': if (!CRM_Utils_Rule::url($value)) { $errors[$fieldName] = 'Invalid link for ' . $fieldName; } break; case 'Boolean': if ($value != '1' && $value != '0') { $errors[$fieldName] = 'Invalid boolean (use 1 or 0) value for ' . $fieldName; } break; case 'Country': if (empty($value)) { break; } if ($htmlType != 'Multi-Select Country' && is_array($value)) { $errors[$fieldName] = 'Invalid country for ' . $fieldName; break; } if (!is_array($value)) { $value = array($value); } $query = "SELECT count(*) FROM civicrm_country WHERE id IN (" . implode(',', $value) . ")"; if (CRM_Core_DAO::singleValueQuery($query) < count($value)) { $errors[$fieldName] = 'Invalid country(s) for ' . $fieldName; } break; case 'StateProvince': if (empty($value)) { break; } if ($htmlType != 'Multi-Select State/Province' && is_array($value)) { $errors[$fieldName] = 'Invalid State/Province for ' . $fieldName; break; } if (!is_array($value)) { $value = array($value); } $query = "\nSELECT count(*)\n FROM civicrm_state_province\n WHERE id IN ('" . implode("','", $value) . "')"; if (CRM_Core_DAO::singleValueQuery($query) < count($value)) { $errors[$fieldName] = 'Invalid State/Province for ' . $fieldName; } break; case 'ContactReference': //FIX ME break; } if (in_array($htmlType, array('Select', 'Multi-Select', 'CheckBox', 'Radio', 'AdvMulti-Select')) && !isset($errors[$fieldName])) { $options = CRM_Core_OptionGroup::valuesByID($fieldDetails['option_group_id']); if (!is_array($value)) { $value = array($value); } $invalidOptions = array_diff($value, array_keys($options)); if (!empty($invalidOptions)) { $errors[$fieldName] = "Invalid option(s) for field '{$fieldName}': " . implode(',', $invalidOptions); } } return $errors; }
/** * Verify that a variable is of a given type. * * @param mixed $data * The value to validate. * @param string $type * The type to validate against. * @param bool $abort * If TRUE, the operation will CRM_Core_Error::fatal() on invalid data. * @name string $name * The name of the attribute * * @return mixed * The data, escaped if necessary */ public static function validate($data, $type, $abort = TRUE, $name = 'One of parameters ') { switch ($type) { case 'Integer': case 'Int': if (CRM_Utils_Rule::integer($data)) { return (int) $data; } break; case 'Positive': if (CRM_Utils_Rule::positiveInteger($data)) { return $data; } break; case 'Boolean': if (CRM_Utils_Rule::boolean($data)) { return $data; } break; case 'Float': case 'Money': if (CRM_Utils_Rule::numeric($data)) { return $data; } break; case 'Text': case 'String': case 'Link': case 'Memo': return $data; case 'Date': // a null date is valid if (strlen(trim($data)) == 0) { return trim($data); } if (preg_match('/^\\d{8}$/', $data) && CRM_Utils_Rule::mysqlDate($data)) { return $data; } break; case 'Timestamp': // a null timestamp is valid if (strlen(trim($data)) == 0) { return trim($data); } if ((preg_match('/^\\d{14}$/', $data) || preg_match('/^\\d{8}$/', $data)) && CRM_Utils_Rule::mysqlDate($data)) { return $data; } break; case 'ContactReference': // null is valid if (strlen(trim($data)) == 0) { return trim($data); } if (CRM_Utils_Rule::validContact($data)) { return $data; } break; default: CRM_Core_Error::fatal("Cannot recognize {$type} for {$data}"); break; } if ($abort) { $data = htmlentities($data); CRM_Core_Error::fatal("{$name} (value: {$data}) is not of the type {$type}"); } return NULL; }
/** * Get contacts by proximity. * * @param array $params * * @return array * @throws Exception */ function civicrm_api3_contact_proximity($params) { $latitude = CRM_Utils_Array::value('latitude', $params); $longitude = CRM_Utils_Array::value('longitude', $params); $distance = CRM_Utils_Array::value('distance', $params); $unit = CRM_Utils_Array::value('unit', $params); // check and ensure that lat/long and distance are floats if (!CRM_Utils_Rule::numeric($latitude) || !CRM_Utils_Rule::numeric($longitude) || !CRM_Utils_Rule::numeric($distance)) { throw new Exception(ts('Latitude, Longitude and Distance should exist and be numeric')); } if ($unit == "mile") { $conversionFactor = 1609.344; } else { $conversionFactor = 1000; } //Distance in meters $distance = $distance * $conversionFactor; $whereClause = CRM_Contact_BAO_ProximityQuery::where($latitude, $longitude, $distance); $query = "\nSELECT civicrm_contact.id as contact_id,\n civicrm_contact.display_name as display_name\nFROM civicrm_contact\nLEFT JOIN civicrm_address ON civicrm_contact.id = civicrm_address.contact_id\nWHERE {$whereClause}\n"; $dao = CRM_Core_DAO::executeQuery($query); $contacts = array(); while ($dao->fetch()) { $contacts[] = $dao->toArray(); } return civicrm_api3_create_success($contacts, $params, 'Contact', 'get_by_location', $dao); }
/** * Helper method to filter Projects by location. * * @param array $params * <ol> * <li>string city - optional. Not used in this function, just passed along for geocoding.</li> * <li>mixed country - required if lat/lon not provided. Can be country_id or string.</li> * <li>float lat - required if country not provided</li> * <li>float lon - required if country not provided</li> * <li>string postal_code - optional. Not used in this function, just passed along for geocoding.</li> * <li>float radius - required</li> * <li>string street_address - optional. Not used in this function, just passed along for geocoding.</li> * <li>string unit - optional, defaults to meters unless 'mile' is specified</li> * </ol> * @return string * SQL fragment (partial where clause) * @throws Exception */ private static function buildProximityWhere(array $params) { $country = $lat = $lon = $radius = $unit = NULL; extract($params, EXTR_IF_EXISTS); // ensure that radius is a float if (!CRM_Utils_Rule::numeric($radius)) { throw new Exception(ts('Radius should exist and be numeric')); } if (!CRM_Utils_Rule::numeric($lat) || !CRM_Utils_Rule::numeric($lon)) { if (empty($country)) { throw new Exception(ts('Either Country or both Latitude and Longitude are required')); } // TODO: I think CRM_Utils_Geocode_*::format should be responsible for this if (CRM_Utils_Type::validate($country, 'Positive', FALSE)) { $country = civicrm_api3('Country', 'getvalue', array('id' => $country, 'return' => 'name')); } // TODO: support other geocoders $geocodeSuccess = CRM_Utils_Geocode_Google::format($params); if (!$geocodeSuccess) { // this is intentionally a string; a query like "SELECT * FROM foo WHERE FALSE" // will return an empty set, which is what we should do if the provided address // can't be geocoded return 'FALSE'; } // $params is passed to the geocoder by reference; on success, these values // will be available $lat = $params['geo_code_1']; $lon = $params['geo_code_2']; } $conversionFactor = $unit == "mile" ? 1609.344 : 1000; //radius in meters $radius = $radius * $conversionFactor; return CRM_Contact_BAO_ProximityQuery::where($lat, $lon, $radius); }
/** * global validation rules for the form * * @param array $fields posted values of the form * * @return array list of errors to be posted back to the form * @static * @access public */ function formRule(&$fields) { $optionLabel = CRM_Utils_Type::escape($fields['label'], 'String'); $optionValue = CRM_Utils_Type::escape($fields['value'], 'String'); if (empty($fields['optionId'])) { $fieldId = $fields['fieldId']; //check label duplicates within a custom field $query = "SELECT count(*) FROM civicrm_custom_option WHERE entity_id = '{$fieldId}' AND entity_table = 'civicrm_custom_field' AND label = '{$optionLabel}'"; if (CRM_Core_DAO::singleValueQuery($query) > 0) { $errors['label'] = 'There is an entry with the same label.'; } //check value duplicates within a custom field $query = "SELECT count(*) FROM civicrm_custom_option WHERE entity_id = '{$fieldId}' AND entity_table = 'civicrm_custom_field' AND value = '{$optionValue}'"; if (CRM_Core_DAO::singleValueQuery($query) > 0) { $errors['value'] = 'There is an entry with the same value.'; } } else { //capture duplicate entries while updating Custom Options $optionId = CRM_Utils_Type::escape($fields['optionId'], 'Integer'); $fieldId = CRM_Utils_Type::escape($fields['fieldId'], 'Integer'); //check label duplicates within a custom field $query = "SELECT count(*) FROM civicrm_custom_option WHERE entity_id = '{$fieldId}' AND entity_table = 'civicrm_custom_field' AND id != '{$optionId}' AND label = '{$optionLabel}'"; if (CRM_Core_DAO::singleValueQuery($query) > 0) { $errors['label'] = 'There is an entry with same label.'; } //check value duplicates within a custom field $query = "SELECT count(*) FROM civicrm_custom_option WHERE entity_id = '{$fieldId}' AND entity_table = 'civicrm_custom_field' AND id != '{$optionId}' AND value = '{$optionValue}'"; if (CRM_Core_DAO::singleValueQuery($query) > 0) { $errors['value'] = 'There is an entry with same value'; } } $query = "SELECT data_type FROM civicrm_custom_field WHERE id = '{$fieldId}'"; $dao = new CRM_Core_DAO(); $dao->query($query); $dao->fetch(); switch ($dao->data_type) { case 'Int': if (!CRM_Utils_Rule::integer($fields["value"])) { $errors['value'] = ts('Please enter a valid integer value.'); } break; case 'Float': case 'Money': if (!CRM_Utils_Rule::numeric($fields["value"])) { $errors['value'] = ts('Please enter a valid number value.'); } break; case 'Date': if (!CRM_Utils_Rule::date($fields["value"])) { $errors['value'] = ts('Please enter a valid date using YYYY-MM-DD format. Example: 2004-12-31.'); } break; case 'Boolean': if (!CRM_Utils_Rule::integer($fields["value"]) && ($fields["value"] != '1' || $fields["value"] != '0')) { $errors['value'] = ts('Please enter 1 or 0 as value.'); } break; case 'Country': if (!empty($fields["value"])) { $fieldCountry = addslashes($fields['value']); $query = "SELECT count(*) FROM civicrm_country WHERE name = '{$fieldCountry}' OR iso_code = '{$fieldCountry}'"; if (CRM_Core_DAO::singleValueQuery($query) <= 0) { $errors['value'] = ts('Invalid default value for country.'); } } break; case 'StateProvince': if (!empty($fields["value"])) { $fieldStateProvince = addslashes($fields['value']); $query = "SELECT count(*) FROM civicrm_state_province WHERE name = '{$fieldStateProvince}' OR abbreviation = '{$fieldStateProvince}'"; if (CRM_Core_DAO::singleValueQuery($query) <= 0) { $errors['value'] = ts('The invalid value for State/Province data type'); } } break; } return empty($errors) ? true : $errors; }
/** * function to check if an error in Core( non-custom fields ) field * * @param String $errorMessage A string containing all the error-fields. * * @access public */ function isErrorInCoreData($params, &$errorMessage) { foreach ($params as $key => $value) { if ($value) { switch ($key) { case 'birth_date': if (!CRM_Utils_Rule::date($value)) { //return _crm_error('Birth Date'); CRM_Import_Parser_Contact::addToErrorMsg('Birth Date', $errorMessage); } break; case 'gender': if (!CRM_Import_Parser_Contact::in_value($value, CRM_Core_PseudoConstant::gender(true))) { //return _crm_error('Invalid value for field : Gender'); CRM_Import_Parser_Contact::addToErrorMsg('Gender', $errorMessage); } break; case 'preferred_communication_method': if (!array_key_exists(strtolower($value), array_change_key_case(CRM_Core_SelectValues::pcm(), CASE_LOWER))) { //return _crm_error('Invalid value for field : Preferred Communication Method'); CRM_Import_Parser_Contact::addToErrorMsg('Preferred Communication Method', $errorMessage); } break; case 'preferred_mail_format': if (!array_key_exists(strtolower($value), array_change_key_case(CRM_Core_SelectValues::pmf(), CASE_LOWER))) { //return _crm_error('Invalid value for field : Preferred Communication Method'); CRM_Import_Parser_Contact::addToErrorMsg('Preferred Mail Format', $errorMessage); } break; case 'individual_prefix': if (!CRM_Import_Parser_Contact::in_value($value, CRM_Core_PseudoConstant::individualPrefix(true))) { //return _crm_error('Invalid value for field : Individual Prefix'); CRM_Import_Parser_Contact::addToErrorMsg('Individual Prefix', $errorMessage); } break; case 'individual_suffix': if (!CRM_Import_Parser_Contact::in_value($value, CRM_Core_PseudoConstant::individualSuffix(true))) { //return _crm_error('Invalid value for field : Individual Suffix'); CRM_Import_Parser_Contact::addToErrorMsg('Individual Suffix', $errorMessage); } break; case 'state_province': if (!empty($value)) { foreach ($value as $stateValue) { if ($stateValue['state_province']) { if (CRM_Import_Parser_Contact::in_value($stateValue['state_province'], CRM_Core_PseudoConstant::stateProvinceAbbreviation()) || CRM_Import_Parser_Contact::in_value($stateValue['state_province'], CRM_Core_PseudoConstant::stateProvince())) { continue; } else { //return _crm_error('Invalid value for field : State Province '); CRM_Import_Parser_Contact::addToErrorMsg('State Province', $errorMessage); } } } } break; case 'country': if (!empty($value)) { foreach ($value as $stateValue) { if ($stateValue['country']) { if (CRM_Import_Parser_Contact::in_value($stateValue['country'], CRM_Core_PseudoConstant::countryIsoCode()) || CRM_Import_Parser_Contact::in_value($stateValue['country'], CRM_Core_PseudoConstant::country())) { continue; } else { //return _crm_error('Invalid value for field : Country'); CRM_Import_Parser_Contact::addToErrorMsg('Country', $errorMessage); } } } } break; case 'geo_code_1': if (!empty($value)) { foreach ($value as $codeValue) { if ($codeValue['geo_code_1']) { if (CRM_Utils_Rule::numeric($codeValue['geo_code_1'])) { continue; } else { //return _crm_error('Invalid value for field : geo_code_1'); CRM_Import_Parser_Contact::addToErrorMsg('geo_code_1', $errorMessage); } } } } break; case 'geo_code_2': if (!empty($value)) { foreach ($value as $codeValue) { if ($codeValue['geo_code_2']) { if (CRM_Utils_Rule::numeric($codeValue['geo_code_2'])) { continue; } else { //return _crm_error('Invalid value for field : geo_code_2'); CRM_Import_Parser_Contact::addToErrorMsg('geo_code_2', $errorMessage); } } } } } } } //return true; }
/** * Verify that a variable is of a given type * * @param mixed $data The variable * @param string $type The type * @return mixed The data, escaped if necessary * @access public * @static */ function escape($data, $type) { require_once 'CRM/Utils/Rule.php'; switch ($type) { case 'Integer': case 'Int': if (CRM_Utils_Rule::integer($data)) { return $data; } break; case 'Float': case 'Money': if (CRM_Utils_Rule::numeric($data)) { return $data; } break; case 'String': return addslashes($data); break; case 'Date': if (preg_match('/^\\d{8}$/', $data)) { return $data; } break; case 'Timestamp': if (preg_match('/^\\d{14}$/', $data)) { return $data; } break; } }
/** * global validation rules for the form * * @param array $fields (referance) posted values of the form * * @return array if errors then list of errors to be posted back to the form, * true otherwise * @static * @access public */ function formRule(&$fields) { $default = CRM_Utils_Array::value('default_value', $fields); $errors = array(); if ($default) { $dataType = $GLOBALS['_CRM_CUSTOM_FORM_FIELD']['_dataTypeKeys'][$fields['data_type'][0]]; switch ($dataType) { case 'Int': if (!CRM_Utils_Rule::integer($default)) { $errors['default_value'] = ts('Please enter a valid integer as default value.'); } break; case 'Float': case 'Money': if (!CRM_Utils_Rule::numeric($default)) { $errors['default_value'] = ts('Please enter a valid number as default value.'); } break; case 'Date': if (!CRM_Utils_Rule::date($default)) { $errors['default_value'] = ts('Please enter a valid date as default value using YYYY-MM-DD format. Example: 2004-12-31.'); } break; case 'Boolean': if (!CRM_Utils_Rule::integer($default) && ($default != '1' || $default != '0')) { $errors['default_value'] = ts('Please enter 1 or 0 as default value.'); } break; case 'Country': if (!empty($default)) { $fieldCountry = addslashes($fields['default_value']); $query = "SELECT count(*) FROM civicrm_country WHERE name = '{$fieldCountry}' OR iso_code = '{$fieldCountry}'"; if (CRM_Core_DAO::singleValueQuery($query) <= 0) { $errors['default_value'] = ts('Invalid default value for country.'); } } break; case 'StateProvince': if (!empty($default)) { $fieldStateProvince = addslashes($fields['default_value']); $query = "SELECT count(*) FROM civicrm_state_province WHERE name = '{$fieldStateProvince}' OR abbreviation = '{$fieldStateProvince}'"; if (CRM_Core_DAO::singleValueQuery($query) <= 0) { $errors['default_value'] = ts('The invalid default value for State/Province data type'); } } break; } } /** Check the option values entered * Appropriate values are required for the selected datatype * Incomplete row checking is also required. */ if (CRM_CORE_ACTION_ADD) { $_flagOption = $_rowError = 0; $_showHide =& new CRM_Core_ShowHideBlocks('', ''); $dataType = $GLOBALS['_CRM_CUSTOM_FORM_FIELD']['_dataTypeKeys'][$fields['data_type'][0]]; //capture duplicate Custom option values if (!empty($fields['option_value'])) { $countValue = count($fields['option_value']); $uniqueCount = count(array_unique($fields['option_value'])); if ($countValue > $uniqueCount) { $start = 1; while ($start < CRM_CUSTOM_FORM_FIELD_NUM_OPTION) { $nextIndex = $start + 1; while ($nextIndex <= CRM_CUSTOM_FORM_FIELD_NUM_OPTION) { if ($fields['option_value'][$start] == $fields['option_value'][$nextIndex] && !empty($fields['option_value'][$nextIndex])) { $errors['option_value[' . $start . ']'] = ts('Duplicate Option values'); $errors['option_value[' . $nextIndex . ']'] = ts('Duplicate Option values'); $_flagOption = 1; } $nextIndex++; } $start++; } } } //capture duplicate Custom Option label if (!empty($fields['option_label'])) { $countValue = count($fields['option_label']); $uniqueCount = count(array_unique($fields['option_label'])); if ($countValue > $uniqueCount) { $start = 1; while ($start < CRM_CUSTOM_FORM_FIELD_NUM_OPTION) { $nextIndex = $start + 1; while ($nextIndex <= CRM_CUSTOM_FORM_FIELD_NUM_OPTION) { if ($fields['option_label'][$start] == $fields['option_label'][$nextIndex] && !empty($fields['option_label'][$nextIndex])) { $errors['option_label[' . $start . ']'] = ts('Duplicate Option label'); $errors['option_label[' . $nextIndex . ']'] = ts('Duplicate Option label'); $_flagOption = 1; } $nextIndex++; } $start++; } } } for ($i = 1; $i <= CRM_CUSTOM_FORM_FIELD_NUM_OPTION; $i++) { if (!$fields['option_label'][$i]) { if ($fields['option_value'][$i]) { $errors['option_label[' . $i . ']'] = ts('Option label cannot be empty'); $_flagOption = 1; } else { $_emptyRow = 1; } } else { if (!strlen(trim($fields['option_value'][$i]))) { if (!$fields['option_value'][$i]) { $errors['option_value[' . $i . ']'] = ts('Option value cannot be empty'); $_flagOption = 1; } } } if ($fields['option_value'][$i] && $dataType != 'String') { if ($dataType == 'Int') { if (!CRM_Utils_Rule::integer($fields['option_value'][$i])) { $_flagOption = 1; $errors['option_value[' . $i . ']'] = ts('Please enter a valid integer.'); } } else { if (!CRM_Utils_Rule::numeric($fields['option_value'][$i])) { $_flagOption = 1; $errors['option_value[' . $i . ']'] = ts('Please enter a valid number.'); } } } $showBlocks = 'optionField[' . $i . ']'; if ($_flagOption) { $_showHide->addShow($showBlocks); $_rowError = 1; } if ($_emptyRow) { $_showHide->addHide($showBlocks); } else { $_showHide->addShow($showBlocks); } if ($i == CRM_CUSTOM_FORM_FIELD_NUM_OPTION) { $hideBlock = 'additionalOption'; $_showHide->addHide($hideBlock); } $_flagOption = $_emptyRow = 0; } if ($_rowError) { $_showHide->addToTemplate(); CRM_Core_Page::assign('optionRowError', $_rowError); } else { switch ($GLOBALS['_CRM_CUSTOM_FORM_FIELD']['_dataToHTML'][$fields['data_type'][0]][$fields['data_type'][1]]) { case 'Radio': $_fieldError = 1; CRM_Core_Page::assign('fieldError', $_fieldError); break; case 'Checkbox': $_fieldError = 1; CRM_Core_Page::assign('fieldError', $_fieldError); break; case 'Select': $_fieldError = 1; CRM_Core_Page::assign('fieldError', $_fieldError); break; default: $_fieldError = 0; CRM_Core_Page::assign('fieldError', $_fieldError); } for ($idx = 1; $idx <= CRM_CUSTOM_FORM_FIELD_NUM_OPTION; $idx++) { $showBlocks = 'optionField[' . $idx . ']'; if (!empty($fields['option_label'][$idx])) { $_showHide->addShow($showBlocks); } else { $_showHide->addHide($showBlocks); } } $_showHide->addToTemplate(); } } return empty($errors) ? true : $errors; }