Page MenuHomePhabricator

D17181.id41317.diff
No OneTemporary

D17181.id41317.diff

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
@@ -613,6 +613,7 @@
'DiffusionCommandEngine' => 'applications/diffusion/protocol/DiffusionCommandEngine.php',
'DiffusionCommandEngineTestCase' => 'applications/diffusion/protocol/__tests__/DiffusionCommandEngineTestCase.php',
'DiffusionCommitAffectedFilesHeraldField' => 'applications/diffusion/herald/DiffusionCommitAffectedFilesHeraldField.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',
@@ -659,6 +660,7 @@
'DiffusionCommitRevisionReviewersHeraldField' => 'applications/diffusion/herald/DiffusionCommitRevisionReviewersHeraldField.php',
'DiffusionCommitRevisionSubscribersHeraldField' => 'applications/diffusion/herald/DiffusionCommitRevisionSubscribersHeraldField.php',
'DiffusionCommitTagsController' => 'applications/diffusion/controller/DiffusionCommitTagsController.php',
+ 'DiffusionCommitTransactionType' => 'applications/diffusion/xaction/DiffusionCommitTransactionType.php',
'DiffusionCompareController' => 'applications/diffusion/controller/DiffusionCompareController.php',
'DiffusionConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionConduitAPIMethod.php',
'DiffusionController' => 'applications/diffusion/controller/DiffusionController.php',
@@ -5307,6 +5309,7 @@
'DiffusionCommandEngine' => 'Phobject',
'DiffusionCommandEngineTestCase' => 'PhabricatorTestCase',
'DiffusionCommitAffectedFilesHeraldField' => 'DiffusionCommitHeraldField',
+ 'DiffusionCommitAuditorsTransaction' => 'DiffusionCommitTransactionType',
'DiffusionCommitAuthorHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitAutocloseHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitBranchesController' => 'DiffusionController',
@@ -5353,6 +5356,7 @@
'DiffusionCommitRevisionReviewersHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitRevisionSubscribersHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitTagsController' => 'DiffusionController',
+ 'DiffusionCommitTransactionType' => 'PhabricatorModularTransactionType',
'DiffusionCompareController' => 'DiffusionController',
'DiffusionConduitAPIMethod' => 'ConduitAPIMethod',
'DiffusionController' => 'PhabricatorController',
@@ -6756,7 +6760,7 @@
'PhabricatorAuditPreviewController' => 'PhabricatorAuditController',
'PhabricatorAuditReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
'PhabricatorAuditStatusConstants' => 'Phobject',
- 'PhabricatorAuditTransaction' => 'PhabricatorApplicationTransaction',
+ 'PhabricatorAuditTransaction' => 'PhabricatorModularTransaction',
'PhabricatorAuditTransactionComment' => 'PhabricatorApplicationTransactionComment',
'PhabricatorAuditTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorAuditTransactionView' => 'PhabricatorApplicationTransactionView',
diff --git a/src/applications/audit/storage/PhabricatorAuditTransaction.php b/src/applications/audit/storage/PhabricatorAuditTransaction.php
--- a/src/applications/audit/storage/PhabricatorAuditTransaction.php
+++ b/src/applications/audit/storage/PhabricatorAuditTransaction.php
@@ -1,7 +1,7 @@
<?php
final class PhabricatorAuditTransaction
- extends PhabricatorApplicationTransaction {
+ extends PhabricatorModularTransaction {
const TYPE_COMMIT = 'audit:commit';
@@ -20,6 +20,10 @@
return 'audit';
}
+ public function getBaseTransactionClass() {
+ return 'DiffusionCommitTransactionType';
+ }
+
public function getApplicationTransactionType() {
return PhabricatorRepositoryCommitPHIDType::TYPECONST;
}
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
@@ -35,12 +35,14 @@
return id(new PhabricatorRepositoryCommit())
->attachRepository($repository)
- ->attachCommitData($data);
+ ->attachCommitData($data)
+ ->attachAudits(array());
}
protected function newObjectQuery() {
return id(new DiffusionCommitQuery())
- ->needCommitData(true);
+ ->needCommitData(true)
+ ->needAuditRequests(true);
}
protected function getObjectCreateTitleText($object) {
@@ -77,6 +79,19 @@
$fields = array();
+ $fields[] = id(new PhabricatorDatasourceEditField())
+ ->setKey('auditors')
+ ->setLabel(pht('Auditors'))
+ ->setDatasource(new DiffusionAuditorDatasource())
+ ->setUseEdgeTransactions(true)
+ ->setTransactionType(
+ DiffusionCommitAuditorsTransaction::TRANSACTIONTYPE)
+ ->setCommentActionLabel(pht('Change Auditors'))
+ ->setDescription(pht('Auditors for this commit.'))
+ ->setConduitDescription(pht('Change the auditors for this commit.'))
+ ->setConduitTypeDescription(pht('New auditors.'))
+ ->setValue($object->getAuditorPHIDsForEdit());
+
$reason = $data->getCommitDetail('autocloseReason', false);
$reason = PhabricatorRepository::BECAUSE_AUTOCLOSE_FORCED;
if ($reason !== false) {
diff --git a/src/applications/diffusion/xaction/DiffusionCommitAuditorsTransaction.php b/src/applications/diffusion/xaction/DiffusionCommitAuditorsTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/xaction/DiffusionCommitAuditorsTransaction.php
@@ -0,0 +1,231 @@
+<?php
+
+final class DiffusionCommitAuditorsTransaction
+ extends DiffusionCommitTransactionType {
+
+ const TRANSACTIONTYPE = 'diffusion.commit.auditors';
+
+ public function generateOldValue($object) {
+ $auditors = $object->getAudits();
+ return mpull($auditors, 'getAuditStatus', 'getAuditorPHID');
+ }
+
+ public function generateNewValue($object, $value) {
+ $actor = $this->getActor();
+
+ $auditors = $this->generateOldValue($object);
+ $old_auditors = $auditors;
+
+ $request_status = PhabricatorAuditStatusConstants::AUDIT_REQUESTED;
+
+ $rem = idx($value, '-', array());
+ foreach ($rem as $phid) {
+ unset($auditors[$phid]);
+ }
+
+ $add = idx($value, '+', array());
+ $add_map = array();
+ foreach ($add as $phid) {
+ $add_map[$phid] = $request_status;
+ }
+
+ $set = idx($value, '=', null);
+ if ($set !== null) {
+ foreach ($set as $phid) {
+ $add_map[$phid] = $request_status;
+ }
+
+ $auditors = array();
+ }
+
+ foreach ($add_map as $phid => $new_status) {
+ $old_status = idx($old_auditors, $phid);
+
+ if ($old_status) {
+ $auditors[$phid] = $old_status;
+ continue;
+ }
+
+ $auditors[$phid] = $new_status;
+ }
+
+ return $auditors;
+ }
+
+ public function getTransactionHasEffect($object, $old, $new) {
+ ksort($old);
+ ksort($new);
+ return ($old !== $new);
+ }
+
+ public function applyExternalEffects($object, $value) {
+ $src_phid = $object->getPHID();
+
+ $old = $this->generateOldValue($object);
+ $new = $value;
+
+ $auditors = $object->getAudits();
+ $auditors = mpull($auditors, null, 'getAuditorPHID');
+
+ $rem = array_diff_key($old, $new);
+ foreach ($rem as $phid => $status) {
+ $auditor = idx($auditors, $phid);
+ if ($auditor) {
+ $auditor->delete();
+ }
+ }
+
+ 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();
+ }
+ }
+
+ public function getTitle() {
+ $old = $this->getOldValue();
+ $new = $this->getNewValue();
+
+ $rem = array_diff_key($old, $new);
+ $add = array_diff_key($new, $old);
+ $rem_phids = array_keys($rem);
+ $add_phids = array_keys($add);
+ $total_count = count($rem) + count($add);
+
+ if ($rem && $add) {
+ return pht(
+ '%s edited %s auditor(s), removed %s: %s; added %s: %s.',
+ $this->renderAuthor(),
+ new PhutilNumber($total_count),
+ phutil_count($rem_phids),
+ $this->renderHandleList($rem_phids),
+ phutil_count($add_phids),
+ $this->renderHandleList($add_phids));
+ } else if ($add) {
+ return pht(
+ '%s added %s auditor(s): %s.',
+ $this->renderAuthor(),
+ phutil_count($add_phids),
+ $this->renderHandleList($add_phids));
+ } else {
+ return pht(
+ '%s removed %s auditor(s): %s.',
+ $this->renderAuthor(),
+ phutil_count($rem_phids),
+ $this->renderHandleList($rem_phids));
+ }
+ }
+
+ public function getTitleForFeed() {
+ $old = $this->getOldValue();
+ $new = $this->getNewValue();
+
+ $rem = array_diff_key($old, $new);
+ $add = array_diff_key($new, $old);
+ $rem_phids = array_keys($rem);
+ $add_phids = array_keys($add);
+ $total_count = count($rem) + count($add);
+
+ if ($rem && $add) {
+ return pht(
+ '%s edited %s auditor(s) for %s, removed %s: %s; added %s: %s.',
+ $this->renderAuthor(),
+ new PhutilNumber($total_count),
+ $this->renderObject(),
+ phutil_count($rem_phids),
+ $this->renderHandleList($rem_phids),
+ phutil_count($add_phids),
+ $this->renderHandleList($add_phids));
+ } else if ($add) {
+ return pht(
+ '%s added %s auditor(s) for %s: %s.',
+ $this->renderAuthor(),
+ phutil_count($add_phids),
+ $this->renderObject(),
+ $this->renderHandleList($add_phids));
+ } else {
+ return pht(
+ '%s removed %s auditor(s) for %s: %s.',
+ $this->renderAuthor(),
+ phutil_count($rem_phids),
+ $this->renderObject(),
+ $this->renderHandleList($rem_phids));
+ }
+ }
+
+ public function validateTransactions($object, array $xactions) {
+ $actor = $this->getActor();
+ $errors = array();
+
+ if (!$xactions) {
+ return $errors;
+ }
+
+ $author_phid = $object->getAuthorPHID();
+ $can_author_close_key = 'audit.can-author-close-audit';
+ $can_author_close = PhabricatorEnv::getEnvConfig($can_author_close_key);
+
+ $old = $this->generateOldValue($object);
+ foreach ($xactions as $xaction) {
+ $new = $this->generateNewValue($object, $xaction->getNewValue());
+
+ $add = array_diff_key($new, $old);
+ if (!$add) {
+ continue;
+ }
+
+ $objects = id(new PhabricatorObjectQuery())
+ ->setViewer($actor)
+ ->withPHIDs(array_keys($add))
+ ->execute();
+ $objects = mpull($objects, null, 'getPHID');
+
+ foreach ($add as $phid => $status) {
+ if (!isset($objects[$phid])) {
+ $errors[] = $this->newInvalidError(
+ pht(
+ 'Auditor "%s" is not a valid object.',
+ $phid),
+ $xaction);
+ continue;
+ }
+
+ switch (phid_get_type($phid)) {
+ case PhabricatorPeopleUserPHIDType::TYPECONST:
+ case PhabricatorOwnersPackagePHIDType::TYPECONST:
+ case PhabricatorProjectProjectPHIDType::TYPECONST:
+ break;
+ default:
+ $errors[] = $this->newInvalidError(
+ pht(
+ 'Auditor "%s" must be a user, a package, or a project.',
+ $phid),
+ $xaction);
+ continue 2;
+ }
+
+ $is_self = ($phid === $author_phid);
+ if ($is_self && !$can_author_close) {
+ $errors[] = $this->newInvalidError(
+ pht('The author of a commit can not be an auditor.'),
+ $xaction);
+ continue;
+ }
+ }
+ }
+
+ return $errors;
+ }
+
+}
diff --git a/src/applications/diffusion/xaction/DiffusionCommitTransactionType.php b/src/applications/diffusion/xaction/DiffusionCommitTransactionType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diffusion/xaction/DiffusionCommitTransactionType.php
@@ -0,0 +1,4 @@
+<?php
+
+abstract class DiffusionCommitTransactionType
+ extends PhabricatorModularTransactionType {}
diff --git a/src/applications/repository/storage/PhabricatorRepositoryCommit.php b/src/applications/repository/storage/PhabricatorRepositoryCommit.php
--- a/src/applications/repository/storage/PhabricatorRepositoryCommit.php
+++ b/src/applications/repository/storage/PhabricatorRepositoryCommit.php
@@ -203,6 +203,11 @@
return $authority_audits;
}
+ public function getAuditorPHIDsForEdit() {
+ $audits = $this->getAudits();
+ return mpull($audits, 'getAuditorPHID');
+ }
+
public function save() {
if (!$this->mailKey) {
$this->mailKey = Filesystem::readRandomCharacters(20);

File Metadata

Mime Type
text/plain
Expires
Sat, Mar 22, 9:48 PM (3 w, 3 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7717458
Default Alt Text
D17181.id41317.diff (13 KB)

Event Timeline