3 final class DiffusionLintController
extends DiffusionController
{
5 public function shouldAllowPublic() {
9 public function handleRequest(AphrontRequest
$request) {
10 $viewer = $this->getViewer();
12 if ($this->getRepositoryIdentifierFromRequest($request)) {
13 $response = $this->loadDiffusionContext();
18 $drequest = $this->getDiffusionRequest();
23 $code = $request->getStr('lint');
25 return $this->buildDetailsResponse();
30 if (!$request->getArr('owner')) {
31 $owners = array($viewer->getPHID());
33 $owners = array(head($request->getArr('owner')));
37 $codes = $this->loadLintCodes($drequest, $owners);
40 $branches = id(new PhabricatorRepositoryBranch())->loadAllWhere(
42 array_unique(ipull($codes, 'branchID')));
43 $branches = mpull($branches, null, 'getID');
49 $repositories = id(new PhabricatorRepositoryQuery())
51 ->withIDs(mpull($branches, 'getRepositoryID'))
53 $repositories = mpull($repositories, null, 'getID');
55 $repositories = array();
61 foreach ($codes as $code) {
62 $branch = idx($branches, $code['branchID']);
67 $repository = idx($repositories, $branch->getRepositoryID());
75 $href_lint = $drequest->generateURI(
78 'lint' => $code['code'],
81 $href_browse = $drequest->generateURI(
84 'lint' => $code['code'],
87 $href_repo = $drequest->generateURI(
92 $href_lint = $repository->generateURI(
95 'lint' => $code['code'],
98 $href_browse = $repository->generateURI(
100 'action' => 'browse',
101 'lint' => $code['code'],
104 $href_repo = $repository->generateURI(
111 phutil_tag('a', array('href' => $href_lint), $code['n']),
112 phutil_tag('a', array('href' => $href_browse), $code['files']),
116 'href' => $href_repo,
118 $repository->getDisplayName()),
119 ArcanistLintSeverity
::getStringForSeverity($code['maxSeverity']),
122 $code['maxDescription'],
126 $table = id(new AphrontTableView($rows))
136 ->setColumnVisibility(array(true, true, !$drequest))
137 ->setColumnClasses(array('n', 'n', '', '', 'pri', '', ''));
142 $form = id(new AphrontFormView())
146 id(new AphrontFormTokenizerControl())
147 ->setDatasource(new PhabricatorPeopleDatasource())
150 ->setLabel(pht('Owner'))
153 id(new AphrontFormSubmitControl())
154 ->setValue(pht('Filter')));
155 $content[] = id(new AphrontListFilterView())->appendChild($form);
158 $content[] = id(new PHUIObjectBoxView())
159 ->setHeaderText(pht('Lint'))
160 ->setBackground(PHUIObjectBoxView
::BLUE_PROPERTY
)
163 $title = array('Lint');
164 $crumbs = $this->buildCrumbs(
170 $crumbs->setBorder(true);
173 $title[] = $drequest->getRepository()->getDisplayName();
175 $crumbs->addTextCrumb(pht('All Lint'));
179 $branch = $drequest->loadBranch();
181 $header = id(new PHUIHeaderView())
182 ->setHeader(pht('Lint: %s', $this->renderPathLinks($drequest, 'lint')))
184 ->setHeaderIcon('fa-code');
185 $actions = $this->buildActionView($drequest);
186 $properties = $this->buildPropertyView(
192 $object_box = id(new PHUIObjectBoxView())
194 ->setBackground(PHUIObjectBoxView
::BLUE_PROPERTY
)
195 ->addPropertyList($properties);
198 $header = id(new PHUIHeaderView())
199 ->setHeader(pht('All Lint'))
200 ->setHeaderIcon('fa-code');
203 $view = id(new PHUITwoColumnView())
210 return $this->newPage()
219 private function loadLintCodes($drequest, array $owner_phids) {
220 $conn = id(new PhabricatorRepository())->establishConnection('r');
221 $where = array('1 = 1');
224 $branch = $drequest->loadBranch();
229 $where[] = qsprintf($conn, 'branchID = %d', $branch->getID());
231 if ($drequest->getPath() != '') {
232 $path = '/'.$drequest->getPath();
233 $is_dir = (substr($path, -1) == '/');
235 ?
qsprintf($conn, 'path LIKE %>', $path)
236 : qsprintf($conn, 'path = %s', $path));
242 $or[] = qsprintf($conn, 'authorPHID IN (%Ls)', $owner_phids);
245 $packages = id(new PhabricatorOwnersOwner())
246 ->loadAllWhere('userPHID IN (%Ls)', $owner_phids);
248 $paths = id(new PhabricatorOwnersPath())->loadAllWhere(
249 'packageID IN (%Ld)',
250 mpull($packages, 'getPackageID'));
254 $repositories = id(new PhabricatorRepositoryQuery())
255 ->setViewer($this->getRequest()->getUser())
256 ->withPHIDs(mpull($paths, 'getRepositoryPHID'))
258 $repositories = mpull($repositories, 'getID', 'getPHID');
260 $branches = id(new PhabricatorRepositoryBranch())->loadAllWhere(
261 'repositoryID IN (%Ld)',
263 $branches = mgroup($branches, 'getRepositoryID');
266 foreach ($paths as $path) {
271 $path->getRepositoryPHID()));
273 $condition = qsprintf(
275 '(branchID IN (%Ld) AND path LIKE %>)',
278 if ($path->getExcluded()) {
279 $where[] = qsprintf($conn, 'NOT %Q', $condition);
285 $where[] = qsprintf($conn, '%LO', $or);
293 MAX(severity) AS maxSeverity,
294 MAX(name) AS maxName,
295 MAX(description) AS maxDescription,
296 COUNT(DISTINCT path) AS files,
300 GROUP BY branchID, code
302 PhabricatorRepository
::TABLE_LINTMESSAGE
,
306 protected function buildActionView(DiffusionRequest
$drequest) {
307 $viewer = $this->getRequest()->getUser();
309 $view = id(new PhabricatorActionListView())
312 $list_uri = $drequest->generateURI(
319 id(new PhabricatorActionView())
320 ->setName(pht('View As List'))
322 ->setIcon('fa-list'));
324 $history_uri = $drequest->generateURI(
326 'action' => 'history',
330 id(new PhabricatorActionView())
331 ->setName(pht('View History'))
332 ->setHref($history_uri)
333 ->setIcon('fa-clock-o'));
335 $browse_uri = $drequest->generateURI(
337 'action' => 'browse',
341 id(new PhabricatorActionView())
342 ->setName(pht('Browse Content'))
343 ->setHref($browse_uri)
344 ->setIcon('fa-files-o'));
349 protected function buildPropertyView(
350 DiffusionRequest
$drequest,
351 PhabricatorRepositoryBranch
$branch,
353 PhabricatorActionListView
$actions) {
355 $viewer = $this->getRequest()->getUser();
357 $view = id(new PHUIPropertyListView())
359 ->setActionList($actions);
361 $lint_commit = $branch->getLintCommit();
368 'href' => $drequest->generateURI(
370 'action' => 'commit',
371 'commit' => $lint_commit,
374 $drequest->getRepository()->formatCommitName($lint_commit)));
377 pht('Total Messages'),
378 pht('%s', new PhutilNumber($total)));
384 private function buildDetailsResponse() {
385 $request = $this->getRequest();
389 $pager = id(new PHUIPagerView())
390 ->readFromRequest($request)
391 ->setPageSize($limit);
393 $offset = $pager->getOffset();
395 $drequest = $this->getDiffusionRequest();
396 $branch = $drequest->loadBranch();
397 $messages = $this->loadLintMessages($branch, $limit, $offset);
398 $is_dir = (substr('/'.$drequest->getPath(), -1) == '/');
400 $pager->setHasMorePages(count($messages) >= $limit);
402 $authors = $this->loadViewerHandles(ipull($messages, 'authorPHID'));
405 foreach ($messages as $message) {
409 'href' => $drequest->generateURI(array(
411 'path' => $message['path'],
414 substr($message['path'], strlen($drequest->getPath()) +
1));
419 'href' => $drequest->generateURI(array(
420 'action' => 'browse',
421 'path' => $message['path'],
422 'line' => $message['line'],
423 'commit' => $branch->getLintCommit(),
428 $author = $message['authorPHID'];
429 if ($author && $authors[$author]) {
430 $author = $authors[$author]->renderLink();
437 ArcanistLintSeverity
::getStringForSeverity($message['severity']),
439 $message['description'],
443 $table = id(new AphrontTableView($rows))
452 ->setColumnClasses(array('', 'n'))
453 ->setColumnVisibility(array($is_dir));
457 $content[] = id(new PHUIObjectBoxView())
458 ->setHeaderText(pht('Lint Details'))
459 ->setBackground(PHUIObjectBoxView
::BLUE_PROPERTY
)
463 $crumbs = $this->buildCrumbs(
469 $crumbs->setBorder(true);
471 $header = id(new PHUIHeaderView())
472 ->setHeader(pht('Lint: %s', $drequest->getRepository()->getDisplayName()))
473 ->setHeaderIcon('fa-code');
475 $view = id(new PHUITwoColumnView())
481 return $this->newPage()
485 $drequest->getRepository()->getDisplayName(),
494 private function loadLintMessages(
495 PhabricatorRepositoryBranch
$branch,
499 $drequest = $this->getDiffusionRequest();
504 $conn = $branch->establishConnection('r');
507 qsprintf($conn, 'branchID = %d', $branch->getID()),
510 if ($drequest->getPath() != '') {
511 $path = '/'.$drequest->getPath();
512 $is_dir = (substr($path, -1) == '/');
514 ?
qsprintf($conn, 'path LIKE %>', $path)
515 : qsprintf($conn, 'path = %s', $path));
518 if ($drequest->getLint() != '') {
522 $drequest->getLint());
530 ORDER BY path, code, line LIMIT %d OFFSET %d',
531 PhabricatorRepository
::TABLE_LINTMESSAGE
,