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