Page MenuHomePhorge

No OneTemporary

diff --git a/src/applications/differential/command/DifferentialActionEmailCommand.php b/src/applications/differential/command/DifferentialActionEmailCommand.php
index a761339141..cbf94487e9 100644
--- a/src/applications/differential/command/DifferentialActionEmailCommand.php
+++ b/src/applications/differential/command/DifferentialActionEmailCommand.php
@@ -1,140 +1,103 @@
<?php
final class DifferentialActionEmailCommand
extends MetaMTAEmailTransactionCommand {
private $command;
private $action;
private $aliases;
private $commandSummary;
private $commandDescription;
public function getCommand() {
return $this->command;
}
private function setCommand($command) {
$this->command = $command;
return $this;
}
private function setAction($action) {
$this->action = $action;
return $this;
}
private function getAction() {
return $this->action;
}
private function setCommandAliases(array $aliases) {
$this->aliases = $aliases;
return $this;
}
public function getCommandAliases() {
return $this->aliases;
}
public function setCommandSummary($command_summary) {
$this->commandSummary = $command_summary;
return $this;
}
public function getCommandSummary() {
return $this->commandSummary;
}
public function setCommandDescription($command_description) {
$this->commandDescription = $command_description;
return $this;
}
public function getCommandDescription() {
return $this->commandDescription;
}
public function getCommandObjects() {
- $actions = array(
- DifferentialAction::ACTION_REJECT => 'request',
- DifferentialAction::ACTION_ABANDON => 'abandon',
- DifferentialAction::ACTION_RECLAIM => 'reclaim',
- DifferentialAction::ACTION_RESIGN => 'resign',
- DifferentialAction::ACTION_RETHINK => 'planchanges',
- DifferentialAction::ACTION_CLAIM => 'commandeer',
- );
-
- if (PhabricatorEnv::getEnvConfig('differential.enable-email-accept')) {
- $actions[DifferentialAction::ACTION_ACCEPT] = 'accept';
- }
-
- $aliases = array(
- DifferentialAction::ACTION_REJECT => array('reject'),
- DifferentialAction::ACTION_CLAIM => array('claim'),
- DifferentialAction::ACTION_RETHINK => array('rethink'),
- );
-
- $summaries = array(
- DifferentialAction::ACTION_REJECT =>
- pht('Request changes to a revision.'),
- DifferentialAction::ACTION_ABANDON =>
- pht('Abandon a revision.'),
- DifferentialAction::ACTION_RECLAIM =>
- pht('Reclaim a revision.'),
- DifferentialAction::ACTION_RESIGN =>
- pht('Resign from a revision.'),
- DifferentialAction::ACTION_RETHINK =>
- pht('Plan changes to a revision.'),
- DifferentialAction::ACTION_CLAIM =>
- pht('Commandeer a revision.'),
- DifferentialAction::ACTION_ACCEPT =>
- pht('Accept a revision.'),
- );
-
- $descriptions = array(
-
- );
+ $actions = DifferentialRevisionActionTransaction::loadAllActions();
+ $actions = msort($actions, 'getRevisionActionOrderVector');
$objects = array();
- foreach ($actions as $action => $keyword) {
- $object = id(new DifferentialActionEmailCommand())
- ->setCommand($keyword)
- ->setAction($action)
- ->setCommandSummary($summaries[$action]);
-
- if (isset($aliases[$action])) {
- $object->setCommandAliases($aliases[$action]);
+ foreach ($actions as $action) {
+ $keyword = $action->getCommandKeyword();
+ if ($keyword === null) {
+ continue;
}
- if (isset($descriptions[$action])) {
- $object->setCommandDescription($descriptions[$action]);
- }
+ $aliases = $action->getCommandAliases();
+ $summary = $action->getCommandSummary();
+
+ $object = id(new self())
+ ->setCommand($keyword)
+ ->setCommandAliases($aliases)
+ ->setAction($action->getTransactionTypeConstant())
+ ->setCommandSummary($summary);
$objects[] = $object;
}
-
return $objects;
}
public function isCommandSupportedForObject(
PhabricatorApplicationTransactionInterface $object) {
return ($object instanceof DifferentialRevision);
}
public function buildTransactions(
PhabricatorUser $viewer,
PhabricatorApplicationTransactionInterface $object,
PhabricatorMetaMTAReceivedMail $mail,
$command,
array $argv) {
$xactions = array();
$xactions[] = $object->getApplicationTransactionTemplate()
- ->setTransactionType(DifferentialTransaction::TYPE_ACTION)
- ->setNewValue($this->getAction());
+ ->setTransactionType($this->getAction())
+ ->setNewValue(true);
return $xactions;
}
}
diff --git a/src/applications/differential/xaction/DifferentialRevisionAbandonTransaction.php b/src/applications/differential/xaction/DifferentialRevisionAbandonTransaction.php
index e4fc7f1a5f..627e1c9d37 100644
--- a/src/applications/differential/xaction/DifferentialRevisionAbandonTransaction.php
+++ b/src/applications/differential/xaction/DifferentialRevisionAbandonTransaction.php
@@ -1,71 +1,83 @@
<?php
final class DifferentialRevisionAbandonTransaction
extends DifferentialRevisionActionTransaction {
const TRANSACTIONTYPE = 'differential.revision.abandon';
const ACTIONKEY = 'abandon';
protected function getRevisionActionLabel() {
return pht('Abandon Revision');
}
protected function getRevisionActionDescription() {
return pht('This revision will be abandoned and closed.');
}
public function getIcon() {
return 'fa-plane';
}
public function getColor() {
return 'indigo';
}
protected function getRevisionActionOrder() {
return 500;
}
+ public function getCommandKeyword() {
+ return 'abandon';
+ }
+
+ public function getCommandAliases() {
+ return array();
+ }
+
+ public function getCommandSummary() {
+ return pht('Abandon a revision.');
+ }
+
public function generateOldValue($object) {
return $object->isAbandoned();
}
public function applyInternalEffects($object, $value) {
$object->setStatus(ArcanistDifferentialRevisionStatus::ABANDONED);
}
protected function validateAction($object, PhabricatorUser $viewer) {
if ($object->isClosed()) {
throw new Exception(
pht(
'You can not abandon this revision because it has already been '.
'closed. Only open revisions can be abandoned.'));
}
$config_key = 'differential.always-allow-abandon';
if (!PhabricatorEnv::getEnvConfig($config_key)) {
if (!$this->isViewerRevisionAuthor($object, $viewer)) {
throw new Exception(
pht(
'You can not abandon this revision because you are not the '.
'author. You can only abandon revisions you own. You can change '.
'this behavior by adjusting the "%s" setting in Config.',
$config_key));
}
}
}
public function getTitle() {
return pht(
'%s abandoned this revision.',
$this->renderAuthor());
}
public function getTitleForFeed() {
return pht(
'%s abandoned %s.',
$this->renderAuthor(),
$this->renderObject());
}
}
diff --git a/src/applications/differential/xaction/DifferentialRevisionAcceptTransaction.php b/src/applications/differential/xaction/DifferentialRevisionAcceptTransaction.php
index c99c663c8d..dcb19c4037 100644
--- a/src/applications/differential/xaction/DifferentialRevisionAcceptTransaction.php
+++ b/src/applications/differential/xaction/DifferentialRevisionAcceptTransaction.php
@@ -1,81 +1,99 @@
<?php
final class DifferentialRevisionAcceptTransaction
extends DifferentialRevisionReviewTransaction {
const TRANSACTIONTYPE = 'differential.revision.accept';
const ACTIONKEY = 'accept';
protected function getRevisionActionLabel() {
return pht("Accept Revision \xE2\x9C\x94");
}
protected function getRevisionActionDescription() {
return pht('These changes will be approved.');
}
public function getIcon() {
return 'fa-check-circle-o';
}
public function getColor() {
return 'green';
}
protected function getRevisionActionOrder() {
return 500;
}
+ public function getCommandKeyword() {
+ $accept_key = 'differential.enable-email-accept';
+ $allow_email_accept = PhabricatorEnv::getEnvConfig($accept_key);
+ if (!$allow_email_accept) {
+ return null;
+ }
+
+ return 'accept';
+ }
+
+ public function getCommandAliases() {
+ return array();
+ }
+
+ public function getCommandSummary() {
+ return pht('Accept a revision.');
+ }
+
public function generateOldValue($object) {
$actor = $this->getActor();
return $this->isViewerAcceptingReviewer($object, $actor);
}
public function applyExternalEffects($object, $value) {
$status = DifferentialReviewerStatus::STATUS_ACCEPTED;
$actor = $this->getActor();
$this->applyReviewerEffect($object, $actor, $value, $status);
}
protected function validateAction($object, PhabricatorUser $viewer) {
if ($object->isClosed()) {
throw new Exception(
pht(
'You can not accept this revision because it has already been '.
'closed. Only open revisions can be accepted.'));
}
$config_key = 'differential.allow-self-accept';
if (!PhabricatorEnv::getEnvConfig($config_key)) {
if ($this->isViewerRevisionAuthor($object, $viewer)) {
throw new Exception(
pht(
'You can not accept this revision because you are the revision '.
'author. You can only accept revisions you do not own. You can '.
'change this behavior by adjusting the "%s" setting in Config.',
$config_key));
}
}
if ($this->isViewerAcceptingReviewer($object, $viewer)) {
throw new Exception(
pht(
'You can not accept this revision because you have already '.
'accepted it.'));
}
}
public function getTitle() {
return pht(
'%s accepted this revision.',
$this->renderAuthor());
}
public function getTitleForFeed() {
return pht(
'%s accepted %s.',
$this->renderAuthor(),
$this->renderObject());
}
}
diff --git a/src/applications/differential/xaction/DifferentialRevisionActionTransaction.php b/src/applications/differential/xaction/DifferentialRevisionActionTransaction.php
index 14d7a1369a..dd80706b44 100644
--- a/src/applications/differential/xaction/DifferentialRevisionActionTransaction.php
+++ b/src/applications/differential/xaction/DifferentialRevisionActionTransaction.php
@@ -1,116 +1,128 @@
<?php
abstract class DifferentialRevisionActionTransaction
extends DifferentialRevisionTransactionType {
final public function getRevisionActionKey() {
return $this->getPhobjectClassConstant('ACTIONKEY', 32);
}
public function isActionAvailable($object, PhabricatorUser $viewer) {
try {
$this->validateAction($object, $viewer);
return true;
} catch (Exception $ex) {
return false;
}
}
abstract protected function validateAction($object, PhabricatorUser $viewer);
abstract protected function getRevisionActionLabel();
+ public function getCommandKeyword() {
+ return null;
+ }
+
+ public function getCommandAliases() {
+ return array();
+ }
+
+ public function getCommandSummary() {
+ return null;
+ }
+
protected function getRevisionActionOrder() {
return 1000;
}
public function getRevisionActionOrderVector() {
return id(new PhutilSortVector())
->addInt($this->getRevisionActionOrder());
}
protected function getRevisionActionGroupKey() {
return DifferentialRevisionEditEngine::ACTIONGROUP_REVISION;
}
protected function getRevisionActionDescription() {
return null;
}
public static function loadAllActions() {
return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->setUniqueMethod('getRevisionActionKey')
->execute();
}
protected function isViewerRevisionAuthor(
DifferentialRevision $revision,
PhabricatorUser $viewer) {
if (!$viewer->getPHID()) {
return false;
}
return ($viewer->getPHID() === $revision->getAuthorPHID());
}
public function newEditField(
DifferentialRevision $revision,
PhabricatorUser $viewer) {
$field = id(new PhabricatorApplyEditField())
->setKey($this->getRevisionActionKey())
->setTransactionType($this->getTransactionTypeConstant())
->setValue(true);
if ($this->isActionAvailable($revision, $viewer)) {
$label = $this->getRevisionActionLabel();
if ($label !== null) {
$field->setCommentActionLabel($label);
$description = $this->getRevisionActionDescription();
$field->setActionDescription($description);
$group_key = $this->getRevisionActionGroupKey();
$field->setCommentActionGroupKey($group_key);
// Currently, every revision action conflicts with every other
// revision action: for example, you can not simultaneously Accept and
// Reject a revision.
// Under some configurations, some combinations of actions are sort of
// technically permissible. For example, you could reasonably Reject
// and Abandon a revision if "anyone can abandon anything" is enabled.
// It's not clear that these combinations are actually useful, so just
// keep things simple for now.
$field->setActionConflictKey('revision.action');
}
}
return $field;
}
public function validateTransactions($object, array $xactions) {
$errors = array();
$actor = $this->getActor();
$action_exception = null;
try {
$this->validateAction($object, $actor);
} catch (Exception $ex) {
$action_exception = $ex;
}
foreach ($xactions as $xaction) {
if ($action_exception) {
$errors[] = $this->newInvalidError(
$action_exception->getMessage(),
$xaction);
}
}
return $errors;
}
}
diff --git a/src/applications/differential/xaction/DifferentialRevisionCommandeerTransaction.php b/src/applications/differential/xaction/DifferentialRevisionCommandeerTransaction.php
index fac7ec8b0b..57ecf5a039 100644
--- a/src/applications/differential/xaction/DifferentialRevisionCommandeerTransaction.php
+++ b/src/applications/differential/xaction/DifferentialRevisionCommandeerTransaction.php
@@ -1,71 +1,85 @@
<?php
final class DifferentialRevisionCommandeerTransaction
extends DifferentialRevisionActionTransaction {
const TRANSACTIONTYPE = 'differential.revision.commandeer';
const ACTIONKEY = 'commandeer';
protected function getRevisionActionLabel() {
return pht('Commandeer Revision');
}
protected function getRevisionActionDescription() {
return pht('You will take control of this revision and become its author.');
}
public function getIcon() {
return 'fa-flag';
}
public function getColor() {
return 'sky';
}
protected function getRevisionActionOrder() {
return 700;
}
+ public function getCommandKeyword() {
+ return 'commandeer';
+ }
+
+ public function getCommandAliases() {
+ return array(
+ 'claim',
+ );
+ }
+
+ public function getCommandSummary() {
+ return pht('Commadeer a revision.');
+ }
+
public function generateOldValue($object) {
return $object->getAuthorPHID();
}
public function generateNewValue($object, $value) {
$actor = $this->getActor();
return $actor->getPHID();
}
public function applyInternalEffects($object, $value) {
$object->setAuthorPHID($value);
}
protected function validateAction($object, PhabricatorUser $viewer) {
if ($object->isClosed()) {
throw new Exception(
pht(
'You can not commandeer this revision because it has already '.
'been closed. You can only commandeer open revisions.'));
}
if ($this->isViewerRevisionAuthor($object, $viewer)) {
throw new Exception(
pht(
'You can not commandeer this revision because you are already '.
'the author.'));
}
}
public function getTitle() {
return pht(
'%s commandeered this revision.',
$this->renderAuthor());
}
public function getTitleForFeed() {
return pht(
'%s commandeered %s.',
$this->renderAuthor(),
$this->renderObject());
}
}
diff --git a/src/applications/differential/xaction/DifferentialRevisionPlanChangesTransaction.php b/src/applications/differential/xaction/DifferentialRevisionPlanChangesTransaction.php
index d33992d36e..35c40273f6 100644
--- a/src/applications/differential/xaction/DifferentialRevisionPlanChangesTransaction.php
+++ b/src/applications/differential/xaction/DifferentialRevisionPlanChangesTransaction.php
@@ -1,79 +1,93 @@
<?php
final class DifferentialRevisionPlanChangesTransaction
extends DifferentialRevisionActionTransaction {
const TRANSACTIONTYPE = 'differential.revision.plan';
const ACTIONKEY = 'plan-changes';
protected function getRevisionActionLabel() {
return pht('Plan Changes');
}
protected function getRevisionActionDescription() {
return pht(
'This revision will be removed from review queues until it is revised.');
}
public function getIcon() {
return 'fa-headphones';
}
public function getColor() {
return 'red';
}
protected function getRevisionActionOrder() {
return 200;
}
+ public function getCommandKeyword() {
+ return 'planchanges';
+ }
+
+ public function getCommandAliases() {
+ return array(
+ 'rethink',
+ );
+ }
+
+ public function getCommandSummary() {
+ return pht('Plan changes to a revision.');
+ }
+
public function generateOldValue($object) {
$status_planned = ArcanistDifferentialRevisionStatus::CHANGES_PLANNED;
return ($object->getStatus() == $status_planned);
}
public function applyInternalEffects($object, $value) {
$status_planned = ArcanistDifferentialRevisionStatus::CHANGES_PLANNED;
$object->setStatus($status_planned);
}
protected function validateAction($object, PhabricatorUser $viewer) {
$status_planned = ArcanistDifferentialRevisionStatus::CHANGES_PLANNED;
if ($object->getStatus() == $status_planned) {
throw new Exception(
pht(
'You can not request review of this revision because this '.
'revision is already under review and the action would have '.
'no effect.'));
}
if ($object->isClosed()) {
throw new Exception(
pht(
'You can not plan changes to this this revision because it has '.
'already been closed.'));
}
if (!$this->isViewerRevisionAuthor($object, $viewer)) {
throw new Exception(
pht(
'You can not plan changes to this revision because you do not '.
'own it. Only the author of a revision can plan changes to it.'));
}
}
public function getTitle() {
return pht(
'%s planned changes to this revision.',
$this->renderAuthor());
}
public function getTitleForFeed() {
return pht(
'%s planned changes to %s.',
$this->renderAuthor(),
$this->renderObject());
}
}
diff --git a/src/applications/differential/xaction/DifferentialRevisionReclaimTransaction.php b/src/applications/differential/xaction/DifferentialRevisionReclaimTransaction.php
index ce8367f7c3..96a1f4415c 100644
--- a/src/applications/differential/xaction/DifferentialRevisionReclaimTransaction.php
+++ b/src/applications/differential/xaction/DifferentialRevisionReclaimTransaction.php
@@ -1,66 +1,78 @@
<?php
final class DifferentialRevisionReclaimTransaction
extends DifferentialRevisionActionTransaction {
const TRANSACTIONTYPE = 'differential.revision.reclaim';
const ACTIONKEY = 'reclaim';
protected function getRevisionActionLabel() {
return pht('Reclaim Revision');
}
protected function getRevisionActionDescription() {
return pht('This revision will be reclaimed and reopened.');
}
public function getIcon() {
return 'fa-bullhorn';
}
public function getColor() {
return 'sky';
}
protected function getRevisionActionOrder() {
return 600;
}
+ public function getCommandKeyword() {
+ return 'reclaim';
+ }
+
+ public function getCommandAliases() {
+ return array();
+ }
+
+ public function getCommandSummary() {
+ return pht('Reclaim a revision.');
+ }
+
public function generateOldValue($object) {
return !$object->isAbandoned();
}
public function applyInternalEffects($object, $value) {
$object->setStatus(ArcanistDifferentialRevisionStatus::NEEDS_REVIEW);
}
protected function validateAction($object, PhabricatorUser $viewer) {
if (!$object->isAbandoned()) {
throw new Exception(
pht(
'You can not reclaim this revision because it has not been '.
'abandoned. Only abandoned revisions can be reclaimed.'));
}
if (!$this->isViewerRevisionAuthor($object, $viewer)) {
throw new Exception(
pht(
'You can not reclaim this revision because you are not the '.
'revision author. You can only reclaim revisions you own.'));
}
}
public function getTitle() {
return pht(
'%s reclaimed this revision.',
$this->renderAuthor());
}
public function getTitleForFeed() {
return pht(
'%s reclaimed %s.',
$this->renderAuthor(),
$this->renderObject());
}
}
diff --git a/src/applications/differential/xaction/DifferentialRevisionRejectTransaction.php b/src/applications/differential/xaction/DifferentialRevisionRejectTransaction.php
index 17ecca0e20..808412ff78 100644
--- a/src/applications/differential/xaction/DifferentialRevisionRejectTransaction.php
+++ b/src/applications/differential/xaction/DifferentialRevisionRejectTransaction.php
@@ -1,78 +1,92 @@
<?php
final class DifferentialRevisionRejectTransaction
extends DifferentialRevisionReviewTransaction {
const TRANSACTIONTYPE = 'differential.revision.reject';
const ACTIONKEY = 'reject';
protected function getRevisionActionLabel() {
return pht("Request Changes \xE2\x9C\x98");
}
protected function getRevisionActionDescription() {
return pht('This revision will be returned to the author for updates.');
}
public function getIcon() {
return 'fa-times-circle-o';
}
public function getColor() {
return 'red';
}
protected function getRevisionActionOrder() {
return 600;
}
+ public function getCommandKeyword() {
+ return 'request';
+ }
+
+ public function getCommandAliases() {
+ return array(
+ 'reject',
+ );
+ }
+
+ public function getCommandSummary() {
+ return pht('Request changes to a revision.');
+ }
+
public function generateOldValue($object) {
$actor = $this->getActor();
return $this->isViewerRejectingReviewer($object, $actor);
}
public function applyExternalEffects($object, $value) {
$status = DifferentialReviewerStatus::STATUS_REJECTED;
$actor = $this->getActor();
$this->applyReviewerEffect($object, $actor, $value, $status);
}
protected function validateAction($object, PhabricatorUser $viewer) {
if ($object->isClosed()) {
throw new Exception(
pht(
'You can not request changes to this revision because it has '.
'already been closed. You can only request changes to open '.
'revisions.'));
}
if ($this->isViewerRevisionAuthor($object, $viewer)) {
throw new Exception(
pht(
'You can not request changes to this revision because you are the '.
'revision author. You can only request changes to revisions you do '.
'not own.'));
}
if ($this->isViewerRejectingReviewer($object, $viewer)) {
throw new Exception(
pht(
'You can not request changes to this revision because you have '.
'already requested changes.'));
}
}
public function getTitle() {
return pht(
'%s requested changes to this revision.',
$this->renderAuthor());
}
public function getTitleForFeed() {
return pht(
'%s requested changes to %s.',
$this->renderAuthor(),
$this->renderObject());
}
}
diff --git a/src/applications/differential/xaction/DifferentialRevisionResignTransaction.php b/src/applications/differential/xaction/DifferentialRevisionResignTransaction.php
index f994c2f45e..0d3045247d 100644
--- a/src/applications/differential/xaction/DifferentialRevisionResignTransaction.php
+++ b/src/applications/differential/xaction/DifferentialRevisionResignTransaction.php
@@ -1,70 +1,82 @@
<?php
final class DifferentialRevisionResignTransaction
extends DifferentialRevisionReviewTransaction {
const TRANSACTIONTYPE = 'differential.revision.resign';
const ACTIONKEY = 'resign';
protected function getRevisionActionLabel() {
return pht('Resign as Reviewer');
}
protected function getRevisionActionDescription() {
return pht('You will resign as a reviewer for this change.');
}
public function getIcon() {
return 'fa-flag';
}
public function getColor() {
return 'orange';
}
protected function getRevisionActionOrder() {
return 700;
}
+ public function getCommandKeyword() {
+ return 'resign';
+ }
+
+ public function getCommandAliases() {
+ return array();
+ }
+
+ public function getCommandSummary() {
+ return pht('Resign from a revision.');
+ }
+
public function generateOldValue($object) {
$actor = $this->getActor();
return !$this->isViewerAnyReviewer($object, $actor);
}
public function applyExternalEffects($object, $value) {
$status = DifferentialReviewerStatus::STATUS_RESIGNED;
$actor = $this->getActor();
$this->applyReviewerEffect($object, $actor, $value, $status);
}
protected function validateAction($object, PhabricatorUser $viewer) {
if ($object->isClosed()) {
throw new Exception(
pht(
'You can not resign from this revision because it has already '.
'been closed. You can only resign from open revisions.'));
}
if (!$this->isViewerAnyReviewer($object, $viewer)) {
throw new Exception(
pht(
'You can not resign from this revision because you are not a '.
'reviewer. You can only resign from revisions where you are a '.
'reviewer.'));
}
}
public function getTitle() {
return pht(
'%s resigned from this revision.',
$this->renderAuthor());
}
public function getTitleForFeed() {
return pht(
'%s resigned from %s.',
$this->renderAuthor(),
$this->renderObject());
}
}

File Metadata

Mime Type
text/x-diff
Expires
Jan 19 2025, 21:16 (6 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1128844
Default Alt Text
(26 KB)

Event Timeline