}
/**
- * Procedural wrapper for the OO api version 4.
+ * CiviCRM API version 4.
*
- * @param string $entity
- * @param string $action
- * @param array $params
- * @param string|int $index
- * If $index is a string, the results array will be indexed by that key.
- * If $index is an integer, only the result at that index will be returned.
+ * This API (Application Programming Interface) is used to access and manage data in CiviCRM.
+ *
+ * APIv4 is the latest stable version.
+ *
+ * @see https://docs.civicrm.org/dev/en/latest/api/v4/usage/
+ *
+ * @param string $entity Name of the CiviCRM entity to access.
+ * All entity names are capitalized CamelCase, e.g. `ContributionPage`.
+ * Most entities correspond to a database table (e.g. `Contact` is the table `civicrm_contact`).
+ * For a complete list of available entities, call `civicrm_api4('Entity', 'get');`
+ *
+ * @param string $action The "verb" of the api call.
+ * For a complete list of actions for a given entity (e.g. `Contact`), call `civicrm_api4('Contact', 'getActions');`
+ *
+ * @param array $params An array of API input keyed by parameter name.
+ * The easiest way to discover all available parameters is to visit the API Explorer on your CiviCRM site.
+ * The API Explorer is listed in the CiviCRM menu under Support -> Developer.
+ *
+ * @param string|int|array $index Controls the Result array format.
+ * By default the api Result contains a non-associative array of data. Passing an $index tells the api to
+ * automatically reformat the array, depending on the variable type passed:
+ * - **Integer:** return a single result array;
+ * e.g. `$index = 0` will return the first result, 1 will return the second, and -1 will return the last.
+ * - **String:** index the results by a field value;
+ * e.g. `$index = "name"` will return an associative array with the field 'name' as keys.
+ * - **Non-associative array:** return a single value from each result;
+ * e.g. `$index = ['title']` will return a non-associative array of strings - the 'title' field from each result.
+ * - **Associative array:** a combination of the previous two modes;
+ * e.g. `$index = ['name' => 'title']` will return an array of strings - the 'title' field keyed by the 'name' field.
*
* @return \Civi\Api4\Generic\Result
* @throws \API_Exception
*/
function civicrm_api4(string $entity, string $action, array $params = [], $index = NULL) {
$apiCall = \Civi\Api4\Utils\ActionUtil::getAction($entity, $action);
+ $indexField = $index && is_string($index) && !CRM_Utils_Rule::integer($index) ? $index : NULL;
+ $removeIndexField = FALSE;
+
+ // If index field is not part of the select query, we add it here and remove it below
+ if ($indexField && !empty($params['select']) && is_array($params['select']) && !\Civi\Api4\Utils\SelectUtil::isFieldSelected($indexField, $params['select'])) {
+ $params['select'][] = $indexField;
+ $removeIndexField = TRUE;
+ }
foreach ($params as $name => $param) {
$setter = 'set' . ucfirst($name);
$apiCall->$setter($param);
}
+
+ if ($index && is_array($index)) {
+ $indexCol = reset($index);
+ $indexField = key($index);
+ if (property_exists($apiCall, 'select')) {
+ $apiCall->setSelect([$indexCol]);
+ if ($indexField && $indexField != $indexCol) {
+ $apiCall->addSelect($indexField);
+ }
+ }
+ }
+
$result = $apiCall->execute();
// Index results by key
- if ($index && is_string($index) && !CRM_Utils_Rule::integer($index)) {
- $result->indexBy($index);
+ if ($indexField) {
+ $result->indexBy($indexField);
+ if ($removeIndexField) {
+ foreach ($result as $key => $value) {
+ unset($result[$key][$indexField]);
+ }
+ }
}
// Return result at index
- if (CRM_Utils_Rule::integer($index)) {
+ elseif (CRM_Utils_Rule::integer($index)) {
$item = $result->itemAt($index);
if (is_null($item)) {
throw new \API_Exception("Index $index not found in api results");
return $item;
}
$result->exchangeArray($item);
-
+ }
+ if (!empty($indexCol)) {
+ $result->exchangeArray($result->column($indexCol));
}
return $result;
}