Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/diffusion/controller/DiffusionController.php
12242 views
1
<?php
2
3
abstract class DiffusionController extends PhabricatorController {
4
5
private $diffusionRequest;
6
7
protected function getDiffusionRequest() {
8
if (!$this->diffusionRequest) {
9
throw new PhutilInvalidStateException('loadDiffusionContext');
10
}
11
return $this->diffusionRequest;
12
}
13
14
protected function hasDiffusionRequest() {
15
return (bool)$this->diffusionRequest;
16
}
17
18
public function willBeginExecution() {
19
$request = $this->getRequest();
20
21
// Check if this is a VCS request, e.g. from "git clone", "hg clone", or
22
// "svn checkout". If it is, we jump off into repository serving code to
23
// process the request.
24
25
$serve_controller = new DiffusionServeController();
26
if ($serve_controller->isVCSRequest($request)) {
27
return $this->delegateToController($serve_controller);
28
}
29
30
return parent::willBeginExecution();
31
}
32
33
protected function loadDiffusionContextForEdit() {
34
return $this->loadContext(
35
array(
36
'edit' => true,
37
));
38
}
39
40
protected function loadDiffusionContext() {
41
return $this->loadContext(array());
42
}
43
44
private function loadContext(array $options) {
45
$request = $this->getRequest();
46
$viewer = $this->getViewer();
47
require_celerity_resource('diffusion-repository-css');
48
49
$identifier = $this->getRepositoryIdentifierFromRequest($request);
50
51
$params = $options + array(
52
'repository' => $identifier,
53
'user' => $viewer,
54
'blob' => $this->getDiffusionBlobFromRequest($request),
55
'commit' => $request->getURIData('commit'),
56
'path' => $request->getURIData('path'),
57
'line' => $request->getURIData('line'),
58
'branch' => $request->getURIData('branch'),
59
'lint' => $request->getStr('lint'),
60
);
61
62
$drequest = DiffusionRequest::newFromDictionary($params);
63
64
if (!$drequest) {
65
return new Aphront404Response();
66
}
67
68
// If the client is making a request like "/diffusion/1/...", but the
69
// repository has a different canonical path like "/diffusion/XYZ/...",
70
// redirect them to the canonical path.
71
72
// Skip this redirect if the request is an AJAX request, like the requests
73
// that Owners makes to complete and validate paths.
74
75
if (!$request->isAjax()) {
76
$request_path = $request->getPath();
77
$repository = $drequest->getRepository();
78
79
$canonical_path = $repository->getCanonicalPath($request_path);
80
if ($canonical_path !== null) {
81
if ($canonical_path != $request_path) {
82
return id(new AphrontRedirectResponse())->setURI($canonical_path);
83
}
84
}
85
}
86
87
$this->diffusionRequest = $drequest;
88
89
return null;
90
}
91
92
protected function getDiffusionBlobFromRequest(AphrontRequest $request) {
93
return $request->getURIData('dblob');
94
}
95
96
protected function getRepositoryIdentifierFromRequest(
97
AphrontRequest $request) {
98
99
$short_name = $request->getURIData('repositoryShortName');
100
if ($short_name !== null && strlen($short_name)) {
101
// If the short name ends in ".git", ignore it.
102
$short_name = preg_replace('/\\.git\z/', '', $short_name);
103
return $short_name;
104
}
105
106
$identifier = $request->getURIData('repositoryCallsign');
107
if ($identifier !== null && strlen($identifier)) {
108
return $identifier;
109
}
110
111
$id = $request->getURIData('repositoryID');
112
if ($id !== null && strlen($id)) {
113
return (int)$id;
114
}
115
116
return null;
117
}
118
119
public function buildCrumbs(array $spec = array()) {
120
$crumbs = $this->buildApplicationCrumbs();
121
$crumb_list = $this->buildCrumbList($spec);
122
foreach ($crumb_list as $crumb) {
123
$crumbs->addCrumb($crumb);
124
}
125
return $crumbs;
126
}
127
128
private function buildCrumbList(array $spec = array()) {
129
130
$spec = $spec + array(
131
'commit' => null,
132
'tags' => null,
133
'branches' => null,
134
'view' => null,
135
);
136
137
$crumb_list = array();
138
139
// On the home page, we don't have a DiffusionRequest.
140
if ($this->hasDiffusionRequest()) {
141
$drequest = $this->getDiffusionRequest();
142
$repository = $drequest->getRepository();
143
} else {
144
$drequest = null;
145
$repository = null;
146
}
147
148
if (!$repository) {
149
return $crumb_list;
150
}
151
152
$repository_name = $repository->getName();
153
154
if (!$spec['commit'] && !$spec['tags'] && !$spec['branches']) {
155
$branch_name = $drequest->getBranch();
156
if (strlen($branch_name)) {
157
$repository_name .= ' ('.$branch_name.')';
158
}
159
}
160
161
$crumb = id(new PHUICrumbView())
162
->setName($repository_name);
163
if (!$spec['view'] && !$spec['commit'] &&
164
!$spec['tags'] && !$spec['branches']) {
165
$crumb_list[] = $crumb;
166
return $crumb_list;
167
}
168
$crumb->setHref(
169
$drequest->generateURI(
170
array(
171
'action' => 'branch',
172
'path' => '/',
173
)));
174
$crumb_list[] = $crumb;
175
176
$stable_commit = $drequest->getStableCommit();
177
$commit_name = $repository->formatCommitName($stable_commit, $local = true);
178
$commit_uri = $repository->getCommitURI($stable_commit);
179
180
if ($spec['tags']) {
181
$crumb = new PHUICrumbView();
182
if ($spec['commit']) {
183
$crumb->setName(pht('Tags for %s', $commit_name));
184
$crumb->setHref($commit_uri);
185
} else {
186
$crumb->setName(pht('Tags'));
187
}
188
$crumb_list[] = $crumb;
189
return $crumb_list;
190
}
191
192
if ($spec['branches']) {
193
$crumb = id(new PHUICrumbView())
194
->setName(pht('Branches'));
195
$crumb_list[] = $crumb;
196
return $crumb_list;
197
}
198
199
if ($spec['commit']) {
200
$crumb = id(new PHUICrumbView())
201
->setName($commit_name);
202
$crumb_list[] = $crumb;
203
return $crumb_list;
204
}
205
206
$crumb = new PHUICrumbView();
207
$view = $spec['view'];
208
209
switch ($view) {
210
case 'history':
211
$view_name = pht('History');
212
break;
213
case 'browse':
214
$view_name = pht('Browse');
215
break;
216
case 'lint':
217
$view_name = pht('Lint');
218
break;
219
case 'change':
220
$view_name = pht('Change');
221
break;
222
case 'compare':
223
$view_name = pht('Compare');
224
break;
225
}
226
227
$crumb = id(new PHUICrumbView())
228
->setName($view_name);
229
230
$crumb_list[] = $crumb;
231
return $crumb_list;
232
}
233
234
protected function callConduitWithDiffusionRequest(
235
$method,
236
array $params = array()) {
237
238
$user = $this->getRequest()->getUser();
239
$drequest = $this->getDiffusionRequest();
240
241
return DiffusionQuery::callConduitWithDiffusionRequest(
242
$user,
243
$drequest,
244
$method,
245
$params);
246
}
247
248
protected function callConduitMethod($method, array $params = array()) {
249
$user = $this->getViewer();
250
$drequest = $this->getDiffusionRequest();
251
252
return DiffusionQuery::callConduitWithDiffusionRequest(
253
$user,
254
$drequest,
255
$method,
256
$params,
257
true);
258
}
259
260
protected function getRepositoryControllerURI(
261
PhabricatorRepository $repository,
262
$path) {
263
return $repository->getPathURI($path);
264
}
265
266
protected function renderPathLinks(DiffusionRequest $drequest, $action) {
267
$path = $drequest->getPath();
268
$path_parts = array();
269
if ($path !== null && strlen($path)) {
270
$path_parts = array_filter(explode('/', trim($path, '/')));
271
}
272
273
$divider = phutil_tag(
274
'span',
275
array(
276
'class' => 'phui-header-divider',
277
),
278
'/');
279
280
$links = array();
281
if ($path_parts) {
282
$links[] = phutil_tag(
283
'a',
284
array(
285
'href' => $drequest->generateURI(
286
array(
287
'action' => $action,
288
'path' => '',
289
)),
290
),
291
$drequest->getRepository()->getDisplayName());
292
$links[] = $divider;
293
$accum = '';
294
$last_key = last_key($path_parts);
295
foreach ($path_parts as $key => $part) {
296
$accum .= '/'.$part;
297
if ($key === $last_key) {
298
$links[] = $part;
299
} else {
300
$links[] = phutil_tag(
301
'a',
302
array(
303
'href' => $drequest->generateURI(
304
array(
305
'action' => $action,
306
'path' => $accum.'/',
307
)),
308
),
309
$part);
310
$links[] = $divider;
311
}
312
}
313
} else {
314
$links[] = $drequest->getRepository()->getDisplayName();
315
$links[] = $divider;
316
}
317
318
return $links;
319
}
320
321
protected function renderStatusMessage($title, $body) {
322
return id(new PHUIInfoView())
323
->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
324
->setTitle($title)
325
->setFlush(true)
326
->appendChild($body);
327
}
328
329
protected function renderCommitHashTag(DiffusionRequest $drequest) {
330
$stable_commit = $drequest->getStableCommit();
331
$commit = phutil_tag(
332
'a',
333
array(
334
'href' => $drequest->generateURI(
335
array(
336
'action' => 'commit',
337
'commit' => $stable_commit,
338
)),
339
),
340
$drequest->getRepository()->formatCommitName($stable_commit, true));
341
342
$tag = id(new PHUITagView())
343
->setName($commit)
344
->setColor(PHUITagView::COLOR_INDIGO)
345
->setBorder(PHUITagView::BORDER_NONE)
346
->setType(PHUITagView::TYPE_SHADE);
347
348
return $tag;
349
}
350
351
protected function renderBranchTag(DiffusionRequest $drequest) {
352
$branch = $drequest->getBranch();
353
$branch = id(new PhutilUTF8StringTruncator())
354
->setMaximumGlyphs(24)
355
->truncateString($branch);
356
357
$tag = id(new PHUITagView())
358
->setName($branch)
359
->setColor(PHUITagView::COLOR_INDIGO)
360
->setBorder(PHUITagView::BORDER_NONE)
361
->setType(PHUITagView::TYPE_OUTLINE)
362
->addClass('diffusion-header-branch-tag');
363
364
return $tag;
365
}
366
367
protected function renderSymbolicCommit(DiffusionRequest $drequest) {
368
$symbolic_tag = $drequest->getSymbolicCommit();
369
$symbolic_tag = id(new PhutilUTF8StringTruncator())
370
->setMaximumGlyphs(24)
371
->truncateString($symbolic_tag);
372
373
$tag = id(new PHUITagView())
374
->setName($symbolic_tag)
375
->setIcon('fa-tag')
376
->setColor(PHUITagView::COLOR_INDIGO)
377
->setBorder(PHUITagView::BORDER_NONE)
378
->setType(PHUITagView::TYPE_SHADE);
379
380
return $tag;
381
}
382
383
protected function renderDirectoryReadme(DiffusionBrowseResultSet $browse) {
384
$readme_path = $browse->getReadmePath();
385
if ($readme_path === null) {
386
return null;
387
}
388
389
$drequest = $this->getDiffusionRequest();
390
$viewer = $this->getViewer();
391
$repository = $drequest->getRepository();
392
$repository_phid = $repository->getPHID();
393
$stable_commit = $drequest->getStableCommit();
394
395
$stable_commit_hash = PhabricatorHash::digestForIndex($stable_commit);
396
$readme_path_hash = PhabricatorHash::digestForIndex($readme_path);
397
398
$cache = PhabricatorCaches::getMutableStructureCache();
399
$cache_key = "diffusion".
400
".repository({$repository_phid})".
401
".commit({$stable_commit_hash})".
402
".readme({$readme_path_hash})";
403
404
$readme_cache = $cache->getKey($cache_key);
405
if (!$readme_cache) {
406
try {
407
$result = $this->callConduitWithDiffusionRequest(
408
'diffusion.filecontentquery',
409
array(
410
'path' => $readme_path,
411
'commit' => $drequest->getStableCommit(),
412
));
413
} catch (Exception $ex) {
414
return null;
415
}
416
417
$file_phid = $result['filePHID'];
418
if (!$file_phid) {
419
return null;
420
}
421
422
$file = id(new PhabricatorFileQuery())
423
->setViewer($viewer)
424
->withPHIDs(array($file_phid))
425
->executeOne();
426
if (!$file) {
427
return null;
428
}
429
430
$corpus = $file->loadFileData();
431
432
$readme_cache = array(
433
'corpus' => $corpus,
434
);
435
436
$cache->setKey($cache_key, $readme_cache);
437
}
438
439
$readme_corpus = $readme_cache['corpus'];
440
if (!strlen($readme_corpus)) {
441
return null;
442
}
443
444
return id(new DiffusionReadmeView())
445
->setUser($this->getViewer())
446
->setPath($readme_path)
447
->setContent($readme_corpus);
448
}
449
450
protected function renderSearchForm($path = '/') {
451
$drequest = $this->getDiffusionRequest();
452
$viewer = $this->getViewer();
453
switch ($drequest->getRepository()->getVersionControlSystem()) {
454
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
455
return null;
456
}
457
458
$search_term = $this->getRequest()->getStr('grep');
459
require_celerity_resource('diffusion-icons-css');
460
require_celerity_resource('diffusion-css');
461
462
$href = $drequest->generateURI(array(
463
'action' => 'browse',
464
'path' => $path,
465
));
466
467
$bar = javelin_tag(
468
'input',
469
array(
470
'type' => 'text',
471
'id' => 'diffusion-search-input',
472
'name' => 'grep',
473
'class' => 'diffusion-search-input',
474
'sigil' => 'diffusion-search-input',
475
'placeholder' => pht('Pattern Search'),
476
'value' => $search_term,
477
));
478
479
$form = phabricator_form(
480
$viewer,
481
array(
482
'method' => 'GET',
483
'action' => $href,
484
'sigil' => 'diffusion-search-form',
485
'class' => 'diffusion-search-form',
486
'id' => 'diffusion-search-form',
487
),
488
array(
489
$bar,
490
));
491
492
$form_view = phutil_tag(
493
'div',
494
array(
495
'class' => 'diffusion-search-form-view',
496
),
497
$form);
498
499
return $form_view;
500
}
501
502
protected function buildTabsView($key) {
503
$drequest = $this->getDiffusionRequest();
504
$repository = $drequest->getRepository();
505
506
$view = new PHUIListView();
507
508
$view->addMenuItem(
509
id(new PHUIListItemView())
510
->setKey('code')
511
->setName(pht('Code'))
512
->setIcon('fa-code')
513
->setHref($drequest->generateURI(
514
array(
515
'action' => 'browse',
516
)))
517
->setSelected($key == 'code'));
518
519
if (!$repository->isSVN()) {
520
$view->addMenuItem(
521
id(new PHUIListItemView())
522
->setKey('branch')
523
->setName(pht('Branches'))
524
->setIcon('fa-code-fork')
525
->setHref($drequest->generateURI(
526
array(
527
'action' => 'branches',
528
)))
529
->setSelected($key == 'branch'));
530
}
531
532
if (!$repository->isSVN()) {
533
$view->addMenuItem(
534
id(new PHUIListItemView())
535
->setKey('tags')
536
->setName(pht('Tags'))
537
->setIcon('fa-tags')
538
->setHref($drequest->generateURI(
539
array(
540
'action' => 'tags',
541
)))
542
->setSelected($key == 'tags'));
543
}
544
545
$view->addMenuItem(
546
id(new PHUIListItemView())
547
->setKey('history')
548
->setName(pht('History'))
549
->setIcon('fa-history')
550
->setHref($drequest->generateURI(
551
array(
552
'action' => 'history',
553
)))
554
->setSelected($key == 'history'));
555
556
return $view;
557
558
}
559
560
}
561
562