2014-02-21 20:54:32 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
final class DifferentialReviewersField
|
|
|
|
extends DifferentialCoreCustomField {
|
|
|
|
|
|
|
|
public function getFieldKey() {
|
|
|
|
return 'differential:reviewers';
|
|
|
|
}
|
|
|
|
|
2014-03-08 02:05:00 +01:00
|
|
|
public function getFieldKeyForConduit() {
|
|
|
|
return 'reviewerPHIDs';
|
|
|
|
}
|
|
|
|
|
2014-02-21 20:54:32 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2015-03-31 23:10:55 +02:00
|
|
|
public function renderEditControl(array $handles) {
|
2014-10-13 21:57:08 +02:00
|
|
|
$phids = array();
|
|
|
|
if ($this->getValue()) {
|
|
|
|
$phids = mpull($this->getValue(), 'getReviewerPHID');
|
|
|
|
}
|
2014-02-21 20:54:32 +01:00
|
|
|
|
|
|
|
return id(new AphrontFormTokenizerControl())
|
2015-03-31 23:10:55 +02:00
|
|
|
->setUser($this->getViewer())
|
2014-02-21 20:54:32 +01:00
|
|
|
->setName($this->getFieldKey())
|
2014-07-18 00:45:07 +02:00
|
|
|
->setDatasource(new PhabricatorProjectOrUserDatasource())
|
2015-03-31 23:10:55 +02:00
|
|
|
->setValue($phids)
|
2014-02-21 20:54:32 +01:00
|
|
|
->setError($this->getFieldError())
|
|
|
|
->setLabel($this->getFieldName());
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getApplicationTransactionType() {
|
|
|
|
return PhabricatorTransactions::TYPE_EDGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getApplicationTransactionMetadata() {
|
|
|
|
return array(
|
2015-01-01 04:43:26 +01:00
|
|
|
'edge:type' => DifferentialRevisionHasReviewerEdgeType::EDGECONST,
|
2014-02-21 20:54:32 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2014-02-26 23:46:18 +01:00
|
|
|
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;
|
|
|
|
}
|
2014-03-08 02:05:00 +01:00
|
|
|
|
|
|
|
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(
|
2014-07-24 00:05:46 +02:00
|
|
|
PhabricatorPeopleUserPHIDType::TYPECONST,
|
|
|
|
PhabricatorProjectProjectPHIDType::TYPECONST,
|
2014-03-08 02:05:00 +01:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getRequiredHandlePHIDsForCommitMessage() {
|
|
|
|
return mpull($this->getValue(), 'getReviewerPHID');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function readValueFromCommitMessage($value) {
|
2014-03-12 01:12:47 +01:00
|
|
|
$current_reviewers = $this->getObject()->getReviewerStatus();
|
|
|
|
$current_reviewers = mpull($current_reviewers, null, 'getReviewerPHID');
|
|
|
|
|
2014-03-08 02:05:00 +01:00
|
|
|
$reviewers = array();
|
|
|
|
foreach ($value as $phid) {
|
2014-03-12 01:12:47 +01:00
|
|
|
$reviewer = idx($current_reviewers, $phid);
|
|
|
|
if ($reviewer) {
|
|
|
|
$reviewers[] = $reviewer;
|
|
|
|
} else {
|
|
|
|
$data = array(
|
|
|
|
'status' => DifferentialReviewerStatus::STATUS_ADDED,
|
|
|
|
);
|
|
|
|
$reviewers[] = new DifferentialReviewer($phid, $data);
|
|
|
|
}
|
2014-03-08 02:05:00 +01:00
|
|
|
}
|
2014-03-12 01:12:47 +01:00
|
|
|
|
2014-03-08 02:05:00 +01:00
|
|
|
$this->setValue($reviewers);
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function renderCommitMessageValue(array $handles) {
|
|
|
|
return $this->renderObjectList($handles);
|
|
|
|
}
|
|
|
|
|
2014-03-12 14:04:30 +01:00
|
|
|
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.'));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-02 13:58:51 +02:00
|
|
|
public function getRequiredHandlePHIDsForRevisionHeaderWarnings() {
|
|
|
|
return mpull($this->getValue(), 'getReviewerPHID');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getWarningsForRevisionHeader(array $handles) {
|
|
|
|
$revision = $this->getObject();
|
|
|
|
|
|
|
|
$status_needs_review = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW;
|
|
|
|
if ($revision->getStatus() != $status_needs_review) {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($this->getValue() as $reviewer) {
|
|
|
|
if (!$handles[$reviewer->getReviewerPHID()]->isDisabled()) {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$warnings = array();
|
|
|
|
if ($this->getValue()) {
|
|
|
|
$warnings[] = pht(
|
|
|
|
'This revision needs review, but all specified reviewers are '.
|
|
|
|
'disabled or inactive.');
|
|
|
|
} else {
|
|
|
|
$warnings[] = pht(
|
|
|
|
'This revision needs review, but there are no reviewers specified.');
|
|
|
|
}
|
|
|
|
|
|
|
|
return $warnings;
|
|
|
|
}
|
2014-03-12 14:04:30 +01:00
|
|
|
|
2014-02-21 20:54:32 +01:00
|
|
|
}
|