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