mirror of
https://we.phorge.it/source/phorge.git
synced 2025-04-07 18:08:31 +02:00
Implement a "Reviewers" CustomField
Summary: Ref T3886: - Adds a "Reviewers" field as a modern CustomField. Ref T418: - Allows CustomFields to emit transaction metadata. Test Plan: {F116254} Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T418, T3886 Differential Revision: https://secure.phabricator.com/D8291
This commit is contained in:
parent
aa7ba4c6e6
commit
c5ba75ee9e
8 changed files with 165 additions and 18 deletions
|
@ -441,6 +441,7 @@ phutil_register_library_map(array(
|
||||||
'DifferentialReviewedByFieldSpecification' => 'applications/differential/field/specification/DifferentialReviewedByFieldSpecification.php',
|
'DifferentialReviewedByFieldSpecification' => 'applications/differential/field/specification/DifferentialReviewedByFieldSpecification.php',
|
||||||
'DifferentialReviewer' => 'applications/differential/storage/DifferentialReviewer.php',
|
'DifferentialReviewer' => 'applications/differential/storage/DifferentialReviewer.php',
|
||||||
'DifferentialReviewerStatus' => 'applications/differential/constants/DifferentialReviewerStatus.php',
|
'DifferentialReviewerStatus' => 'applications/differential/constants/DifferentialReviewerStatus.php',
|
||||||
|
'DifferentialReviewersField' => 'applications/differential/customfield/DifferentialReviewersField.php',
|
||||||
'DifferentialReviewersFieldSpecification' => 'applications/differential/field/specification/DifferentialReviewersFieldSpecification.php',
|
'DifferentialReviewersFieldSpecification' => 'applications/differential/field/specification/DifferentialReviewersFieldSpecification.php',
|
||||||
'DifferentialReviewersView' => 'applications/differential/view/DifferentialReviewersView.php',
|
'DifferentialReviewersView' => 'applications/differential/view/DifferentialReviewersView.php',
|
||||||
'DifferentialRevision' => 'applications/differential/storage/DifferentialRevision.php',
|
'DifferentialRevision' => 'applications/differential/storage/DifferentialRevision.php',
|
||||||
|
@ -2979,6 +2980,7 @@ phutil_register_library_map(array(
|
||||||
'DifferentialRevertPlanFieldSpecification' => 'DifferentialFieldSpecification',
|
'DifferentialRevertPlanFieldSpecification' => 'DifferentialFieldSpecification',
|
||||||
'DifferentialReviewRequestMail' => 'DifferentialMail',
|
'DifferentialReviewRequestMail' => 'DifferentialMail',
|
||||||
'DifferentialReviewedByFieldSpecification' => 'DifferentialFieldSpecification',
|
'DifferentialReviewedByFieldSpecification' => 'DifferentialFieldSpecification',
|
||||||
|
'DifferentialReviewersField' => 'DifferentialCoreCustomField',
|
||||||
'DifferentialReviewersFieldSpecification' => 'DifferentialFieldSpecification',
|
'DifferentialReviewersFieldSpecification' => 'DifferentialFieldSpecification',
|
||||||
'DifferentialReviewersView' => 'AphrontView',
|
'DifferentialReviewersView' => 'AphrontView',
|
||||||
'DifferentialRevision' =>
|
'DifferentialRevision' =>
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class DifferentialReviewersField
|
||||||
|
extends DifferentialCoreCustomField {
|
||||||
|
|
||||||
|
public function getFieldKey() {
|
||||||
|
return 'differential:reviewers';
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,11 +6,11 @@ final class DifferentialTransactionEditor
|
||||||
public function getTransactionTypes() {
|
public function getTransactionTypes() {
|
||||||
$types = parent::getTransactionTypes();
|
$types = parent::getTransactionTypes();
|
||||||
|
|
||||||
|
$types[] = PhabricatorTransactions::TYPE_EDGE;
|
||||||
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
|
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
|
||||||
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
|
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
$types[] = PhabricatorTransactions::TYPE_EDGE;
|
|
||||||
|
|
||||||
$types[] = DifferentialTransaction::TYPE_INLINE;
|
$types[] = DifferentialTransaction::TYPE_INLINE;
|
||||||
$types[] = DifferentialTransaction::TYPE_UPDATE;
|
$types[] = DifferentialTransaction::TYPE_UPDATE;
|
||||||
|
@ -59,6 +59,9 @@ final class DifferentialTransactionEditor
|
||||||
$object->setEditPolicy($xaction->getNewValue());
|
$object->setEditPolicy($xaction->getNewValue());
|
||||||
return;
|
return;
|
||||||
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
|
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
|
||||||
|
case PhabricatorTransactions::TYPE_EDGE:
|
||||||
|
// TODO: When removing reviewers, we may be able to move the revision
|
||||||
|
// to "Accepted".
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +77,7 @@ final class DifferentialTransactionEditor
|
||||||
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
||||||
return;
|
return;
|
||||||
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
|
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
|
||||||
|
case PhabricatorTransactions::TYPE_EDGE:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +97,6 @@ final class DifferentialTransactionEditor
|
||||||
return $errors;
|
return $errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function requireCapabilities(
|
protected function requireCapabilities(
|
||||||
PhabricatorLiskDAO $object,
|
PhabricatorLiskDAO $object,
|
||||||
PhabricatorApplicationTransaction $xaction) {
|
PhabricatorApplicationTransaction $xaction) {
|
||||||
|
|
|
@ -46,4 +46,11 @@ final class DifferentialReviewer {
|
||||||
return $this->authority[$viewer_phid];
|
return $this->authority[$viewer_phid];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getEdgeData() {
|
||||||
|
return array(
|
||||||
|
'status' => $this->status,
|
||||||
|
'diffID' => $this->diffID,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -469,6 +469,7 @@ final class DifferentialRevision extends DifferentialDAO
|
||||||
new DifferentialTitleField(),
|
new DifferentialTitleField(),
|
||||||
new DifferentialSummaryField(),
|
new DifferentialSummaryField(),
|
||||||
new DifferentialTestPlanField(),
|
new DifferentialTestPlanField(),
|
||||||
|
new DifferentialReviewersField(),
|
||||||
new DifferentialSubscribersField(),
|
new DifferentialSubscribersField(),
|
||||||
new DifferentialRepositoryField(),
|
new DifferentialRepositoryField(),
|
||||||
new DifferentialViewPolicyField(),
|
new DifferentialViewPolicyField(),
|
||||||
|
|
|
@ -990,21 +990,24 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
}
|
}
|
||||||
$result[$dst_phid] = $this->normalizeEdgeTransactionValue(
|
$result[$dst_phid] = $this->normalizeEdgeTransactionValue(
|
||||||
$xaction,
|
$xaction,
|
||||||
$edge);
|
$edge,
|
||||||
|
$dst_phid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($new_set !== null) {
|
if ($new_set !== null) {
|
||||||
foreach ($new_set as $dst_phid => $edge) {
|
foreach ($new_set as $dst_phid => $edge) {
|
||||||
$result[$dst_phid] = $this->normalizeEdgeTransactionValue(
|
$result[$dst_phid] = $this->normalizeEdgeTransactionValue(
|
||||||
$xaction,
|
$xaction,
|
||||||
$edge);
|
$edge,
|
||||||
|
$dst_phid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($new_add as $dst_phid => $edge) {
|
foreach ($new_add as $dst_phid => $edge) {
|
||||||
$result[$dst_phid] = $this->normalizeEdgeTransactionValue(
|
$result[$dst_phid] = $this->normalizeEdgeTransactionValue(
|
||||||
$xaction,
|
$xaction,
|
||||||
$edge);
|
$edge,
|
||||||
|
$dst_phid);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($new_rem as $dst_phid => $edge) {
|
foreach ($new_rem as $dst_phid => $edge) {
|
||||||
|
@ -1032,18 +1035,44 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function normalizeEdgeTransactionValue(
|
private function normalizeEdgeTransactionValue(
|
||||||
PhabricatorApplicationTransaction $xaction,
|
PhabricatorApplicationTransaction $xaction,
|
||||||
$edge) {
|
$edge,
|
||||||
|
$dst_phid) {
|
||||||
|
|
||||||
if (!is_array($edge)) {
|
if (!is_array($edge)) {
|
||||||
$edge = array(
|
if ($edge != $dst_phid) {
|
||||||
'dst' => $edge,
|
throw new Exception(
|
||||||
);
|
pht(
|
||||||
|
'Transaction edge data must either be the edge PHID or an edge '.
|
||||||
|
'specification dictionary.'));
|
||||||
|
}
|
||||||
|
$edge = array();
|
||||||
|
} else {
|
||||||
|
foreach ($edge as $key => $value) {
|
||||||
|
switch ($key) {
|
||||||
|
case 'src':
|
||||||
|
case 'dst':
|
||||||
|
case 'type':
|
||||||
|
case 'data':
|
||||||
|
case 'dateCreated':
|
||||||
|
case 'dateModified':
|
||||||
|
case 'seq':
|
||||||
|
case 'dataID':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Transaction edge specification contains unexpected key '.
|
||||||
|
'"%s".',
|
||||||
|
$key));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$edge_type = $xaction->getMetadataValue('edge:type');
|
$edge['dst'] = $dst_phid;
|
||||||
|
|
||||||
|
$edge_type = $xaction->getMetadataValue('edge:type');
|
||||||
if (empty($edge['type'])) {
|
if (empty($edge['type'])) {
|
||||||
$edge['type'] = $edge_type;
|
$edge['type'] = $edge_type;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -744,6 +744,17 @@ abstract class PhabricatorCustomField {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @task appxaction
|
||||||
|
*/
|
||||||
|
public function getApplicationTransactionMetadata() {
|
||||||
|
if ($this->proxy) {
|
||||||
|
return $this->proxy->getApplicationTransactionMetadata();
|
||||||
|
}
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @task appxaction
|
* @task appxaction
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -199,22 +199,32 @@ final class PhabricatorCustomFieldList extends Phobject {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$old_value = $field->getOldValueForApplicationTransactions();
|
|
||||||
|
|
||||||
$field->readValueFromRequest($request);
|
|
||||||
$transaction_type = $field->getApplicationTransactionType();
|
$transaction_type = $field->getApplicationTransactionType();
|
||||||
|
|
||||||
$xaction = id(clone $template)
|
$xaction = id(clone $template)
|
||||||
->setTransactionType($transaction_type)
|
->setTransactionType($transaction_type);
|
||||||
->setMetadataValue('customfield:key', $field->getFieldKey())
|
|
||||||
->setNewValue($field->getNewValueForApplicationTransactions());
|
|
||||||
|
|
||||||
if ($transaction_type == PhabricatorTransactions::TYPE_CUSTOMFIELD) {
|
if ($transaction_type == PhabricatorTransactions::TYPE_CUSTOMFIELD) {
|
||||||
// For TYPE_CUSTOMFIELD transactions only, we provide the old value
|
// For TYPE_CUSTOMFIELD transactions only, we provide the old value
|
||||||
// as an input.
|
// as an input.
|
||||||
|
$old_value = $field->getOldValueForApplicationTransactions();
|
||||||
$xaction->setOldValue($old_value);
|
$xaction->setOldValue($old_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$field->readValueFromRequest($request);
|
||||||
|
|
||||||
|
$xaction
|
||||||
|
->setNewValue($field->getNewValueForApplicationTransactions());
|
||||||
|
|
||||||
|
if ($transaction_type == PhabricatorTransactions::TYPE_CUSTOMFIELD) {
|
||||||
|
// For TYPE_CUSTOMFIELD transactions, add the field key in metadata.
|
||||||
|
$xaction->setMetadataValue('customfield:key', $field->getFieldKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
$metadata = $field->getApplicationTransactionMetadata();
|
||||||
|
foreach ($metadata as $key => $value) {
|
||||||
|
$xaction->setMetadataValue($key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
$xactions[] = $xaction;
|
$xactions[] = $xaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue