@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 PhabricatorCursorPagedPolicyAwareQuery<HarbormasterBuild>
5 */
6final class HarbormasterBuildQuery
7 extends PhabricatorCursorPagedPolicyAwareQuery {
8
9 private $ids;
10 private $phids;
11 private $buildStatuses;
12 private $buildablePHIDs;
13 private $buildPlanPHIDs;
14 private $initiatorPHIDs;
15 private $needBuildTargets;
16 private $autobuilds;
17
18 public function withIDs(array $ids) {
19 $this->ids = $ids;
20 return $this;
21 }
22
23 public function withPHIDs(array $phids) {
24 $this->phids = $phids;
25 return $this;
26 }
27
28 public function withBuildStatuses(array $build_statuses) {
29 $this->buildStatuses = $build_statuses;
30 return $this;
31 }
32
33 public function withBuildablePHIDs(array $buildable_phids) {
34 $this->buildablePHIDs = $buildable_phids;
35 return $this;
36 }
37
38 public function withBuildPlanPHIDs(array $build_plan_phids) {
39 $this->buildPlanPHIDs = $build_plan_phids;
40 return $this;
41 }
42
43 public function withInitiatorPHIDs(array $initiator_phids) {
44 $this->initiatorPHIDs = $initiator_phids;
45 return $this;
46 }
47
48 public function withAutobuilds($with_autobuilds) {
49 $this->autobuilds = $with_autobuilds;
50 return $this;
51 }
52
53 public function needBuildTargets($need_targets) {
54 $this->needBuildTargets = $need_targets;
55 return $this;
56 }
57
58 public function newResultObject() {
59 return new HarbormasterBuild();
60 }
61
62 protected function willFilterPage(array $page) {
63 $buildables = array();
64
65 $buildable_phids = array_filter(mpull($page, 'getBuildablePHID'));
66 if ($buildable_phids) {
67 $buildables = id(new PhabricatorObjectQuery())
68 ->setViewer($this->getViewer())
69 ->withPHIDs($buildable_phids)
70 ->setParentQuery($this)
71 ->execute();
72 $buildables = mpull($buildables, null, 'getPHID');
73 }
74
75 foreach ($page as $key => $build) {
76 $buildable_phid = $build->getBuildablePHID();
77 if (empty($buildables[$buildable_phid])) {
78 unset($page[$key]);
79 continue;
80 }
81 $build->attachBuildable($buildables[$buildable_phid]);
82 }
83
84 return $page;
85 }
86
87 protected function didFilterPage(array $page) {
88 $plans = array();
89
90 $plan_phids = array_filter(mpull($page, 'getBuildPlanPHID'));
91 if ($plan_phids) {
92 $plans = id(new PhabricatorObjectQuery())
93 ->setViewer($this->getViewer())
94 ->withPHIDs($plan_phids)
95 ->setParentQuery($this)
96 ->execute();
97 $plans = mpull($plans, null, 'getPHID');
98 }
99
100 foreach ($page as $key => $build) {
101 $plan_phid = $build->getBuildPlanPHID();
102 $build->attachBuildPlan(idx($plans, $plan_phid));
103 }
104
105 $build_phids = mpull($page, 'getPHID');
106 $messages = id(new HarbormasterBuildMessage())->loadAllWhere(
107 'receiverPHID IN (%Ls) AND isConsumed = 0 ORDER BY id ASC',
108 $build_phids);
109 $messages = mgroup($messages, 'getReceiverPHID');
110 foreach ($page as $build) {
111 $unprocessed_messages = idx($messages, $build->getPHID(), array());
112 $build->attachUnprocessedMessages($unprocessed_messages);
113 }
114
115 if ($this->needBuildTargets) {
116 $targets = id(new HarbormasterBuildTargetQuery())
117 ->setViewer($this->getViewer())
118 ->setParentQuery($this)
119 ->withBuildPHIDs($build_phids)
120 ->execute();
121
122 // TODO: Some day, when targets have dependencies, we should toposort
123 // these. For now, just put them into chronological order.
124 $targets = array_reverse($targets);
125
126 $targets = mgroup($targets, 'getBuildPHID');
127 foreach ($page as $build) {
128 $build_targets = idx($targets, $build->getPHID(), array());
129
130 foreach ($build_targets as $phid => $target) {
131 if ($target->getBuildGeneration() !== $build->getBuildGeneration()) {
132 unset($build_targets[$phid]);
133 }
134 }
135
136 $build->attachBuildTargets($build_targets);
137 }
138 }
139
140 return $page;
141 }
142
143 protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
144 $where = parent::buildWhereClauseParts($conn);
145
146 if ($this->ids !== null) {
147 $where[] = qsprintf(
148 $conn,
149 'b.id IN (%Ld)',
150 $this->ids);
151 }
152
153 if ($this->phids !== null) {
154 $where[] = qsprintf(
155 $conn,
156 'b.phid in (%Ls)',
157 $this->phids);
158 }
159
160 if ($this->buildStatuses !== null) {
161 $where[] = qsprintf(
162 $conn,
163 'b.buildStatus in (%Ls)',
164 $this->buildStatuses);
165 }
166
167 if ($this->buildablePHIDs !== null) {
168 $where[] = qsprintf(
169 $conn,
170 'b.buildablePHID IN (%Ls)',
171 $this->buildablePHIDs);
172 }
173
174 if ($this->buildPlanPHIDs !== null) {
175 $where[] = qsprintf(
176 $conn,
177 'b.buildPlanPHID IN (%Ls)',
178 $this->buildPlanPHIDs);
179 }
180
181 if ($this->initiatorPHIDs !== null) {
182 $where[] = qsprintf(
183 $conn,
184 'b.initiatorPHID IN (%Ls)',
185 $this->initiatorPHIDs);
186 }
187
188 if ($this->autobuilds !== null) {
189 if ($this->autobuilds) {
190 $where[] = qsprintf(
191 $conn,
192 'p.planAutoKey IS NOT NULL');
193 } else {
194 $where[] = qsprintf(
195 $conn,
196 'p.planAutoKey IS NULL');
197 }
198 }
199
200 return $where;
201 }
202
203 protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
204 $joins = parent::buildJoinClauseParts($conn);
205
206 if ($this->shouldJoinPlanTable()) {
207 $joins[] = qsprintf(
208 $conn,
209 'JOIN %T p ON b.buildPlanPHID = p.phid',
210 id(new HarbormasterBuildPlan())->getTableName());
211 }
212
213 return $joins;
214 }
215
216 private function shouldJoinPlanTable() {
217 if ($this->autobuilds !== null) {
218 return true;
219 }
220
221 return false;
222 }
223
224 public function getQueryApplicationClass() {
225 return PhabricatorHarbormasterApplication::class;
226 }
227
228 protected function getPrimaryTableAlias() {
229 return 'b';
230 }
231
232}