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