@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Use CustomField for `differential.updaterevision`

Summary: Ref T2222. Ref T3794. Medium term goal is to remove `DifferentialRevisionEditor`. This removes one of two callsites.

Test Plan: Used `arc diff --edit` to repeatedly update a revision, making changes to various fields.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T3794, T2222

Differential Revision: https://secure.phabricator.com/D8451

+135 -24
+103 -20
src/applications/differential/conduit/ConduitAPI_differential_updaterevision_Method.php
··· 1 1 <?php 2 2 3 - /** 4 - * @group conduit 5 - */ 6 3 final class ConduitAPI_differential_updaterevision_Method 7 4 extends ConduitAPIMethod { 8 5 9 6 public function getMethodDescription() { 10 - return "Update a Differential revision."; 7 + return pht("Update a Differential revision."); 11 8 } 12 9 13 10 public function defineParamTypes() { ··· 33 30 } 34 31 35 32 protected function execute(ConduitAPIRequest $request) { 33 + $viewer = $request->getUser(); 34 + 36 35 $diff = id(new DifferentialDiffQuery()) 37 - ->setViewer($request->getUser()) 36 + ->setViewer($viewer) 38 37 ->withIDs(array($request->getValue('diffid'))) 39 38 ->executeOne(); 40 39 if (!$diff) { ··· 44 43 $revision = id(new DifferentialRevisionQuery()) 45 44 ->setViewer($request->getUser()) 46 45 ->withIDs(array($request->getValue('id'))) 46 + ->needReviewerStatus(true) 47 + ->needActiveDiffs(true) 48 + ->requireCapabilities( 49 + array( 50 + PhabricatorPolicyCapability::CAN_VIEW, 51 + PhabricatorPolicyCapability::CAN_EDIT, 52 + )) 47 53 ->executeOne(); 48 54 if (!$revision) { 49 55 throw new ConduitException('ERR_BAD_REVISION'); 50 56 } 51 57 52 - if ($request->getUser()->getPHID() !== $revision->getAuthorPHID()) { 53 - throw new ConduitException('ERR_WRONG_USER'); 58 + if ($revision->getStatus() == ArcanistDifferentialRevisionStatus::CLOSED) { 59 + throw new ConduitException('ERR_CLOSED'); 54 60 } 55 61 56 - if ($revision->getStatus() == ArcanistDifferentialRevisionStatus::CLOSED) { 57 - throw new ConduitException('ERR_CLOSED'); 62 + $field_list = PhabricatorCustomField::getObjectFields( 63 + $revision, 64 + DifferentialCustomField::ROLE_COMMITMESSAGEEDIT); 65 + 66 + $field_list 67 + ->setViewer($viewer) 68 + ->readFieldsFromStorage($revision); 69 + $field_map = mpull($field_list->getFields(), null, 'getFieldKeyForConduit'); 70 + 71 + $xactions = array(); 72 + 73 + $xactions[] = id(new DifferentialTransaction()) 74 + ->setTransactionType(DifferentialTransaction::TYPE_UPDATE) 75 + ->setNewValue($diff->getPHID()); 76 + 77 + $values = $request->getValue('fields', array()); 78 + foreach ($values as $key => $value) { 79 + $field = idx($field_map, $key); 80 + if (!$field) { 81 + // NOTE: We're just ignoring fields we don't know about. This isn't 82 + // ideal, but the way the workflow currently works involves us getting 83 + // several read-only fields, like the revision ID field, which we should 84 + // just skip. 85 + continue; 86 + } 87 + 88 + $role = PhabricatorCustomField::ROLE_APPLICATIONTRANSACTIONS; 89 + if (!$field->shouldEnableForRole($role)) { 90 + throw new Exception( 91 + pht( 92 + 'Request attempts to update field "%s", but that field can not '. 93 + 'perform transactional updates.', 94 + $key)); 95 + } 96 + 97 + // TODO: This is fairly similar to PhabricatorCustomField's 98 + // buildFieldTransactionsFromRequest() method, but that's currently not 99 + // easy to reuse. 100 + 101 + $transaction_type = $field->getApplicationTransactionType(); 102 + $xaction = id(new DifferentialTransaction()) 103 + ->setTransactionType($transaction_type); 104 + 105 + if ($transaction_type == PhabricatorTransactions::TYPE_CUSTOMFIELD) { 106 + // For TYPE_CUSTOMFIELD transactions only, we provide the old value 107 + // as an input. 108 + $old_value = $field->getOldValueForApplicationTransactions(); 109 + $xaction->setOldValue($old_value); 110 + } 111 + 112 + // The transaction itself will be validated so this is somewhat 113 + // redundant, but this validator will sometimes give us a better error 114 + // message or a better reaction to a bad value type. 115 + $field->validateCommitMessageValue($value); 116 + $field->readValueFromCommitMessage($value); 117 + 118 + $xaction 119 + ->setNewValue($field->getNewValueForApplicationTransactions()); 120 + 121 + if ($transaction_type == PhabricatorTransactions::TYPE_CUSTOMFIELD) { 122 + // For TYPE_CUSTOMFIELD transactions, add the field key in metadata. 123 + $xaction->setMetadataValue('customfield:key', $field->getFieldKey()); 124 + } 125 + 126 + $metadata = $field->getApplicationTransactionMetadata(); 127 + foreach ($metadata as $meta_key => $meta_value) { 128 + $xaction->setMetadataValue($meta_key, $meta_value); 129 + } 130 + 131 + $xactions[] = $xaction; 58 132 } 59 133 60 - $content_source = PhabricatorContentSource::newForSource( 61 - PhabricatorContentSource::SOURCE_CONDUIT, 62 - array()); 134 + $message = $request->getValue('message'); 135 + if (strlen($message)) { 136 + // This is a little awkward, and should maybe move inside the transaction 137 + // editor. It largely exists for legacy reasons. 138 + $first_line = head(phutil_split_lines($message, false)); 139 + $diff->setDescription($first_line); 140 + $diff->save(); 63 141 64 - $editor = new DifferentialRevisionEditor( 65 - $revision); 66 - $editor->setActor($request->getUser()); 67 - $editor->setContentSource($content_source); 68 - $fields = $request->getValue('fields'); 69 - $editor->addDiff($diff, $request->getValue('message')); 70 - $editor->copyFieldsFromConduit($fields); 142 + $xactions[] = id(new DifferentialTransaction()) 143 + ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) 144 + ->attachComment( 145 + id(new DifferentialTransactionComment()) 146 + ->setContent($message)); 147 + } 148 + 149 + $editor = id(new DifferentialTransactionEditor()) 150 + ->setActor($viewer) 151 + ->setContentSourceFromConduitRequest($request) 152 + ->setContinueOnNoEffect(true) 153 + ->setContinueOnMissingFields(true); 71 154 72 - $editor->save(); 155 + $editor->applyTransactions($revision, $xactions); 73 156 74 157 return array( 75 158 'revisionid' => $revision->getID(),
+31 -4
src/applications/differential/customfield/DifferentialManiphestTasksField.php
··· 1 1 <?php 2 2 3 3 final class DifferentialManiphestTasksField 4 - extends DifferentialCustomField { 4 + extends DifferentialCoreCustomField { 5 5 6 6 public function getFieldKey() { 7 7 return 'differential:maniphest-tasks'; ··· 12 12 } 13 13 14 14 public function canDisableField() { 15 + return false; 16 + } 17 + 18 + public function shouldAppearInEditView() { 15 19 return false; 16 20 } 17 21 ··· 31 35 return $this->getFieldName(); 32 36 } 33 37 34 - public function getRequiredHandlePHIDsForPropertyView() { 35 - if (!$this->getObject()->getPHID()) { 38 + public function readValueFromRevision(DifferentialRevision $revision) { 39 + if (!$revision->getPHID()) { 36 40 return array(); 37 41 } 38 42 39 43 return PhabricatorEdgeQuery::loadDestinationPHIDs( 40 - $this->getObject()->getPHID(), 44 + $revision->getPHID(), 41 45 PhabricatorEdgeConfig::TYPE_DREV_HAS_RELATED_TASK); 46 + } 47 + 48 + public function getApplicationTransactionType() { 49 + return PhabricatorTransactions::TYPE_EDGE; 50 + } 51 + 52 + public function getApplicationTransactionMetadata() { 53 + return array( 54 + 'edge:type' => PhabricatorEdgeConfig::TYPE_DREV_HAS_RELATED_TASK, 55 + ); 56 + } 57 + 58 + public function getNewValueForApplicationTransactions() { 59 + $edges = array(); 60 + foreach ($this->getValue() as $phid) { 61 + $edges[$phid] = $phid; 62 + } 63 + 64 + return array('=' => $edges); 65 + } 66 + 67 + public function getRequiredHandlePHIDsForPropertyView() { 68 + return $this->getValue(); 42 69 } 43 70 44 71 public function renderPropertyViewValue(array $handles) {
+1
src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
··· 1496 1496 $field_list = PhabricatorCustomField::getObjectFields( 1497 1497 $object, 1498 1498 PhabricatorCustomField::ROLE_EDIT); 1499 + $field_list->setViewer($this->getActor()); 1499 1500 1500 1501 $role_xactions = PhabricatorCustomField::ROLE_APPLICATIONTRANSACTIONS; 1501 1502 foreach ($field_list->getFields() as $field) {