@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3/**
4 * @extends DrydockQuery<DrydockBlueprint>
5 */
6final class DrydockBlueprintQuery extends DrydockQuery {
7
8 private $ids;
9 private $phids;
10 private $blueprintClasses;
11 private $datasourceQuery;
12 private $disabled;
13 private $authorizedPHIDs;
14
15 private $identifiers;
16 private $identifierIDs;
17 private $identifierPHIDs;
18 private $identifierMap;
19
20 public function withIDs(array $ids) {
21 $this->ids = $ids;
22 return $this;
23 }
24
25 public function withPHIDs(array $phids) {
26 $this->phids = $phids;
27 return $this;
28 }
29
30 public function withBlueprintClasses(array $classes) {
31 $this->blueprintClasses = $classes;
32 return $this;
33 }
34
35 public function withDatasourceQuery($query) {
36 $this->datasourceQuery = $query;
37 return $this;
38 }
39
40 public function withDisabled($disabled) {
41 $this->disabled = $disabled;
42 return $this;
43 }
44
45 public function withAuthorizedPHIDs(array $phids) {
46 $this->authorizedPHIDs = $phids;
47 return $this;
48 }
49
50 public function withNameNgrams($ngrams) {
51 return $this->withNgramsConstraint(
52 new DrydockBlueprintNameNgrams(),
53 $ngrams);
54 }
55
56 public function withIdentifiers(array $identifiers) {
57 if (!$identifiers) {
58 throw new Exception(
59 pht(
60 'Can not issue a query with an empty identifier list.'));
61 }
62
63 $this->identifiers = $identifiers;
64
65 $ids = array();
66 $phids = array();
67
68 foreach ($identifiers as $identifier) {
69 if (ctype_digit($identifier)) {
70 $ids[] = $identifier;
71 } else {
72 $phids[] = $identifier;
73 }
74 }
75
76 $this->identifierIDs = $ids;
77 $this->identifierPHIDs = $phids;
78
79 return $this;
80 }
81
82 public function getIdentifierMap() {
83 if ($this->identifierMap === null) {
84 throw new Exception(
85 pht(
86 'Execute a query with identifiers before getting the '.
87 'identifier map.'));
88 }
89
90 return $this->identifierMap;
91 }
92
93 public function newResultObject() {
94 return new DrydockBlueprint();
95 }
96
97 protected function getPrimaryTableAlias() {
98 return 'blueprint';
99 }
100
101 protected function willExecute() {
102 if ($this->identifiers) {
103 $this->identifierMap = array();
104 } else {
105 $this->identifierMap = null;
106 }
107 }
108
109 protected function willFilterPage(array $blueprints) {
110 $impls = DrydockBlueprintImplementation::getAllBlueprintImplementations();
111 foreach ($blueprints as $key => $blueprint) {
112 $impl = idx($impls, $blueprint->getClassName());
113 if (!$impl) {
114 $this->didRejectResult($blueprint);
115 unset($blueprints[$key]);
116 continue;
117 }
118 $impl = clone $impl;
119 $blueprint->attachImplementation($impl);
120 }
121
122 if ($this->identifiers) {
123 $id_map = mpull($blueprints, null, 'getID');
124 $phid_map = mpull($blueprints, null, 'getPHID');
125
126 $map = $this->identifierMap;
127
128 foreach ($this->identifierIDs as $id) {
129 if (isset($id_map[$id])) {
130 $map[$id] = $id_map[$id];
131 }
132 }
133
134 foreach ($this->identifierPHIDs as $phid) {
135 if (isset($phid_map[$phid])) {
136 $map[$phid] = $phid_map[$phid];
137 }
138 }
139
140 // Just for consistency, reorder the map to match input order.
141 $map = array_select_keys($map, $this->identifiers);
142
143 $this->identifierMap = $map;
144 }
145
146 return $blueprints;
147 }
148
149 protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
150 $where = parent::buildWhereClauseParts($conn);
151
152 if ($this->ids !== null) {
153 $where[] = qsprintf(
154 $conn,
155 'blueprint.id IN (%Ld)',
156 $this->ids);
157 }
158
159 if ($this->phids !== null) {
160 $where[] = qsprintf(
161 $conn,
162 'blueprint.phid IN (%Ls)',
163 $this->phids);
164 }
165
166 if ($this->datasourceQuery !== null) {
167 $where[] = qsprintf(
168 $conn,
169 'blueprint.blueprintName LIKE %>',
170 $this->datasourceQuery);
171 }
172
173 if ($this->blueprintClasses !== null) {
174 $where[] = qsprintf(
175 $conn,
176 'blueprint.className IN (%Ls)',
177 $this->blueprintClasses);
178 }
179
180 if ($this->disabled !== null) {
181 $where[] = qsprintf(
182 $conn,
183 'blueprint.isDisabled = %d',
184 (int)$this->disabled);
185 }
186
187 if ($this->identifiers !== null) {
188 $parts = array();
189
190 if ($this->identifierIDs) {
191 $parts[] = qsprintf(
192 $conn,
193 'blueprint.id IN (%Ld)',
194 $this->identifierIDs);
195 }
196
197 if ($this->identifierPHIDs) {
198 $parts[] = qsprintf(
199 $conn,
200 'blueprint.phid IN (%Ls)',
201 $this->identifierPHIDs);
202 }
203
204 $where[] = qsprintf(
205 $conn,
206 '%LO',
207 $parts);
208 }
209
210 return $where;
211 }
212
213 protected function shouldGroupQueryResultRows() {
214 if ($this->authorizedPHIDs !== null) {
215 return true;
216 }
217 return parent::shouldGroupQueryResultRows();
218 }
219
220 protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
221 $joins = parent::buildJoinClauseParts($conn);
222
223 if ($this->authorizedPHIDs !== null) {
224 $joins[] = qsprintf(
225 $conn,
226 'JOIN %T authorization
227 ON authorization.blueprintPHID = blueprint.phid
228 AND authorization.objectPHID IN (%Ls)
229 AND authorization.objectAuthorizationState = %s
230 AND authorization.blueprintAuthorizationState = %s',
231 id(new DrydockAuthorization())->getTableName(),
232 $this->authorizedPHIDs,
233 DrydockAuthorization::OBJECTAUTH_ACTIVE,
234 DrydockAuthorization::BLUEPRINTAUTH_AUTHORIZED);
235 }
236
237 return $joins;
238 }
239
240}