1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-23 22:10:55 +01:00

Add "Resign from Audit" and "Close Audit" actions to Diffusion

Summary:
See some discussion in D2002. Add two new actions:

  - Resign: (auditor only) closes your open request (user request ONLY) by putting it in a "resigned" state.
  - Close: (author only) closes all open requests by putting them in a "closed" state.

@davidreuss, this is probably conflict-city with D2002 -- I'll wait for you to land first and then handle the merge on my end.

Test Plan: Resigned from and closed audits.

Reviewers: 20after4, davidreuss, btrahan

Reviewed By: btrahan

CC: aran, epriestley

Maniphest Tasks: T904

Differential Revision: https://secure.phabricator.com/D2013
This commit is contained in:
epriestley 2012-03-26 09:44:06 -07:00
parent 638627cea5
commit 2044e51206
13 changed files with 339 additions and 86 deletions

View file

@ -21,33 +21,35 @@ final class PhabricatorAuditActionConstants {
const CONCERN = 'concern'; const CONCERN = 'concern';
const ACCEPT = 'accept'; const ACCEPT = 'accept';
const COMMENT = 'comment'; const COMMENT = 'comment';
const RESIGN = 'resign';
const CLOSE = 'close';
public static function getActionNameMap() { public static function getActionNameMap() {
static $map = array( static $map = array(
self::COMMENT => 'Comment', self::COMMENT => 'Comment',
self::CONCERN => 'Raise Concern', self::CONCERN => 'Raise Concern',
self::ACCEPT => 'Accept Commit', self::ACCEPT => 'Accept Commit',
self::RESIGN => 'Resign from Audit',
self::CLOSE => 'Close Audit',
); );
return $map; return $map;
} }
public static function getActionName($constant) {
$map = self::getActionNameMap();
return idx($map, $constant, 'Unknown');
}
public static function getActionPastTenseVerb($action) { public static function getActionPastTenseVerb($action) {
static $map = array( static $map = array(
self::COMMENT => 'commented on', self::COMMENT => 'commented on',
self::CONCERN => 'raised a concern with', self::CONCERN => 'raised a concern with',
self::ACCEPT => 'accepted', self::ACCEPT => 'accepted',
self::RESIGN => 'resigned from',
self::CLOSE => 'closed',
); );
return idx($map, $action, 'updated'); return idx($map, $action, 'updated');
} }
public static function getStatusNameMap() {
static $map = array(
self::CONCERN => PhabricatorAuditStatusConstants::CONCERNED,
self::ACCEPT => PhabricatorAuditStatusConstants::ACCEPTED,
);
return $map;
}
} }

View file

@ -6,8 +6,6 @@
phutil_require_module('phabricator', 'applications/audit/constants/status');
phutil_require_module('phutil', 'utils'); phutil_require_module('phutil', 'utils');

View file

@ -24,6 +24,8 @@ final class PhabricatorAuditStatusConstants {
const CONCERNED = 'concerned'; const CONCERNED = 'concerned';
const ACCEPTED = 'accepted'; const ACCEPTED = 'accepted';
const AUDIT_REQUESTED = 'requested'; const AUDIT_REQUESTED = 'requested';
const RESIGNED = 'resigned';
const CLOSED = 'closed';
public static function getStatusNameMap() { public static function getStatusNameMap() {
static $map = array( static $map = array(
@ -33,6 +35,8 @@ final class PhabricatorAuditStatusConstants {
self::CONCERNED => 'Concern Raised', self::CONCERNED => 'Concern Raised',
self::ACCEPTED => 'Accepted', self::ACCEPTED => 'Accepted',
self::AUDIT_REQUESTED => 'Audit Requested', self::AUDIT_REQUESTED => 'Audit Requested',
self::RESIGNED => 'Resigned',
self::CLOSED => 'Closed',
); );
return $map; return $map;
@ -42,4 +46,16 @@ final class PhabricatorAuditStatusConstants {
return idx(self::getStatusNameMap(), $code, 'Unknown'); return idx(self::getStatusNameMap(), $code, 'Unknown');
} }
public static function getOpenStatusConstants() {
return array(
self::AUDIT_REQUIRED,
self::AUDIT_REQUESTED,
self::CONCERNED,
);
}
public static function isOpenStatus($status) {
return in_array($status, self::getOpenStatusConstants());
}
} }

View file

@ -301,6 +301,8 @@ final class PhabricatorAuditListController extends PhabricatorAuditController {
$query->setLimit($pager->getPageSize() + 1); $query->setLimit($pager->getPageSize() + 1);
} }
$awaiting = null;
$phids = null; $phids = null;
switch ($this->filter) { switch ($this->filter) {
case 'user': case 'user':
@ -312,6 +314,7 @@ final class PhabricatorAuditListController extends PhabricatorAuditController {
throw new Exception("Invalid user!"); throw new Exception("Invalid user!");
} }
$phids = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($obj); $phids = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($obj);
$awaiting = $obj;
break; break;
case 'project': case 'project':
case 'package': case 'package':
@ -327,6 +330,10 @@ final class PhabricatorAuditListController extends PhabricatorAuditController {
$query->withAuditorPHIDs($phids); $query->withAuditorPHIDs($phids);
} }
if ($awaiting) {
$query->withAwaitingUser($awaiting);
}
switch ($this->filter) { switch ($this->filter) {
case 'audits': case 'audits':
case 'user': case 'user':

View file

@ -83,37 +83,103 @@ final class PhabricatorAuditCommentEditor {
$commit->getPHID()); $commit->getPHID());
$action = $comment->getAction(); $action = $comment->getAction();
$status_map = PhabricatorAuditActionConstants::getStatusNameMap();
$status = idx($status_map, $action, null);
// Status may be empty for updates which don't affect status, like
// "comment". // TODO: We should validate the action, currently we allow anyone to, e.g.,
// close an audit if they muck with form parameters. I'll followup with this
// and handle the no-effect cases (e.g., closing and already-closed audit).
$user_is_author = ($user->getPHID() == $commit->getAuthorPHID());
if ($action == PhabricatorAuditActionConstants::CLOSE) {
// "Close" means wipe out all the concerns.
$concerned_status = PhabricatorAuditStatusConstants::CONCERNED;
foreach ($requests as $request) {
if ($request->getAuditStatus() == $concerned_status) {
$request->setAuditStatus(PhabricatorAuditStatusConstants::CLOSED);
$request->save();
}
}
} else {
$have_any_requests = false; $have_any_requests = false;
foreach ($requests as $request) { foreach ($requests as $request) {
if (empty($audit_phids[$request->getAuditorPHID()])) { if (empty($audit_phids[$request->getAuditorPHID()])) {
continue; continue;
} }
$request_is_for_user = ($request->getAuditorPHID() == $user->getPHID());
$have_any_requests = true; $have_any_requests = true;
if ($status) { $new_status = null;
$request->setAuditStatus($status); switch ($action) {
case PhabricatorAuditActionConstants::COMMENT:
// Comments don't change audit statuses.
break;
case PhabricatorAuditActionConstants::ACCEPT:
if (!$user_is_author || $request_is_for_user) {
// When modifying your own commits, you act only on behalf of
// yourself, not your packages/projects -- the idea being that
// you can't accept your own commits.
$new_status = PhabricatorAuditStatusConstants::ACCEPTED;
}
break;
case PhabricatorAuditActionConstants::CONCERN:
if (!$user_is_author || $request_is_for_user) {
// See above.
$new_status = PhabricatorAuditStatusConstants::CONCERNED;
}
break;
case PhabricatorAuditActionConstants::RESIGN:
// NOTE: Resigning resigns ONLY your user request, not the requests
// of any projects or packages you are a member of.
if ($request_is_for_user) {
$new_status = PhabricatorAuditStatusConstants::RESIGNED;
}
break;
default:
throw new Exception("Unknown action '{$action}'!");
}
if ($new_status !== null) {
$request->setAuditStatus($new_status);
$request->save(); $request->save();
} }
} }
if (!$have_any_requests) {
// If the user has no current authority over any audit trigger, make a // If the user has no current authority over any audit trigger, make a
// new one to represent their audit state. // new one to represent their audit state.
if (!$have_any_requests) {
$new_status = null;
switch ($action) {
case PhabricatorAuditActionConstants::COMMENT:
$new_status = PhabricatorAuditStatusConstants::AUDIT_NOT_REQUIRED;
break;
case PhabricatorAuditActionConstants::ACCEPT:
$new_status = PhabricatorAuditStatusConstants::ACCEPTED;
break;
case PhabricatorAuditActionConstants::CONCERN:
$new_status = PhabricatorAuditStatusConstants::CONCERNED;
break;
case PhabricatorAuditActionConstants::RESIGN:
// If you're on an audit because of a package, we write an explicit
// resign row to remove it from your queue.
$new_status = PhabricatorAuditStatusConstants::RESIGNED;
break;
case PhabricatorAuditActionConstants::CLOSE:
// Impossible to reach this block with 'close'.
default:
throw new Exception("Unknown or invalid action '{$action}'!");
}
$request = id(new PhabricatorRepositoryAuditRequest()) $request = id(new PhabricatorRepositoryAuditRequest())
->setCommitPHID($commit->getPHID()) ->setCommitPHID($commit->getPHID())
->setAuditorPHID($user->getPHID()) ->setAuditorPHID($user->getPHID())
->setAuditStatus( ->setAuditStatus($new_status)
$status
? $status
: PhabricatorAuditStatusConstants::AUDIT_NOT_REQUIRED)
->setAuditReasons(array("Voluntary Participant")) ->setAuditReasons(array("Voluntary Participant"))
->save(); ->save();
$requests[] = $request; $requests[] = $request;
} }
}
$commit->updateAuditStatus($requests); $commit->updateAuditStatus($requests);
$commit->save(); $commit->save();
@ -206,6 +272,8 @@ final class PhabricatorAuditCommentEditor {
$map = array( $map = array(
PhabricatorAuditActionConstants::CONCERN => 'Raised Concern', PhabricatorAuditActionConstants::CONCERN => 'Raised Concern',
PhabricatorAuditActionConstants::ACCEPT => 'Accepted', PhabricatorAuditActionConstants::ACCEPT => 'Accepted',
PhabricatorAuditActionConstants::RESIGN => 'Resigned',
PhabricatorAuditActionConstants::CLOSE => 'Closed',
); );
$verb = idx($map, $comment->getAction(), 'Commented On'); $verb = idx($map, $comment->getAction(), 'Commented On');

View file

@ -27,6 +27,8 @@ final class PhabricatorAuditQuery {
private $needCommits; private $needCommits;
private $needCommitData; private $needCommitData;
private $awaitingUser;
private $status = 'status-any'; private $status = 'status-any';
const STATUS_ANY = 'status-any'; const STATUS_ANY = 'status-any';
const STATUS_OPEN = 'status-open'; const STATUS_OPEN = 'status-open';
@ -43,6 +45,11 @@ final class PhabricatorAuditQuery {
return $this; return $this;
} }
public function withAwaitingUser(PhabricatorUser $user) {
$this->awaitingUser = $user;
return $this;
}
public function withStatus($status) { public function withStatus($status) {
$this->status = $status; $this->status = $status;
return $this; return $this;
@ -72,14 +79,16 @@ final class PhabricatorAuditQuery {
$table = new PhabricatorRepositoryAuditRequest(); $table = new PhabricatorRepositoryAuditRequest();
$conn_r = $table->establishConnection('r'); $conn_r = $table->establishConnection('r');
$joins = $this->buildJoinClause($conn_r);
$where = $this->buildWhereClause($conn_r); $where = $this->buildWhereClause($conn_r);
$order = $this->buildOrderClause($conn_r); $order = $this->buildOrderClause($conn_r);
$limit = $this->buildLimitClause($conn_r); $limit = $this->buildLimitClause($conn_r);
$data = queryfx_all( $data = queryfx_all(
$conn_r, $conn_r,
'SELECT * FROM %T %Q %Q %Q', 'SELECT req.* FROM %T req %Q %Q %Q %Q',
$table->getTableName(), $table->getTableName(),
$joins,
$where, $where,
$order, $order,
$limit); $limit);
@ -112,34 +121,77 @@ final class PhabricatorAuditQuery {
return $this->commits; return $this->commits;
} }
private function buildJoinClause($conn_r) {
$joins = array();
if ($this->awaitingUser) {
// Join the request table on the awaiting user's requests, so we can
// filter out package and project requests which the user has resigned
// from.
$joins[] = qsprintf(
$conn_r,
'LEFT JOIN %T awaiting ON req.commitPHID = awaiting.commitPHID AND
awaiting.auditorPHID = %s',
id(new PhabricatorRepositoryAuditRequest())->getTableName(),
$this->awaitingUser->getPHID());
// Join the commit table so we can get the commit author into the result
// row and filter by it later.
$joins[] = qsprintf(
$conn_r,
'JOIN %T commit ON req.commitPHID = commit.phid',
id(new PhabricatorRepositoryCommit())->getTableName());
}
if ($joins) {
return implode(' ', $joins);
} else {
return '';
}
}
private function buildWhereClause($conn_r) { private function buildWhereClause($conn_r) {
$where = array(); $where = array();
if ($this->commitPHIDs) { if ($this->commitPHIDs) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn_r,
'commitPHID IN (%Ls)', 'req.commitPHID IN (%Ls)',
$this->commitPHIDs); $this->commitPHIDs);
} }
if ($this->auditorPHIDs) { if ($this->auditorPHIDs) {
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn_r,
'auditorPHID IN (%Ls)', 'req.auditorPHID IN (%Ls)',
$this->auditorPHIDs); $this->auditorPHIDs);
} }
if ($this->awaitingUser) {
// Exclude package and project audits associated with commits where
// the user is the author.
$where[] = qsprintf(
$conn_r,
'(commit.authorPHID IS NULL OR commit.authorPHID != %s)
OR (req.auditorPHID = %s)',
$this->awaitingUser->getPHID(),
$this->awaitingUser->getPHID());
}
$status = $this->status; $status = $this->status;
switch ($status) { switch ($status) {
case self::STATUS_OPEN: case self::STATUS_OPEN:
$where[] = qsprintf( $where[] = qsprintf(
$conn_r, $conn_r,
'auditStatus in (%Ls)', 'req.auditStatus in (%Ls)',
array( PhabricatorAuditStatusConstants::getOpenStatusConstants());
PhabricatorAuditStatusConstants::AUDIT_REQUIRED, if ($this->awaitingUser) {
PhabricatorAuditStatusConstants::CONCERNED, $where[] = qsprintf(
PhabricatorAuditStatusConstants::AUDIT_REQUESTED, $conn_r,
)); 'awaiting.auditStatus IS NULL OR awaiting.auditStatus != %s',
PhabricatorAuditStatusConstants::RESIGNED);
}
break; break;
case self::STATUS_ANY: case self::STATUS_ANY:
break; break;
@ -169,7 +221,7 @@ final class PhabricatorAuditQuery {
} }
private function buildOrderClause($conn_r) { private function buildOrderClause($conn_r) {
return 'ORDER BY id DESC'; return 'ORDER BY req.id DESC';
} }
} }

View file

@ -9,6 +9,7 @@
phutil_require_module('phabricator', 'applications/audit/constants/status'); phutil_require_module('phabricator', 'applications/audit/constants/status');
phutil_require_module('phabricator', 'applications/audit/query/commit'); phutil_require_module('phabricator', 'applications/audit/query/commit');
phutil_require_module('phabricator', 'applications/repository/storage/auditrequest'); phutil_require_module('phabricator', 'applications/repository/storage/auditrequest');
phutil_require_module('phabricator', 'applications/repository/storage/commit');
phutil_require_module('phabricator', 'storage/qsprintf'); phutil_require_module('phabricator', 'storage/qsprintf');
phutil_require_module('phabricator', 'storage/queryfx'); phutil_require_module('phabricator', 'storage/queryfx');

View file

@ -23,6 +23,8 @@ final class PhabricatorAuditListView extends AphrontView {
private $authorityPHIDs = array(); private $authorityPHIDs = array();
private $noDataString; private $noDataString;
private $commits; private $commits;
private $user;
private $showDescriptions = true;
public function setAudits(array $audits) { public function setAudits(array $audits) {
$this->audits = $audits; $this->audits = $audits;
@ -53,6 +55,16 @@ final class PhabricatorAuditListView extends AphrontView {
return $this; return $this;
} }
public function setUser(PhabricatorUser $user) {
$this->user = $user;
return $this;
}
public function setShowDescriptions($show_descriptions) {
$this->showDescriptions = $show_descriptions;
return $this;
}
public function getRequiredHandlePHIDs() { public function getRequiredHandlePHIDs() {
$phids = array(); $phids = array();
foreach ($this->audits as $audit) { foreach ($this->audits as $audit) {
@ -84,6 +96,7 @@ final class PhabricatorAuditListView extends AphrontView {
} }
public function render() { public function render() {
$user = $this->user;
$authority = array_fill_keys($this->authorityPHIDs, true); $authority = array_fill_keys($this->authorityPHIDs, true);
@ -120,13 +133,26 @@ final class PhabricatorAuditListView extends AphrontView {
$reasons, $reasons,
); );
if (empty($authority[$audit->getAuditorPHID()])) { $row_class = null;
$rowc[] = null;
} else { $has_authority = !empty($authority[$audit->getAuditorPHID()]);
$rowc[] = 'highlighted'; if ($has_authority) {
$commit_author = $this->commits[$commit_phid]->getAuthorPHID();
// You don't have authority over package and project audits on your own
// commits.
$auditor_is_user = ($audit->getAuditorPHID() == $user->getPHID());
$user_is_author = ($commit_author == $user->getPHID());
if ($auditor_is_user || !$user_is_author) {
$row_class = 'highlighted';
} }
} }
$rowc[] = $row_class;
}
$table = new AphrontTableView($rows); $table = new AphrontTableView($rows);
$table->setHeaders( $table->setHeaders(
array( array(
@ -139,16 +165,16 @@ final class PhabricatorAuditListView extends AphrontView {
$table->setColumnClasses( $table->setColumnClasses(
array( array(
'pri', 'pri',
(($this->commits === null) ? '' : 'wide'), ($this->showDescriptions ? 'wide' : ''),
'', '',
'', '',
(($this->commits === null) ? 'wide' : ''), ($this->showDescriptions ? '' : 'wide'),
)); ));
$table->setRowClasses($rowc); $table->setRowClasses($rowc);
$table->setColumnVisibility( $table->setColumnVisibility(
array( array(
true, $this->showDescriptions,
($this->commits !== null), $this->showDescriptions,
true, true,
true, true,
true, true,

View file

@ -20,6 +20,8 @@ final class DiffusionCommitController extends DiffusionController {
const CHANGES_LIMIT = 100; const CHANGES_LIMIT = 100;
private $auditAuthorityPHIDs;
public function willProcessRequest(array $data) { public function willProcessRequest(array $data) {
// This controller doesn't use blob/path stuff, just pass the dictionary // This controller doesn't use blob/path stuff, just pass the dictionary
// in directly instead of using the AphrontRequest parsing mechanism. // in directly instead of using the AphrontRequest parsing mechanism.
@ -50,6 +52,7 @@ final class DiffusionCommitController extends DiffusionController {
} }
$commit_data = $drequest->loadCommitData(); $commit_data = $drequest->loadCommitData();
$commit->attachCommitData($commit_data);
$is_foreign = $commit_data->getCommitDetail('foreign-svn-stub'); $is_foreign = $commit_data->getCommitDetail('foreign-svn-stub');
if ($is_foreign) { if ($is_foreign) {
@ -93,7 +96,14 @@ final class DiffusionCommitController extends DiffusionController {
$content[] = $detail_panel; $content[] = $detail_panel;
} }
$content[] = $this->buildAuditTable($commit); $query = new PhabricatorAuditQuery();
$query->withCommitPHIDs(array($commit->getPHID()));
$audit_requests = $query->execute();
$this->auditAuthorityPHIDs =
PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($user);
$content[] = $this->buildAuditTable($commit, $audit_requests);
$content[] = $this->buildComments($commit); $content[] = $this->buildComments($commit);
$change_query = DiffusionPathChangeQuery::newFromDiffusionRequest( $change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(
@ -247,7 +257,7 @@ final class DiffusionCommitController extends DiffusionController {
$content[] = $change_list; $content[] = $change_list;
} }
$content[] = $this->buildAddCommentView($commit); $content[] = $this->buildAddCommentView($commit, $audit_requests);
return $this->buildStandardPageResponse( return $this->buildStandardPageResponse(
$content, $content,
@ -331,21 +341,19 @@ final class DiffusionCommitController extends DiffusionController {
'</table>'; '</table>';
} }
private function buildAuditTable($commit) { private function buildAuditTable($commit, $audits) {
$user = $this->getRequest()->getUser(); $user = $this->getRequest()->getUser();
$query = new PhabricatorAuditQuery();
$query->withCommitPHIDs(array($commit->getPHID()));
$audits = $query->execute();
$view = new PhabricatorAuditListView(); $view = new PhabricatorAuditListView();
$view->setAudits($audits); $view->setAudits($audits);
$view->setCommits(array($commit));
$view->setUser($user);
$view->setShowDescriptions(false);
$phids = $view->getRequiredHandlePHIDs(); $phids = $view->getRequiredHandlePHIDs();
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
$view->setHandles($handles); $view->setHandles($handles);
$view->setAuthorityPHIDs( $view->setAuthorityPHIDs($this->auditAuthorityPHIDs);
PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($user));
$panel = new AphrontPanelView(); $panel = new AphrontPanelView();
$panel->setHeader('Audits'); $panel->setHeader('Audits');
@ -387,7 +395,7 @@ final class DiffusionCommitController extends DiffusionController {
return $view; return $view;
} }
private function buildAddCommentView($commit) { private function buildAddCommentView($commit, array $audit_requests) {
$user = $this->getRequest()->getUser(); $user = $this->getRequest()->getUser();
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
@ -409,6 +417,8 @@ final class DiffusionCommitController extends DiffusionController {
$draft = null; $draft = null;
} }
$actions = $this->getAuditActions($commit, $audit_requests);
$form = id(new AphrontFormView()) $form = id(new AphrontFormView())
->setUser($user) ->setUser($user)
->setAction('/audit/addcomment/') ->setAction('/audit/addcomment/')
@ -418,7 +428,7 @@ final class DiffusionCommitController extends DiffusionController {
->setLabel('Action') ->setLabel('Action')
->setName('action') ->setName('action')
->setID('audit-action') ->setID('audit-action')
->setOptions(PhabricatorAuditActionConstants::getActionNameMap())) ->setOptions($actions))
->appendChild( ->appendChild(
id(new AphrontFormTextAreaControl()) id(new AphrontFormTextAreaControl())
->setLabel('Comments') ->setLabel('Comments')
@ -466,6 +476,80 @@ final class DiffusionCommitController extends DiffusionController {
return $view; return $view;
} }
/**
* Return a map of available audit actions for rendering into a <select />.
* This shows the user valid actions, and does not show nonsense/invalid
* actions (like closing an already-closed commit, or resigning from a commit
* you have no association with).
*/
private function getAuditActions(
PhabricatorRepositoryCommit $commit,
array $audit_requests) {
$user = $this->getRequest()->getUser();
$user_is_author = ($commit->getAuthorPHID() == $user->getPHID());
$user_request = null;
foreach ($audit_requests as $audit_request) {
if ($audit_request->getAuditorPHID() == $user->getPHID()) {
$user_request = $audit_request;
break;
}
}
$actions = array();
$actions[PhabricatorAuditActionConstants::COMMENT] = true;
// We allow you to accept your own commits. A use case here is that you
// notice an issue with your own commit and "Raise Concern" as an indicator
// to other auditors that you're on top of the issue, then later resolve it
// and "Accept". You can not accept on behalf of projects or packages,
// however.
$actions[PhabricatorAuditActionConstants::ACCEPT] = true;
$actions[PhabricatorAuditActionConstants::CONCERN] = true;
// To resign, a user must have authority on some request and not be the
// commit's author.
if (!$user_is_author) {
$may_resign = false;
foreach ($audit_requests as $request) {
if (empty($this->auditAuthorityPHIDs[$request->getAuditorPHID()])) {
continue;
}
$may_resign = true;
break;
}
// If the user has already resigned, don't show "Resign...".
$status_resigned = PhabricatorAuditStatusConstants::RESIGNED;
if ($user_request) {
if ($user_request->getAuditStatus() == $status_resigned) {
$may_resign = false;
}
}
if ($may_resign) {
$actions[PhabricatorAuditActionConstants::RESIGN] = true;
}
}
$status_concern = PhabricatorAuditCommitStatusConstants::CONCERN_RAISED;
$concern_raised = ($commit->getAuditStatus() == $status_concern);
if ($user_is_author && $concern_raised) {
$actions[PhabricatorAuditActionConstants::CLOSE] = true;
}
foreach ($actions as $constant => $ignored) {
$actions[$constant] =
PhabricatorAuditActionConstants::getActionName($constant);
}
return $actions;
}
private function buildMergesTable(PhabricatorRepositoryCommit $commit) { private function buildMergesTable(PhabricatorRepositoryCommit $commit) {
$drequest = $this->getDiffusionRequest(); $drequest = $this->getDiffusionRequest();

View file

@ -8,6 +8,7 @@
phutil_require_module('phabricator', 'applications/audit/constants/action'); phutil_require_module('phabricator', 'applications/audit/constants/action');
phutil_require_module('phabricator', 'applications/audit/constants/commitstatus'); phutil_require_module('phabricator', 'applications/audit/constants/commitstatus');
phutil_require_module('phabricator', 'applications/audit/constants/status');
phutil_require_module('phabricator', 'applications/audit/editor/comment'); phutil_require_module('phabricator', 'applications/audit/editor/comment');
phutil_require_module('phabricator', 'applications/audit/query/audit'); phutil_require_module('phabricator', 'applications/audit/query/audit');
phutil_require_module('phabricator', 'applications/audit/storage/auditcomment'); phutil_require_module('phabricator', 'applications/audit/storage/auditcomment');

View file

@ -110,19 +110,11 @@ final class DiffusionCommentView extends AphrontView {
$author = $this->getHandle($comment->getActorPHID()); $author = $this->getHandle($comment->getActorPHID());
$author_link = $author->renderLink(); $author_link = $author->renderLink();
$action = $comment->getAction();
$verb = PhabricatorAuditActionConstants::getActionPastTenseVerb($action);
$actions = array(); $actions = array();
switch ($comment->getAction()) { $actions[] = "{$author_link} ".phutil_escape_html($verb)." this commit.";
case PhabricatorAuditActionConstants::ACCEPT:
$actions[] = "{$author_link} accepted this commit.";
break;
case PhabricatorAuditActionConstants::CONCERN:
$actions[] = "{$author_link} raised concerns with this commit.";
break;
case PhabricatorAuditActionConstants::COMMENT:
default:
$actions[] = "{$author_link} commented on this commit.";
break;
}
foreach ($actions as $key => $action) { foreach ($actions as $key => $action) {
$actions[$key] = '<div>'.$action.'</div>'; $actions[$key] = '<div>'.$action.'</div>';
@ -135,12 +127,16 @@ final class DiffusionCommentView extends AphrontView {
$comment = $this->comment; $comment = $this->comment;
$engine = $this->getEngine(); $engine = $this->getEngine();
if (!strlen($comment->getContent())) {
return null;
} else {
return return
'<div class="phabricator-remarkup">'. '<div class="phabricator-remarkup">'.
$engine->markupText($comment->getContent()). $engine->markupText($comment->getContent()).
$this->renderSingleView($this->renderInlines()). $this->renderSingleView($this->renderInlines()).
'</div>'; '</div>';
} }
}
private function renderInlines() { private function renderInlines() {
if (!$this->inlineComments) { if (!$this->inlineComments) {

View file

@ -12,6 +12,7 @@ phutil_require_module('phabricator', 'infrastructure/diff/view/inline');
phutil_require_module('phabricator', 'view/base'); phutil_require_module('phabricator', 'view/base');
phutil_require_module('phabricator', 'view/layout/transaction'); phutil_require_module('phabricator', 'view/layout/transaction');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils'); phutil_require_module('phutil', 'utils');

View file

@ -576,6 +576,7 @@ final class PhabricatorDirectoryMainController
$query = new PhabricatorAuditQuery(); $query = new PhabricatorAuditQuery();
$query->withAuditorPHIDs($phids); $query->withAuditorPHIDs($phids);
$query->withStatus(PhabricatorAuditQuery::STATUS_OPEN); $query->withStatus(PhabricatorAuditQuery::STATUS_OPEN);
$query->withAwaitingUser($user);
$query->needCommitData(true); $query->needCommitData(true);
$query->setLimit(10); $query->setLimit(10);