Correct Aphlict websocket URI construction after PHP8 compatibility changes
[phabricator.git] / src / applications / diffusion / controller / DiffusionCompareController.php
blob26d888dfb2ef33482e5252f7f1bf9af3ae92ca93
1 <?php
3 final class DiffusionCompareController extends DiffusionController {
5 public function shouldAllowPublic() {
6 return true;
9 public function handleRequest(AphrontRequest $request) {
10 $response = $this->loadDiffusionContext();
11 if ($response) {
12 return $response;
15 $viewer = $this->getViewer();
16 $drequest = $this->getDiffusionRequest();
17 $repository = $drequest->getRepository();
18 require_celerity_resource('diffusion-css');
20 if (!$repository->supportsBranchComparison()) {
21 return $this->newDialog()
22 ->setTitle(pht('Not Supported'))
23 ->appendParagraph(
24 pht(
25 'Branch comparison is not supported for this version control '.
26 'system.'))
27 ->addCancelButton($this->getApplicationURI(), pht('Okay'));
30 $head_ref = $request->getStr('head');
31 $against_ref = $request->getStr('against');
33 $must_prompt = false;
34 if (!$request->isFormPost()) {
35 if (!strlen($head_ref)) {
36 $head_ref = $drequest->getSymbolicCommit();
37 if (!strlen($head_ref)) {
38 $head_ref = $drequest->getBranch();
42 if (!strlen($against_ref)) {
43 $default_branch = $repository->getDefaultBranch();
44 if ($default_branch != $head_ref) {
45 $against_ref = $default_branch;
47 // If we filled this in by default, we want to prompt the user to
48 // confirm that this is really what they want.
49 $must_prompt = true;
54 $refs = $drequest->resolveRefs(
55 array_filter(
56 array(
57 $head_ref,
58 $against_ref,
59 )));
61 $identical = false;
62 if ($head_ref === $against_ref) {
63 $identical = true;
64 } else {
65 if (count($refs) == 2) {
66 if ($refs[$head_ref] === $refs[$against_ref]) {
67 $identical = true;
72 if ($must_prompt || count($refs) != 2 || $identical) {
73 return $this->buildCompareDialog(
74 $head_ref,
75 $against_ref,
76 $refs,
77 $identical);
80 if ($request->isFormPost()) {
81 // Redirect to a stable URI that can be copy/pasted.
82 $compare_uri = $drequest->generateURI(
83 array(
84 'action' => 'compare',
85 'head' => $head_ref,
86 'against' => $against_ref,
87 ));
89 return id(new AphrontRedirectResponse())->setURI($compare_uri);
92 $crumbs = $this->buildCrumbs(
93 array(
94 'view' => 'compare',
95 ));
96 $crumbs->setBorder(true);
98 $pager = id(new PHUIPagerView())
99 ->readFromRequest($request);
101 $history = null;
102 try {
103 $history_results = $this->callConduitWithDiffusionRequest(
104 'diffusion.historyquery',
105 array(
106 'commit' => $head_ref,
107 'against' => $against_ref,
108 'path' => $drequest->getPath(),
109 'offset' => $pager->getOffset(),
110 'limit' => $pager->getPageSize() + 1,
112 $history = DiffusionPathChange::newFromConduit(
113 $history_results['pathChanges']);
114 $history = $pager->sliceResults($history);
116 $history_view = $this->newHistoryView(
117 $history_results,
118 $history,
119 $pager,
120 $head_ref,
121 $against_ref);
123 } catch (Exception $ex) {
124 if ($repository->isImporting()) {
125 $history_view = $this->renderStatusMessage(
126 pht('Still Importing...'),
127 pht(
128 'This repository is still importing. History is not yet '.
129 'available.'));
130 } else {
131 $history_view = $this->renderStatusMessage(
132 pht('Unable to Retrieve History'),
133 $ex->getMessage());
137 $header = id(new PHUIHeaderView())
138 ->setHeader(
139 pht(
140 'Changes on %s but not %s',
141 phutil_tag('em', array(), $head_ref),
142 phutil_tag('em', array(), $against_ref)));
144 $curtain = $this->buildCurtain($head_ref, $against_ref);
146 $column_view = id(new PHUITwoColumnView())
147 ->setHeader($header)
148 ->setCurtain($curtain)
149 ->setMainColumn(
150 array(
151 $history_view,
154 return $this->newPage()
155 ->setTitle(
156 array(
157 $repository->getName(),
158 $repository->getDisplayName(),
160 ->setCrumbs($crumbs)
161 ->appendChild($column_view);
164 private function buildCompareDialog(
165 $head_ref,
166 $against_ref,
167 array $resolved,
168 $identical) {
170 $viewer = $this->getViewer();
171 $request = $this->getRequest();
172 $drequest = $this->getDiffusionRequest();
173 $repository = $drequest->getRepository();
175 $e_head = null;
176 $e_against = null;
177 $errors = array();
178 if ($request->isFormPost()) {
179 if (!strlen($head_ref)) {
180 $e_head = pht('Required');
181 $errors[] = pht(
182 'You must provide two different commits to compare.');
183 } else if (!isset($resolved[$head_ref])) {
184 $e_head = pht('Not Found');
185 $errors[] = pht(
186 'Commit "%s" is not a valid commit in this repository.',
187 $head_ref);
190 if (!strlen($against_ref)) {
191 $e_against = pht('Required');
192 $errors[] = pht(
193 'You must provide two different commits to compare.');
194 } else if (!isset($resolved[$against_ref])) {
195 $e_against = pht('Not Found');
196 $errors[] = pht(
197 'Commit "%s" is not a valid commit in this repository.',
198 $against_ref);
201 if ($identical) {
202 $e_head = pht('Identical');
203 $e_against = pht('Identical');
204 $errors[] = pht(
205 'Both references identify the same commit. You can not compare a '.
206 'commit against itself.');
210 $form = id(new AphrontFormView())
211 ->setViewer($viewer)
212 ->appendControl(
213 id(new AphrontFormTextControl())
214 ->setLabel(pht('Head'))
215 ->setName('head')
216 ->setError($e_head)
217 ->setValue($head_ref))
218 ->appendControl(
219 id(new AphrontFormTextControl())
220 ->setLabel(pht('Against'))
221 ->setName('against')
222 ->setError($e_against)
223 ->setValue($against_ref));
225 $cancel_uri = $repository->generateURI(
226 array(
227 'action' => 'browse',
230 return $this->newDialog()
231 ->setTitle(pht('Compare Against'))
232 ->setWidth(AphrontDialogView::WIDTH_FORM)
233 ->setErrors($errors)
234 ->appendForm($form)
235 ->addSubmitButton(pht('Compare'))
236 ->addCancelButton($cancel_uri, pht('Cancel'));
239 private function buildCurtain($head_ref, $against_ref) {
240 $viewer = $this->getViewer();
241 $request = $this->getRequest();
242 $drequest = $this->getDiffusionRequest();
243 $repository = $drequest->getRepository();
245 $curtain = $this->newCurtainView(null);
247 $reverse_uri = $drequest->generateURI(
248 array(
249 'action' => 'compare',
250 'head' => $against_ref,
251 'against' => $head_ref,
254 $curtain->addAction(
255 id(new PhabricatorActionView())
256 ->setName(pht('Reverse Comparison'))
257 ->setHref($reverse_uri)
258 ->setIcon('fa-refresh'));
260 $compare_uri = $drequest->generateURI(
261 array(
262 'action' => 'compare',
263 'head' => $head_ref,
266 $curtain->addAction(
267 id(new PhabricatorActionView())
268 ->setName(pht('Compare Against...'))
269 ->setIcon('fa-code-fork')
270 ->setWorkflow(true)
271 ->setHref($compare_uri));
273 // TODO: Provide a "Show Diff" action.
275 return $curtain;
278 private function newHistoryView(
279 array $results,
280 array $history,
281 PHUIPagerView $pager,
282 $head_ref,
283 $against_ref) {
285 $request = $this->getRequest();
286 $viewer = $this->getViewer();
287 $drequest = $this->getDiffusionRequest();
289 if (!$history) {
290 return $this->renderStatusMessage(
291 pht('Up To Date'),
292 pht(
293 'There are no commits on %s that are not already on %s.',
294 phutil_tag('strong', array(), $head_ref),
295 phutil_tag('strong', array(), $against_ref)));
298 $history_view = id(new DiffusionCommitGraphView())
299 ->setViewer($viewer)
300 ->setDiffusionRequest($drequest)
301 ->setHistory($history)
302 ->setParents($results['parents'])
303 ->setFilterParents(true)
304 ->setIsHead(!$pager->getOffset())
305 ->setIsTail(!$pager->getHasMorePages());
307 return $history_view;