Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14832920
D17182.id41322.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
19 KB
Referenced Files
None
Subscribers
None
D17182.id41322.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -612,13 +612,17 @@
'DiffusionCloneURIView' => 'applications/diffusion/view/DiffusionCloneURIView.php',
'DiffusionCommandEngine' => 'applications/diffusion/protocol/DiffusionCommandEngine.php',
'DiffusionCommandEngineTestCase' => 'applications/diffusion/protocol/__tests__/DiffusionCommandEngineTestCase.php',
+ 'DiffusionCommitAcceptTransaction' => 'applications/diffusion/xaction/DiffusionCommitAcceptTransaction.php',
+ 'DiffusionCommitActionTransaction' => 'applications/diffusion/xaction/DiffusionCommitActionTransaction.php',
'DiffusionCommitAffectedFilesHeraldField' => 'applications/diffusion/herald/DiffusionCommitAffectedFilesHeraldField.php',
+ 'DiffusionCommitAuditTransaction' => 'applications/diffusion/xaction/DiffusionCommitAuditTransaction.php',
'DiffusionCommitAuditorsTransaction' => 'applications/diffusion/xaction/DiffusionCommitAuditorsTransaction.php',
'DiffusionCommitAuthorHeraldField' => 'applications/diffusion/herald/DiffusionCommitAuthorHeraldField.php',
'DiffusionCommitAutocloseHeraldField' => 'applications/diffusion/herald/DiffusionCommitAutocloseHeraldField.php',
'DiffusionCommitBranchesController' => 'applications/diffusion/controller/DiffusionCommitBranchesController.php',
'DiffusionCommitBranchesHeraldField' => 'applications/diffusion/herald/DiffusionCommitBranchesHeraldField.php',
'DiffusionCommitCommitterHeraldField' => 'applications/diffusion/herald/DiffusionCommitCommitterHeraldField.php',
+ 'DiffusionCommitConcernTransaction' => 'applications/diffusion/xaction/DiffusionCommitConcernTransaction.php',
'DiffusionCommitController' => 'applications/diffusion/controller/DiffusionCommitController.php',
'DiffusionCommitDiffContentAddedHeraldField' => 'applications/diffusion/herald/DiffusionCommitDiffContentAddedHeraldField.php',
'DiffusionCommitDiffContentHeraldField' => 'applications/diffusion/herald/DiffusionCommitDiffContentHeraldField.php',
@@ -652,6 +656,7 @@
'DiffusionCommitRemarkupRuleTestCase' => 'applications/diffusion/remarkup/__tests__/DiffusionCommitRemarkupRuleTestCase.php',
'DiffusionCommitRepositoryHeraldField' => 'applications/diffusion/herald/DiffusionCommitRepositoryHeraldField.php',
'DiffusionCommitRepositoryProjectsHeraldField' => 'applications/diffusion/herald/DiffusionCommitRepositoryProjectsHeraldField.php',
+ 'DiffusionCommitResignTransaction' => 'applications/diffusion/xaction/DiffusionCommitResignTransaction.php',
'DiffusionCommitRevertedByCommitEdgeType' => 'applications/diffusion/edge/DiffusionCommitRevertedByCommitEdgeType.php',
'DiffusionCommitRevertsCommitEdgeType' => 'applications/diffusion/edge/DiffusionCommitRevertsCommitEdgeType.php',
'DiffusionCommitReviewerHeraldField' => 'applications/diffusion/herald/DiffusionCommitReviewerHeraldField.php',
@@ -5313,13 +5318,17 @@
'DiffusionCloneURIView' => 'AphrontView',
'DiffusionCommandEngine' => 'Phobject',
'DiffusionCommandEngineTestCase' => 'PhabricatorTestCase',
+ 'DiffusionCommitAcceptTransaction' => 'DiffusionCommitAuditTransaction',
+ 'DiffusionCommitActionTransaction' => 'DiffusionCommitTransactionType',
'DiffusionCommitAffectedFilesHeraldField' => 'DiffusionCommitHeraldField',
+ 'DiffusionCommitAuditTransaction' => 'DiffusionCommitActionTransaction',
'DiffusionCommitAuditorsTransaction' => 'DiffusionCommitTransactionType',
'DiffusionCommitAuthorHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitAutocloseHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitBranchesController' => 'DiffusionController',
'DiffusionCommitBranchesHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitCommitterHeraldField' => 'DiffusionCommitHeraldField',
+ 'DiffusionCommitConcernTransaction' => 'DiffusionCommitAuditTransaction',
'DiffusionCommitController' => 'DiffusionController',
'DiffusionCommitDiffContentAddedHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitDiffContentHeraldField' => 'DiffusionCommitHeraldField',
@@ -5353,6 +5362,7 @@
'DiffusionCommitRemarkupRuleTestCase' => 'PhabricatorTestCase',
'DiffusionCommitRepositoryHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitRepositoryProjectsHeraldField' => 'DiffusionCommitHeraldField',
+ 'DiffusionCommitResignTransaction' => 'DiffusionCommitAuditTransaction',
'DiffusionCommitRevertedByCommitEdgeType' => 'PhabricatorEdgeType',
'DiffusionCommitRevertsCommitEdgeType' => 'PhabricatorEdgeType',
'DiffusionCommitReviewerHeraldField' => 'DiffusionCommitHeraldField',
diff --git a/src/applications/diffusion/editor/DiffusionCommitEditEngine.php b/src/applications/diffusion/editor/DiffusionCommitEditEngine.php
--- a/src/applications/diffusion/editor/DiffusionCommitEditEngine.php
+++ b/src/applications/diffusion/editor/DiffusionCommitEditEngine.php
@@ -5,6 +5,9 @@
const ENGINECONST = 'diffusion.commit';
+ const ACTIONGROUP_AUDIT = 'audit';
+ const ACTIONGROUP_COMMIT = 'commit';
+
public function isEngineConfigurable() {
return false;
}
@@ -130,6 +133,13 @@
->setValue(array($desc, " \xC2\xB7 ", $doc_link));
}
+ $actions = DiffusionCommitActionTransaction::loadAllActions();
+ $actions = msortv($actions, 'getCommitActionOrderVector');
+
+ foreach ($actions as $key => $action) {
+ $fields[] = $action->newEditField($object, $viewer);
+ }
+
return $fields;
}
diff --git a/src/applications/diffusion/xaction/DiffusionCommitAcceptTransaction.php b/src/applications/diffusion/xaction/DiffusionCommitAcceptTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/xaction/DiffusionCommitAcceptTransaction.php
@@ -0,0 +1,74 @@
+<?php
+
+final class DiffusionCommitAcceptTransaction
+ extends DiffusionCommitAuditTransaction {
+
+ const TRANSACTIONTYPE = 'diffusion.commit.accept';
+ const ACTIONKEY = 'accept';
+
+ protected function getCommitActionLabel() {
+ return pht("Accept Commit \xE2\x9C\x94");
+ }
+
+ protected function getCommitActionDescription() {
+ return pht('This commit will be approved.');
+ }
+
+ public function getIcon() {
+ return 'fa-check-circle-o';
+ }
+
+ public function getColor() {
+ return 'green';
+ }
+
+ protected function getCommitActionOrder() {
+ return 500;
+ }
+
+ public function generateOldValue($object) {
+ $actor = $this->getActor();
+ return $this->isViewerAcceptingAuditor($object, $actor);
+ }
+
+ public function applyExternalEffects($object, $value) {
+ $status = PhabricatorAuditStatusConstants::ACCEPTED;
+ $actor = $this->getActor();
+ $this->applyAuditorEffect($object, $actor, $value, $status);
+ }
+
+ protected function validateAction($object, PhabricatorUser $viewer) {
+ $config_key = 'audit.can-author-close-audit';
+ if (!PhabricatorEnv::getEnvConfig($config_key)) {
+ if ($this->isViewerCommitAuthor($object, $viewer)) {
+ throw new Exception(
+ pht(
+ 'You can not accept this commit because you are the commit '.
+ 'author. You can only accept commits you did not author. You can '.
+ 'change this behavior by adjusting the "%s" setting in Config.',
+ $config_key));
+ }
+ }
+
+ if ($this->isViewerAcceptingAuditor($object, $viewer)) {
+ throw new Exception(
+ pht(
+ 'You can not accept this commit because you have already '.
+ 'accepted it.'));
+ }
+ }
+
+ public function getTitle() {
+ return pht(
+ '%s accepted this commit.',
+ $this->renderAuthor());
+ }
+
+ public function getTitleForFeed() {
+ return pht(
+ '%s accepted %s.',
+ $this->renderAuthor(),
+ $this->renderObject());
+ }
+
+}
diff --git a/src/applications/diffusion/xaction/DiffusionCommitActionTransaction.php b/src/applications/diffusion/xaction/DiffusionCommitActionTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/xaction/DiffusionCommitActionTransaction.php
@@ -0,0 +1,118 @@
+<?php
+
+abstract class DiffusionCommitActionTransaction
+ extends DiffusionCommitTransactionType {
+
+ final public function getCommitActionKey() {
+ 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 getCommitActionLabel();
+
+ public function getCommandKeyword() {
+ return null;
+ }
+
+ public function getCommandAliases() {
+ return array();
+ }
+
+ public function getCommandSummary() {
+ return null;
+ }
+
+ protected function getCommitActionOrder() {
+ return 1000;
+ }
+
+ public function getCommitActionOrderVector() {
+ return id(new PhutilSortVector())
+ ->addInt($this->getCommitActionOrder());
+ }
+
+ protected function getCommitActionGroupKey() {
+ return DiffusionCommitEditEngine::ACTIONGROUP_COMMIT;
+ }
+
+ protected function getCommitActionDescription() {
+ return null;
+ }
+
+ public static function loadAllActions() {
+ return id(new PhutilClassMapQuery())
+ ->setAncestorClass(__CLASS__)
+ ->setUniqueMethod('getCommitActionKey')
+ ->execute();
+ }
+
+ protected function isViewerCommitAuthor(
+ PhabricatorRepositoryCommit $commit,
+ PhabricatorUser $viewer) {
+
+ if (!$viewer->getPHID()) {
+ return false;
+ }
+
+ return ($viewer->getPHID() === $commit->getAuthorPHID());
+ }
+
+ public function newEditField(
+ PhabricatorRepositoryCommit $commit,
+ PhabricatorUser $viewer) {
+
+ $field = id(new PhabricatorApplyEditField())
+ ->setKey($this->getCommitActionKey())
+ ->setTransactionType($this->getTransactionTypeConstant())
+ ->setValue(true);
+
+ if ($this->isActionAvailable($commit, $viewer)) {
+ $label = $this->getCommitActionLabel();
+ if ($label !== null) {
+ $field->setCommentActionLabel($label);
+
+ $description = $this->getCommitActionDescription();
+ $field->setActionDescription($description);
+
+ $group_key = $this->getCommitActionGroupKey();
+ $field->setCommentActionGroupKey($group_key);
+
+ $field->setActionConflictKey('commit.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/diffusion/xaction/DiffusionCommitAuditTransaction.php b/src/applications/diffusion/xaction/DiffusionCommitAuditTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/xaction/DiffusionCommitAuditTransaction.php
@@ -0,0 +1,101 @@
+<?php
+
+abstract class DiffusionCommitAuditTransaction
+ extends DiffusionCommitActionTransaction {
+
+ protected function getCommitActionGroupKey() {
+ return DiffusionCommitEditEngine::ACTIONGROUP_AUDIT;
+ }
+
+ protected function isViewerAnyAuditor(
+ PhabricatorRepositoryCommit $commit,
+ PhabricatorUser $viewer) {
+ return ($this->getViewerAuditStatus($commit, $viewer) !== null);
+ }
+
+ protected function isViewerAcceptingAuditor(
+ PhabricatorRepositoryCommit $commit,
+ PhabricatorUser $viewer) {
+ return $this->isViewerAuditStatusAmong(
+ $commit,
+ $viewer,
+ array(
+ PhabricatorAuditStatusConstants::ACCEPTED,
+ ));
+ }
+
+ protected function isViewerRejectingAuditor(
+ PhabricatorRepositoryCommit $commit,
+ PhabricatorUser $viewer) {
+ return $this->isViewerAuditStatusAmong(
+ $commit,
+ $viewer,
+ array(
+ PhabricatorAuditStatusConstants::CONCERNED,
+ ));
+ }
+
+ protected function getViewerAuditStatus(
+ PhabricatorRepositoryCommit $commit,
+ PhabricatorUser $viewer) {
+
+ if (!$viewer->getPHID()) {
+ return null;
+ }
+
+ foreach ($commit->getAudits() as $audit) {
+ if ($audit->getAuditorPHID() != $viewer->getPHID()) {
+ continue;
+ }
+
+ return $audit->getAuditStatus();
+ }
+
+ return null;
+ }
+
+ protected function isViewerAuditStatusAmong(
+ PhabricatorRepositoryCommit $commit,
+ PhabricatorUser $viewer,
+ array $status_list) {
+
+ $status = $this->getViewerAuditStatus($commit, $viewer);
+ if ($status === null) {
+ return false;
+ }
+
+ $status_map = array_fuse($status_list);
+ return isset($status_map[$status]);
+ }
+
+ protected function applyAuditorEffect(
+ PhabricatorRepositoryCommit $commit,
+ PhabricatorUser $viewer,
+ $value,
+ $status) {
+
+ $audits = $commit->getAudits();
+ $audits = mpull($audits, null, 'getAuditorPHID');
+
+ $map = array();
+
+ $with_authority = ($status != PhabricatorAuditStatusConstants::RESIGNED);
+ if ($with_authority) {
+ $has_authority = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser(
+ $viewer);
+ $has_authority = array_fuse($has_authority);
+ foreach ($audits as $audit) {
+ $auditor_phid = $audit->getAuditorPHID();
+ if (isset($has_authority[$auditor_phid])) {
+ $map[$auditor_phid] = $status;
+ }
+ }
+ }
+
+ // In all cases, you affect yourself.
+ $map[$viewer->getPHID()] = $status;
+
+ $this->updateAudits($commit, $map);
+ }
+
+}
diff --git a/src/applications/diffusion/xaction/DiffusionCommitAuditorsTransaction.php b/src/applications/diffusion/xaction/DiffusionCommitAuditorsTransaction.php
--- a/src/applications/diffusion/xaction/DiffusionCommitAuditorsTransaction.php
+++ b/src/applications/diffusion/xaction/DiffusionCommitAuditorsTransaction.php
@@ -75,22 +75,7 @@
}
}
- foreach ($new as $phid => $status) {
- $auditor = idx($auditors, $phid);
- if (!$auditor) {
- $auditor = id(new PhabricatorRepositoryAuditRequest())
- ->setAuditorPHID($phid)
- ->setCommitPHID($object->getPHID());
- } else {
- if ($auditor->getAuditStatus() === $status) {
- continue;
- }
- }
-
- $auditor
- ->setAuditStatus($status)
- ->save();
- }
+ $this->updateAudits($object, $new);
}
public function getTitle() {
diff --git a/src/applications/diffusion/xaction/DiffusionCommitConcernTransaction.php b/src/applications/diffusion/xaction/DiffusionCommitConcernTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/xaction/DiffusionCommitConcernTransaction.php
@@ -0,0 +1,70 @@
+<?php
+
+final class DiffusionCommitConcernTransaction
+ extends DiffusionCommitAuditTransaction {
+
+ const TRANSACTIONTYPE = 'diffusion.commit.concern';
+ const ACTIONKEY = 'concern';
+
+ protected function getCommitActionLabel() {
+ return pht("Raise Concern \xE2\x9C\x98");
+ }
+
+ protected function getCommitActionDescription() {
+ return pht('This commit will be returned to the author for consideration.');
+ }
+
+ public function getIcon() {
+ return 'fa-times-circle-o';
+ }
+
+ public function getColor() {
+ return 'red';
+ }
+
+ protected function getCommitActionOrder() {
+ return 600;
+ }
+
+ public function generateOldValue($object) {
+ $actor = $this->getActor();
+ return $this->isViewerRejectingAuditor($object, $actor);
+ }
+
+ public function applyExternalEffects($object, $value) {
+ $status = PhabricatorAuditStatusConstants::CONCERNED;
+ $actor = $this->getActor();
+ $this->applyAuditorEffect($object, $actor, $value, $status);
+ }
+
+ protected function validateAction($object, PhabricatorUser $viewer) {
+ if ($this->isViewerCommitAuthor($object, $viewer)) {
+ throw new Exception(
+ pht(
+ 'You can not raise a concern with this commit because you are '.
+ 'the commit author. You can only raise concerns with commits '.
+ 'you did not author.'));
+ }
+
+ if ($this->isViewerRejectingAuditor($object, $viewer)) {
+ throw new Exception(
+ pht(
+ 'You can not raise a concern with this commit because you have '.
+ 'already raised a concern with it.'));
+ }
+ }
+
+ public function getTitle() {
+ return pht(
+ '%s raised a concern with this commit.',
+ $this->renderAuthor());
+ }
+
+ public function getTitleForFeed() {
+ return pht(
+ '%s raised a concern with %s.',
+ $this->renderAuthor(),
+ $this->renderObject());
+ }
+
+}
diff --git a/src/applications/diffusion/xaction/DiffusionCommitResignTransaction.php b/src/applications/diffusion/xaction/DiffusionCommitResignTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/xaction/DiffusionCommitResignTransaction.php
@@ -0,0 +1,62 @@
+<?php
+
+final class DiffusionCommitResignTransaction
+ extends DiffusionCommitAuditTransaction {
+
+ const TRANSACTIONTYPE = 'diffusion.commit.resign';
+ const ACTIONKEY = 'resign';
+
+ protected function getCommitActionLabel() {
+ return pht('Resign as Auditor');
+ }
+
+ protected function getCommitActionDescription() {
+ return pht('You will resign as an auditor for this commit.');
+ }
+
+ public function getIcon() {
+ return 'fa-flag';
+ }
+
+ public function getColor() {
+ return 'orange';
+ }
+
+ protected function getCommitActionOrder() {
+ return 700;
+ }
+
+ public function generateOldValue($object) {
+ $actor = $this->getActor();
+ return !$this->isViewerAnyAuditor($object, $actor);
+ }
+
+ public function applyExternalEffects($object, $value) {
+ $status = PhabricatorAuditStatusConstants::RESIGNED;
+ $actor = $this->getActor();
+ $this->applyAuditorEffect($object, $actor, $value, $status);
+ }
+
+ protected function validateAction($object, PhabricatorUser $viewer) {
+ if (!$this->isViewerAnyAuditor($object, $viewer)) {
+ throw new Exception(
+ pht(
+ 'You can not resign from this commit because you are not an '.
+ 'auditor.'));
+ }
+ }
+
+ public function getTitle() {
+ return pht(
+ '%s resigned from this commit.',
+ $this->renderAuthor());
+ }
+
+ public function getTitleForFeed() {
+ return pht(
+ '%s resigned from %s.',
+ $this->renderAuthor(),
+ $this->renderObject());
+ }
+
+}
diff --git a/src/applications/diffusion/xaction/DiffusionCommitTransactionType.php b/src/applications/diffusion/xaction/DiffusionCommitTransactionType.php
--- a/src/applications/diffusion/xaction/DiffusionCommitTransactionType.php
+++ b/src/applications/diffusion/xaction/DiffusionCommitTransactionType.php
@@ -1,4 +1,37 @@
<?php
abstract class DiffusionCommitTransactionType
- extends PhabricatorModularTransactionType {}
+ extends PhabricatorModularTransactionType {
+
+ protected function updateAudits(
+ PhabricatorRepositoryCommit $commit,
+ array $new) {
+
+ $audits = $commit->getAudits();
+ $audits = mpull($audits, null, 'getAuditorPHID');
+
+ foreach ($new as $phid => $status) {
+ $audit = idx($audits, $phid);
+ if (!$audit) {
+ $audit = id(new PhabricatorRepositoryAuditRequest())
+ ->setAuditorPHID($phid)
+ ->setCommitPHID($commit->getPHID());
+
+ $audits[$phid] = $audit;
+ } else {
+ if ($audit->getAuditStatus() === $status) {
+ continue;
+ }
+ }
+
+ $audit
+ ->setAuditStatus($status)
+ ->save();
+ }
+
+ $commit->attachAudits($audits);
+
+ return $audits;
+ }
+
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jan 31, 7:33 AM (8 h, 58 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7077784
Default Alt Text
D17182.id41322.diff (19 KB)
Attached To
Mode
D17182: Add modern "Accept", "Raise Concern" and "Resign" transactions to Audit
Attached
Detach File
Event Timeline
Log In to Comment