Merge pull request #21850 from mariav0/patch-1
[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
19b53e5b
C
13namespace Civi\Api4\Generic;
14
9d2afe25
CW
15use Civi\Api4\Utils\CoreUtil;
16
19b53e5b 17/**
fc95d9a5 18 * Base class for all actions that need to fetch records (`Get`, `Update`, `Delete`, etc.).
19b53e5b
C
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 */
31abstract class AbstractQueryAction extends AbstractAction {
32
33 /**
e3c6d5ff 34 * Criteria for selecting $ENTITIES.
19b53e5b 35 *
fc95d9a5
CW
36 * ```php
37 * $example->addWhere('contact_type', 'IN', ['Individual', 'Household'])
38 * ```
19b53e5b
C
39 * @var array
40 */
41 protected $where = [];
42
43 /**
fc95d9a5 44 * Array of field(s) to use in ordering the results.
19b53e5b
C
45 *
46 * Defaults to id ASC
47 *
fc95d9a5 48 * ```php
19b53e5b 49 * $example->addOrderBy('sort_name', 'ASC')
fc95d9a5 50 * ```
19b53e5b
C
51 * @var array
52 */
53 protected $orderBy = [];
54
55 /**
e3c6d5ff 56 * Maximum number of $ENTITIES to return.
19b53e5b 57 *
d71cde6c 58 * Defaults to `0` - unlimited.
19b53e5b 59 *
d71cde6c 60 * Note: the Api Explorer sets this to `25` by default to avoid timeouts.
19b53e5b
C
61 * Change or remove this default for your application code.
62 *
63 * @var int
64 */
65 protected $limit = 0;
66
67 /**
fc95d9a5 68 * Zero-based index of first $ENTITY to return.
19b53e5b 69 *
d71cde6c 70 * Defaults to `0` - first $ENTITY found.
19b53e5b
C
71 *
72 * @var int
73 */
74 protected $offset = 0;
75
76 /**
121ec912 77 * @param string $fieldName
19b53e5b
C
78 * @param string $op
79 * @param mixed $value
80 * @return $this
81 * @throws \API_Exception
82 */
121ec912 83 public function addWhere(string $fieldName, string $op, $value = NULL) {
9d2afe25 84 if (!in_array($op, CoreUtil::getOperators())) {
19b53e5b
C
85 throw new \API_Exception('Unsupported operator');
86 }
121ec912 87 $this->where[] = [$fieldName, $op, $value];
19b53e5b
C
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 */
121ec912 101 public function addClause(string $operator, $condition1) {
19b53e5b
C
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 /**
121ec912
CW
110 * Adds to the orderBy clause
111 * @param string $fieldName
19b53e5b
C
112 * @param string $direction
113 * @return $this
114 */
121ec912
CW
115 public function addOrderBy(string $fieldName, $direction = 'ASC') {
116 $this->orderBy[$fieldName] = $direction;
19b53e5b
C
117 return $this;
118 }
119
120 /**
121ec912 121 * Produces a human-readable where clause, for the reading enjoyment of you humans.
19b53e5b
C
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 }
9d2afe25 143 elseif (isset($whereClause[1]) && in_array($whereClause[1], CoreUtil::getOperators())) {
19b53e5b
C
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}