Merge pull request #17878 from civicrm/5.28
[civicrm-core.git] / Civi / Api4 / Generic / AbstractQueryAction.php
1 <?php
2
3 /*
4 +--------------------------------------------------------------------+
5 | Copyright CiviCRM LLC. All rights reserved. |
6 | |
7 | This work is published under the GNU AGPLv3 license with some |
8 | permitted exceptions and without any warranty. For full license |
9 | and copyright information, see https://civicrm.org/licensing |
10 +--------------------------------------------------------------------+
11 */
12
13 /**
14 *
15 * @package CRM
16 * @copyright CiviCRM LLC https://civicrm.org/licensing
17 * $Id$
18 *
19 */
20
21
22 namespace Civi\Api4\Generic;
23
24 /**
25 * Base class for all actions that need to fetch records (`Get`, `Update`, `Delete`, etc.).
26 *
27 * @package Civi\Api4\Generic
28 *
29 * @method $this setWhere(array $wheres)
30 * @method array getWhere()
31 * @method $this setOrderBy(array $order)
32 * @method array getOrderBy()
33 * @method $this setLimit(int $limit)
34 * @method int getLimit()
35 * @method $this setOffset(int $offset)
36 * @method int getOffset()
37 */
38 abstract class AbstractQueryAction extends AbstractAction {
39
40 /**
41 * Criteria for selecting $ENTITIES.
42 *
43 * ```php
44 * $example->addWhere('contact_type', 'IN', ['Individual', 'Household'])
45 * ```
46 * @var array
47 */
48 protected $where = [];
49
50 /**
51 * Array of field(s) to use in ordering the results.
52 *
53 * Defaults to id ASC
54 *
55 * ```php
56 * $example->addOrderBy('sort_name', 'ASC')
57 * ```
58 * @var array
59 */
60 protected $orderBy = [];
61
62 /**
63 * Maximum number of $ENTITIES to return.
64 *
65 * Defaults to `0` - unlimited.
66 *
67 * Note: the Api Explorer sets this to `25` by default to avoid timeouts.
68 * Change or remove this default for your application code.
69 *
70 * @var int
71 */
72 protected $limit = 0;
73
74 /**
75 * Zero-based index of first $ENTITY to return.
76 *
77 * Defaults to `0` - first $ENTITY found.
78 *
79 * @var int
80 */
81 protected $offset = 0;
82
83 /**
84 * @param string $fieldName
85 * @param string $op
86 * @param mixed $value
87 * @return $this
88 * @throws \API_Exception
89 */
90 public function addWhere(string $fieldName, string $op, $value = NULL) {
91 if (!in_array($op, \CRM_Core_DAO::acceptedSQLOperators())) {
92 throw new \API_Exception('Unsupported operator');
93 }
94 $this->where[] = [$fieldName, $op, $value];
95 return $this;
96 }
97
98 /**
99 * Adds one or more AND/OR/NOT clause groups
100 *
101 * @param string $operator
102 * @param mixed $condition1 ... $conditionN
103 * Either a nested array of arguments, or a variable number of arguments passed to this function.
104 *
105 * @return $this
106 * @throws \API_Exception
107 */
108 public function addClause(string $operator, $condition1) {
109 if (!is_array($condition1[0])) {
110 $condition1 = array_slice(func_get_args(), 1);
111 }
112 $this->where[] = [$operator, $condition1];
113 return $this;
114 }
115
116 /**
117 * Adds to the orderBy clause
118 * @param string $fieldName
119 * @param string $direction
120 * @return $this
121 */
122 public function addOrderBy(string $fieldName, $direction = 'ASC') {
123 $this->orderBy[$fieldName] = $direction;
124 return $this;
125 }
126
127 /**
128 * Produces a human-readable where clause, for the reading enjoyment of you humans.
129 *
130 * @param array $whereClause
131 * @param string $op
132 * @return string
133 */
134 protected function whereClauseToString($whereClause = NULL, $op = 'AND') {
135 if ($whereClause === NULL) {
136 $whereClause = $this->where;
137 }
138 $output = '';
139 if (!is_array($whereClause) || !$whereClause) {
140 return $output;
141 }
142 if (in_array($whereClause[0], ['AND', 'OR', 'NOT'])) {
143 $op = array_shift($whereClause);
144 if ($op == 'NOT') {
145 $output = 'NOT ';
146 $op = 'AND';
147 }
148 return $output . '(' . $this->whereClauseToString($whereClause, $op) . ')';
149 }
150 elseif (isset($whereClause[1]) && in_array($whereClause[1], \CRM_Core_DAO::acceptedSQLOperators())) {
151 $output = $whereClause[0] . ' ' . $whereClause[1] . ' ';
152 if (isset($whereClause[2])) {
153 $output .= is_array($whereClause[2]) ? '[' . implode(', ', $whereClause[2]) . ']' : $whereClause[2];
154 }
155 }
156 else {
157 $clauses = [];
158 foreach (array_filter($whereClause) as $clause) {
159 $clauses[] = $this->whereClauseToString($clause, $op);
160 }
161 $output = implode(" $op ", $clauses);
162 }
163 return $output;
164 }
165
166 }