1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-16 11:52:40 +01:00
phorge-phorge/src/applications/differential/customfield/DifferentialReviewersField.php
epriestley 9e3baacc95 Restore old "author can not be a reviewer" rule to Transactions
Summary:
This is a bit messy, but not tooo bad:

  - In general, stop the author from being added as a reviewer.
  - In the specific case that "self accept" is enabled, allow it. This is easier than trying to special case it.
  - When commandeering, we make the author a reviewer and make the actor the author, but these happen after validation. At validation time, it looks like we're making the author a reviewer. Just special case this.
  - Provide a slightly nicer message when trying to add yourself from `arc`. We hit the Transactions message anyway, but it's not formatted as cleanly.
  - Don't try to add the author via Herald.

Test Plan:
  - Edited a revision with author = reviewer, got stopped.
  - Commandeered revision.
  - Updated from `arc`.
  - Updated in general.
  - Fired a "add author as reviewer" Herald rule without things breaking.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: aran, epriestley

Differential Revision: https://secure.phabricator.com/D8496
2014-03-12 06:04:30 -07:00

195 lines
5 KiB
PHP

<?php
final class DifferentialReviewersField
extends DifferentialCoreCustomField {
public function getFieldKey() {
return 'differential:reviewers';
}
public function getFieldKeyForConduit() {
return 'reviewerPHIDs';
}
public function getFieldName() {
return pht('Reviewers');
}
public function getFieldDescription() {
return pht('Manage reviewers.');
}
protected function readValueFromRevision(
DifferentialRevision $revision) {
return $revision->getReviewerStatus();
}
public function getNewValueForApplicationTransactions() {
$specs = array();
foreach ($this->getValue() as $reviewer) {
$specs[$reviewer->getReviewerPHID()] = array(
'data' => $reviewer->getEdgeData(),
);
}
return array('=' => $specs);
}
public function readValueFromRequest(AphrontRequest $request) {
// Compute a new set of reviewer objects. For reviewers who haven't been
// added or removed, retain their existing status. Also, respect the new
// order.
$old_status = $this->getValue();
$old_status = mpull($old_status, null, 'getReviewerPHID');
$new_phids = $request->getArr($this->getFieldKey());
$new_phids = array_fuse($new_phids);
$new_status = array();
foreach ($new_phids as $new_phid) {
if (empty($old_status[$new_phid])) {
$new_status[$new_phid] = new DifferentialReviewer(
$new_phid,
array(
'status' => DifferentialReviewerStatus::STATUS_ADDED,
));
} else {
$new_status[$new_phid] = $old_status[$new_phid];
}
}
$this->setValue($new_status);
}
public function getRequiredHandlePHIDsForEdit() {
return mpull($this->getValue(), 'getReviewerPHID');
}
public function renderEditControl(array $handles) {
return id(new AphrontFormTokenizerControl())
->setName($this->getFieldKey())
->setDatasource('/typeahead/common/usersorprojects/')
->setValue($handles)
->setError($this->getFieldError())
->setLabel($this->getFieldName());
}
public function getApplicationTransactionType() {
return PhabricatorTransactions::TYPE_EDGE;
}
public function getApplicationTransactionMetadata() {
return array(
'edge:type' => PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER,
);
}
public function shouldAppearInPropertyView() {
return true;
}
public function renderPropertyViewLabel() {
return $this->getFieldName();
}
public function getRequiredHandlePHIDsForPropertyView() {
return mpull($this->getUserReviewers(), 'getReviewerPHID');
}
public function renderPropertyViewValue(array $handles) {
$reviewers = $this->getUserReviewers();
if (!$reviewers) {
return phutil_tag('em', array(), pht('None'));
}
$view = id(new DifferentialReviewersView())
->setUser($this->getViewer())
->setReviewers($reviewers)
->setHandles($handles);
// TODO: Active diff stuff.
return $view;
}
private function getUserReviewers() {
$reviewers = array();
foreach ($this->getObject()->getReviewerStatus() as $reviewer) {
if ($reviewer->isUser()) {
$reviewers[] = $reviewer;
}
}
return $reviewers;
}
public function shouldAppearInCommitMessage() {
return true;
}
public function shouldAppearInCommitMessageTemplate() {
return true;
}
public function getCommitMessageLabels() {
return array(
'Reviewer',
'Reviewers',
);
}
public function parseValueFromCommitMessage($value) {
return $this->parseObjectList(
$value,
array(
PhabricatorPeoplePHIDTypeUser::TYPECONST,
PhabricatorProjectPHIDTypeProject::TYPECONST,
));
}
public function getRequiredHandlePHIDsForCommitMessage() {
return mpull($this->getValue(), 'getReviewerPHID');
}
public function readValueFromCommitMessage($value) {
$current_reviewers = $this->getObject()->getReviewerStatus();
$current_reviewers = mpull($current_reviewers, null, 'getReviewerPHID');
$reviewers = array();
foreach ($value as $phid) {
$reviewer = idx($current_reviewers, $phid);
if ($reviewer) {
$reviewers[] = $reviewer;
} else {
$data = array(
'status' => DifferentialReviewerStatus::STATUS_ADDED,
);
$reviewers[] = new DifferentialReviewer($phid, $data);
}
}
$this->setValue($reviewers);
return $this;
}
public function renderCommitMessageValue(array $handles) {
return $this->renderObjectList($handles);
}
public function validateCommitMessageValue($value) {
$author_phid = $this->getObject()->getAuthorPHID();
$config_self_accept_key = 'differential.allow-self-accept';
$allow_self_accept = PhabricatorEnv::getEnvConfig($config_self_accept_key);
foreach ($value as $phid) {
if (($phid == $author_phid) && !$allow_self_accept) {
throw new DifferentialFieldValidationException(
pht('The author of a revision can not be a reviewer.'));
}
}
}
}