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 | 22 | use Civi\Api4\Query\Api4SelectQuery; |
9d2afe25 | 23 | use 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 | */ |
35 | class 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 | } |