From 94359f7eb78c7324bd8fcf7c8c4418856f9c3514 Mon Sep 17 00:00:00 2001 From: eileen Date: Fri, 6 Sep 2013 16:54:27 +1200 Subject: [PATCH] CRM-13234 call getfields less times & pass in variables that might affect it (profile_id & potentially later other ones) --- api/api.php | 40 ++++++++++++++++++++++++++++---- api/v3/utils.php | 59 +++++++++++++----------------------------------- 2 files changed, 51 insertions(+), 48 deletions(-) diff --git a/api/api.php b/api/api.php index bd6cec7348..39672c9a37 100644 --- a/api/api.php +++ b/api/api.php @@ -55,15 +55,15 @@ function civicrm_api($entity, $action, $params, $extra = NULL) { } _civicrm_api3_api_check_permission($apiRequest['entity'], $apiRequest['action'], $apiRequest['params']); - + $fields = _civicrm_api3_api_getfields($apiRequest); // we do this before we - _civicrm_api3_swap_out_aliases($apiRequest); + _civicrm_api3_swap_out_aliases($apiRequest, $fields); if (strtolower($action) != 'getfields') { if (!CRM_Utils_Array::value('id', $apiRequest['params'])) { - $apiRequest['params'] = array_merge(_civicrm_api3_getdefaults($apiRequest), $apiRequest['params']); + $apiRequest['params'] = array_merge(_civicrm_api3_getdefaults($apiRequest, $fields), $apiRequest['params']); } //if 'id' is set then only 'version' will be checked but should still be checked for consistency - civicrm_api3_verify_mandatory($apiRequest['params'], NULL, _civicrm_api3_getrequired($apiRequest)); + civicrm_api3_verify_mandatory($apiRequest['params'], NULL, _civicrm_api3_getrequired($apiRequest, $fields)); } // For input filtering, process $apiWrappers in forward order @@ -79,7 +79,7 @@ function civicrm_api($entity, $action, $params, $extra = NULL) { $result = $function($apiRequest); } elseif ($apiRequest['function'] && !$apiRequest['is_generic']) { - _civicrm_api3_validate_fields($apiRequest['entity'], $apiRequest['action'], $apiRequest['params']); + _civicrm_api3_validate_fields($apiRequest['entity'], $apiRequest['action'], $apiRequest['params'], $fields); $result = isset($extra) ? $function($apiRequest['params'], $extra) : $function($apiRequest['params']); } @@ -269,6 +269,36 @@ function civicrm_api3($entity, $action, $params) { return $result; } +/** + * Function to call getfields from api wrapper. This function ensures that settings that could alter + * getfields output (e.g. action for all api & profile_id for profile api ) are consistently passed in. + * + * We check whether the api call is 'getfields' because if getfields is being called we return an empty array + * as no alias swapping, validation or default filling is done on getfields & we want to avoid a loop + * + * @todo other output modifiers include contact_type + * + * @param array $apiRequest + * @return getfields output + */ +function _civicrm_api3_api_getfields(&$apiRequest) { + if (strtolower($apiRequest['action'] == 'getfields')) { + // the main param getfields takes is 'action' - however this param is not compatible with REST + // so we accept 'api_action' as an alias of action on getfields + if (CRM_Utils_Array::value('api_action', $apiRequest['params'])) { + // $apiRequest['params']['action'] = $apiRequest['params']['api_action']; + // unset($apiRequest['params']['api_action']); + } + return array('action' => array('api_aliases' => array('action'))); + } + $getFieldsParams = array('action' => $apiRequest['action']); + $entity = $apiRequest['entity']; + if($entity == 'profile' && array_key_exists('profile_id', $apiRequest['params'])) { + $getFieldsParams['profile_id'] = $apiRequest['params']['profile_id']; + } + $fields = civicrm_api3($entity, 'getfields', $getFieldsParams); + return $fields['values']; +} /** * Load/require all files related to an entity. * diff --git a/api/v3/utils.php b/api/v3/utils.php index d9f011a1e6..ef6bb1dbff 100644 --- a/api/v3/utils.php +++ b/api/v3/utils.php @@ -142,7 +142,8 @@ function civicrm_api3_create_error($msg, $data = array(), &$dao = NULL) { if (is_array($dao)) { if ($msg == 'DB Error: constraint violation' || substr($msg, 0,9) == 'DB Error:' || $msg == 'DB Error: already exists') { try { - _civicrm_api3_validate_fields($dao['entity'], $dao['action'], $dao['params'], TRUE); + $fields = _civicrm_api3_api_getfields($dao); + _civicrm_api3_validate_fields($dao['entity'], $dao['action'], $dao['params'], $fields, TRUE); } catch(Exception $e) { $msg = $e->getMessage(); @@ -1074,16 +1075,12 @@ function _civicrm_api3_custom_data_get(&$returnArray, $entity, $entity_id, $grou * @param string $entity * @param string $action * @param array $params - + * @param boolean errorMode do intensive post fail checks? + * @param array $fields response from getfields * all variables are the same as per civicrm_api */ -function _civicrm_api3_validate_fields($entity, $action, &$params, $errorMode = NULL) { - //skip any entities without working getfields functions - $skippedEntities = array('entity', 'mailinggroup', 'customvalue', 'custom_value', 'mailing_group'); - if (in_array(strtolower($entity), $skippedEntities) || strtolower($action) == 'getfields') { - return; - } - $fields = civicrm_api($entity, 'getfields', array('version' => 3, 'action' => $action)); - $fields = array_intersect_key($fields['values'], $params); +function _civicrm_api3_validate_fields($entity, $action, &$params, $fields, $errorMode = False) { + $fields = array_intersect_key($fields, $params); foreach ($fields as $fieldName => $fieldInfo) { switch (CRM_Utils_Array::value('type', $fieldInfo)) { case CRM_Utils_Type::T_INT: @@ -1387,17 +1384,10 @@ function _getStandardTypeFromCustomDataType($dataType) { /** * Return array of defaults for the given API (function is a wrapper on getfields) */ -function _civicrm_api3_getdefaults($apiRequest) { +function _civicrm_api3_getdefaults($apiRequest, $fields) { $defaults = array(); - $result = civicrm_api3($apiRequest['entity'], - 'getfields', - array( - 'action' => $apiRequest['action'], - ) - ); - - foreach ($result['values'] as $field => $values) { + foreach ($fields as $field => $values) { if (isset($values['api.default'])) { $defaults[$field] = $values['api.default']; } @@ -1408,17 +1398,10 @@ function _civicrm_api3_getdefaults($apiRequest) { /** * Return array of defaults for the given API (function is a wrapper on getfields) */ -function _civicrm_api3_getrequired($apiRequest) { +function _civicrm_api3_getrequired($apiRequest, $fields) { $required = array('version'); - $result = civicrm_api($apiRequest['entity'], - 'getfields', - array( - 'version' => 3, - 'action' => $apiRequest['action'], - ) - ); - foreach ($result['values'] as $field => $values) { + foreach ($fields as $field => $values) { if (CRM_Utils_Array::value('api.required', $values)) { $required[] = $field; } @@ -1432,22 +1415,8 @@ function _civicrm_api3_getrequired($apiRequest) { * * Function also swaps unique fields for non-unique fields & vice versa. */ -function _civicrm_api3_swap_out_aliases(&$apiRequest) { - if (strtolower($apiRequest['action'] == 'getfields')) { - if (CRM_Utils_Array::value('api_action', $apiRequest['params'])) { - $apiRequest['params']['action'] = $apiRequest['params']['api_action']; - unset($apiRequest['params']['api_action']); - } - return; - } - $result = civicrm_api3($apiRequest['entity'], - 'getfields', - array( - 'action' => $apiRequest['action'], - ) - ); - - foreach ($result['values'] as $field => $values) { +function _civicrm_api3_swap_out_aliases(&$apiRequest, $fields) { + foreach ($fields as $field => $values) { $uniqueName = CRM_Utils_Array::value('uniqueName', $values); if (CRM_Utils_Array::value('api.aliases', $values)) { // if aliased field is not set we try to use field alias @@ -1615,6 +1584,10 @@ function _civicrm_api3_validate_string(&$params, &$fieldName, &$fieldInfo, $enti function _civicrm_api3_api_match_pseudoconstant(&$params, $entity, $fieldName, $fieldInfo) { $options = CRM_Utils_Array::value('options', $fieldInfo); if (!$options) { + if(strtolower($entity) == 'profile' && !empty($fieldInfo['entity'])) { + // we need to get the options from the entity the field relates to + $entity = $fieldInfo['entity']; + } $options = civicrm_api($entity, 'getoptions', array('version' => 3, 'field' => $fieldInfo['name'], 'context' => 'validate')); $options = CRM_Utils_Array::value('values', $options, array()); } -- 2.25.1