mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 08:52:39 +01:00
Show commits in /audit/
Summary: The general idea here is to build a Differential-like dashboard which shows all the things you need to audit and all the things that other people have raised issues with, so you have a one-stop "what do I need to deal with?" interface. - Add problem commits to the "active" view of /audit/. - Add problem commits to homepage. - Add commit browsing interfaces to /audit/. - Add an "Audit" app button. Test Plan: Looked at homepage, commit filters. Audited commits, verified state changes reflected properly. Reviewers: btrahan, jungejason Reviewed By: btrahan CC: aran, epriestley Maniphest Tasks: T904 Differential Revision: https://secure.phabricator.com/D1712
This commit is contained in:
parent
4117cdbdfb
commit
f3549bb2d3
14 changed files with 646 additions and 82 deletions
|
@ -445,6 +445,8 @@ phutil_register_library_map(array(
|
|||
'PhabricatorAuditAddCommentController' => 'applications/audit/controller/addcomment',
|
||||
'PhabricatorAuditComment' => 'applications/audit/storage/auditcomment',
|
||||
'PhabricatorAuditCommentEditor' => 'applications/audit/editor/comment',
|
||||
'PhabricatorAuditCommitListView' => 'applications/audit/view/commitlist',
|
||||
'PhabricatorAuditCommitQuery' => 'applications/audit/query/commit',
|
||||
'PhabricatorAuditCommitStatusConstants' => 'applications/audit/constants/commitstatus',
|
||||
'PhabricatorAuditController' => 'applications/audit/controller/base',
|
||||
'PhabricatorAuditDAO' => 'applications/audit/storage/base',
|
||||
|
@ -1240,6 +1242,7 @@ phutil_register_library_map(array(
|
|||
'Phabricator404Controller' => 'PhabricatorController',
|
||||
'PhabricatorAuditAddCommentController' => 'PhabricatorAuditController',
|
||||
'PhabricatorAuditComment' => 'PhabricatorAuditDAO',
|
||||
'PhabricatorAuditCommitListView' => 'AphrontView',
|
||||
'PhabricatorAuditController' => 'PhabricatorController',
|
||||
'PhabricatorAuditDAO' => 'PhabricatorLiskDAO',
|
||||
'PhabricatorAuditEditController' => 'PhabricatorAuditController',
|
||||
|
|
|
@ -56,6 +56,7 @@ final class PhabricatorAuditListController extends PhabricatorAuditController {
|
|||
$message = 'Choose a project to view audits for.';
|
||||
break;
|
||||
case 'package':
|
||||
case 'packagecommits':
|
||||
$title = 'Choose a Package';
|
||||
$message = 'Choose a package to view audits for.';
|
||||
break;
|
||||
|
@ -63,79 +64,14 @@ final class PhabricatorAuditListController extends PhabricatorAuditController {
|
|||
}
|
||||
|
||||
if (!$message) {
|
||||
$pager = new AphrontPagerView();
|
||||
$pager->setURI($request->getRequestURI(), 'offset');
|
||||
|
||||
$query = new PhabricatorAuditQuery();
|
||||
$query->setOffset($pager->getOffset());
|
||||
$query->setLimit($pager->getPageSize() + 1);
|
||||
|
||||
$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);
|
||||
break;
|
||||
case 'project':
|
||||
case 'package':
|
||||
$phids = array($handle->getPHID());
|
||||
break;
|
||||
case 'all';
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown filter!");
|
||||
}
|
||||
|
||||
if ($phids) {
|
||||
$query->withAuditorPHIDs($phids);
|
||||
}
|
||||
|
||||
switch ($this->filter) {
|
||||
case 'all':
|
||||
case 'user':
|
||||
case 'project':
|
||||
case 'package':
|
||||
switch ($this->filterStatus) {
|
||||
case 'open':
|
||||
$query->withStatus(PhabricatorAuditQuery::STATUS_OPEN);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'active':
|
||||
$query->withStatus(PhabricatorAuditQuery::STATUS_OPEN);
|
||||
break;
|
||||
}
|
||||
|
||||
$audits = $query->execute();
|
||||
$audits = $pager->sliceResults($audits);
|
||||
|
||||
$view = new PhabricatorAuditListView();
|
||||
$view->setAudits($audits);
|
||||
|
||||
$phids = $view->getRequiredHandlePHIDs();
|
||||
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
|
||||
$view->setHandles($handles);
|
||||
|
||||
$panel = new AphrontPanelView();
|
||||
$panel->appendChild($view);
|
||||
$panel->setHeader('Audits');
|
||||
|
||||
$nav->appendChild($this->buildViews($handle));
|
||||
} else {
|
||||
$panel = id(new AphrontErrorView())
|
||||
->setSeverity(AphrontErrorView::SEVERITY_NODATA)
|
||||
->setTitle($title)
|
||||
->appendChild($message);
|
||||
$pager = null;
|
||||
}
|
||||
|
||||
$nav->appendChild($panel);
|
||||
$nav->appendChild($pager);
|
||||
}
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
$nav,
|
||||
|
@ -149,12 +85,18 @@ final class PhabricatorAuditListController extends PhabricatorAuditController {
|
|||
$nav->setBaseURI(new PhutilURI('/audit/view/'));
|
||||
$nav->addLabel('Active');
|
||||
$nav->addFilter('active', 'Need Attention');
|
||||
|
||||
$nav->addLabel('Audits');
|
||||
$nav->addFilter('all', 'All');
|
||||
$nav->addFilter('audits', 'All');
|
||||
$nav->addFilter('user', 'By User');
|
||||
$nav->addFilter('project', 'By Project');
|
||||
$nav->addFilter('package', 'By Package');
|
||||
|
||||
$nav->addLabel('Commits');
|
||||
$nav->addFilter('commits', 'All');
|
||||
$nav->addFilter('author', 'By User');
|
||||
$nav->addFilter('packagecommits', 'By Package');
|
||||
|
||||
$this->filter = $nav->selectFilter($this->filter, 'active');
|
||||
|
||||
return $nav;
|
||||
|
@ -173,12 +115,14 @@ final class PhabricatorAuditListController extends PhabricatorAuditController {
|
|||
$show_package = false;
|
||||
|
||||
switch ($this->filter) {
|
||||
case 'all':
|
||||
case 'audits':
|
||||
case 'commits':
|
||||
$show_status = true;
|
||||
break;
|
||||
case 'active':
|
||||
$show_user = true;
|
||||
break;
|
||||
case 'author':
|
||||
case 'user':
|
||||
$show_user = true;
|
||||
$show_status = true;
|
||||
|
@ -188,6 +132,7 @@ final class PhabricatorAuditListController extends PhabricatorAuditController {
|
|||
$show_status = true;
|
||||
break;
|
||||
case 'package':
|
||||
case 'packagecommits':
|
||||
$show_package = true;
|
||||
$show_status = true;
|
||||
break;
|
||||
|
@ -251,6 +196,7 @@ final class PhabricatorAuditListController extends PhabricatorAuditController {
|
|||
switch ($this->filter) {
|
||||
case 'user':
|
||||
case 'active':
|
||||
case 'author':
|
||||
$default = $request->getUser()->getPHID();
|
||||
break;
|
||||
}
|
||||
|
@ -272,11 +218,13 @@ final class PhabricatorAuditListController extends PhabricatorAuditController {
|
|||
switch ($this->filter) {
|
||||
case 'active':
|
||||
case 'user':
|
||||
case 'author':
|
||||
if ($handle->getType() !== PhabricatorPHIDConstants::PHID_TYPE_USER) {
|
||||
throw new Exception("PHID must be a user PHID!");
|
||||
}
|
||||
break;
|
||||
case 'package':
|
||||
case 'packagecommits':
|
||||
if ($handle->getType() !== PhabricatorPHIDConstants::PHID_TYPE_OPKG) {
|
||||
throw new Exception("PHID must be a package PHID!");
|
||||
}
|
||||
|
@ -286,11 +234,220 @@ final class PhabricatorAuditListController extends PhabricatorAuditController {
|
|||
throw new Exception("PHID must be a project PHID!");
|
||||
}
|
||||
break;
|
||||
case 'all':
|
||||
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->buildAuditView($handle);
|
||||
$views[] = $this->buildCommitView($handle);
|
||||
break;
|
||||
case 'audits':
|
||||
case 'user':
|
||||
case 'package':
|
||||
case 'project':
|
||||
$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();
|
||||
|
||||
$pager = new AphrontPagerView();
|
||||
$pager->setURI($request->getRequestURI(), 'offset');
|
||||
|
||||
$query = new PhabricatorAuditQuery();
|
||||
|
||||
if ($this->filter != 'active') {
|
||||
$query->setOffset($pager->getOffset());
|
||||
$query->setLimit($pager->getPageSize() + 1);
|
||||
}
|
||||
|
||||
$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);
|
||||
break;
|
||||
case 'project':
|
||||
case 'package':
|
||||
$phids = array($handle->getPHID());
|
||||
break;
|
||||
case 'audits';
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown filter!");
|
||||
}
|
||||
|
||||
if ($phids) {
|
||||
$query->withAuditorPHIDs($phids);
|
||||
}
|
||||
|
||||
switch ($this->filter) {
|
||||
case 'audits':
|
||||
case 'user':
|
||||
case 'project':
|
||||
case 'package':
|
||||
switch ($this->filterStatus) {
|
||||
case 'open':
|
||||
$query->withStatus(PhabricatorAuditQuery::STATUS_OPEN);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'active':
|
||||
$query->withStatus(PhabricatorAuditQuery::STATUS_OPEN);
|
||||
break;
|
||||
}
|
||||
|
||||
if ($handle) {
|
||||
$handle_name = phutil_escape_html($handle->getName());
|
||||
} else {
|
||||
$handle_name = null;
|
||||
}
|
||||
|
||||
switch ($this->filter) {
|
||||
case 'active':
|
||||
$header = 'Required Audits';
|
||||
$nodata = 'No commits require your audit.';
|
||||
break;
|
||||
case 'user':
|
||||
$header = "Audits for {$handle_name}";
|
||||
$nodata = "No matching audits by {$handle_name}.";
|
||||
break;
|
||||
case 'audits':
|
||||
$header = "Audits";
|
||||
$nodata = "No matching audits.";
|
||||
break;
|
||||
case 'project':
|
||||
$header = "Audits in Project '{$handle_name}'";
|
||||
$nodata = "No matching audits in project '{$handle_name}'.";
|
||||
break;
|
||||
case 'package':
|
||||
$header = "Audits for Package '{$handle_name}'";
|
||||
$nodata = "No matching audits in package '{$handle_name}'.";
|
||||
break;
|
||||
}
|
||||
|
||||
$audits = $query->execute();
|
||||
$audits = $pager->sliceResults($audits);
|
||||
|
||||
$view = new PhabricatorAuditListView();
|
||||
$view->setAudits($audits);
|
||||
$view->setNoDataString($nodata);
|
||||
|
||||
$phids = $view->getRequiredHandlePHIDs();
|
||||
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
|
||||
$view->setHandles($handles);
|
||||
|
||||
$panel = new AphrontPanelView();
|
||||
$panel->setHeader($header);
|
||||
$panel->appendChild($view);
|
||||
$panel->appendChild($pager);
|
||||
|
||||
return $panel;
|
||||
}
|
||||
|
||||
private function buildCommitView(PhabricatorObjectHandle $handle = null) {
|
||||
$request = $this->getRequest();
|
||||
|
||||
$pager = new AphrontPagerView();
|
||||
$pager->setURI($request->getRequestURI(), 'offset');
|
||||
|
||||
$query = new PhabricatorAuditCommitQuery();
|
||||
$query->needCommitData(true);
|
||||
|
||||
if ($this->filter != 'active') {
|
||||
$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(PhabricatorAuditQuery::STATUS_OPEN);
|
||||
break;
|
||||
case 'author':
|
||||
case 'packagecommits':
|
||||
switch ($this->filterStatus) {
|
||||
case 'open':
|
||||
$query->withStatus(PhabricatorAuditQuery::STATUS_OPEN);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ($handle) {
|
||||
$handle_name = phutil_escape_html($handle->getName());
|
||||
} else {
|
||||
$handle_name = null;
|
||||
}
|
||||
|
||||
switch ($this->filter) {
|
||||
case 'active':
|
||||
$header = 'Problem Commits';
|
||||
$nodata = 'None of your commits have open concerns.';
|
||||
break;
|
||||
case 'author':
|
||||
$header = "Commits by {$handle_name}";
|
||||
$nodata = "No matching commits by {$handle_name}.";
|
||||
break;
|
||||
case 'commits':
|
||||
$header = "Commits";
|
||||
$nodata = "No matching commits.";
|
||||
break;
|
||||
case 'packagecommits':
|
||||
$header = "Commits in Package '{$handle_name}'";
|
||||
$nodata = "No matching commits in package '{$handle_name}'.";
|
||||
break;
|
||||
}
|
||||
|
||||
$commits = $query->execute();
|
||||
$commits = $pager->sliceResults($commits);
|
||||
|
||||
$view = new PhabricatorAuditCommitListView();
|
||||
$view->setUser($request->getUser());
|
||||
$view->setCommits($commits);
|
||||
$view->setNoDataString($nodata);
|
||||
|
||||
$phids = $view->getRequiredHandlePHIDs();
|
||||
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
|
||||
$view->setHandles($handles);
|
||||
|
||||
$panel = new AphrontPanelView();
|
||||
$panel->setHeader($header);
|
||||
$panel->appendChild($view);
|
||||
$panel->appendChild($pager);
|
||||
|
||||
return $panel;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ phutil_require_module('phabricator', 'aphront/response/redirect');
|
|||
phutil_require_module('phabricator', 'applications/audit/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/audit/editor/comment');
|
||||
phutil_require_module('phabricator', 'applications/audit/query/audit');
|
||||
phutil_require_module('phabricator', 'applications/audit/query/commit');
|
||||
phutil_require_module('phabricator', 'applications/audit/view/commitlist');
|
||||
phutil_require_module('phabricator', 'applications/audit/view/list');
|
||||
phutil_require_module('phabricator', 'applications/people/storage/user');
|
||||
phutil_require_module('phabricator', 'applications/phid/constants');
|
||||
|
@ -24,6 +26,7 @@ phutil_require_module('phabricator', 'view/layout/listfilter');
|
|||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
phutil_require_module('phabricator', 'view/layout/sidenavfilter');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'parser/uri');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorAuditCommitQuery {
|
||||
|
||||
private $offset;
|
||||
private $limit;
|
||||
|
||||
private $authorPHIDs;
|
||||
private $packagePHIDs;
|
||||
private $packageConstraint;
|
||||
|
||||
private $needCommitData;
|
||||
|
||||
private $status = 'status-any';
|
||||
const STATUS_ANY = 'status-any';
|
||||
const STATUS_OPEN = 'status-open';
|
||||
|
||||
public function withAuthorPHIDs(array $author_phids) {
|
||||
$this->authorPHIDs = $author_phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withPackagePHIDs(array $phids) {
|
||||
$this->packagePHIDs = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withStatus($status) {
|
||||
$this->status = $status;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function needCommitData($need) {
|
||||
$this->needCommitData = $need;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setOffset($offset) {
|
||||
$this->offset = $offset;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setLimit($limit) {
|
||||
$this->limit = $limit;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
|
||||
if ($this->packagePHIDs) {
|
||||
|
||||
// TODO: This is an odd, awkward query plan because these rows aren't
|
||||
// on the same database as the commits. Once they're migrated we can
|
||||
// resolve this via JOIN.
|
||||
|
||||
$table = new PhabricatorOwnersPackageCommitRelationship();
|
||||
$conn_r = $table->establishConnection('r');
|
||||
$phids = queryfx_all(
|
||||
$conn_r,
|
||||
'SELECT DISTINCT commitPHID FROM %T WHERE packagePHID IN (%Ls)
|
||||
ORDER BY id DESC %Q',
|
||||
$table->getTableName(),
|
||||
$this->packagePHIDs,
|
||||
$this->buildLimitClause($conn_r));
|
||||
$this->packageConstraint = ipull($phids, 'commitPHID');
|
||||
$this->limit = null;
|
||||
$this->offset = null;
|
||||
}
|
||||
|
||||
$table = new PhabricatorRepositoryCommit();
|
||||
$conn_r = $table->establishConnection('r');
|
||||
|
||||
$where = $this->buildWhereClause($conn_r);
|
||||
$order = $this->buildOrderClause($conn_r);
|
||||
$limit = $this->buildLimitClause($conn_r);
|
||||
|
||||
$data = queryfx_all(
|
||||
$conn_r,
|
||||
'SELECT * FROM %T %Q %Q %Q',
|
||||
$table->getTableName(),
|
||||
$where,
|
||||
$order,
|
||||
$limit);
|
||||
|
||||
$commits = $table->loadAllFromArray($data);
|
||||
|
||||
if ($this->needCommitData && $commits) {
|
||||
$data = id(new PhabricatorRepositoryCommitData())->loadAllWhere(
|
||||
'commitID in (%Ld)',
|
||||
mpull($commits, 'getID'));
|
||||
$data = mpull($data, null, 'getCommitID');
|
||||
foreach ($commits as $commit) {
|
||||
if (idx($data, $commit->getID())) {
|
||||
$commit->attachCommitData($data[$commit->getID()]);
|
||||
} else {
|
||||
$commit->attachCommitData(new PhabricatorRepositoryCommitData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $commits;
|
||||
|
||||
}
|
||||
|
||||
private function buildOrderClause($conn_r) {
|
||||
return 'ORDER BY epoch DESC';
|
||||
}
|
||||
|
||||
private function buildWhereClause($conn_r) {
|
||||
$where = array();
|
||||
|
||||
if ($this->authorPHIDs) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'authorPHID IN (%Ls)',
|
||||
$this->authorPHIDs);
|
||||
}
|
||||
|
||||
if ($this->packageConstraint !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'phid IN (%Ls)',
|
||||
$this->packageConstraint);
|
||||
}
|
||||
|
||||
$status = $this->status;
|
||||
switch ($status) {
|
||||
case self::STATUS_OPEN:
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'auditStatus = %s',
|
||||
PhabricatorAuditCommitStatusConstants::CONCERN_RAISED);
|
||||
break;
|
||||
case self::STATUS_ANY:
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown status '{$status}'!");
|
||||
}
|
||||
|
||||
if ($where) {
|
||||
$where = 'WHERE ('.implode(') AND (', $where).')';
|
||||
} else {
|
||||
$where = '';
|
||||
}
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
private function buildLimitClause($conn_r) {
|
||||
if ($this->limit && $this->offset) {
|
||||
return qsprintf($conn_r, 'LIMIT %d, %d', $this->offset, $this->limit);
|
||||
} else if ($this->limit) {
|
||||
return qsprintf($conn_r, 'LIMIT %d', $this->limit);
|
||||
} else if ($this->offset) {
|
||||
return qsprintf($conn_r, 'LIMIT %d, %d', $this->offset, PHP_INT_MAX);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
19
src/applications/audit/query/commit/__init__.php
Normal file
19
src/applications/audit/query/commit/__init__.php
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/audit/constants/commitstatus');
|
||||
phutil_require_module('phabricator', 'applications/owners/storage/packagecommitrelationship');
|
||||
phutil_require_module('phabricator', 'applications/repository/storage/commit');
|
||||
phutil_require_module('phabricator', 'applications/repository/storage/commitdata');
|
||||
phutil_require_module('phabricator', 'storage/qsprintf');
|
||||
phutil_require_module('phabricator', 'storage/queryfx');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorAuditCommitQuery.php');
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorAuditCommitListView extends AphrontView {
|
||||
|
||||
private $user;
|
||||
private $commits;
|
||||
private $handles;
|
||||
private $noDataString;
|
||||
|
||||
public function setUser(PhabricatorUser $user) {
|
||||
$this->user = $user;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setNoDataString($no_data_string) {
|
||||
$this->noDataString = $no_data_string;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setCommits(array $commits) {
|
||||
$this->commits = $commits;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setHandles(array $handles) {
|
||||
$this->handles = $handles;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setAuthorityPHIDs(array $phids) {
|
||||
$this->authorityPHIDs = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRequiredHandlePHIDs() {
|
||||
$phids = array();
|
||||
foreach ($this->commits as $commit) {
|
||||
if ($commit->getAuthorPHID()) {
|
||||
$phids[$commit->getAuthorPHID()] = true;
|
||||
}
|
||||
$phids[$commit->getPHID()] = true;
|
||||
}
|
||||
return array_keys($phids);
|
||||
}
|
||||
|
||||
private function getHandle($phid) {
|
||||
$handle = idx($this->handles, $phid);
|
||||
if (!$handle) {
|
||||
throw new Exception("No handle for '{$phid}'!");
|
||||
}
|
||||
return $handle;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$rows = array();
|
||||
foreach ($this->commits as $commit) {
|
||||
$commit_name = $this->getHandle($commit->getPHID())->renderLink();
|
||||
$author_name = null;
|
||||
if ($commit->getAuthorPHID()) {
|
||||
$author_name = $this->getHandle($commit->getAuthorPHID())->renderLink();
|
||||
}
|
||||
$rows[] = array(
|
||||
$commit_name,
|
||||
$author_name,
|
||||
phutil_escape_html($commit->getCommitData()->getSummary()),
|
||||
PhabricatorAuditCommitStatusConstants::getStatusName(
|
||||
$commit->getAuditStatus()),
|
||||
phabricator_datetime($commit->getEpoch(), $this->user),
|
||||
);
|
||||
}
|
||||
|
||||
$table = new AphrontTableView($rows);
|
||||
$table->setHeaders(
|
||||
array(
|
||||
'Commit',
|
||||
'Author',
|
||||
'Summary',
|
||||
'Audit Status',
|
||||
'Date',
|
||||
));
|
||||
$table->setColumnClasses(
|
||||
array(
|
||||
'n',
|
||||
'',
|
||||
'wide',
|
||||
'',
|
||||
'',
|
||||
));
|
||||
|
||||
if ($this->noDataString) {
|
||||
$table->setNoDataString($this->noDataString);
|
||||
}
|
||||
|
||||
return $table->render();
|
||||
}
|
||||
|
||||
}
|
18
src/applications/audit/view/commitlist/__init__.php
Normal file
18
src/applications/audit/view/commitlist/__init__.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/audit/constants/commitstatus');
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
phutil_require_module('phabricator', 'view/control/table');
|
||||
phutil_require_module('phabricator', 'view/utils');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorAuditCommitListView.php');
|
|
@ -21,6 +21,7 @@ final class PhabricatorAuditListView extends AphrontView {
|
|||
private $audits;
|
||||
private $handles;
|
||||
private $authorityPHIDs = array();
|
||||
private $noDataString;
|
||||
|
||||
public function setAudits(array $audits) {
|
||||
$this->audits = $audits;
|
||||
|
@ -37,6 +38,15 @@ final class PhabricatorAuditListView extends AphrontView {
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function setNoDataString($no_data_string) {
|
||||
$this->noDataString = $no_data_string;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNoDataString() {
|
||||
return $this->noDataString;
|
||||
}
|
||||
|
||||
public function getRequiredHandlePHIDs() {
|
||||
$phids = array();
|
||||
foreach ($this->audits as $audit) {
|
||||
|
@ -112,6 +122,10 @@ final class PhabricatorAuditListView extends AphrontView {
|
|||
));
|
||||
$table->setRowClasses($rowc);
|
||||
|
||||
if ($this->noDataString) {
|
||||
$table->setNoDataString($this->noDataString);
|
||||
}
|
||||
|
||||
return $table->render();
|
||||
}
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ class PhabricatorDirectoryMainController
|
|||
$revision_panel = $this->buildRevisionPanel();
|
||||
$app_panel = $this->buildAppPanel();
|
||||
$audit_panel = $this->buildAuditPanel();
|
||||
$commit_panel = $this->buildCommitPanel();
|
||||
|
||||
$content = array(
|
||||
$app_panel,
|
||||
|
@ -87,6 +88,7 @@ class PhabricatorDirectoryMainController
|
|||
$revision_panel,
|
||||
$tasks_panel,
|
||||
$audit_panel,
|
||||
$commit_panel,
|
||||
);
|
||||
|
||||
$nav->appendChild($content);
|
||||
|
@ -577,6 +579,11 @@ class PhabricatorDirectoryMainController
|
|||
'/diffusion/',
|
||||
'diffusion');
|
||||
|
||||
$nav_buttons[] = array(
|
||||
'Audit Code',
|
||||
'/audit/',
|
||||
'audit');
|
||||
|
||||
$view = new AphrontNullView();
|
||||
$view->appendChild('<div class="phabricator-app-buttons">');
|
||||
foreach ($nav_buttons as $info) {
|
||||
|
@ -638,13 +645,9 @@ class PhabricatorDirectoryMainController
|
|||
$audits = $query->execute();
|
||||
|
||||
if (!$audits) {
|
||||
$panel = new AphrontMiniPanelView();
|
||||
$panel->appendChild(
|
||||
'<p>'.
|
||||
'<strong>No Audits:</strong> '.
|
||||
'No commits are waiting for you to audit them.'.
|
||||
'</p>');
|
||||
return $panel;
|
||||
return $this->renderMinipanel(
|
||||
'No Audits',
|
||||
'No commits are waiting for you to audit them.');
|
||||
}
|
||||
|
||||
$view = new PhabricatorAuditListView();
|
||||
|
@ -670,4 +673,48 @@ class PhabricatorDirectoryMainController
|
|||
return $panel;
|
||||
}
|
||||
|
||||
public function buildCommitPanel() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
$phids = array($user->getPHID());
|
||||
|
||||
$query = new PhabricatorAuditCommitQuery();
|
||||
$query->withAuthorPHIDs($phids);
|
||||
$query->withStatus(PhabricatorAuditQuery::STATUS_OPEN);
|
||||
$query->needCommitData(true);
|
||||
$query->setLimit(10);
|
||||
|
||||
$commits = $query->execute();
|
||||
|
||||
if (!$commits) {
|
||||
return $this->renderMinipanel(
|
||||
'No Problem Commits',
|
||||
'No one has raised concerns with your commits.');
|
||||
}
|
||||
|
||||
$view = new PhabricatorAuditCommitListView();
|
||||
$view->setCommits($commits);
|
||||
$view->setUser($user);
|
||||
|
||||
$phids = $view->getRequiredHandlePHIDs();
|
||||
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
|
||||
$view->setHandles($handles);
|
||||
|
||||
$panel = new AphrontPanelView();
|
||||
$panel->setHeader('Problem Commits');
|
||||
$panel->setCaption('Commits which auditors have raised concerns about.');
|
||||
$panel->appendChild($view);
|
||||
$panel->addButton(
|
||||
phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/audit/',
|
||||
'class' => 'button grey',
|
||||
),
|
||||
"View Problem Commits \xC2\xBB"));
|
||||
|
||||
return $panel;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||
phutil_require_module('phabricator', 'applications/audit/editor/comment');
|
||||
phutil_require_module('phabricator', 'applications/audit/query/audit');
|
||||
phutil_require_module('phabricator', 'applications/audit/query/commit');
|
||||
phutil_require_module('phabricator', 'applications/audit/view/commitlist');
|
||||
phutil_require_module('phabricator', 'applications/audit/view/list');
|
||||
phutil_require_module('phabricator', 'applications/differential/query/revision');
|
||||
phutil_require_module('phabricator', 'applications/differential/view/revisionlist');
|
||||
|
|
|
@ -218,6 +218,7 @@ class PhabricatorObjectHandle {
|
|||
public function getLinkName() {
|
||||
switch ($this->getType()) {
|
||||
case PhabricatorPHIDConstants::PHID_TYPE_USER:
|
||||
case PhabricatorPHIDConstants::PHID_TYPE_CMIT:
|
||||
$name = $this->getName();
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -265,8 +265,14 @@ class PhabricatorObjectHandleData {
|
|||
// we don't have have info about the repository anymore.
|
||||
if ($repository) {
|
||||
$vcs = $repository->getVersionControlSystem();
|
||||
if ($vcs == PhabricatorRepositoryType::REPOSITORY_TYPE_GIT) {
|
||||
$short_identifier = substr($commit_identifier, 0, 16);
|
||||
|
||||
$type_git = PhabricatorRepositoryType::REPOSITORY_TYPE_GIT;
|
||||
$type_hg = PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL;
|
||||
|
||||
$is_git = ($vcs == $type_git);
|
||||
$is_hg = ($vcs == $type_hg);
|
||||
if ($is_git || $is_hg) {
|
||||
$short_identifier = substr($commit_identifier, 0, 12);
|
||||
} else {
|
||||
$short_identifier = $commit_identifier;
|
||||
}
|
||||
|
|
|
@ -97,3 +97,7 @@ a.phabricator-button-caption:visited {
|
|||
.icon-diffusion {
|
||||
background-position: 0 -300px;
|
||||
}
|
||||
|
||||
.icon-audit {
|
||||
background-position: 0 -350px;
|
||||
}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.9 KiB |
Loading…
Reference in a new issue