Files
phabricator/src/applications/audit/controller/PhabricatorAuditListController.php
epriestley 0598600476 Always pass handles to tokenizers, not <phid -> name> maps
Summary: Ref T1279. Prerequisite for adding icons or other type information to tokenizers, since we don't currently have enough information to prefill them when rendering things from the server side. By passing handles in, the tokenizer can extract type information.

Test Plan:
- Searched by user in Audit.
- Sent Conpherence from profile page.
- Tried to send an empty conpherence.
- Searched Countdown by user.
- Edited CCs in Differential.
- Edited reviewers in Differential.
- Edited a commit's projects.
- Searched lint by owner.
- Searched feed by owner/project.
- Searched files by owner.
- Searched Herald by owner.
- Searched Legalpad by owner.
- Searched Macro by owner.
- Filtered Maniphest reports by project.
- Edited CCs in Maniphest.
- Searched Owners by owner.
- Edited an Owners package.
- Searched Paste by owner.
- Searched activity logs by owner.
- Searched for mocks by owner.
- Edited a mock's CCs.
- Searched Ponder by owner.
- Searched projects by owner.
- Edited a Releeph project's pushers.
- Searched Releeph by requestor.
- Edited "Uses Symbols" for an Arcanist project.
- Edited all tokenizers in main search.
- Searched Slowvote by user.

Reviewers: chad, btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T1279

Differential Revision: https://secure.phabricator.com/D7248
2013-10-07 12:51:24 -07:00

501 lines
13 KiB
PHP

<?php
final class PhabricatorAuditListController extends PhabricatorAuditController {
private $name;
private $filterStatus;
public function willProcessRequest(array $data) {
$this->filter = idx($data, 'filter');
$this->name = idx($data, 'name');
}
public function processRequest() {
$request = $this->getRequest();
$nav = $this->buildSideNavView();
if ($request->isFormPost()) {
// If the list filter is POST'ed, redirect to GET so the page can be
// bookmarked.
$uri = $request->getRequestURI();
$phid = head($request->getArr('set_phid'));
$user = id(new PhabricatorUser())->loadOneWhere(
'phid = %s',
$phid);
$uri = $request->getRequestURI();
if ($user) {
$username = phutil_escape_uri($user->getUsername());
$uri = '/audit/view/'.$this->filter.'/'.$username.'/';
} else if ($phid) {
$uri = $request->getRequestURI();
$uri = $uri->alter('phid', $phid);
}
return id(new AphrontRedirectResponse())->setURI($uri);
}
$this->filterStatus = $request->getStr('status', 'all');
$handle = $this->loadHandle();
$nav->appendChild($this->buildListFilters($handle));
$title = null;
$message = null;
if (!$handle) {
switch ($this->filter) {
case 'project':
$title = pht('Choose A Project');
$message = pht('Choose a project to view audits for.');
break;
case 'repository':
$title = pht('Choose A Repository');
$message = pht('Choose a repository to view audits for.');
break;
case 'package':
case 'packagecommits':
$title = pht('Choose a Package');
$message = pht('Choose a package to view audits for.');
break;
}
}
if (!$message) {
$nav->appendChild($this->buildViews($handle));
} else {
$panel = id(new AphrontErrorView())
->setSeverity(AphrontErrorView::SEVERITY_NODATA)
->setTitle($title)
->appendChild($message);
$nav->appendChild($panel);
}
return $this->buildApplicationPage(
$nav,
array(
'title' => pht('Audits'),
'device' => true,
));
}
private function buildListFilters(PhabricatorObjectHandle $handle = null) {
$request = $this->getRequest();
$user = $request->getUser();
$form = new AphrontFormView();
$form->setUser($user);
$show_status = false;
$show_user = false;
$show_project = false;
$show_package = false;
$show_repository = false;
switch ($this->filter) {
case 'audits':
case 'commits':
$show_status = true;
break;
case 'active':
$show_user = true;
break;
case 'author':
case 'user':
$show_user = true;
$show_status = true;
break;
case 'project':
$show_project = true;
$show_status = true;
break;
case 'repository':
$show_repository = true;
$show_status = true;
break;
case 'package':
case 'packagecommits':
$show_package = true;
$show_status = true;
break;
}
if ($show_user || $show_project || $show_package || $show_repository) {
if ($show_user) {
$uri = '/typeahead/common/users/';
$label = pht('User');
} else if ($show_project) {
$uri = '/typeahead/common/projects/';
$label = pht('Project');
} else if ($show_package) {
$uri = '/typeahead/common/packages/';
$label = pht('Package');
} else if ($show_repository) {
$uri = '/typeahead/common/repositories/';
$label = pht('Repository');
}
$tok_value = null;
if ($handle) {
$tok_value = array($handle);
}
$form->appendChild(
id(new AphrontFormTokenizerControl())
->setName('set_phid')
->setLabel($label)
->setLimit(1)
->setDatasource($uri)
->setValue($tok_value));
}
if ($show_status) {
$form->appendChild(
id(new AphrontFormToggleButtonsControl())
->setName('status')
->setLabel(pht('Status'))
->setBaseURI($request->getRequestURI(), 'status')
->setValue($this->filterStatus)
->setButtons(
array(
'all' => pht('All'),
'open' => pht('Open'),
'concern' => pht('Concern Raised'),
)));
}
$form->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Filter Audits')));
$view = new AphrontListFilterView();
$view->appendChild($form);
return $view;
}
private function loadHandle() {
$request = $this->getRequest();
$default = null;
switch ($this->filter) {
case 'user':
case 'active':
case 'author':
$default = $request->getUser()->getPHID();
if ($this->name) {
$user = id(new PhabricatorUser())->loadOneWhere(
'username = %s',
$this->name);
if ($user) {
$default = $user->getPHID();
}
}
break;
}
$phid = $request->getStr('phid', $default);
if (!$phid) {
return null;
}
$phids = array($phid);
$handles = $this->loadViewerHandles($phids);
$handle = $handles[$phid];
$this->validateHandle($handle);
return $handle;
}
private function validateHandle(PhabricatorObjectHandle $handle) {
$type = $handle->getType();
switch ($this->filter) {
case 'active':
case 'user':
case 'author':
if ($type !== PhabricatorPeoplePHIDTypeUser::TYPECONST) {
throw new Exception("PHID must be a user PHID!");
}
break;
case 'package':
case 'packagecommits':
if ($type !== PhabricatorOwnersPHIDTypePackage::TYPECONST) {
throw new Exception("PHID must be a package PHID!");
}
break;
case 'project':
if ($type !== PhabricatorProjectPHIDTypeProject::TYPECONST) {
throw new Exception("PHID must be a project PHID!");
}
break;
case 'repository':
if ($type !== PhabricatorRepositoryPHIDTypeRepository::TYPECONST) {
throw new Exception("PHID must be a repository PHID!");
}
break;
case 'audits':
case 'commits':
break;
default:
throw new Exception("Unknown filter '{$this->filter}'!");
}
}
private function buildViews(PhabricatorObjectHandle $handle = null) {
$views = array();
switch ($this->filter) {
case 'active':
$views[] = $this->buildCommitView($handle);
$views[] = $this->buildAuditView($handle);
break;
case 'audits':
case 'user':
case 'package':
case 'project':
case 'repository':
$views[] = $this->buildAuditView($handle);
break;
case 'commits':
case 'packagecommits':
case 'author':
$views[] = $this->buildCommitView($handle);
break;
}
return $views;
}
private function buildAuditView(PhabricatorObjectHandle $handle = null) {
$request = $this->getRequest();
$query = new PhabricatorAuditQuery();
$use_pager = ($this->filter != 'active');
if ($use_pager) {
$pager = new AphrontPagerView();
$pager->setURI($request->getRequestURI(), 'offset');
$pager->setOffset($request->getInt('offset'));
$query->setOffset($pager->getOffset());
$query->setLimit($pager->getPageSize() + 1);
}
$awaiting = null;
$phids = null;
$repository_phids = null;
switch ($this->filter) {
case 'user':
case 'active':
$obj = id(new PhabricatorUser())->loadOneWhere(
'phid = %s',
$handle->getPHID());
if (!$obj) {
throw new Exception("Invalid user!");
}
$phids = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($obj);
$awaiting = $obj;
break;
case 'project':
case 'package':
$phids = array($handle->getPHID());
break;
case 'repository':
$repository_phids = array($handle->getPHID());
break;
case 'audits';
break;
default:
throw new Exception("Unknown filter!");
}
if ($phids) {
$query->withAuditorPHIDs($phids);
}
if ($repository_phids) {
$query->withRepositoryPHIDs($repository_phids);
}
if ($awaiting) {
$query->withAwaitingUser($awaiting);
}
switch ($this->filter) {
case 'active':
$query->withStatus(PhabricatorAuditQuery::STATUS_OPEN);
break;
default:
switch ($this->filterStatus) {
case 'open':
$query->withStatus(PhabricatorAuditQuery::STATUS_OPEN);
break;
case 'concern':
$query->withStatus(PhabricatorAuditQuery::STATUS_CONCERN);
break;
}
break;
}
if ($handle) {
$handle_name = $handle->getFullName();
} else {
$handle_name = null;
}
switch ($this->filter) {
case 'active':
$header = pht('Required Audits');
$nodata = pht('No commits require your audit.');
break;
case 'user':
$header = pht("Audits for %s", $handle_name);
$nodata = pht("No matching audits by %s.", $handle_name);
break;
case 'audits':
$header = pht('Audits');
$nodata = pht('No matching audits.');
break;
case 'project':
$header = pht("Audits in Project %s", $handle_name);
$nodata = pht("No matching audits in project %s.", $handle_name);
break;
case 'package':
$header = pht("Audits for Package %s", $handle_name);
$nodata = pht("No matching audits in package %s.", $handle_name);
break;
case 'repository':
$header = pht("Audits in Repository %s", $handle_name);
$nodata = pht("No matching audits in repository %s.", $handle_name);
break;
}
$query->needCommitData(true);
$audits = $query->execute();
if ($use_pager) {
$audits = $pager->sliceResults($audits);
}
$view = new PhabricatorAuditListView();
$view->setAudits($audits);
$view->setCommits($query->getCommits());
$view->setUser($request->getUser());
$view->setNoDataString($nodata);
$phids = $view->getRequiredHandlePHIDs();
$handles = $this->loadViewerHandles($phids);
$view->setHandles($handles);
$panel = new AphrontPanelView();
$panel->setHeader($header);
$panel->appendChild($view);
$panel->setNoBackground();
if ($use_pager) {
$panel->appendChild($pager);
}
return $panel;
}
private function buildCommitView(PhabricatorObjectHandle $handle = null) {
$request = $this->getRequest();
$query = new PhabricatorAuditCommitQuery();
$query->needCommitData(true);
$query->needAudits(true);
$use_pager = ($this->filter != 'active');
if ($use_pager) {
$pager = new AphrontPagerView();
$pager->setURI($request->getRequestURI(), 'offset');
$pager->setOffset($request->getInt('offset'));
$query->setOffset($pager->getOffset());
$query->setLimit($pager->getPageSize() + 1);
}
switch ($this->filter) {
case 'active':
case 'author':
$query->withAuthorPHIDs(array($handle->getPHID()));
break;
case 'packagecommits':
$query->withPackagePHIDs(array($handle->getPHID()));
break;
}
switch ($this->filter) {
case 'active':
$query->withStatus(PhabricatorAuditCommitQuery::STATUS_CONCERN);
break;
default:
switch ($this->filterStatus) {
case 'open':
$query->withStatus(PhabricatorAuditCommitQuery::STATUS_OPEN);
break;
case 'concern':
$query->withStatus(PhabricatorAuditCommitQuery::STATUS_CONCERN);
break;
}
break;
}
if ($handle) {
$handle_name = $handle->getName();
} else {
$handle_name = null;
}
switch ($this->filter) {
case 'active':
$header = pht('Problem Commits');
$nodata = pht('None of your commits have open concerns.');
break;
case 'author':
$header = pht("Commits by %s", $handle_name);
$nodata = pht("No matching commits by %s.", $handle_name);
break;
case 'commits':
$header = pht("Commits");
$nodata = pht("No matching commits.");
break;
case 'packagecommits':
$header = pht("Commits in Package %s", $handle_name);
$nodata = pht("No matching commits in package %s.", $handle_name);
break;
}
$commits = $query->execute();
if ($use_pager) {
$commits = $pager->sliceResults($commits);
}
$view = new PhabricatorAuditCommitListView();
$view->setUser($request->getUser());
$view->setCommits($commits);
$view->setNoDataString($nodata);
$phids = $view->getRequiredHandlePHIDs();
$handles = $this->loadViewerHandles($phids);
$view->setHandles($handles);
$panel = new AphrontPanelView();
$panel->setHeader($header);
$panel->appendChild($view);
$panel->setNoBackground();
if ($use_pager) {
$panel->appendChild($pager);
}
return $panel;
}
}