X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=api%2Fapi.php;h=4f53c542fc0324b54e6361ee65a70ba28f963cc5;hb=af3775b322b9e4f11d097067367f0ea7763f5f10;hp=d0aa4653e9a7416ae2cf072ced4c2c92db69f6b4;hpb=0f643fb2c7553ba4d6256b2ccc6ef1f7cb7d74cd;p=civicrm-core.git diff --git a/api/api.php b/api/api.php index d0aa4653e9..4f53c542fc 100644 --- a/api/api.php +++ b/api/api.php @@ -1,16 +1,14 @@ $stdFunction, 'is_generic' => FALSE); - return $cache[$cachekey]; - } - - $stdFiles = array( - // By convention, the $camelName.php is more likely to contain the function, so test it first - 'api/v' . $apiRequest['version'] . '/' . $camelName . '.php', - 'api/v' . $apiRequest['version'] . '/' . $camelName . '/' . $actionCamelName . '.php', - ); - foreach ($stdFiles as $stdFile) { - if (CRM_Utils_File::isIncludable($stdFile)) { - require_once $stdFile; - if (function_exists($stdFunction)) { - $cache[$cachekey] = array('function' => $stdFunction, 'is_generic' => FALSE); - return $cache[$cachekey]; - } - } - } - - // Determine if there is a generic implementation of the action - require_once 'api/v3/Generic.php'; - # $genericFunction = 'civicrm_api3_generic_' . $apiRequest['action']; - $genericFunction = civicrm_api_get_function_name('generic', $apiRequest['action'], $apiRequest['version']); - $genericFiles = array( - // By convention, the Generic.php is more likely to contain the function, so test it first - 'api/v' . $apiRequest['version'] . '/Generic.php', - 'api/v' . $apiRequest['version'] . '/Generic/' . $actionCamelName . '.php', - ); - foreach ($genericFiles as $genericFile) { - if (CRM_Utils_File::isIncludable($genericFile)) { - require_once $genericFile; - if (function_exists($genericFunction)) { - $cache[$cachekey] = array('function' => $genericFunction, 'is_generic' => TRUE); - return $cache[$cachekey]; - } - } - } - - $cache[$cachekey] = array('function' => FALSE, 'is_generic' => FALSE); - return $cache[$cachekey]; -} - -/** - * Version 3 wrapper for civicrm_api. Throws exception + * Throws exception. * - * @param string $entity type of entities to deal with - * @param string $action create, get, delete or some special action name. - * @param array $params array to be passed to function + * @param string $entity + * Type of entities to deal with. + * @param string $action + * Create, get, delete or some special action name. + * @param array $params + * Array to be passed to function. * * @throws CiviCRM_API3_Exception * @return array @@ -108,138 +41,49 @@ function _civicrm_api_resolve($apiRequest) { function civicrm_api3($entity, $action, $params = array()) { $params['version'] = 3; $result = civicrm_api($entity, $action, $params); - if(is_array($result) && !empty($result['is_error'])){ + if (is_array($result) && !empty($result['is_error'])) { throw new CiviCRM_API3_Exception($result['error_message'], CRM_Utils_Array::value('error_code', $result, 'undefined'), $result); } 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. + * 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 + * 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 + * + * @return array + * 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 (!empty($apiRequest['params']['api_action'])) { - // $apiRequest['params']['action'] = $apiRequest['params']['api_action']; - // unset($apiRequest['params']['api_action']); + // $apiRequest['params']['action'] = $apiRequest['params']['api_action']; + // unset($apiRequest['params']['api_action']); } return array('action' => array('api.aliases' => array('api_action'))); } $getFieldsParams = array('action' => $apiRequest['action']); $entity = $apiRequest['entity']; - if($entity == 'profile' && array_key_exists('profile_id', $apiRequest['params'])) { + 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. - * - * This should not normally be called because it's does a file-system scan; it's - * only appropriate when introspection is really required (eg for "getActions"). - * - * @param string $entity - * @param int $version - * - * @return void - */ -function _civicrm_api_loadEntity($entity, $version = 3) { - /* - $apiRequest = array(); - $apiRequest['entity'] = $entity; - $apiRequest['action'] = 'pretty sure it will never exist. Trick to [try to] force resolve to scan everywhere'; - $apiRequest['version'] = $version; - // look up function, file, is_generic - $apiRequest = _civicrm_api_resolve($apiRequest); - */ - - $camelName = _civicrm_api_get_camel_name($entity, $version); - - // Check for master entity file; to match _civicrm_api_resolve(), only load the first one - $stdFile = 'api/v' . $version . '/' . $camelName . '.php'; - if (CRM_Utils_File::isIncludable($stdFile)) { - require_once $stdFile; - } - - // Check for standalone action files; to match _civicrm_api_resolve(), only load the first one - $loaded_files = array(); // array($relativeFilePath => TRUE) - $include_dirs = array_unique(explode(PATH_SEPARATOR, get_include_path())); - foreach ($include_dirs as $include_dir) { - $action_dir = implode(DIRECTORY_SEPARATOR, array($include_dir, 'api', "v${version}", $camelName)); - if (! is_dir($action_dir)) { - continue; - } - - $iterator = new DirectoryIterator($action_dir); - foreach ($iterator as $fileinfo) { - $file = $fileinfo->getFilename(); - if (array_key_exists($file, $loaded_files)) { - continue; // action provided by an earlier item on include_path - } - - $parts = explode(".", $file); - if (end($parts) == "php" && !preg_match('/Tests?\.php$/', $file) ) { - require_once $action_dir . DIRECTORY_SEPARATOR . $file; - $loaded_files[$file] = TRUE; - } - } - } -} - -/** - * - * @deprecated - */ -function civicrm_api_get_function_name($entity, $action, $version = NULL) { - - if (empty($version)) { - $version = civicrm_get_api_version(); - } - - $entity = _civicrm_api_get_entity_name_from_camel($entity); - return 'civicrm_api3' . '_' . $entity . '_' . $action; -} - -/** - * We must be sure that every request uses only one version of the API. - * - * @param $desired_version : array or integer - * One chance to set the version number. - * After that, this version number will be used for the remaining request. - * This can either be a number, or an array(.., 'version' => $version, ..). - * This allows to directly pass the $params array. - * @return int - */ -function civicrm_get_api_version($desired_version = NULL) { - - if (is_array($desired_version)) { - // someone gave the full $params array. - $params = $desired_version; - $desired_version = empty($params['version']) ? NULL : (int) $params['version']; - } - if (isset($desired_version) && is_integer($desired_version)) { - $_version = $desired_version; - } - else { - // we will set the default to version 3 as soon as we find that it works. - $_version = 3; - } - return $_version; -} - /** * Check if the result is an error. Note that this function has been retained from * api v2 for convenience but the result is more standardised in v3 and param @@ -248,11 +92,8 @@ function civicrm_get_api_version($desired_version = NULL) { * * @param $result * - * @internal param array $params (reference ) input parameters - * - * @return boolean true if error, false otherwise - * @static void - * @access public + * @return bool + * true if error, false otherwise */ function civicrm_error($result) { if (is_array($result)) { @@ -263,140 +104,38 @@ function civicrm_error($result) { return FALSE; } -function _civicrm_api_get_camel_name($entity, $version = NULL) { - if (empty($version)) { - $version = civicrm_get_api_version(); - } - - $fragments = explode('_', $entity); - foreach ($fragments as & $fragment) { - $fragment = ucfirst($fragment); - } - // Special case: UFGroup, UFJoin, UFMatch, UFField - if ($fragments[0] === 'Uf') { - $fragments[0] = 'UF'; - } - return implode('', $fragments); -} - /** - * Call any nested api calls + * Get camel case version of entity name. + * + * @param string|null $entity + * + * @return string|null */ -function _civicrm_api_call_nested_api(&$params, &$result, $action, $entity, $version) { - $entity = _civicrm_api_get_entity_name_from_camel($entity); - - //we don't need to worry about nested api in the getfields/getoptions actions, so just return immediately - if (in_array(strtolower($action), array('getfields', 'getoptions'))) { - return; - } - - if(strtolower($action) == 'getsingle'){ - // I don't understand the protocol here, but we don't want - // $result to be a recursive array - // $result['values'][0] = $result; - $oldResult = $result; - $result = array('values' => array(0 => $oldResult)); - } - foreach ($params as $field => $newparams) { - if ((is_array($newparams) || $newparams === 1) && $field <> 'api.has_parent' && substr($field, 0, 3) == 'api') { - - // 'api.participant.delete' => 1 is a valid options - handle 1 instead of an array - if ($newparams === 1) { - $newparams = array('version' => $version); - } - // can be api_ or api. - $separator = $field[3]; - if (!($separator == '.' || $separator == '_')) { - continue; - } - $subAPI = explode($separator, $field); - - $subaction = empty($subAPI[2]) ? $action : $subAPI[2]; - $subParams = array( - 'debug' => CRM_Utils_Array::value('debug', $params), - ); - $subEntity = $subAPI[1]; - - foreach ($result['values'] as $idIndex => $parentAPIValues) { - - if (strtolower($subEntity) != 'contact') { - //contact spits the dummy at activity_id so what else won't it like? - //set entity_id & entity table based on the parent's id & entity. e.g for something like - //note if the parent call is contact 'entity_table' will be set to 'contact' & 'id' to the contact id from - //the parent call. - //in this case 'contact_id' will also be set to the parent's id - $subParams["entity_id"] = $parentAPIValues['id']; - $subParams['entity_table'] = 'civicrm_' . _civicrm_api_get_entity_name_from_camel($entity); - $subParams[strtolower($entity) . "_id"] = $parentAPIValues['id']; - } - if (strtolower($entity) != 'contact' && CRM_Utils_Array::value(strtolower($subEntity . "_id"), $parentAPIValues)) { - //e.g. if event_id is in the values returned & subentity is event then pass in event_id as 'id' - //don't do this for contact as it does some wierd things like returning primary email & - //thus limiting the ability to chain email - //TODO - this might need the camel treatment - $subParams['id'] = $parentAPIValues[$subEntity . "_id"]; - } - - if (CRM_Utils_Array::value('entity_table', $result['values'][$idIndex]) == $subEntity) { - $subParams['id'] = $result['values'][$idIndex]['entity_id']; - } - // if we are dealing with the same entity pass 'id' through (useful for get + delete for example) - if (strtolower($entity) == strtolower($subEntity)) { - $subParams['id'] = $result['values'][$idIndex]['id']; - } - - - $subParams['version'] = $version; - if(!empty($params['check_permissions'])){ - $subParams['check_permissions'] = $params['check_permissions']; - } - $subParams['sequential'] = 1; - $subParams['api.has_parent'] = 1; - if (array_key_exists(0, $newparams)) { - $genericParams = $subParams; - // it is a numerically indexed array - ie. multiple creates - foreach ($newparams as $entityparams) { - $subParams = array_merge($genericParams, $entityparams); - _civicrm_api_replace_variables($subAPI[1], $subaction, $subParams, $result['values'][$idIndex], $separator); - $result['values'][$result['id']][$field][] = civicrm_api($subEntity, $subaction, $subParams); - if ($result['is_error'] === 1) { - throw new Exception($subEntity . ' ' . $subaction . 'call failed with' . $result['error_message']); - } - } - } - else { - - $subParams = array_merge($subParams, $newparams); - _civicrm_api_replace_variables($subAPI[1], $subaction, $subParams, $result['values'][$idIndex], $separator); - $result['values'][$idIndex][$field] = civicrm_api($subEntity, $subaction, $subParams); - if (!empty($result['is_error'])) { - throw new Exception($subEntity . ' ' . $subaction . 'call failed with' . $result['error_message']); - } - } - } - } - } - if(strtolower($action) == 'getsingle'){ - $result = $result['values'][0]; - } +function _civicrm_api_get_camel_name($entity) { + return is_string($entity) ? CRM_Utils_String::convertStringToCamel($entity) : NULL; } /** - * Swap out any $values vars - ie. the value after $value is swapped for the parent $result + * Swap out any $values vars. + * + * Ie. the value after $value is swapped for the parent $result * 'activity_type_id' => '$value.testfield', - 'tag_id' => '$value.api.tag.create.id', - 'tag1_id' => '$value.api.entity.create.0.id' + * 'tag_id' => '$value.api.tag.create.id', + * 'tag1_id' => '$value.api.entity.create.0.id' + * + * @param array $params + * @param array $parentResult + * @param string $separator */ -function _civicrm_api_replace_variables($entity, $action, &$params, &$parentResult, $separator = '.') { - +function _civicrm_api_replace_variables(&$params, &$parentResult, $separator = '.') { foreach ($params as $field => $value) { if (is_string($value) && substr($value, 0, 6) == '$value') { - $valuesubstitute = substr($value, 7); + $valueSubstitute = substr($value, 7); - if (!empty($parentResult[$valuesubstitute])) { - $params[$field] = $parentResult[$valuesubstitute]; + if (!empty($parentResult[$valueSubstitute])) { + $params[$field] = $parentResult[$valueSubstitute]; } else { @@ -411,8 +150,8 @@ function _civicrm_api_replace_variables($entity, $action, &$params, &$parentResu $fieldname .= "." . array_shift($stringParts); if (array_key_exists($fieldname, $parentResult) && is_array($parentResult[$fieldname])) { $arrayLocation = $parentResult[$fieldname]; - foreach ($stringParts as $key => $value) { - $arrayLocation = CRM_Utils_Array::value($value, $arrayLocation); + foreach ($stringParts as $key => $innerValue) { + $arrayLocation = CRM_Utils_Array::value($innerValue, $arrayLocation); } $params[$field] = $arrayLocation; } @@ -424,15 +163,17 @@ function _civicrm_api_replace_variables($entity, $action, &$params, &$parentResu } /** - * Convert possibly camel name to underscore separated entity name + * Convert possibly camel name to underscore separated entity name. * - * @param string $entity entity name in various formats e.g. Contribution, contribution, OptionValue, option_value, UFJoin, uf_join - * @return string $entity entity name in underscore separated format + * @param string $entity + * Entity name in various formats e.g. Contribution, contribution, + * OptionValue, option_value, UFJoin, uf_join. * - * FIXME: Why isn't this called first thing in civicrm_api wrapper? + * @return string + * Entity name in underscore separated format. */ function _civicrm_api_get_entity_name_from_camel($entity) { - if ($entity == strtolower($entity)) { + if (!$entity || $entity === strtolower($entity)) { return $entity; } else { @@ -446,58 +187,14 @@ function _civicrm_api_get_entity_name_from_camel($entity) { } /** - * Having a DAO object find the entity name - * @param object $bao DAO being passed in + * Having a DAO object find the entity name. + * + * @param object $bao + * DAO being passed in. + * * @return string */ -function _civicrm_api_get_entity_name_from_dao($bao){ +function _civicrm_api_get_entity_name_from_dao($bao) { $daoName = str_replace("BAO", "DAO", get_class($bao)); - return _civicrm_api_get_entity_name_from_camel(CRM_Core_DAO_AllCoreTables::getBriefName($daoName)); -} - -/** - * Sets the tsLocale and dbLocale for multi-lingual sites. - * Some code duplication from CRM/Core/BAO/ConfigSetting.php retrieve() - * to avoid regressions from refactoring. - */ -function _civicrm_api_set_locale($lcMessagesRequest) { - // We must validate whether the locale is valid, otherwise setting a bad - // dbLocale could probably lead to sql-injection. - $domain = new CRM_Core_DAO_Domain(); - $domain->id = CRM_Core_Config::domainID(); - $domain->find(TRUE); - - if ($domain->config_backend) { - $defaults = unserialize($domain->config_backend); - - // are we in a multi-language setup? - $multiLang = $domain->locales ? TRUE : FALSE; - $lcMessages = NULL; - - // on multi-lang sites based on request and civicrm_uf_match - if ($multiLang) { - $languageLimit = array(); - if (array_key_exists('languageLimit', $defaults) && is_array($defaults['languageLimit'])) { - $languageLimit = $defaults['languageLimit']; - } - - if (in_array($lcMessagesRequest, array_keys($languageLimit))) { - $lcMessages = $lcMessagesRequest; - } - else { - throw new API_Exception(ts('Language not enabled: %1', array(1 => $lcMessagesRequest))); - } - } - - global $dbLocale; - - // set suffix for table names - use views if more than one language - if ($lcMessages) { - $dbLocale = $multiLang && $lcMessages ? "_{$lcMessages}" : ''; - - // FIXME: an ugly hack to fix CRM-4041 - global $tsLocale; - $tsLocale = $lcMessages; - } - } + return CRM_Core_DAO_AllCoreTables::getBriefName($daoName); }