Something went wrong. Try again.
@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
Something went wrong. Try again.
13 kB · 514 lines
PHP
at commit dfc8f8bc
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515<?php
final class DiffusionLintController extends DiffusionController {
public function shouldAllowPublic() { return true; }
public function handleRequest(AphrontRequest $request) { $viewer = $this->getViewer();
if ($this->getRepositoryIdentifierFromRequest($request)) { $response = $this->loadDiffusionContext(); if ($response) { return $response; }
$drequest = $this->getDiffusionRequest(); } else { $drequest = null; }
$code = $request->getStr('lint'); if (strlen($code)) { return $this->buildDetailsResponse(); }
$owners = array(); if (!$drequest) { if (!$request->getArr('owner')) { $owners = array($viewer->getPHID()); } else { $owners = array(head($request->getArr('owner'))); } }
$codes = $this->loadLintCodes($drequest, $owners);
if ($codes) { $branches = id(new PhabricatorRepositoryBranch())->loadAllWhere( 'id IN (%Ld)', array_unique(ipull($codes, 'branchID'))); $branches = mpull($branches, null, 'getID'); } else { $branches = array(); }
if ($branches) { $repositories = id(new PhabricatorRepositoryQuery()) ->setViewer($viewer) ->withIDs(mpull($branches, 'getRepositoryID')) ->execute(); $repositories = mpull($repositories, null, 'getID'); } else { $repositories = array(); }
$rows = array(); $total = 0; foreach ($codes as $code) { $branch = idx($branches, $code['branchID']); if (!$branch) { continue; }
$repository = idx($repositories, $branch->getRepositoryID()); if (!$repository) { continue; }
$total += $code['n'];
if ($drequest) { $href_lint = $drequest->generateURI( array( 'action' => 'lint', 'lint' => $code['code'], ));
$href_browse = $drequest->generateURI( array( 'action' => 'browse', 'lint' => $code['code'], ));
$href_repo = $drequest->generateURI( array( 'action' => 'lint', )); } else { $href_lint = $repository->generateURI( array( 'action' => 'lint', 'lint' => $code['code'], ));
$href_browse = $repository->generateURI( array( 'action' => 'browse', 'lint' => $code['code'], ));
$href_repo = $repository->generateURI( array( 'action' => 'lint', )); }
$rows[] = array( phutil_tag('a', array('href' => $href_lint), $code['n']), phutil_tag('a', array('href' => $href_browse), $code['files']), phutil_tag( 'a', array( 'href' => $href_repo, ), $repository->getDisplayName()), ArcanistLintSeverity::getStringForSeverity($code['maxSeverity']), $code['code'], $code['maxName'], $code['maxDescription'], ); }
$table = id(new AphrontTableView($rows)) ->setHeaders(array( pht('Problems'), pht('Files'), pht('Repository'), pht('Severity'), pht('Code'), pht('Name'), pht('Example'), )) ->setColumnVisibility(array(true, true, !$drequest)) ->setColumnClasses(array('n', 'n', '', '', 'pri', '', ''));
$content = array();
if (!$drequest) { $form = id(new AphrontFormView()) ->setUser($viewer) ->setMethod('GET') ->appendControl( id(new AphrontFormTokenizerControl()) ->setDatasource(new PhabricatorPeopleDatasource()) ->setLimit(1) ->setName('owner') ->setLabel(pht('Owner')) ->setValue($owners)) ->appendChild( id(new AphrontFormSubmitControl()) ->setValue(pht('Filter'))); $content[] = id(new AphrontListFilterView())->appendChild($form); }
$content[] = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Lint')) ->setTable($table);
$title = array('Lint'); $crumbs = $this->buildCrumbs( array( 'branch' => true, 'path' => true, 'view' => 'lint', ));
if ($drequest) { $title[] = $drequest->getRepository()->getDisplayName(); } else { $crumbs->addTextCrumb(pht('All Lint')); }
if ($drequest) { $branch = $drequest->loadBranch();
$header = id(new PHUIHeaderView()) ->setHeader($this->renderPathLinks($drequest, 'lint')) ->setUser($viewer) ->setPolicyObject($drequest->getRepository()); $actions = $this->buildActionView($drequest); $properties = $this->buildPropertyView( $drequest, $branch, $total, $actions);
$object_box = id(new PHUIObjectBoxView()) ->setHeader($header) ->addPropertyList($properties); } else { $object_box = null; }
return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->appendChild( array( $object_box, $content, )); }
private function loadLintCodes($drequest, array $owner_phids) { $conn = id(new PhabricatorRepository())->establishConnection('r'); $where = array('1 = 1');
if ($drequest) { $branch = $drequest->loadBranch(); if (!$branch) { return array(); }
$where[] = qsprintf($conn, 'branchID = %d', $branch->getID());
if ($drequest->getPath() != '') { $path = '/'.$drequest->getPath(); $is_dir = (substr($path, -1) == '/'); $where[] = ($is_dir ? qsprintf($conn, 'path LIKE %>', $path) : qsprintf($conn, 'path = %s', $path)); } }
if ($owner_phids) { $or = array(); $or[] = qsprintf($conn, 'authorPHID IN (%Ls)', $owner_phids);
$paths = array(); $packages = id(new PhabricatorOwnersOwner()) ->loadAllWhere('userPHID IN (%Ls)', $owner_phids); if ($packages) { $paths = id(new PhabricatorOwnersPath())->loadAllWhere( 'packageID IN (%Ld)', mpull($packages, 'getPackageID')); }
if ($paths) { $repositories = id(new PhabricatorRepositoryQuery()) ->setViewer($this->getRequest()->getUser()) ->withPHIDs(mpull($paths, 'getRepositoryPHID')) ->execute(); $repositories = mpull($repositories, 'getID', 'getPHID');
$branches = id(new PhabricatorRepositoryBranch())->loadAllWhere( 'repositoryID IN (%Ld)', $repositories); $branches = mgroup($branches, 'getRepositoryID'); }
foreach ($paths as $path) { $branch = idx( $branches, idx( $repositories, $path->getRepositoryPHID())); if ($branch) { $condition = qsprintf( $conn, '(branchID IN (%Ld) AND path LIKE %>)', array_keys($branch), $path->getPath()); if ($path->getExcluded()) { $where[] = 'NOT '.$condition; } else { $or[] = $condition; } } } $where[] = '('.implode(' OR ', $or).')'; }
return queryfx_all( $conn, 'SELECT branchID, code, MAX(severity) AS maxSeverity, MAX(name) AS maxName, MAX(description) AS maxDescription, COUNT(DISTINCT path) AS files, COUNT(*) AS n FROM %T WHERE %Q GROUP BY branchID, code ORDER BY n DESC', PhabricatorRepository::TABLE_LINTMESSAGE, implode(' AND ', $where)); }
protected function buildActionView(DiffusionRequest $drequest) { $viewer = $this->getRequest()->getUser();
$view = id(new PhabricatorActionListView()) ->setUser($viewer);
$list_uri = $drequest->generateURI( array( 'action' => 'lint', 'lint' => '', ));
$view->addAction( id(new PhabricatorActionView()) ->setName(pht('View As List')) ->setHref($list_uri) ->setIcon('fa-list'));
$history_uri = $drequest->generateURI( array( 'action' => 'history', ));
$view->addAction( id(new PhabricatorActionView()) ->setName(pht('View History')) ->setHref($history_uri) ->setIcon('fa-clock-o'));
$browse_uri = $drequest->generateURI( array( 'action' => 'browse', ));
$view->addAction( id(new PhabricatorActionView()) ->setName(pht('Browse Content')) ->setHref($browse_uri) ->setIcon('fa-files-o'));
return $view; }
protected function buildPropertyView( DiffusionRequest $drequest, PhabricatorRepositoryBranch $branch, $total, PhabricatorActionListView $actions) {
$viewer = $this->getRequest()->getUser();
$view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setActionList($actions);
$lint_commit = $branch->getLintCommit();
$view->addProperty( pht('Lint Commit'), phutil_tag( 'a', array( 'href' => $drequest->generateURI( array( 'action' => 'commit', 'commit' => $lint_commit, )), ), $drequest->getRepository()->formatCommitName($lint_commit)));
$view->addProperty( pht('Total Messages'), pht('%s', new PhutilNumber($total)));
return $view; }
private function buildDetailsResponse() { $request = $this->getRequest();
$limit = 500;
$pager = id(new PHUIPagerView()) ->readFromRequest($request) ->setPageSize($limit);
$offset = $pager->getOffset();
$drequest = $this->getDiffusionRequest(); $branch = $drequest->loadBranch(); $messages = $this->loadLintMessages($branch, $limit, $offset); $is_dir = (substr('/'.$drequest->getPath(), -1) == '/');
$pager->setHasMorePages(count($messages) >= $limit);
$authors = $this->loadViewerHandles(ipull($messages, 'authorPHID'));
$rows = array(); foreach ($messages as $message) { $path = phutil_tag( 'a', array( 'href' => $drequest->generateURI(array( 'action' => 'lint', 'path' => $message['path'], )), ), substr($message['path'], strlen($drequest->getPath()) + 1));
$line = phutil_tag( 'a', array( 'href' => $drequest->generateURI(array( 'action' => 'browse', 'path' => $message['path'], 'line' => $message['line'], 'commit' => $branch->getLintCommit(), )), ), $message['line']);
$author = $message['authorPHID']; if ($author && $authors[$author]) { $author = $authors[$author]->renderLink(); }
$rows[] = array( $path, $line, $author, ArcanistLintSeverity::getStringForSeverity($message['severity']), $message['name'], $message['description'], ); }
$table = id(new AphrontTableView($rows)) ->setHeaders(array( pht('Path'), pht('Line'), pht('Author'), pht('Severity'), pht('Name'), pht('Description'), )) ->setColumnClasses(array('', 'n')) ->setColumnVisibility(array($is_dir));
$content = array();
$content[] = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Lint Details')) ->setTable($table);
$crumbs = $this->buildCrumbs( array( 'branch' => true, 'path' => true, 'view' => 'lint', ));
$pager_box = $this->renderTablePagerBox($pager);
return $this->newPage() ->setTitle( array( pht('Lint'), $drequest->getRepository()->getDisplayName(), )) ->setCrumbs($crumbs) ->appendChild( array( $content, $pager_box, )); }
private function loadLintMessages( PhabricatorRepositoryBranch $branch, $limit, $offset) {
$drequest = $this->getDiffusionRequest(); if (!$branch) { return array(); }
$conn = $branch->establishConnection('r');
$where = array( qsprintf($conn, 'branchID = %d', $branch->getID()), );
if ($drequest->getPath() != '') { $path = '/'.$drequest->getPath(); $is_dir = (substr($path, -1) == '/'); $where[] = ($is_dir ? qsprintf($conn, 'path LIKE %>', $path) : qsprintf($conn, 'path = %s', $path)); }
if ($drequest->getLint() != '') { $where[] = qsprintf( $conn, 'code = %s', $drequest->getLint()); }
return queryfx_all( $conn, 'SELECT * FROM %T WHERE %Q ORDER BY path, code, line LIMIT %d OFFSET %d', PhabricatorRepository::TABLE_LINTMESSAGE, implode(' AND ', $where), $limit, $offset); }}