Use trait instead of class for Entity Bridges; add OptionList trait
[civicrm-core.git] / Civi / Api4 / Generic / DAOGetAction.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
3c7c8fa6 22use Civi\Api4\Query\Api4SelectQuery;
9d2afe25 23use Civi\Api4\Utils\CoreUtil;
3c7c8fa6 24
19b53e5b 25/**
e3c6d5ff 26 * Retrieve $ENTITIES based on criteria specified in the `where` parameter.
19b53e5b 27 *
fc95d9a5 28 * Use the `select` param to determine which fields are returned, defaults to `[*]`.
19b53e5b
C
29 *
30 * Perform joins on other related entities using a dot notation.
c9e3ae2e
CW
31 *
32 * @method $this setHaving(array $clauses)
33 * @method array getHaving()
19b53e5b
C
34 */
35class DAOGetAction extends AbstractGetAction {
36 use Traits\DAOActionTrait;
37
39e0f675 38 /**
2f69b203
CW
39 * Fields to return. Defaults to all non-custom fields `['*']`.
40 *
41 * The keyword `"custom.*"` selects all custom fields. So to select all core + custom fields, select `['*', 'custom.*']`.
39e0f675 42 *
fc95d9a5 43 * Use the dot notation to perform joins in the select clause, e.g. selecting `['*', 'contact.*']` from `Email::get()`
39e0f675
CW
44 * will select all fields for the email + all fields for the related contact.
45 *
46 * @var array
47 * @inheritDoc
48 */
49 protected $select = [];
50
16f5a13d
CW
51 /**
52 * Joins to other entities.
53 *
90908aac
CW
54 * Each join is an array of properties:
55 *
56 * ```
57 * [Entity, Required, Bridge, [field, op, value]...]
58 * ```
59 *
60 * - `Entity`: the name of the api entity to join onto.
61 * - `Required`: `TRUE` for an `INNER JOIN`, `FALSE` for a `LEFT JOIN`.
465bc32a 62 * - `Bridge` (optional): Name of a Bridge to incorporate into the join.
90908aac
CW
63 * - `[field, op, value]...`: zero or more conditions for the ON clause, using the same nested format as WHERE and HAVING
64 * but with the difference that "value" is interpreted as an expression (e.g. can be the name of a field).
65 * Enclose literal values with quotes.
66 *
16f5a13d 67 * @var array
465bc32a 68 * @see \Civi\Api4\Generic\Traits\EntityBridge
16f5a13d
CW
69 */
70 protected $join = [];
71
f0acec37
CW
72 /**
73 * Field(s) by which to group the results.
74 *
75 * @var array
76 */
77 protected $groupBy = [];
78
79 /**
80 * Clause for filtering results after grouping and filters are applied.
81 *
82 * Each expression should correspond to an item from the SELECT array.
83 *
84 * @var array
85 */
86 protected $having = [];
87
19b53e5b 88 public function _run(Result $result) {
06f83d5c
CW
89 // Early return if table doesn't exist yet due to pending upgrade
90 $baoName = $this->getBaoName();
91 if (!$baoName::tableHasBeenAdded()) {
3519db92 92 \Civi::log()->warning("Could not read from {$this->getEntityName()} before table has been added. Upgrade required.", ['civi.tag' => 'upgrade_needed']);
06f83d5c
CW
93 return;
94 }
95
19b53e5b 96 $this->setDefaultWhereClause();
39e0f675 97 $this->expandSelectClauseWildcards();
651c4c95 98 $this->getObjects($result);
19b53e5b
C
99 }
100
3c7c8fa6 101 /**
651c4c95 102 * @param \Civi\Api4\Generic\Result $result
3c7c8fa6 103 */
651c4c95
CW
104 protected function getObjects(Result $result) {
105 $getCount = in_array('row_count', $this->getSelect());
106 $onlyCount = $this->getSelect() === ['row_count'];
107
108 if (!$onlyCount) {
109 $query = new Api4SelectQuery($this);
110 $rows = $query->run();
111 \CRM_Utils_API_HTMLInputCoder::singleton()->decodeRows($rows);
112 $result->exchangeArray($rows);
113 // No need to fetch count if we got a result set below the limit
114 if (!$this->getLimit() || count($rows) < $this->getLimit()) {
115 $result->rowCount = count($rows) + $this->getOffset();
116 $getCount = FALSE;
117 }
118 }
119 if ($getCount) {
120 $query = new Api4SelectQuery($this);
121 $result->rowCount = $query->getCount();
3c7c8fa6 122 }
3c7c8fa6
CW
123 }
124
f0acec37
CW
125 /**
126 * @return array
127 */
128 public function getGroupBy(): array {
129 return $this->groupBy;
130 }
131
132 /**
133 * @param array $groupBy
134 * @return $this
135 */
136 public function setGroupBy(array $groupBy) {
137 $this->groupBy = $groupBy;
138 return $this;
139 }
140
141 /**
142 * @param string $field
143 * @return $this
144 */
145 public function addGroupBy(string $field) {
146 $this->groupBy[] = $field;
147 return $this;
148 }
149
150 /**
151 * @param string $expr
152 * @param string $op
153 * @param mixed $value
154 * @return $this
155 * @throws \API_Exception
156 */
157 public function addHaving(string $expr, string $op, $value = NULL) {
9d2afe25 158 if (!in_array($op, CoreUtil::getOperators())) {
f0acec37
CW
159 throw new \API_Exception('Unsupported operator');
160 }
161 $this->having[] = [$expr, $op, $value];
162 return $this;
163 }
164
16f5a13d
CW
165 /**
166 * @param string $entity
167 * @param bool $required
90908aac 168 * @param string $bridge
16f5a13d
CW
169 * @param array ...$conditions
170 * @return DAOGetAction
171 */
90908aac
CW
172 public function addJoin(string $entity, bool $required = FALSE, $bridge = NULL, ...$conditions): DAOGetAction {
173 if ($bridge) {
174 array_unshift($conditions, $bridge);
175 }
16f5a13d
CW
176 array_unshift($conditions, $entity, $required);
177 $this->join[] = $conditions;
178 return $this;
179 }
180
181 /**
182 * @param array $join
183 * @return DAOGetAction
184 */
185 public function setJoin(array $join): DAOGetAction {
186 $this->join = $join;
187 return $this;
188 }
189
190 /**
191 * @return array
192 */
193 public function getJoin(): array {
194 return $this->join;
195 }
196
19b53e5b 197}