X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=api%2Fv3%2Futils.php;h=3fb9699444568f795502c324bd11f4cb4696ecae;hb=85bb0909cffd925f4cd5c0022a68a1ff74d3ad8e;hp=1ee834087b9e59ff4d970db954dedc249fb7d344;hpb=fb7f68ebd620e5b50faa18212d414a755345b3f7;p=civicrm-core.git diff --git a/api/v3/utils.php b/api/v3/utils.php index 1ee834087b..3fb9699444 100644 --- a/api/v3/utils.php +++ b/api/v3/utils.php @@ -50,9 +50,8 @@ function _civicrm_api3_initialize() { * * @param array $params array of fields to checkl * @param array $daoName string DAO to check for required fields (create functions only) - * @param array $keyoptions + * @param array $keyoptions list of required fields options. One of the options is required * - * @internal param array $keys list of required fields options. One of the options is required * @return null or throws error if there the required fields not present * @ */ @@ -308,6 +307,7 @@ function _civicrm_api3_get_DAO($name) { if(file_exists("api/v3/$name.php")) { include_once "api/v3/$name.php"; } + $daoFn = "_civicrm_api3_" . _civicrm_api_get_entity_name_from_camel($name) . "_DAO"; if (function_exists($daoFn)) { return $daoFn(); @@ -408,11 +408,10 @@ function _civicrm_api3_store_values(&$fields, &$params, &$values) { * 2 variants call * @param $entity * @param array $params as passed into api get or getcount function - * @param array $additional_options + * @param array $additional_options array of options (so we can modify the filter) * @param bool $getCount are we just after the count * * @return - * @internal param array $options array of options (so we can modify the filter) */ function _civicrm_api3_get_using_query_object($entity, $params, $additional_options = array(), $getCount = NULL){ @@ -926,9 +925,25 @@ function _civicrm_api3_object_to_array_unique_fields(&$dao, &$values) { */ function _civicrm_api3_custom_format_params($params, &$values, $extends, $entityId = NULL) { $values['custom'] = array(); + $checkCheckBoxField = FALSE; + $entity = $extends; + if(in_array($extends, array('Household', 'Individual', 'Organization'))) { + $entity = 'Contact'; + } + + $fields = civicrm_api($entity, 'getfields', array('version' => 3, 'action' => 'create')); + if(!$fields['is_error']) { + // not sure if fields could be error - maybe change to using civicrm_api3 wrapper later - this is conservative + $fields = $fields['values']; + $checkCheckBoxField = TRUE; + } + foreach ($params as $key => $value) { list($customFieldID, $customValueID) = CRM_Core_BAO_CustomField::getKeyID($key, TRUE); if ($customFieldID && (!IS_NULL($value))) { + if ($checkCheckBoxField && !empty($fields['custom_' . $customFieldID]) && $fields['custom_' . $customFieldID]['html_type'] == 'CheckBox') { + formatCheckBoxField($value, 'custom_' . $customFieldID, $entity); + } CRM_Core_BAO_CustomField::formatCustomField($customFieldID, $values['custom'], $value, $extends, $customValueID, $entityId, FALSE, FALSE ); @@ -952,6 +967,101 @@ function _civicrm_api3_format_params_for_create(&$params, $entity) { $params = array_merge($params, $values); } +/** + * we can't rely on downstream to add separators to checkboxes so we'll check here. We should look at pushing to BAO function + * and / or validate function but this is a safe place for now as it has massive test coverage & we can keep the change very specific + * note that this is specifically tested in the GRANT api test case so later refactoring should use that as a checking point + * + * We will only alter the value if we are sure that changing it will make it correct - if it appears wrong but does not appear to have a clear fix we + * don't touch - lots of very cautious code in here + * + * The resulting array should look like + * array( + * 'key' => 1, + * 'key1' => 1, + * ); + * + * OR one or more keys wrapped in a CRM_Core_DAO::VALUE_SEPARATOR - either it accepted by the receiving function + * + * @todo - we are probably skipping handling disabled options as presumably getoptions is not giving us them. This should be non-regressive but might + * be fixed in future + * + * @param $checkboxFieldValue + * @param $customFieldLabel + * @param $entity + * + */ +function formatCheckBoxField(&$checkboxFieldValue, $customFieldLabel, $entity) { + + if (is_string($checkboxFieldValue) && stristr($checkboxFieldValue, CRM_Core_DAO::VALUE_SEPARATOR)) { + // we can assume it's pre-formatted + return; + } + $options = civicrm_api($entity, 'getoptions', array('field' => $customFieldLabel, 'version' => 3)); + if (!empty($options['is_error'])) { + //the check is precautionary - can probably be removed later + return; + } + + $options = $options['values']; + $validValue = TRUE; + if (is_array($checkboxFieldValue)) { + foreach ($checkboxFieldValue as $key => $value) { + if (!array_key_exists($key, $options)) { + $validValue = FALSE; + } + } + if ($validValue) { + // we have been passed an array that is already in the 'odd' custom field format + return; + } + } + + // so we either have an array that is not keyed by the value or we have a string that doesn't hold separators + // if the array only has one item we'll treat it like any other string + if (is_array($checkboxFieldValue) && count($checkboxFieldValue) == 1) { + $possibleValue = reset($checkboxFieldValue); + } + if (is_string($checkboxFieldValue)) { + $possibleValue = $checkboxFieldValue; + } + if (isset($possibleValue) && array_key_exists($possibleValue, $options)) { + $checkboxFieldValue = CRM_Core_DAO::VALUE_SEPARATOR . $possibleValue . CRM_Core_DAO::VALUE_SEPARATOR; + return; + } + elseif (is_array($checkboxFieldValue)) { + // so this time around we are considering the values in the array + $possibleValues = $checkboxFieldValue; + $formatValue = TRUE; + } + elseif (stristr($checkboxFieldValue, ',')) { + $formatValue = TRUE; + //lets see if we should separate it - we do this near the end so we + // ensure we have already checked that the comma is not part of a legitimate match + // and of course, we don't make any changes if we don't now have matches + $possibleValues = explode(',', $checkboxFieldValue); + } + else { + // run out of ideas as to what the format might be - if it's a string it doesn't match with or without the ',' + return; + } + + foreach ($possibleValues as $index => $possibleValue) { + if (array_key_exists($possibleValue, $options)) { + // do nothing - we will leave formatValue set to true unless another value is not found (which would cause us to ignore the whole value set) + } + elseif (array_key_exists(trim($possibleValue), $options)) { + $possibleValues[$index] = trim($possibleValue); + } + else { + $formatValue = FALSE; + } + } + if ($formatValue) { + $checkboxFieldValue = CRM_Core_DAO::VALUE_SEPARATOR . implode(CRM_Core_DAO::VALUE_SEPARATOR, $possibleValues) . CRM_Core_DAO::VALUE_SEPARATOR; + } +} + /** * @deprecated * This function ensures that we have the right input parameters @@ -1281,7 +1391,7 @@ function _civicrm_api3_validate_fields($entity, $action, &$params, $fields, $err * * @param array $params params from civicrm_api * @param string $fieldName uniquename of field being checked - * @param array $fieldInfo + * @param array $fieldInfo array of fields from getfields function * @throws Exception */ function _civicrm_api3_validate_date(&$params, &$fieldName, &$fieldInfo) { @@ -1327,9 +1437,8 @@ function _civicrm_api3_getValidDate($dateValue, $fieldName, $fieldType) { * * @param array $params params from civicrm_api * @param string $fieldName uniquename of field being checked - * @param $fieldInfo + * @param array $fieldInfo array of fields from getfields function * @throws Exception - * @internal param array $fieldinfo array of fields from getfields function */ function _civicrm_api3_validate_constraint(&$params, &$fieldName, &$fieldInfo) { $dao = new $fieldInfo['FKClassName']; @@ -1346,9 +1455,8 @@ function _civicrm_api3_validate_constraint(&$params, &$fieldName, &$fieldInfo) { * * @param array $params params from civicrm_api * @param string $fieldName uniquename of field being checked - * @param $fieldInfo + * @param $fieldInfo array of fields from getfields function * @throws Exception - * @internal param array $fieldinfo array of fields from getfields function */ function _civicrm_api3_validate_uniquekey(&$params, &$fieldName, &$fieldInfo) { $existing = civicrm_api($params['entity'], 'get', array( @@ -1601,10 +1709,9 @@ function _civicrm_api3_swap_out_aliases(&$apiRequest, $fields) { * * @param array $params params from civicrm_api * @param string $fieldName uniquename of field being checked - * @param $fieldInfo - * @param $entity + * @param array $fieldInfo array of fields from getfields function + * @param string $entity * @throws API_Exception - * @internal param array $fieldinfo array of fields from getfields function */ function _civicrm_api3_validate_integer(&$params, &$fieldName, &$fieldInfo, $entity) { if (!empty($params[$fieldName])) { @@ -1669,13 +1776,13 @@ function _civicrm_api3_resolve_contactID($contactIdExpr) { /** * Validate html (check for scripting attack) - * @param $params - * @param $fieldName - * @param $fieldInfo + * @param array $params + * @param string $fieldName + * @param array $fieldInfo * * @throws API_Exception */ -function _civicrm_api3_validate_html(&$params, &$fieldName, &$fieldInfo) { +function _civicrm_api3_validate_html(&$params, &$fieldName, $fieldInfo) { if ($value = CRM_Utils_Array::value($fieldName, $params)) { if (!CRM_Utils_Rule::xssString($value)) { throw new API_Exception('Illegal characters in input (potential scripting attack)', array("field"=>$fieldName,"error_code"=>"xss")); @@ -1688,7 +1795,7 @@ function _civicrm_api3_validate_html(&$params, &$fieldName, &$fieldInfo) { * @param array $params params from civicrm_api * @param string $fieldName uniquename of field being checked * @param array $fieldInfo array of fields from getfields function - * @param $entity + * @param string $entity * @throws API_Exception * @throws Exception */ @@ -1716,8 +1823,8 @@ function _civicrm_api3_validate_string(&$params, &$fieldName, &$fieldInfo, $enti _civicrm_api3_api_match_pseudoconstant($params, $entity, $fieldName, $fieldInfo); } // Check our field length - elseif (is_string($value) && !empty($fieldInfo['maxlength']) && strlen($value) > $fieldInfo['maxlength']) { - throw new API_Exception("Value for $fieldName is " . strlen($value) . " characters - This field has a maxlength of {$fieldInfo['maxlength']} characters.", + elseif (is_string($value) && !empty($fieldInfo['maxlength']) && strlen(utf8_decode($value)) > $fieldInfo['maxlength']) { + throw new API_Exception("Value for $fieldName is " . strlen(utf8_decode($value)) . " characters - This field has a maxlength of {$fieldInfo['maxlength']} characters.", 2100, array('field' => $fieldName) ); } @@ -1727,10 +1834,10 @@ function _civicrm_api3_validate_string(&$params, &$fieldName, &$fieldInfo, $enti /** * Validate & swap out any pseudoconstants / options * - * @param $params: api parameters - * @param $entity: api entity name - * @param $fieldName: field name used in api call (not necessarily the canonical name) - * @param $fieldInfo: getfields meta-data + * @param array $params: api parameters + * @param string $entity: api entity name + * @param string $fieldName: field name used in api call (not necessarily the canonical name) + * @param array $fieldInfo: getfields meta-data */ function _civicrm_api3_api_match_pseudoconstant(&$params, $entity, $fieldName, $fieldInfo) { $options = CRM_Utils_Array::value('options', $fieldInfo); @@ -1771,9 +1878,9 @@ function _civicrm_api3_api_match_pseudoconstant(&$params, $entity, $fieldName, $ /** * Validate & swap a single option value for a field * - * @param $value: field value - * @param $options: array of options for this field - * @param $fieldName: field name used in api call (not necessarily the canonical name) + * @param string $value: field value + * @param array $options: array of options for this field + * @param string $fieldName: field name used in api call (not necessarily the canonical name) * @throws API_Exception */ function _civicrm_api3_api_match_pseudoconstant_value(&$value, $options, $fieldName) {