Merge pull request #13980 from seamuslee001/new_coder_style_check_api
[civicrm-core.git] / api / v3 / Generic / Getlist.php
CommitLineData
fe43b7c9 1<?php
fe43b7c9
CW
2/*
3 +--------------------------------------------------------------------+
fee14197 4 | CiviCRM version 5 |
b081365f 5 +--------------------------------------------------------------------+
6b83d5bd 6 | Copyright CiviCRM LLC (c) 2004-2019 |
b081365f
CW
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
e70a7fc0 26 */
b081365f
CW
27
28/**
29 * @package CiviCRM_APIv3
30 */
31
fe43b7c9 32/**
2fb1dd66 33 * Generic api wrapper used for quicksearch and autocomplete.
fe43b7c9 34 *
72b3a70c 35 * @param array $apiRequest
2fb1dd66 36 *
fe43b7c9
CW
37 * @return mixed
38 */
39function civicrm_api3_generic_getList($apiRequest) {
40 $entity = _civicrm_api_get_entity_name_from_camel($apiRequest['entity']);
41 $request = $apiRequest['params'];
cf8f0fff 42 $meta = civicrm_api3_generic_getfields(['action' => 'get'] + $apiRequest, FALSE);
ebf2b57b 43
bc255d1d
CW
44 // Hey api, would you like to provide default values?
45 $fnName = "_civicrm_api3_{$entity}_getlist_defaults";
cf8f0fff 46 $defaults = function_exists($fnName) ? $fnName($request) : [];
6b4c9564 47 _civicrm_api3_generic_getList_defaults($entity, $request, $defaults, $meta['values']);
ebf2b57b 48
fe43b7c9
CW
49 // Hey api, would you like to format the search params?
50 $fnName = "_civicrm_api3_{$entity}_getlist_params";
51 $fnName = function_exists($fnName) ? $fnName : '_civicrm_api3_generic_getlist_params';
52 $fnName($request);
79ae07d9
CW
53
54 $request['params']['check_permissions'] = !empty($apiRequest['params']['check_permissions']);
fe43b7c9
CW
55 $result = civicrm_api3($entity, 'get', $request['params']);
56
57 // Hey api, would you like to format the output?
58 $fnName = "_civicrm_api3_{$entity}_getlist_output";
59 $fnName = function_exists($fnName) ? $fnName : '_civicrm_api3_generic_getlist_output';
6b4c9564 60 $values = $fnName($result, $request, $entity, $meta['values']);
fe43b7c9 61
27d7d241
CW
62 _civicrm_api3_generic_getlist_postprocess($result, $request, $values);
63
cf8f0fff 64 $output = ['page_num' => $request['page_num']];
78b203e5
CW
65
66 // Limit is set for searching but not fetching by id
a6c6059d 67 if (!empty($request['params']['options']['limit'])) {
fe43b7c9 68 // If we have an extra result then this is not the last page
a6c6059d 69 $last = $request['params']['options']['limit'] - 1;
78b203e5
CW
70 $output['more_results'] = isset($values[$last]);
71 unset($values[$last]);
72 }
fe43b7c9
CW
73
74 return civicrm_api3_create_success($values, $request['params'], $entity, 'getlist', CRM_Core_DAO::$_nullObject, $output);
75}
76
77/**
211e2fca 78 * Set defaults for api.getlist.
fe43b7c9 79 *
8c6b335b
CW
80 * @param string $entity
81 * @param array $request
bc255d1d 82 * @param array $apiDefaults
3bdf1f3a 83 * @param array $fields
fe43b7c9 84 */
6b4c9564 85function _civicrm_api3_generic_getList_defaults($entity, &$request, $apiDefaults, $fields) {
cf8f0fff 86 $defaults = [
fe43b7c9
CW
87 'page_num' => 1,
88 'input' => '',
89 'image_field' => NULL,
4fcc9877 90 'color_field' => isset($fields['color']) ? 'color' : NULL,
0724132d 91 'id_field' => $entity == 'option_value' ? 'value' : 'id',
cf8f0fff 92 'description_field' => [],
81b7bb6f 93 'add_wildcard' => Civi::settings()->get('includeWildCardInName'),
cf8f0fff
CW
94 'params' => [],
95 'extra' => [],
96 ];
fe43b7c9 97 // Find main field from meta
cf8f0fff 98 foreach (['sort_name', 'title', 'label', 'name', 'subject'] as $field) {
fe43b7c9
CW
99 if (isset($fields[$field])) {
100 $defaults['label_field'] = $defaults['search_field'] = $field;
101 break;
102 }
103 }
8250601e 104 // Find fields to be used for the description
cf8f0fff 105 foreach (['description'] as $field) {
fe43b7c9 106 if (isset($fields[$field])) {
8250601e 107 $defaults['description_field'][] = $field;
fe43b7c9
CW
108 }
109 }
89595c92 110 $resultsPerPage = Civi::settings()->get('search_autocomplete_count');
6b4c9564
CW
111 if (isset($request['params']) && isset($apiDefaults['params'])) {
112 $request['params'] += $apiDefaults['params'];
113 }
bc255d1d 114 $request += $apiDefaults + $defaults;
fe43b7c9 115 // Default api params
cf8f0fff 116 $params = [
fe43b7c9 117 'sequential' => 1,
cf8f0fff
CW
118 'options' => [],
119 ];
76ec9ca7 120 // When searching e.g. autocomplete
fe43b7c9 121 if ($request['input']) {
cf8f0fff 122 $params[$request['search_field']] = ['LIKE' => ($request['add_wildcard'] ? '%' : '') . $request['input'] . '%'];
fe43b7c9 123 }
76ec9ca7
CW
124 // When looking up a field e.g. displaying existing record
125 if (!empty($request['id'])) {
83e11123
CW
126 if (is_string($request['id']) && strpos($request['id'], ',')) {
127 $request['id'] = explode(',', trim($request['id'], ', '));
76ec9ca7 128 }
78b203e5 129 // Don't run into search limits when prefilling selection
ba3b21c3
CW
130 $params['options']['limit'] = NULL;
131 unset($params['options']['offset'], $request['params']['options']['limit'], $request['params']['options']['offset']);
cf8f0fff 132 $params[$request['id_field']] = is_array($request['id']) ? ['IN' => $request['id']] : $request['id'];
76ec9ca7 133 }
fe43b7c9 134 $request['params'] += $params;
deb188d8 135
cf8f0fff 136 $request['params']['options'] += [
deb188d8
FW
137 // Add pagination parameters
138 'sort' => $request['label_field'],
139 // Adding one extra result allows us to see if there are any more
140 'limit' => $resultsPerPage + 1,
141 // Because sql is zero-based
142 'offset' => ($request['page_num'] - 1) * $resultsPerPage,
cf8f0fff 143 ];
fe43b7c9
CW
144}
145
146/**
c1a920f1 147 * Fallback implementation of getlist_params. May be overridden by individual apis.
fe43b7c9 148 *
8c6b335b 149 * @param array $request
fe43b7c9
CW
150 */
151function _civicrm_api3_generic_getlist_params(&$request) {
cf8f0fff 152 $fieldsToReturn = [$request['id_field'], $request['label_field']];
ff88d165
CW
153 if (!empty($request['image_field'])) {
154 $fieldsToReturn[] = $request['image_field'];
155 }
4fcc9877
CW
156 if (!empty($request['color_field'])) {
157 $fieldsToReturn[] = $request['color_field'];
158 }
ff88d165 159 if (!empty($request['description_field'])) {
8250601e 160 $fieldsToReturn = array_merge($fieldsToReturn, (array) $request['description_field']);
ff88d165 161 }
8250601e 162 $request['params']['return'] = array_unique(array_merge($fieldsToReturn, $request['extra']));
fe43b7c9
CW
163}
164
165/**
211e2fca 166 * Fallback implementation of getlist_output. May be overridden by individual api functions.
fe43b7c9 167 *
8c6b335b
CW
168 * @param array $result
169 * @param array $request
b233e1b4 170 * @param string $entity
6b4c9564 171 * @param array $fields
fe43b7c9
CW
172 *
173 * @return array
174 */
6b4c9564 175function _civicrm_api3_generic_getlist_output($result, $request, $entity, $fields) {
cf8f0fff 176 $output = [];
fe43b7c9
CW
177 if (!empty($result['values'])) {
178 foreach ($result['values'] as $row) {
cf8f0fff 179 $data = [
76ec9ca7 180 'id' => $row[$request['id_field']],
fe43b7c9 181 'label' => $row[$request['label_field']],
cf8f0fff 182 ];
ff88d165 183 if (!empty($request['description_field'])) {
cf8f0fff 184 $data['description'] = [];
8250601e
CW
185 foreach ((array) $request['description_field'] as $field) {
186 if (!empty($row[$field])) {
6b4c9564
CW
187 if (!isset($fields[$field]['pseudoconstant'])) {
188 $data['description'][] = $row[$field];
189 }
190 else {
191 $data['description'][] = CRM_Core_PseudoConstant::getLabel(
192 _civicrm_api3_get_BAO($entity),
193 $field,
194 $row[$field]
195 );
196 }
8250601e
CW
197 }
198 }
ff88d165
CW
199 };
200 if (!empty($request['image_field'])) {
201 $data['image'] = isset($row[$request['image_field']]) ? $row[$request['image_field']] : '';
8250601e 202 }
4fcc9877
CW
203 if (isset($row[$request['color_field']])) {
204 $data['color'] = $row[$request['color_field']];
205 }
ff88d165 206 $output[] = $data;
fe43b7c9
CW
207 }
208 }
209 return $output;
210}
f7b2fef0 211
27d7d241
CW
212/**
213 * Common postprocess for getlist output
214 *
215 * @param $result
216 * @param $request
217 * @param $values
218 */
219function _civicrm_api3_generic_getlist_postprocess($result, $request, &$values) {
cf8f0fff 220 $chains = [];
27d7d241
CW
221 foreach ($request['params'] as $field => $param) {
222 if (substr($field, 0, 4) === 'api.') {
223 $chains[] = $field;
224 }
225 }
226 if (!empty($result['values'])) {
227 foreach (array_values($result['values']) as $num => $row) {
228 foreach ($request['extra'] as $field) {
229 $values[$num]['extra'][$field] = isset($row[$field]) ? $row[$field] : NULL;
230 }
231 foreach ($chains as $chain) {
232 $values[$num][$chain] = isset($row[$chain]) ? $row[$chain] : NULL;
233 }
234 }
235 }
236}
237
f7b2fef0
CW
238/**
239 * Provide metadata for this api
240 *
241 * @param array $params
242 * @param array $apiRequest
243 */
244function _civicrm_api3_generic_getlist_spec(&$params, $apiRequest) {
cf8f0fff
CW
245 $params += [
246 'page_num' => [
f7b2fef0
CW
247 'title' => 'Page Number',
248 'description' => "Current page of a multi-page lookup",
249 'type' => CRM_Utils_Type::T_INT,
cf8f0fff
CW
250 ],
251 'input' => [
f7b2fef0
CW
252 'title' => 'Search Input',
253 'description' => "String to search on",
254 'type' => CRM_Utils_Type::T_TEXT,
cf8f0fff
CW
255 ],
256 'params' => [
f7b2fef0
CW
257 'title' => 'API Params',
258 'description' => "Additional filters to send to the {$apiRequest['entity']} API.",
cf8f0fff
CW
259 ],
260 'extra' => [
f7b2fef0
CW
261 'title' => 'Extra',
262 'description' => 'Array of additional fields to return.',
cf8f0fff
CW
263 ],
264 'image_field' => [
f7b2fef0
CW
265 'title' => 'Image Field',
266 'description' => "Field that this entity uses to store icons (usually automatic)",
267 'type' => CRM_Utils_Type::T_TEXT,
cf8f0fff
CW
268 ],
269 'id_field' => [
f7b2fef0
CW
270 'title' => 'ID Field',
271 'description' => "Field that uniquely identifies this entity (usually automatic)",
272 'type' => CRM_Utils_Type::T_TEXT,
cf8f0fff
CW
273 ],
274 'description_field' => [
f7b2fef0
CW
275 'title' => 'Description Field',
276 'description' => "Field that this entity uses to store summary text (usually automatic)",
277 'type' => CRM_Utils_Type::T_TEXT,
cf8f0fff
CW
278 ],
279 'label_field' => [
fee3e3c3 280 'title' => 'Label Field',
f7b2fef0
CW
281 'description' => "Field to display as title of results (usually automatic)",
282 'type' => CRM_Utils_Type::T_TEXT,
cf8f0fff
CW
283 ],
284 'search_field' => [
f7b2fef0
CW
285 'title' => 'Search Field',
286 'description' => "Field to search on (assumed to be the same as label field unless otherwise specified)",
287 'type' => CRM_Utils_Type::T_TEXT,
cf8f0fff
CW
288 ],
289 ];
f7b2fef0 290}