1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-10 08:52:39 +01:00

Improve organization of Diffusion browse controllers

Summary:
Currently we have this:

  - DiffusionController (abstract, has some random shared browse code)
    - DiffusionBrowseController (concrete, Handles routing, directories, and search)
    - DiffusionBrowseFileController (concrete, handles files)

Instead, do this:

  - DiffusionController (no browse-related code)
    - DiffusionBrowseController (abstract, shared browse code)
      - DiffusionBrowseMainController (concrete, handles routing)
      - DiffusionBrowseDirectoryController (concrete, handles directories)
      - DiffusionBrowseFileController (concrete, handles files)
      - DiffusionBrowseSearchController (concrete, handles search)

Feels a lot cleaner.

Test Plan: Looked at directories, searches, and files.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Differential Revision: https://secure.phabricator.com/D7045
This commit is contained in:
epriestley 2013-09-19 16:01:34 -07:00
parent 1ec021bf8c
commit 0139fb9178
8 changed files with 389 additions and 353 deletions

View file

@ -433,8 +433,11 @@ phutil_register_library_map(array(
'DiffusionBranchTableController' => 'applications/diffusion/controller/DiffusionBranchTableController.php',
'DiffusionBranchTableView' => 'applications/diffusion/view/DiffusionBranchTableView.php',
'DiffusionBrowseController' => 'applications/diffusion/controller/DiffusionBrowseController.php',
'DiffusionBrowseDirectoryController' => 'applications/diffusion/controller/DiffusionBrowseDirectoryController.php',
'DiffusionBrowseFileController' => 'applications/diffusion/controller/DiffusionBrowseFileController.php',
'DiffusionBrowseMainController' => 'applications/diffusion/controller/DiffusionBrowseMainController.php',
'DiffusionBrowseResultSet' => 'applications/diffusion/data/DiffusionBrowseResultSet.php',
'DiffusionBrowseSearchController' => 'applications/diffusion/controller/DiffusionBrowseSearchController.php',
'DiffusionBrowseTableView' => 'applications/diffusion/view/DiffusionBrowseTableView.php',
'DiffusionChangeController' => 'applications/diffusion/controller/DiffusionChangeController.php',
'DiffusionCommentListView' => 'applications/diffusion/view/DiffusionCommentListView.php',
@ -2498,7 +2501,10 @@ phutil_register_library_map(array(
'DiffusionBranchTableController' => 'DiffusionController',
'DiffusionBranchTableView' => 'DiffusionView',
'DiffusionBrowseController' => 'DiffusionController',
'DiffusionBrowseFileController' => 'DiffusionController',
'DiffusionBrowseDirectoryController' => 'DiffusionBrowseController',
'DiffusionBrowseFileController' => 'DiffusionBrowseController',
'DiffusionBrowseMainController' => 'DiffusionBrowseController',
'DiffusionBrowseSearchController' => 'DiffusionBrowseController',
'DiffusionBrowseTableView' => 'DiffusionView',
'DiffusionChangeController' => 'DiffusionController',
'DiffusionCommentListView' => 'AphrontView',

View file

@ -50,7 +50,7 @@ final class PhabricatorApplicationDiffusion extends PhabricatorApplication {
'repository/(?P<dblob>.*)' => 'DiffusionRepositoryController',
'change/(?P<dblob>.*)' => 'DiffusionChangeController',
'history/(?P<dblob>.*)' => 'DiffusionHistoryController',
'browse/(?P<dblob>.*)' => 'DiffusionBrowseController',
'browse/(?P<dblob>.*)' => 'DiffusionBrowseMainController',
'lastmodified/(?P<dblob>.*)' => 'DiffusionLastModifiedController',
'diff/' => 'DiffusionDiffController',
'tags/(?P<dblob>.*)' => 'DiffusionTagListController',

View file

@ -1,123 +1,8 @@
<?php
final class DiffusionBrowseController extends DiffusionController {
abstract class DiffusionBrowseController extends DiffusionController {
public function processRequest() {
$drequest = $this->diffusionRequest;
$is_file = false;
if ($this->getRequest()->getStr('before')) {
$is_file = true;
} else if ($this->getRequest()->getStr('grep') == '') {
$results = DiffusionBrowseResultSet::newFromConduit(
$this->callConduitWithDiffusionRequest(
'diffusion.browsequery',
array(
'path' => $drequest->getPath(),
'commit' => $drequest->getCommit(),
)));
$reason = $results->getReasonForEmptyResultSet();
$is_file = ($reason == DiffusionBrowseResultSet::REASON_IS_FILE);
}
if ($is_file) {
$controller = new DiffusionBrowseFileController($this->getRequest());
$controller->setDiffusionRequest($drequest);
$controller->setCurrentApplication($this->getCurrentApplication());
return $this->delegateToController($controller);
}
$content = array();
$content[] = $this->buildHeaderView($drequest);
$content[] = $this->buildBrowseActionView($drequest);
$content[] = $this->buildPropertyView($drequest);
$content[] = $this->renderSearchForm();
if ($this->getRequest()->getStr('grep') != '') {
$content[] = $this->renderSearchResults();
} else {
if (!$results->isValidResults()) {
$empty_result = new DiffusionEmptyResultView();
$empty_result->setDiffusionRequest($drequest);
$empty_result->setDiffusionBrowseResultSet($results);
$empty_result->setView($this->getRequest()->getStr('view'));
$content[] = $empty_result;
} else {
$phids = array();
foreach ($results->getPaths() as $result) {
$data = $result->getLastCommitData();
if ($data) {
if ($data->getCommitDetail('authorPHID')) {
$phids[$data->getCommitDetail('authorPHID')] = true;
}
}
}
$phids = array_keys($phids);
$handles = $this->loadViewerHandles($phids);
$browse_table = new DiffusionBrowseTableView();
$browse_table->setDiffusionRequest($drequest);
$browse_table->setHandles($handles);
$browse_table->setPaths($results->getPaths());
$browse_table->setUser($this->getRequest()->getUser());
$browse_panel = new AphrontPanelView();
$browse_panel->appendChild($browse_table);
$browse_panel->setNoBackground();
$content[] = $browse_panel;
}
$content[] = $this->buildOpenRevisions();
$readme = $this->callConduitWithDiffusionRequest(
'diffusion.readmequery',
array(
'paths' => $results->getPathDicts(),
));
if ($readme) {
$box = new PHUIBoxView();
$box->setShadow(true);
$box->appendChild($readme);
$box->addPadding(PHUI::PADDING_LARGE);
$box->addMargin(PHUI::MARGIN_LARGE);
$header = id(new PHUIHeaderView())
->setHeader(pht('README'));
$content[] = array(
$header,
$box,
);
}
}
$crumbs = $this->buildCrumbs(
array(
'branch' => true,
'path' => true,
'view' => 'browse',
));
return $this->buildApplicationPage(
array(
$crumbs,
$content,
),
array(
'device' => true,
'title' => array(
nonempty(basename($drequest->getPath()), '/'),
$drequest->getRepository()->getCallsign().' Repository',
),
));
}
private function renderSearchForm() {
protected function renderSearchForm($collapsed) {
$drequest = $this->getDiffusionRequest();
$form = id(new AphrontFormView())
->setUser($this->getRequest()->getUser())
@ -145,7 +30,7 @@ final class DiffusionBrowseController extends DiffusionController {
$filter = new AphrontListFilterView();
$filter->appendChild($form);
if (!strlen($this->getRequest()->getStr('grep'))) {
if ($collapsed) {
$filter->setCollapsed(
pht('Show Search'),
pht('Hide Search'),
@ -156,103 +41,7 @@ final class DiffusionBrowseController extends DiffusionController {
return $filter;
}
private function renderSearchResults() {
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$results = array();
$no_data = pht('No results found.');
$limit = 100;
$page = $this->getRequest()->getInt('page', 0);
$pager = new AphrontPagerView();
$pager->setPageSize($limit);
$pager->setOffset($page);
$pager->setURI($this->getRequest()->getRequestURI(), 'page');
try {
$results = $this->callConduitWithDiffusionRequest(
'diffusion.searchquery',
array(
'grep' => $this->getRequest()->getStr('grep'),
'stableCommitName' => $drequest->getStableCommitName(),
'path' => $drequest->getPath(),
'limit' => $limit + 1,
'offset' => $page));
} catch (ConduitException $ex) {
$err = $ex->getErrorDescription();
if ($err != '') {
return id(new AphrontErrorView())
->setTitle(pht('Search Error'))
->appendChild($err);
}
}
$results = $pager->sliceResults($results);
require_celerity_resource('syntax-highlighting-css');
// NOTE: This can be wrong because we may find the string inside the
// comment. But it's correct in most cases and highlighting the whole file
// would be too expensive.
$futures = array();
$engine = PhabricatorSyntaxHighlighter::newEngine();
foreach ($results as $result) {
list($path, $line, $string) = $result;
$futures["{$path}:{$line}"] = $engine->getHighlightFuture(
$engine->getLanguageFromFilename($path),
ltrim($string));
}
try {
Futures($futures)->limit(8)->resolveAll();
} catch (PhutilSyntaxHighlighterException $ex) {
}
$rows = array();
foreach ($results as $result) {
list($path, $line, $string) = $result;
$href = $drequest->generateURI(array(
'action' => 'browse',
'path' => $path,
'line' => $line,
));
try {
$string = $futures["{$path}:{$line}"]->resolve();
} catch (PhutilSyntaxHighlighterException $ex) {
}
$string = phutil_tag(
'pre',
array('class' => 'PhabricatorMonospaced'),
$string);
$path = Filesystem::readablePath($path, $drequest->getPath());
$rows[] = array(
phutil_tag('a', array('href' => $href), $path),
$line,
$string,
);
}
$table = id(new AphrontTableView($rows))
->setClassName('remarkup-code')
->setHeaders(array(pht('Path'), pht('Line'), pht('String')))
->setColumnClasses(array('', 'n', 'wide'))
->setNoDataString($no_data);
return id(new AphrontPanelView())
->setNoBackground(true)
->appendChild($table)
->appendChild($pager);
}
private function markupText($text) {
protected function markupText($text) {
$engine = PhabricatorMarkupEngine::newDiffusionMarkupEngine();
$engine->setConfig('viewer', $this->getRequest()->getUser());
$text = $engine->markupText($text);
@ -267,7 +56,7 @@ final class DiffusionBrowseController extends DiffusionController {
return $text;
}
private function buildHeaderView(DiffusionRequest $drequest) {
protected function buildHeaderView(DiffusionRequest $drequest) {
$viewer = $this->getRequest()->getUser();
$header = id(new PHUIHeaderView())
@ -278,7 +67,56 @@ final class DiffusionBrowseController extends DiffusionController {
return $header;
}
private function buildPropertyView(DiffusionRequest $drequest) {
protected function buildActionView(DiffusionRequest $drequest) {
$viewer = $this->getRequest()->getUser();
$view = id(new PhabricatorActionListView())
->setUser($viewer);
$history_uri = $drequest->generateURI(
array(
'action' => 'history',
));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('View History'))
->setHref($history_uri)
->setIcon('perflab'));
$behind_head = $drequest->getRawCommit();
$head_uri = $drequest->generateURI(
array(
'commit' => '',
'action' => 'browse',
));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Jump to HEAD'))
->setHref($head_uri)
->setIcon('home')
->setDisabled(!$behind_head));
// TODO: Ideally, this should live in Owners and be event-triggered, but
// there's no reasonable object for it to react to right now.
$owners_uri = id(new PhutilURI('/owners/view/search/'))
->setQueryParams(
array(
'repository' => $drequest->getCallsign(),
'path' => '/'.$drequest->getPath(),
));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Find Owners'))
->setHref((string)$owners_uri)
->setIcon('preview'));
return $view;
}
protected function buildPropertyView(DiffusionRequest $drequest) {
$viewer = $this->getRequest()->getUser();
$view = id(new PhabricatorPropertyListView())
@ -312,4 +150,49 @@ final class DiffusionBrowseController extends DiffusionController {
return $view;
}
protected function buildOpenRevisions() {
$user = $this->getRequest()->getUser();
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$path = $drequest->getPath();
$path_map = id(new DiffusionPathIDQuery(array($path)))->loadPathIDs();
$path_id = idx($path_map, $path);
if (!$path_id) {
return null;
}
$revisions = id(new DifferentialRevisionQuery())
->setViewer($user)
->withPath($repository->getID(), $path_id)
->withStatus(DifferentialRevisionQuery::STATUS_OPEN)
->setOrder(DifferentialRevisionQuery::ORDER_PATH_MODIFIED)
->setLimit(10)
->needRelationships(true)
->execute();
if (!$revisions) {
return null;
}
$view = id(new DifferentialRevisionListView())
->setRevisions($revisions)
->setFields(DifferentialRevisionListView::getDefaultFields($user))
->setUser($user)
->loadAssets();
$phids = $view->getRequiredHandlePHIDs();
$handles = $this->loadViewerHandles($phids);
$view->setHandles($handles);
$header = id(new PHUIHeaderView())
->setHeader(pht('Pending Differential Revisions'));
return array(
$header,
$view,
);
}
}

View file

@ -0,0 +1,108 @@
<?php
final class DiffusionBrowseDirectoryController
extends DiffusionBrowseController {
private $browseQueryResults;
public function setBrowseQueryResults(DiffusionBrowseResultSet $results) {
$this->browseQueryResults = $results;
return $this;
}
public function getBrowseQueryResults() {
return $this->browseQueryResults;
}
public function processRequest() {
$drequest = $this->diffusionRequest;
$results = $this->getBrowseQueryResults();
$reason = $results->getReasonForEmptyResultSet();
$content = array();
$content[] = $this->buildHeaderView($drequest);
$content[] = $this->buildActionView($drequest);
$content[] = $this->buildPropertyView($drequest);
$content[] = $this->renderSearchForm($collapsed = true);
if (!$results->isValidResults()) {
$empty_result = new DiffusionEmptyResultView();
$empty_result->setDiffusionRequest($drequest);
$empty_result->setDiffusionBrowseResultSet($results);
$empty_result->setView($this->getRequest()->getStr('view'));
$content[] = $empty_result;
} else {
$phids = array();
foreach ($results->getPaths() as $result) {
$data = $result->getLastCommitData();
if ($data) {
if ($data->getCommitDetail('authorPHID')) {
$phids[$data->getCommitDetail('authorPHID')] = true;
}
}
}
$phids = array_keys($phids);
$handles = $this->loadViewerHandles($phids);
$browse_table = new DiffusionBrowseTableView();
$browse_table->setDiffusionRequest($drequest);
$browse_table->setHandles($handles);
$browse_table->setPaths($results->getPaths());
$browse_table->setUser($this->getRequest()->getUser());
$browse_panel = new AphrontPanelView();
$browse_panel->appendChild($browse_table);
$browse_panel->setNoBackground();
$content[] = $browse_panel;
}
$content[] = $this->buildOpenRevisions();
$readme = $this->callConduitWithDiffusionRequest(
'diffusion.readmequery',
array(
'paths' => $results->getPathDicts(),
));
if ($readme) {
$box = new PHUIBoxView();
$box->setShadow(true);
$box->appendChild($readme);
$box->addPadding(PHUI::PADDING_LARGE);
$box->addMargin(PHUI::MARGIN_LARGE);
$header = id(new PHUIHeaderView())
->setHeader(pht('README'));
$content[] = array(
$header,
$box,
);
}
$crumbs = $this->buildCrumbs(
array(
'branch' => true,
'path' => true,
'view' => 'browse',
));
return $this->buildApplicationPage(
array(
$crumbs,
$content,
),
array(
'device' => true,
'title' => array(
nonempty(basename($drequest->getPath()), '/'),
$drequest->getRepository()->getCallsign().' Repository',
),
));
}
}

View file

@ -1,6 +1,6 @@
<?php
final class DiffusionBrowseFileController extends DiffusionController {
final class DiffusionBrowseFileController extends DiffusionBrowseController {
private $corpusType = 'text';
@ -8,7 +8,6 @@ final class DiffusionBrowseFileController extends DiffusionController {
private $lintMessages;
public function processRequest() {
$request = $this->getRequest();
$drequest = $this->getDiffusionRequest();
@ -75,7 +74,7 @@ final class DiffusionBrowseFileController extends DiffusionController {
$content = array();
$content[] = $this->buildHeaderView($drequest);
$view = $this->buildBrowseActionView($drequest);
$view = $this->buildActionView($drequest);
$content[] = $this->enrichActionView($view, $drequest, $selected);
$content[] = $this->buildPropertyView($drequest);
@ -968,40 +967,4 @@ final class DiffusionBrowseFileController extends DiffusionController {
return head($parents);
}
private function buildHeaderView(DiffusionRequest $drequest) {
$viewer = $this->getRequest()->getUser();
$header = id(new PHUIHeaderView())
->setUser($viewer)
->setHeader($this->renderPathLinks($drequest))
->setPolicyObject($drequest->getRepository());
return $header;
}
private function buildPropertyView(DiffusionRequest $drequest) {
$viewer = $this->getRequest()->getUser();
$view = id(new PhabricatorPropertyListView())
->setUser($viewer);
$stable_commit = $drequest->getStableCommitName();
$callsign = $drequest->getRepository()->getCallsign();
$view->addProperty(
pht('Commit'),
phutil_tag(
'a',
array(
'href' => $drequest->generateURI(
array(
'action' => 'commit',
'commit' => $stable_commit,
)),
),
$drequest->getRepository()->formatCommitName($stable_commit)));
return $view;
}
}

View file

@ -0,0 +1,39 @@
<?php
final class DiffusionBrowseMainController extends DiffusionBrowseController {
public function processRequest() {
$drequest = $this->diffusionRequest;
$request = $this->getRequest();
// Figure out if we're browsing a directory, a file, or a search result
// list. Then delegate to the appropriate controller.
$search = $request->getStr('grep');
if (strlen($search)) {
$controller = new DiffusionBrowseSearchController($request);
} else {
$results = DiffusionBrowseResultSet::newFromConduit(
$this->callConduitWithDiffusionRequest(
'diffusion.browsequery',
array(
'path' => $drequest->getPath(),
'commit' => $drequest->getCommit(),
)));
$reason = $results->getReasonForEmptyResultSet();
$is_file = ($reason == DiffusionBrowseResultSet::REASON_IS_FILE);
if ($is_file) {
$controller = new DiffusionBrowseFileController($request);
} else {
$controller = new DiffusionBrowseDirectoryController($request);
$controller->setBrowseQueryResults($results);
}
}
$controller->setDiffusionRequest($drequest);
$controller->setCurrentApplication($this->getCurrentApplication());
return $this->delegateToController($controller);
}
}

View file

@ -0,0 +1,132 @@
<?php
final class DiffusionBrowseSearchController extends DiffusionBrowseController {
public function processRequest() {
$drequest = $this->diffusionRequest;
$content = array();
$content[] = $this->buildHeaderView($drequest);
$content[] = $this->buildActionView($drequest);
$content[] = $this->buildPropertyView($drequest);
$content[] = $this->renderSearchForm($collapsed = false);
$content[] = $this->renderSearchResults();
$crumbs = $this->buildCrumbs(
array(
'branch' => true,
'path' => true,
'view' => 'browse',
));
return $this->buildApplicationPage(
array(
$crumbs,
$content,
),
array(
'device' => true,
'title' => array(
nonempty(basename($drequest->getPath()), '/'),
$drequest->getRepository()->getCallsign().' Repository',
),
));
}
private function renderSearchResults() {
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$results = array();
$no_data = pht('No results found.');
$limit = 100;
$page = $this->getRequest()->getInt('page', 0);
$pager = new AphrontPagerView();
$pager->setPageSize($limit);
$pager->setOffset($page);
$pager->setURI($this->getRequest()->getRequestURI(), 'page');
try {
$results = $this->callConduitWithDiffusionRequest(
'diffusion.searchquery',
array(
'grep' => $this->getRequest()->getStr('grep'),
'stableCommitName' => $drequest->getStableCommitName(),
'path' => $drequest->getPath(),
'limit' => $limit + 1,
'offset' => $page));
} catch (ConduitException $ex) {
$err = $ex->getErrorDescription();
if ($err != '') {
return id(new AphrontErrorView())
->setTitle(pht('Search Error'))
->appendChild($err);
}
}
$results = $pager->sliceResults($results);
require_celerity_resource('syntax-highlighting-css');
// NOTE: This can be wrong because we may find the string inside the
// comment. But it's correct in most cases and highlighting the whole file
// would be too expensive.
$futures = array();
$engine = PhabricatorSyntaxHighlighter::newEngine();
foreach ($results as $result) {
list($path, $line, $string) = $result;
$futures["{$path}:{$line}"] = $engine->getHighlightFuture(
$engine->getLanguageFromFilename($path),
ltrim($string));
}
try {
Futures($futures)->limit(8)->resolveAll();
} catch (PhutilSyntaxHighlighterException $ex) {
}
$rows = array();
foreach ($results as $result) {
list($path, $line, $string) = $result;
$href = $drequest->generateURI(array(
'action' => 'browse',
'path' => $path,
'line' => $line,
));
try {
$string = $futures["{$path}:{$line}"]->resolve();
} catch (PhutilSyntaxHighlighterException $ex) {
}
$string = phutil_tag(
'pre',
array('class' => 'PhabricatorMonospaced'),
$string);
$path = Filesystem::readablePath($path, $drequest->getPath());
$rows[] = array(
phutil_tag('a', array('href' => $href), $path),
$line,
$string,
);
}
$table = id(new AphrontTableView($rows))
->setClassName('remarkup-code')
->setHeaders(array(pht('Path'), pht('Line'), pht('String')))
->setColumnClasses(array('', 'n', 'wide'))
->setNoDataString($no_data);
return id(new AphrontPanelView())
->setNoBackground(true)
->appendChild($table)
->appendChild($pager);
}
}

View file

@ -97,51 +97,6 @@ abstract class DiffusionController extends PhabricatorController {
return $crumbs;
}
protected function buildOpenRevisions() {
$user = $this->getRequest()->getUser();
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$path = $drequest->getPath();
$path_map = id(new DiffusionPathIDQuery(array($path)))->loadPathIDs();
$path_id = idx($path_map, $path);
if (!$path_id) {
return null;
}
$revisions = id(new DifferentialRevisionQuery())
->setViewer($user)
->withPath($repository->getID(), $path_id)
->withStatus(DifferentialRevisionQuery::STATUS_OPEN)
->setOrder(DifferentialRevisionQuery::ORDER_PATH_MODIFIED)
->setLimit(10)
->needRelationships(true)
->execute();
if (!$revisions) {
return null;
}
$view = id(new DifferentialRevisionListView())
->setRevisions($revisions)
->setFields(DifferentialRevisionListView::getDefaultFields($user))
->setUser($user)
->loadAssets();
$phids = $view->getRequiredHandlePHIDs();
$handles = $this->loadViewerHandles($phids);
$view->setHandles($handles);
$header = id(new PHUIHeaderView())
->setHeader(pht('Pending Differential Revisions'));
return array(
$header,
$view,
);
}
private function buildCrumbList(array $spec = array()) {
$spec = $spec + array(
@ -344,56 +299,6 @@ abstract class DiffusionController extends PhabricatorController {
return $this->getApplicationURI($repository->getCallsign().'/'.$path);
}
protected function buildBrowseActionView(DiffusionRequest $drequest) {
$viewer = $this->getRequest()->getUser();
$view = id(new PhabricatorActionListView())
->setUser($viewer);
$history_uri = $drequest->generateURI(
array(
'action' => 'history',
));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('View History'))
->setHref($history_uri)
->setIcon('perflab'));
$behind_head = $drequest->getRawCommit();
$head_uri = $drequest->generateURI(
array(
'commit' => '',
'action' => 'browse',
));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Jump to HEAD'))
->setHref($head_uri)
->setIcon('home')
->setDisabled(!$behind_head));
// TODO: Ideally, this should live in Owners and be event-triggered, but
// there's no reasonable object for it to react to right now.
$owners_uri = id(new PhutilURI('/owners/view/search/'))
->setQueryParams(
array(
'repository' => $drequest->getCallsign(),
'path' => '/'.$drequest->getPath(),
));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Find Owners'))
->setHref((string)$owners_uri)
->setIcon('preview'));
return $view;
}
protected function renderPathLinks(DiffusionRequest $drequest) {
$path = $drequest->getPath();
$path_parts = array_filter(explode('/', trim($path, '/')));