+
+/**
+ * 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
+ */
+function _civicrm_api3_api_match_pseudoconstant(&$params, $entity, $fieldName, $fieldInfo) {
+ $options = CRM_Utils_Array::value('options', $fieldInfo);
+ if (!$options) {
+ $options = civicrm_api($entity, 'getoptions', array('version' => 3, 'field' => $fieldInfo['name'], 'context' => 'validate'));
+ $options = CRM_Utils_Array::value('values', $options, array());
+ }
+
+ // If passed a value-seperated string, explode to an array, then re-implode after matching values
+ $implode = FALSE;
+ if (is_string($params[$fieldName]) && strpos($params[$fieldName], CRM_Core_DAO::VALUE_SEPARATOR) !== FALSE) {
+ $params[$fieldName] = CRM_Utils_Array::explodePadded($params[$fieldName]);
+ $implode = TRUE;
+ }
+ // If passed multiple options, validate each
+ if (is_array($params[$fieldName])) {
+ foreach ($params[$fieldName] as &$value) {
+ if (!is_array($value)) {
+ _civicrm_api3_api_match_pseudoconstant_value($value, $options, $fieldName);
+ }
+ }
+ // TODO: unwrap the call to implodePadded from the conditional and do it always
+ // need to verify that this is safe and doesn't break anything though.
+ // Better yet would be to leave it as an array and ensure that every dao/bao can handle array input
+ if ($implode) {
+ CRM_Utils_Array::implodePadded($params[$fieldName]);
+ }
+ }
+ else {
+ _civicrm_api3_api_match_pseudoconstant_value($params[$fieldName], $options, $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)
+ */
+function _civicrm_api3_api_match_pseudoconstant_value(&$value, $options, $fieldName) {
+ // If option is a key, no need to translate
+ if (array_key_exists($value, $options)) {
+ return;
+ }
+
+ // Translate value into key
+ $newValue = array_search($value, $options);
+ if ($newValue !== FALSE) {
+ $value = $newValue;
+ return;
+ }
+ // Case-insensitive matching
+ $newValue = strtolower($value);
+ $options = array_map("strtolower", $options);
+ $newValue = array_search($newValue, $options);
+ if ($newValue === FALSE) {
+ throw new API_Exception("'$value' is not a valid option for field $fieldName", 2001, array('error_field' => $fieldName));
+ }
+ $value = $newValue;
+}
+
+/**
+ * Returns the canonical name of a field
+ * @param $entity: api entity name (string should already be standardized - no camelCase)
+ * @param $fieldName: any variation of a field's name (name, unique_name, api.alias)
+ *
+ * @return (string|bool) fieldName or FALSE if the field does not exist
+ */
+function _civicrm_api3_api_resolve_alias($entity, $fieldName) {
+ if (strpos($fieldName, 'custom_') === 0 && is_numeric($fieldName[7])) {
+ return $fieldName;
+ }
+ if ($fieldName == "{$entity}_id") {
+ return 'id';
+ }
+ $result = civicrm_api($entity, 'getfields', array(
+ 'version' => 3,
+ 'action' => 'create',
+ ));
+ $meta = $result['values'];
+ if (!isset($meta[$fieldName]['name']) && isset($meta[$fieldName . '_id'])) {
+ $fieldName = $fieldName . '_id';
+ }
+ if (isset($meta[$fieldName])) {
+ return $meta[$fieldName]['name'];
+ }
+ foreach ($meta as $info) {
+ if ($fieldName == CRM_Utils_Array::value('uniqueName', $info)) {
+ return $info['name'];
+ }
+ if (array_search($fieldName, CRM_Utils_Array::value('api.aliases', $info, array())) !== FALSE) {
+ return $info['name'];
+ }
+ }
+ return FALSE;
+}