@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 DifferentialDiffViewController extends DifferentialController {
4
5 public function shouldAllowPublic() {
6 return true;
7 }
8
9 public function handleRequest(AphrontRequest $request) {
10 $viewer = $this->getViewer();
11 $id = $request->getURIData('id');
12
13 $diff = id(new DifferentialDiffQuery())
14 ->setViewer($viewer)
15 ->withIDs(array($id))
16 ->executeOne();
17 if (!$diff) {
18 return new Aphront404Response();
19 }
20
21 if ($diff->getRevisionID()) {
22 return id(new AphrontRedirectResponse())
23 ->setURI('/D'.$diff->getRevisionID().'?id='.$diff->getID());
24 }
25
26 if ($request->isFormPost()) {
27 $diff_id = $diff->getID();
28 $revision_id = $request->getInt('revisionID');
29 if ($revision_id) {
30 $attach_uri = "/revision/attach/{$diff_id}/to/{$revision_id}/";
31 } else {
32 $attach_uri = "/revision/attach/{$diff_id}/to/";
33 }
34 $attach_uri = $this->getApplicationURI($attach_uri);
35
36 return id(new AphrontRedirectResponse())
37 ->setURI($attach_uri);
38 }
39
40 $diff_phid = $diff->getPHID();
41 $buildables = id(new HarbormasterBuildableQuery())
42 ->setViewer($viewer)
43 ->withBuildablePHIDs(array($diff_phid))
44 ->withManualBuildables(false)
45 ->needBuilds(true)
46 ->needTargets(true)
47 ->execute();
48 $buildables = mpull($buildables, null, 'getBuildablePHID');
49 $diff->attachBuildable(idx($buildables, $diff_phid));
50
51 // TODO: implement optgroup support in AphrontFormSelectControl?
52 $select = array();
53 $select[] = hsprintf('<optgroup label="%s">', pht('Create New Revision'));
54 $select[] = phutil_tag(
55 'option',
56 array('value' => ''),
57 pht('Create a new Revision...'));
58 $select[] = hsprintf('</optgroup>');
59
60 $selected_id = $request->getInt('revisionID');
61
62 $revisions = $this->loadSelectableRevisions($viewer, $selected_id);
63
64 if ($revisions) {
65 $select[] = hsprintf(
66 '<optgroup label="%s">',
67 pht('Update Existing Revision'));
68 foreach ($revisions as $revision) {
69 if ($selected_id == $revision->getID()) {
70 $selected = 'selected';
71 } else {
72 $selected = null;
73 }
74
75 $select[] = phutil_tag(
76 'option',
77 array(
78 'value' => $revision->getID(),
79 'selected' => $selected,
80 ),
81 id(new PhutilUTF8StringTruncator())
82 ->setMaximumGlyphs(128)
83 ->truncateString(
84 'D'.$revision->getID().' '.$revision->getTitle()));
85 }
86 $select[] = hsprintf('</optgroup>');
87 }
88
89 $select = phutil_tag(
90 'select',
91 array('name' => 'revisionID'),
92 $select);
93
94 $form = id(new AphrontFormView())
95 ->setViewer($viewer)
96 ->appendRemarkupInstructions(
97 pht(
98 'Review the diff for correctness. When you are satisfied, either '.
99 '**create a new revision** or **update an existing revision**.'))
100 ->appendChild(
101 id(new AphrontFormMarkupControl())
102 ->setLabel(pht('Attach To'))
103 ->setValue($select))
104 ->appendChild(
105 id(new AphrontFormSubmitControl())
106 ->setValue(pht('Continue')));
107
108 $props = id(new DifferentialDiffProperty())->loadAllWhere(
109 'diffID = %d',
110 $diff->getID());
111 $props = mpull($props, 'getData', 'getName');
112
113 $property_head = id(new PHUIHeaderView())
114 ->setHeader(pht('Properties'));
115
116 $property_view = new PHUIPropertyListView();
117
118 $changesets = $diff->loadChangesets();
119 $changesets = msort($changesets, 'getSortKey');
120
121 $this->buildPackageMaps($changesets);
122
123 $table_of_contents = $this->buildTableOfContents(
124 $changesets,
125 $changesets,
126 $diff->loadCoverageMap($viewer));
127
128 $refs = array();
129 foreach ($changesets as $changeset) {
130 $refs[$changeset->getID()] = $changeset->getID();
131 }
132
133 $details = id(new DifferentialChangesetListView())
134 ->setChangesets($changesets)
135 ->setVisibleChangesets($changesets)
136 ->setRenderingReferences($refs)
137 ->setStandaloneURI('/differential/changeset/')
138 ->setDiff($diff)
139 ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
140 ->setTitle(pht('Diff %d', $diff->getID()))
141 ->setUser($request->getUser());
142
143 $title = pht('Diff %d', $diff->getID());
144 $crumbs = $this->buildApplicationCrumbs();
145 $crumbs->addTextCrumb($title);
146 $crumbs->setBorder(true);
147
148 $header = id(new PHUIHeaderView())
149 ->setHeader($title);
150
151 $prop_box = id(new PHUIObjectBoxView())
152 ->setHeader($property_head)
153 ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
154 ->addPropertyList($property_view)
155 ->setForm($form);
156
157 $view = id(new PHUITwoColumnView())
158 ->setHeader($header)
159 ->setMainColumn(array(
160
161 ))
162 ->setFooter(array(
163 $prop_box,
164 $table_of_contents,
165 $details,
166 ));
167
168 $page = $this->newPage()
169 ->setTitle(pht('Diff View'))
170 ->setCrumbs($crumbs)
171 ->appendChild($view);
172 return $page;
173 }
174
175 private function loadSelectableRevisions(
176 PhabricatorUser $viewer,
177 $selected_id) {
178
179 $revisions = id(new DifferentialRevisionQuery())
180 ->setViewer($viewer)
181 ->withAuthors(array($viewer->getPHID()))
182 ->withIsOpen(true)
183 ->requireCapabilities(
184 array(
185 PhabricatorPolicyCapability::CAN_VIEW,
186 PhabricatorPolicyCapability::CAN_EDIT,
187 ))
188 ->execute();
189 $revisions = mpull($revisions, null, 'getID');
190
191 // If a specific revision is selected (for example, because the user is
192 // following the "Update Diff" workflow), but not present in the dropdown,
193 // try to add it to the dropdown even if it is closed. This allows the
194 // workflow to be used to update abandoned revisions.
195
196 if ($selected_id) {
197 if (empty($revisions[$selected_id])) {
198 $selected = id(new DifferentialRevisionQuery())
199 ->setViewer($viewer)
200 ->withIDs(array($selected_id))
201 ->requireCapabilities(
202 array(
203 PhabricatorPolicyCapability::CAN_VIEW,
204 PhabricatorPolicyCapability::CAN_EDIT,
205 ))
206 ->execute();
207 $revisions = mpull($selected, null, 'getID') + $revisions;
208 }
209 }
210
211 return $revisions;
212 }
213
214
215}