@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 DifferentialRevisionUpdateHistoryView extends AphrontView {
4
5 private $diffs = array();
6 private $selectedVersusDiffID;
7 private $selectedDiffID;
8 private $commitsForLinks = array();
9 private $unitStatus = array();
10
11 /**
12 * @param array<DifferentialDiff> $diffs
13 */
14 public function setDiffs(array $diffs) {
15 assert_instances_of($diffs, DifferentialDiff::class);
16 $this->diffs = $diffs;
17 return $this;
18 }
19
20 public function setSelectedVersusDiffID($id) {
21 $this->selectedVersusDiffID = $id;
22 return $this;
23 }
24
25 public function setSelectedDiffID($id) {
26 $this->selectedDiffID = $id;
27 return $this;
28 }
29
30 /**
31 * @param array<PhabricatorRepositoryCommit> $commits
32 */
33 public function setCommitsForLinks(array $commits) {
34 assert_instances_of($commits, PhabricatorRepositoryCommit::class);
35 $this->commitsForLinks = $commits;
36 return $this;
37 }
38
39 public function setDiffUnitStatuses(array $unit_status) {
40 $this->unitStatus = $unit_status;
41 return $this;
42 }
43
44 public function render() {
45 $this->requireResource('differential-core-view-css');
46 $this->requireResource('differential-revision-history-css');
47
48 $data = array(
49 array(
50 'name' => pht('Base'),
51 'id' => null,
52 'desc' => pht('Base'),
53 'age' => null,
54 'obj' => null,
55 ),
56 );
57
58 $seq = 0;
59 foreach ($this->diffs as $diff) {
60 $data[] = array(
61 'name' => pht('Diff %d', ++$seq),
62 'id' => $diff->getID(),
63 'desc' => $diff->getDescription(),
64 'age' => $diff->getDateCreated(),
65 'obj' => $diff,
66 );
67 }
68
69 $max_id = $diff->getID();
70 $revision_id = $diff->getRevisionID();
71
72 $idx = 0;
73 $rows = array();
74 $disable = false;
75 $radios = array();
76 $last_base = null;
77 $rowc = array();
78 foreach ($data as $row) {
79
80 $diff = $row['obj'];
81 $name = $row['name'];
82 $id = $row['id'];
83
84 $old_class = false;
85 $new_class = false;
86
87 if ($id) {
88 $new_checked = ($this->selectedDiffID == $id);
89 $new = javelin_tag(
90 'input',
91 array(
92 'type' => 'radio',
93 'name' => 'id',
94 'value' => $id,
95 'checked' => $new_checked ? 'checked' : null,
96 'sigil' => 'differential-new-radio',
97 ));
98 if ($new_checked) {
99 $new_class = true;
100 $disable = true;
101 }
102 $new = phutil_tag(
103 'div',
104 array(
105 'class' => 'differential-update-history-radio',
106 ),
107 $new);
108 } else {
109 $new = null;
110 }
111
112 if ($max_id != $id) {
113 $uniq = celerity_generate_unique_node_id();
114 $old_checked = ($this->selectedVersusDiffID == $id);
115 $old = phutil_tag(
116 'input',
117 array(
118 'type' => 'radio',
119 'name' => 'vs',
120 'value' => $id,
121 'id' => $uniq,
122 'checked' => $old_checked ? 'checked' : null,
123 'disabled' => $disable ? 'disabled' : null,
124 ));
125 $radios[] = $uniq;
126 if ($old_checked) {
127 $old_class = true;
128 }
129 $old = phutil_tag(
130 'div',
131 array(
132 'class' => 'differential-update-history-radio',
133 ),
134 $old);
135 } else {
136 $old = null;
137 }
138
139 $desc = $row['desc'];
140
141 if ($row['age']) {
142 $age = phabricator_datetime($row['age'], $this->getUser());
143 } else {
144 $age = null;
145 }
146
147 if ($diff) {
148 $lint = $this->newLintStatusView($diff);
149 $unit = $this->newUnitStatusView($diff);
150 $base = $this->renderBaseRevision($diff);
151 } else {
152 $lint = null;
153 $unit = null;
154 $base = null;
155 }
156
157 if ($last_base !== null && $base !== $last_base) {
158 // TODO: Render some kind of notice about rebases.
159 }
160 $last_base = $base;
161
162 if ($revision_id) {
163 $id_link = phutil_tag(
164 'a',
165 array(
166 'href' => '/D'.$revision_id.'?id='.$id,
167 ),
168 $id);
169 } else {
170 $id_link = phutil_tag(
171 'a',
172 array(
173 'href' => '/differential/diff/'.$id.'/',
174 ),
175 $id);
176 }
177
178 $rows[] = array(
179 $name,
180 $id_link,
181 $base,
182 $desc,
183 $age,
184 $lint,
185 $unit,
186 $old,
187 $new,
188 );
189
190 $classes = array();
191 if ($old_class) {
192 $classes[] = 'differential-update-history-old-now';
193 }
194 if ($new_class) {
195 $classes[] = 'differential-update-history-new-now';
196 }
197 $rowc[] = nonempty(implode(' ', $classes), null);
198 }
199
200 Javelin::initBehavior(
201 'differential-diff-radios',
202 array(
203 'radios' => $radios,
204 ));
205
206 $table = new AphrontTableView($rows);
207 $table->setHeaders(
208 array(
209 pht('Diff'),
210 pht('ID'),
211 pht('Base'),
212 pht('Description'),
213 pht('Created'),
214 pht('Lint'),
215 pht('Unit'),
216 '',
217 '',
218 ));
219 $table->setColumnClasses(
220 array(
221 'pri',
222 '',
223 '',
224 'wide',
225 'date',
226 'center',
227 'center',
228 'center differential-update-history-old',
229 'center differential-update-history-new',
230 ));
231 $table->setRowClasses($rowc);
232 $table->setDeviceVisibility(
233 array(
234 true,
235 true,
236 false,
237 true,
238 false,
239 false,
240 false,
241 true,
242 true,
243 ));
244
245 $show_diff = phutil_tag(
246 'div',
247 array(
248 'class' => 'differential-update-history-footer',
249 ),
250 array(
251 phutil_tag(
252 'button',
253 array(),
254 pht('Show Diff')),
255 ));
256
257 $content = phabricator_form(
258 $this->getUser(),
259 array(
260 'action' => '/D'.$revision_id.'#toc',
261 ),
262 array(
263 $table,
264 $show_diff,
265 ));
266
267 return $content;
268 }
269
270 private function renderBaseRevision(DifferentialDiff $diff) {
271 switch ($diff->getSourceControlSystem()) {
272 case 'git':
273 $base = $diff->getSourceControlBaseRevision();
274 if (strpos($base, '@') === false) {
275 $label = substr($base, 0, 7);
276 } else {
277 // The diff is from git-svn
278 $base = explode('@', $base);
279 $base = last($base);
280 $label = $base;
281 }
282 break;
283 case 'svn':
284 $base = $diff->getSourceControlBaseRevision();
285 $base = explode('@', $base);
286 $base = last($base);
287 $label = $base;
288 break;
289 default:
290 $label = null;
291 break;
292 }
293 $link = null;
294 if ($label) {
295 $commit_for_link = idx(
296 $this->commitsForLinks,
297 $diff->getSourceControlBaseRevision());
298 if ($commit_for_link) {
299 $link = phutil_tag(
300 'a',
301 array('href' => $commit_for_link->getURI()),
302 $label);
303 } else {
304 $link = $label;
305 }
306 }
307 return $link;
308 }
309
310 private function newLintStatusView(DifferentialDiff $diff) {
311 $value = $diff->getLintStatus();
312 $status = DifferentialLintStatus::newStatusFromValue($value);
313
314 $icon = $status->getIconIcon();
315 $color = $status->getIconColor();
316 $name = $status->getName();
317
318 return $this->newDiffStatusIconView($icon, $color, $name);
319 }
320
321 private function newUnitStatusView(DifferentialDiff $diff) {
322 $value = $diff->getUnitStatus();
323
324 // NOTE: We may be overriding the value on the diff with a value from
325 // Harbormaster.
326 $value = idx($this->unitStatus, $diff->getPHID(), $value);
327
328 $status = DifferentialUnitStatus::newStatusFromValue($value);
329
330 $icon = $status->getIconIcon();
331 $color = $status->getIconColor();
332 $name = $status->getName();
333
334 return $this->newDiffStatusIconView($icon, $color, $name);
335 }
336
337 private function newDiffStatusIconView($icon, $color, $name) {
338 return id(new PHUIIconView())
339 ->setIcon($icon, $color)
340 ->addSigil('has-tooltip')
341 ->setMetadata(
342 array(
343 'tip' => $name,
344 ));
345 }
346
347}