@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
3final class DifferentialRevisionRequiredActionResultBucket
4 extends DifferentialRevisionResultBucket {
5
6 const BUCKETKEY = 'action';
7
8 const KEY_MUSTREVIEW = 'must-review';
9 const KEY_SHOULDREVIEW = 'should-review';
10
11 private $objects;
12
13 public function getResultBucketName() {
14 return pht('Bucket by Required Action');
15 }
16
17 protected function buildResultGroups(
18 PhabricatorSavedQuery $query,
19 array $objects) {
20
21 $this->objects = $objects;
22
23 $phids = $query->getEvaluatedParameter('responsiblePHIDs');
24 if (!$phids) {
25 throw new Exception(
26 pht(
27 'You can not bucket results by required action without '.
28 'specifying "Responsible Users".'));
29 }
30 $phids = array_fuse($phids);
31
32 // Before continuing, throw away any revisions which responsible users
33 // have explicitly resigned from.
34
35 // The goal is to allow users to resign from revisions they don't want to
36 // review to get these revisions off their dashboard, even if there are
37 // other project or package reviewers which they have authority over.
38 $this->filterResigned($phids);
39
40 // We also throw away draft revisions which you aren't the author of.
41 $this->filterOtherDrafts($phids);
42
43 $groups = array();
44
45 $groups[] = $this->newGroup()
46 ->setName(pht('Must Review'))
47 ->setKey(self::KEY_MUSTREVIEW)
48 ->setNoDataString(pht('No revisions are blocked on your review.'))
49 ->setObjects($this->filterMustReview($phids));
50
51 $groups[] = $this->newGroup()
52 ->setName(pht('Ready to Review'))
53 ->setKey(self::KEY_SHOULDREVIEW)
54 ->setNoDataString(pht('No revisions are waiting on you to review them.'))
55 ->setObjects($this->filterShouldReview($phids));
56
57 $groups[] = $this->newGroup()
58 ->setName(pht('Ready to Land'))
59 ->setNoDataString(pht('No revisions are ready to land.'))
60 ->setObjects($this->filterShouldLand($phids));
61
62 $groups[] = $this->newGroup()
63 ->setName(pht('Ready to Update'))
64 ->setNoDataString(pht('No revisions are waiting for updates.'))
65 ->setObjects($this->filterShouldUpdate($phids));
66
67 $groups[] = $this->newGroup()
68 ->setName(pht('Drafts'))
69 ->setNoDataString(pht('You have no draft revisions.'))
70 ->setObjects($this->filterDrafts($phids));
71
72 $groups[] = $this->newGroup()
73 ->setName(pht('Waiting on Review'))
74 ->setNoDataString(pht('None of your revisions are waiting on review.'))
75 ->setObjects($this->filterWaitingForReview($phids));
76
77 $groups[] = $this->newGroup()
78 ->setName(pht('Waiting on Authors'))
79 ->setNoDataString(pht('No revisions are waiting on author action.'))
80 ->setObjects($this->filterWaitingOnAuthors($phids));
81
82 $groups[] = $this->newGroup()
83 ->setName(pht('Waiting on Other Reviewers'))
84 ->setNoDataString(pht('No revisions are waiting for other reviewers.'))
85 ->setObjects($this->filterWaitingOnOtherReviewers($phids));
86
87 // Because you can apply these buckets to queries which include revisions
88 // that have been closed, add an "Other" bucket if we still have stuff
89 // that didn't get filtered into any of the previous buckets.
90 if ($this->objects) {
91 $groups[] = $this->newGroup()
92 ->setName(pht('Other Revisions'))
93 ->setObjects($this->objects);
94 }
95
96 return $groups;
97 }
98
99 private function filterMustReview(array $phids) {
100 $blocking = array(
101 DifferentialReviewerStatus::STATUS_BLOCKING,
102 DifferentialReviewerStatus::STATUS_REJECTED,
103 DifferentialReviewerStatus::STATUS_REJECTED_OLDER,
104 );
105 $blocking = array_fuse($blocking);
106
107 $objects = $this->getRevisionsUnderReview($this->objects, $phids);
108
109 $results = array();
110 foreach ($objects as $key => $object) {
111 if (!$this->hasReviewersWithStatus($object, $phids, $blocking)) {
112 continue;
113 }
114
115 $results[$key] = $object;
116 unset($this->objects[$key]);
117 }
118
119 return $results;
120 }
121
122 private function filterShouldReview(array $phids) {
123 $reviewing = array(
124 DifferentialReviewerStatus::STATUS_ADDED,
125 DifferentialReviewerStatus::STATUS_COMMENTED,
126
127 // If an author has used "Request Review" to put an accepted revision
128 // back into the "Needs Review" state, include "Accepted" reviewers
129 // whose reviews have been voided in the "Should Review" bucket.
130
131 // If we don't do this, they end up in "Waiting on Other Reviewers",
132 // even if there are no other reviewers.
133 DifferentialReviewerStatus::STATUS_ACCEPTED,
134 );
135 $reviewing = array_fuse($reviewing);
136
137 $objects = $this->getRevisionsUnderReview($this->objects, $phids);
138
139 $results = array();
140 foreach ($objects as $key => $object) {
141 if (!$this->hasReviewersWithStatus($object, $phids, $reviewing, true)) {
142 continue;
143 }
144
145 $results[$key] = $object;
146 unset($this->objects[$key]);
147 }
148
149 return $results;
150 }
151
152 private function filterShouldLand(array $phids) {
153 $objects = $this->getRevisionsAuthored($this->objects, $phids);
154
155 $results = array();
156 foreach ($objects as $key => $object) {
157 if (!$object->isAccepted()) {
158 continue;
159 }
160
161 $results[$key] = $object;
162 unset($this->objects[$key]);
163 }
164
165 return $results;
166 }
167
168 private function filterShouldUpdate(array $phids) {
169 $statuses = array(
170 DifferentialRevisionStatus::NEEDS_REVISION,
171 DifferentialRevisionStatus::CHANGES_PLANNED,
172 );
173 $statuses = array_fuse($statuses);
174
175 $objects = $this->getRevisionsAuthored($this->objects, $phids);
176
177 $results = array();
178 foreach ($objects as $key => $object) {
179 if (empty($statuses[$object->getModernRevisionStatus()])) {
180 continue;
181 }
182
183 $results[$key] = $object;
184 unset($this->objects[$key]);
185 }
186
187 return $results;
188 }
189
190 private function filterWaitingForReview(array $phids) {
191 $objects = $this->getRevisionsAuthored($this->objects, $phids);
192
193 $results = array();
194 foreach ($objects as $key => $object) {
195 if (!$object->isNeedsReview()) {
196 continue;
197 }
198
199 $results[$key] = $object;
200 unset($this->objects[$key]);
201 }
202
203 return $results;
204 }
205
206 private function filterWaitingOnAuthors(array $phids) {
207 $statuses = array(
208 DifferentialRevisionStatus::ACCEPTED,
209 DifferentialRevisionStatus::NEEDS_REVISION,
210 DifferentialRevisionStatus::CHANGES_PLANNED,
211 );
212 $statuses = array_fuse($statuses);
213
214 $objects = $this->getRevisionsNotAuthored($this->objects, $phids);
215
216 $results = array();
217 foreach ($objects as $key => $object) {
218 if (empty($statuses[$object->getModernRevisionStatus()])) {
219 continue;
220 }
221
222 $results[$key] = $object;
223 unset($this->objects[$key]);
224 }
225
226 return $results;
227 }
228
229 private function filterWaitingOnOtherReviewers(array $phids) {
230 $objects = $this->getRevisionsNotAuthored($this->objects, $phids);
231
232 $results = array();
233 foreach ($objects as $key => $object) {
234 if (!$object->isNeedsReview()) {
235 continue;
236 }
237
238 $results[$key] = $object;
239 unset($this->objects[$key]);
240 }
241
242 return $results;
243 }
244
245 private function filterResigned(array $phids) {
246 $resigned = array(
247 DifferentialReviewerStatus::STATUS_RESIGNED,
248 );
249 $resigned = array_fuse($resigned);
250
251 $objects = $this->getRevisionsNotAuthored($this->objects, $phids);
252
253 $results = array();
254 foreach ($objects as $key => $object) {
255 if (!$this->hasReviewersWithStatus($object, $phids, $resigned)) {
256 continue;
257 }
258
259 $results[$key] = $object;
260 unset($this->objects[$key]);
261 }
262
263 return $results;
264 }
265
266 private function filterOtherDrafts(array $phids) {
267 $objects = $this->getRevisionsNotAuthored($this->objects, $phids);
268
269 $results = array();
270 foreach ($objects as $key => $object) {
271 if (!$object->isDraft()) {
272 continue;
273 }
274
275 $results[$key] = $object;
276 unset($this->objects[$key]);
277 }
278
279 return $results;
280 }
281
282 private function filterDrafts(array $phids) {
283 $objects = $this->getRevisionsAuthored($this->objects, $phids);
284
285 $results = array();
286 foreach ($objects as $key => $object) {
287 if (!$object->isDraft()) {
288 continue;
289 }
290
291 $results[$key] = $object;
292 unset($this->objects[$key]);
293 }
294
295 return $results;
296 }
297
298}