3 abstract class DiffusionController
extends PhabricatorController
{
5 private $diffusionRequest;
7 protected function getDiffusionRequest() {
8 if (!$this->diffusionRequest
) {
9 throw new PhutilInvalidStateException('loadDiffusionContext');
11 return $this->diffusionRequest
;
14 protected function hasDiffusionRequest() {
15 return (bool)$this->diffusionRequest
;
18 public function willBeginExecution() {
19 $request = $this->getRequest();
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.
25 $serve_controller = new DiffusionServeController();
26 if ($serve_controller->isVCSRequest($request)) {
27 return $this->delegateToController($serve_controller);
30 return parent
::willBeginExecution();
33 protected function loadDiffusionContextForEdit() {
34 return $this->loadContext(
40 protected function loadDiffusionContext() {
41 return $this->loadContext(array());
44 private function loadContext(array $options) {
45 $request = $this->getRequest();
46 $viewer = $this->getViewer();
47 require_celerity_resource('diffusion-repository-css');
49 $identifier = $this->getRepositoryIdentifierFromRequest($request);
51 $params = $options +
array(
52 'repository' => $identifier,
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'),
62 $drequest = DiffusionRequest
::newFromDictionary($params);
65 return new Aphront404Response();
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.
72 // Skip this redirect if the request is an AJAX request, like the requests
73 // that Owners makes to complete and validate paths.
75 if (!$request->isAjax()) {
76 $request_path = $request->getPath();
77 $repository = $drequest->getRepository();
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);
87 $this->diffusionRequest
= $drequest;
92 protected function getDiffusionBlobFromRequest(AphrontRequest
$request) {
93 return $request->getURIData('dblob');
96 protected function getRepositoryIdentifierFromRequest(
97 AphrontRequest
$request) {
99 $short_name = $request->getURIData('repositoryShortName');
100 if (strlen($short_name)) {
101 // If the short name ends in ".git", ignore it.
102 $short_name = preg_replace('/\\.git\z/', '', $short_name);
106 $identifier = $request->getURIData('repositoryCallsign');
107 if (strlen($identifier)) {
111 $id = $request->getURIData('repositoryID');
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);
128 private function buildCrumbList(array $spec = array()) {
130 $spec = $spec +
array(
137 $crumb_list = array();
139 // On the home page, we don't have a DiffusionRequest.
140 if ($this->hasDiffusionRequest()) {
141 $drequest = $this->getDiffusionRequest();
142 $repository = $drequest->getRepository();
152 $repository_name = $repository->getName();
154 if (!$spec['commit'] && !$spec['tags'] && !$spec['branches']) {
155 $branch_name = $drequest->getBranch();
156 if (strlen($branch_name)) {
157 $repository_name .= ' ('.$branch_name.')';
161 $crumb = id(new PHUICrumbView())
162 ->setName($repository_name);
163 if (!$spec['view'] && !$spec['commit'] &&
164 !$spec['tags'] && !$spec['branches']) {
165 $crumb_list[] = $crumb;
169 $drequest->generateURI(
171 'action' => 'branch',
174 $crumb_list[] = $crumb;
176 $stable_commit = $drequest->getStableCommit();
177 $commit_name = $repository->formatCommitName($stable_commit, $local = true);
178 $commit_uri = $repository->getCommitURI($stable_commit);
181 $crumb = new PHUICrumbView();
182 if ($spec['commit']) {
183 $crumb->setName(pht('Tags for %s', $commit_name));
184 $crumb->setHref($commit_uri);
186 $crumb->setName(pht('Tags'));
188 $crumb_list[] = $crumb;
192 if ($spec['branches']) {
193 $crumb = id(new PHUICrumbView())
194 ->setName(pht('Branches'));
195 $crumb_list[] = $crumb;
199 if ($spec['commit']) {
200 $crumb = id(new PHUICrumbView())
201 ->setName($commit_name);
202 $crumb_list[] = $crumb;
206 $crumb = new PHUICrumbView();
207 $view = $spec['view'];
211 $view_name = pht('History');
214 $view_name = pht('Browse');
217 $view_name = pht('Lint');
220 $view_name = pht('Change');
223 $view_name = pht('Compare');
227 $crumb = id(new PHUICrumbView())
228 ->setName($view_name);
230 $crumb_list[] = $crumb;
234 protected function callConduitWithDiffusionRequest(
236 array $params = array()) {
238 $user = $this->getRequest()->getUser();
239 $drequest = $this->getDiffusionRequest();
241 return DiffusionQuery
::callConduitWithDiffusionRequest(
248 protected function callConduitMethod($method, array $params = array()) {
249 $user = $this->getViewer();
250 $drequest = $this->getDiffusionRequest();
252 return DiffusionQuery
::callConduitWithDiffusionRequest(
260 protected function getRepositoryControllerURI(
261 PhabricatorRepository
$repository,
263 return $repository->getPathURI($path);
266 protected function renderPathLinks(DiffusionRequest
$drequest, $action) {
267 $path = $drequest->getPath();
268 $path_parts = array_filter(explode('/', trim($path, '/')));
270 $divider = phutil_tag(
273 'class' => 'phui-header-divider',
279 $links[] = phutil_tag(
282 'href' => $drequest->generateURI(
288 $drequest->getRepository()->getDisplayName());
291 $last_key = last_key($path_parts);
292 foreach ($path_parts as $key => $part) {
294 if ($key === $last_key) {
297 $links[] = phutil_tag(
300 'href' => $drequest->generateURI(
303 'path' => $accum.'/',
311 $links[] = $drequest->getRepository()->getDisplayName();
318 protected function renderStatusMessage($title, $body) {
319 return id(new PHUIInfoView())
320 ->setSeverity(PHUIInfoView
::SEVERITY_NOTICE
)
323 ->appendChild($body);
326 protected function renderCommitHashTag(DiffusionRequest
$drequest) {
327 $stable_commit = $drequest->getStableCommit();
328 $commit = phutil_tag(
331 'href' => $drequest->generateURI(
333 'action' => 'commit',
334 'commit' => $stable_commit,
337 $drequest->getRepository()->formatCommitName($stable_commit, true));
339 $tag = id(new PHUITagView())
341 ->setColor(PHUITagView
::COLOR_INDIGO
)
342 ->setBorder(PHUITagView
::BORDER_NONE
)
343 ->setType(PHUITagView
::TYPE_SHADE
);
348 protected function renderBranchTag(DiffusionRequest
$drequest) {
349 $branch = $drequest->getBranch();
350 $branch = id(new PhutilUTF8StringTruncator())
351 ->setMaximumGlyphs(24)
352 ->truncateString($branch);
354 $tag = id(new PHUITagView())
356 ->setColor(PHUITagView
::COLOR_INDIGO
)
357 ->setBorder(PHUITagView
::BORDER_NONE
)
358 ->setType(PHUITagView
::TYPE_OUTLINE
)
359 ->addClass('diffusion-header-branch-tag');
364 protected function renderSymbolicCommit(DiffusionRequest
$drequest) {
365 $symbolic_tag = $drequest->getSymbolicCommit();
366 $symbolic_tag = id(new PhutilUTF8StringTruncator())
367 ->setMaximumGlyphs(24)
368 ->truncateString($symbolic_tag);
370 $tag = id(new PHUITagView())
371 ->setName($symbolic_tag)
373 ->setColor(PHUITagView
::COLOR_INDIGO
)
374 ->setBorder(PHUITagView
::BORDER_NONE
)
375 ->setType(PHUITagView
::TYPE_SHADE
);
380 protected function renderDirectoryReadme(DiffusionBrowseResultSet
$browse) {
381 $readme_path = $browse->getReadmePath();
382 if ($readme_path === null) {
386 $drequest = $this->getDiffusionRequest();
387 $viewer = $this->getViewer();
388 $repository = $drequest->getRepository();
389 $repository_phid = $repository->getPHID();
390 $stable_commit = $drequest->getStableCommit();
392 $stable_commit_hash = PhabricatorHash
::digestForIndex($stable_commit);
393 $readme_path_hash = PhabricatorHash
::digestForIndex($readme_path);
395 $cache = PhabricatorCaches
::getMutableStructureCache();
396 $cache_key = "diffusion".
397 ".repository({$repository_phid})".
398 ".commit({$stable_commit_hash})".
399 ".readme({$readme_path_hash})";
401 $readme_cache = $cache->getKey($cache_key);
402 if (!$readme_cache) {
404 $result = $this->callConduitWithDiffusionRequest(
405 'diffusion.filecontentquery',
407 'path' => $readme_path,
408 'commit' => $drequest->getStableCommit(),
410 } catch (Exception
$ex) {
414 $file_phid = $result['filePHID'];
419 $file = id(new PhabricatorFileQuery())
421 ->withPHIDs(array($file_phid))
427 $corpus = $file->loadFileData();
429 $readme_cache = array(
433 $cache->setKey($cache_key, $readme_cache);
436 $readme_corpus = $readme_cache['corpus'];
437 if (!strlen($readme_corpus)) {
441 return id(new DiffusionReadmeView())
442 ->setUser($this->getViewer())
443 ->setPath($readme_path)
444 ->setContent($readme_corpus);
447 protected function renderSearchForm($path = '/') {
448 $drequest = $this->getDiffusionRequest();
449 $viewer = $this->getViewer();
450 switch ($drequest->getRepository()->getVersionControlSystem()) {
451 case PhabricatorRepositoryType
::REPOSITORY_TYPE_SVN
:
455 $search_term = $this->getRequest()->getStr('grep');
456 require_celerity_resource('diffusion-icons-css');
457 require_celerity_resource('diffusion-css');
459 $href = $drequest->generateURI(array(
460 'action' => 'browse',
468 'id' => 'diffusion-search-input',
470 'class' => 'diffusion-search-input',
471 'sigil' => 'diffusion-search-input',
472 'placeholder' => pht('Pattern Search'),
473 'value' => $search_term,
476 $form = phabricator_form(
481 'sigil' => 'diffusion-search-form',
482 'class' => 'diffusion-search-form',
483 'id' => 'diffusion-search-form',
489 $form_view = phutil_tag(
492 'class' => 'diffusion-search-form-view',
499 protected function buildTabsView($key) {
500 $drequest = $this->getDiffusionRequest();
501 $repository = $drequest->getRepository();
503 $view = new PHUIListView();
506 id(new PHUIListItemView())
508 ->setName(pht('Code'))
510 ->setHref($drequest->generateURI(
512 'action' => 'browse',
514 ->setSelected($key == 'code'));
516 if (!$repository->isSVN()) {
518 id(new PHUIListItemView())
520 ->setName(pht('Branches'))
521 ->setIcon('fa-code-fork')
522 ->setHref($drequest->generateURI(
524 'action' => 'branches',
526 ->setSelected($key == 'branch'));
529 if (!$repository->isSVN()) {
531 id(new PHUIListItemView())
533 ->setName(pht('Tags'))
535 ->setHref($drequest->generateURI(
539 ->setSelected($key == 'tags'));
543 id(new PHUIListItemView())
545 ->setName(pht('History'))
546 ->setIcon('fa-history')
547 ->setHref($drequest->generateURI(
549 'action' => 'history',
551 ->setSelected($key == 'history'));