@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.

Add a "Pro" version of the Differential comment save controller

Summary: Ref T2222. Adds a mostly-functional "Pro" comment controller. This does the core stuff, but does not yet do actions (accept, reject, etc.) or inline comments.

Test Plan: Changed the `if (false)` to an `if (true)`, then made some comments, etc. This is normally unreachable.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2222

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

+192 -55
+2
src/__phutil_library_map__.php
··· 354 354 'DifferentialCommentPreviewController' => 'applications/differential/controller/DifferentialCommentPreviewController.php', 355 355 'DifferentialCommentQuery' => 'applications/differential/query/DifferentialCommentQuery.php', 356 356 'DifferentialCommentSaveController' => 'applications/differential/controller/DifferentialCommentSaveController.php', 357 + 'DifferentialCommentSaveControllerPro' => 'applications/differential/controller/DifferentialCommentSaveControllerPro.php', 357 358 'DifferentialCommitsFieldSpecification' => 'applications/differential/field/specification/DifferentialCommitsFieldSpecification.php', 358 359 'DifferentialConflictsFieldSpecification' => 'applications/differential/field/specification/DifferentialConflictsFieldSpecification.php', 359 360 'DifferentialController' => 'applications/differential/controller/DifferentialController.php', ··· 2903 2904 'DifferentialCommentPreviewController' => 'DifferentialController', 2904 2905 'DifferentialCommentQuery' => 'PhabricatorOffsetPagedQuery', 2905 2906 'DifferentialCommentSaveController' => 'DifferentialController', 2907 + 'DifferentialCommentSaveControllerPro' => 'DifferentialController', 2906 2908 'DifferentialCommitsFieldSpecification' => 'DifferentialFieldSpecification', 2907 2909 'DifferentialConflictsFieldSpecification' => 'DifferentialFieldSpecification', 2908 2910 'DifferentialController' => 'PhabricatorController',
+1
src/applications/differential/application/PhabricatorApplicationDifferential.php
··· 56 56 'comment/' => array( 57 57 'preview/(?P<id>[1-9]\d*)/' => 'DifferentialCommentPreviewController', 58 58 'save/' => 'DifferentialCommentSaveController', 59 + 'savepro/(?P<id>[1-9]\d*)/' => 'DifferentialCommentSaveControllerPro', 59 60 'inline/' => array( 60 61 'preview/(?P<id>[1-9]\d*)/' 61 62 => 'DifferentialInlineCommentPreviewController',
+133
src/applications/differential/controller/DifferentialCommentSaveControllerPro.php
··· 1 + <?php 2 + 3 + final class DifferentialCommentSaveControllerPro 4 + extends DifferentialController { 5 + 6 + private $id; 7 + 8 + public function willProcessRequest(array $data) { 9 + $this->id = $data['id']; 10 + } 11 + 12 + public function processRequest() { 13 + $request = $this->getRequest(); 14 + $viewer = $request->getUser(); 15 + 16 + if (!$request->isFormPost()) { 17 + return new Aphront400Response(); 18 + } 19 + 20 + $revision = id(new DifferentialRevisionQuery()) 21 + ->setViewer($viewer) 22 + ->withIDs(array($this->id)) 23 + ->needReviewerStatus(true) 24 + ->executeOne(); 25 + if (!$revision) { 26 + return new Aphront404Response(); 27 + } 28 + 29 + $type_action = DifferentialTransaction::TYPE_ACTION; 30 + $type_subscribers = PhabricatorTransactions::TYPE_SUBSCRIBERS; 31 + $type_edge = PhabricatorTransactions::TYPE_EDGE; 32 + $type_comment = PhabricatorTransactions::TYPE_COMMENT; 33 + $type_inline = DifferentialTransaction::TYPE_INLINE; 34 + 35 + $edge_reviewer = PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER; 36 + 37 + $xactions = array(); 38 + 39 + $action = $request->getStr('action'); 40 + switch ($action) { 41 + case DifferentialAction::ACTION_COMMENT: 42 + case DifferentialAction::ACTION_ADDREVIEWERS: 43 + case DifferentialAction::ACTION_ADDCCS: 44 + // These transaction types have no direct effect, they just 45 + // accompany other transaction types which can have an effect. 46 + break; 47 + default: 48 + $xactions[] = id(new DifferentialTransaction()) 49 + ->setTransactionType($type_action) 50 + ->setNewValue($request->getStr('action')); 51 + break; 52 + } 53 + 54 + $ccs = $request->getArr('ccs'); 55 + if ($ccs) { 56 + $xactions[] = id(new DifferentialTransaction()) 57 + ->setTransactionType($type_subscribers) 58 + ->setNewValue(array('+' => $ccs)); 59 + } 60 + 61 + $current_reviewers = mpull( 62 + $revision->getReviewerStatus(), 63 + null, 64 + 'getReviewerPHID'); 65 + 66 + $reviewer_edges = array(); 67 + $add_reviewers = $request->getArr('reviewers'); 68 + foreach ($add_reviewers as $reviewer_phid) { 69 + if (isset($current_reviewers[$reviewer_phid])) { 70 + continue; 71 + } 72 + $reviewer = new DifferentialReviewer( 73 + $reviewer_phid, 74 + array( 75 + 'status' => DifferentialReviewerStatus::STATUS_ADDED, 76 + )); 77 + $reviewer_edges[$reviewer_phid] = array( 78 + 'data' => $reviewer->getEdgeData(), 79 + ); 80 + } 81 + 82 + if ($add_reviewers) { 83 + $xactions[] = id(new DifferentialTransaction()) 84 + ->setTransactionType($type_edge) 85 + ->setMetadataValue('edge:type', $edge_reviewer) 86 + ->setNewValue(array('+' => $reviewer_edges)); 87 + } 88 + 89 + $comment = $request->getStr('comment'); 90 + if (strlen($comment)) { 91 + $xactions[] = id(new DifferentialTransaction()) 92 + ->setTransactionType($type_comment) 93 + ->attachComment( 94 + id(new DifferentialTransactionComment()) 95 + ->setRevisionPHID($revision->getPHID()) 96 + ->setContent($comment)); 97 + } 98 + 99 + // TODO: Inlines! 100 + 101 + $editor = id(new DifferentialTransactionEditor()) 102 + ->setActor($viewer) 103 + ->setContentSourceFromRequest($request) 104 + ->setContinueOnMissingFields(true) 105 + ->setContinueOnNoEffect($request->isContinueRequest()); 106 + 107 + $revision_uri = '/D'.$revision->getID(); 108 + 109 + try { 110 + $editor->applyTransactions($revision, $xactions); 111 + } catch (PhabricatorApplicationTransactionNoEffectException $ex) { 112 + return id(new PhabricatorApplicationTransactionNoEffectResponse()) 113 + ->setCancelURI($revision_uri) 114 + ->setException($ex); 115 + } 116 + 117 + // TODO: Diff change detection? 118 + 119 + $user = $request->getUser(); 120 + $draft = id(new PhabricatorDraft())->loadOneWhere( 121 + 'authorPHID = %s AND draftKey = %s', 122 + $user->getPHID(), 123 + 'differential-comment-'.$revision->getID()); 124 + if ($draft) { 125 + $draft->delete(); 126 + } 127 + DifferentialDraft::deleteAllDrafts($user->getPHID(), $revision->getPHID()); 128 + 129 + return id(new AphrontRedirectResponse()) 130 + ->setURI('/D'.$revision->getID()); 131 + } 132 + 133 + }
+9 -1
src/applications/differential/controller/DifferentialRevisionViewController.php
··· 342 342 $comment_form->setRevision($revision); 343 343 $comment_form->setAuxFields($aux_fields); 344 344 $comment_form->setActions($this->getRevisionCommentActions($revision)); 345 - $comment_form->setActionURI('/differential/comment/save/'); 345 + 346 + $action_uri = '/differential/comment/save/'; 347 + if (false) { 348 + // TODO: Temporary for testing the new comment workflow. 349 + $action_uri = $this->getApplicationURI( 350 + 'comment/savepro/'.$revision->getID().'/'); 351 + } 352 + 353 + $comment_form->setActionURI($action_uri); 346 354 $comment_form->setUser($user); 347 355 $comment_form->setDraft($draft); 348 356 $comment_form->setReviewers(mpull($reviewers, 'getFullName', 'getPHID'));
-40
src/applications/differential/editor/DifferentialRevisionEditor.php
··· 539 539 ->queueDocumentForIndexing($revision->getPHID()); 540 540 } 541 541 542 - public static function addCCAndUpdateRevision( 543 - $revision, 544 - $phid, 545 - PhabricatorUser $actor) { 546 - 547 - self::addCC($revision, $phid, $actor->getPHID()); 548 - 549 - $type = PhabricatorEdgeConfig::TYPE_OBJECT_HAS_UNSUBSCRIBER; 550 - id(new PhabricatorEdgeEditor()) 551 - ->setActor($actor) 552 - ->removeEdge($revision->getPHID(), $type, $phid) 553 - ->save(); 554 - } 555 - 556 - public static function removeCCAndUpdateRevision( 557 - $revision, 558 - $phid, 559 - PhabricatorUser $actor) { 560 - 561 - self::removeCC($revision, $phid, $actor->getPHID()); 562 - 563 - $type = PhabricatorEdgeConfig::TYPE_OBJECT_HAS_UNSUBSCRIBER; 564 - id(new PhabricatorEdgeEditor()) 565 - ->setActor($actor) 566 - ->addEdge($revision->getPHID(), $type, $phid) 567 - ->save(); 568 - } 569 - 570 542 public static function addCC( 571 543 DifferentialRevision $revision, 572 544 $phid, ··· 576 548 $revision->getCCPHIDs(), 577 549 $rem = array(), 578 550 $add = array($phid), 579 - $reason); 580 - } 581 - 582 - public static function removeCC( 583 - DifferentialRevision $revision, 584 - $phid, 585 - $reason) { 586 - return self::alterCCs( 587 - $revision, 588 - $revision->getCCPHIDs(), 589 - $rem = array($phid), 590 - $add = array(), 591 551 $reason); 592 552 } 593 553
+24 -1
src/applications/differential/editor/DifferentialTransactionEditor.php
··· 6 6 public function getTransactionTypes() { 7 7 $types = parent::getTransactionTypes(); 8 8 9 + $types[] = PhabricatorTransactions::TYPE_COMMENT; 9 10 $types[] = PhabricatorTransactions::TYPE_EDGE; 10 11 $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; 11 12 $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; 12 13 14 + $types[] = DifferentialTransaction::TYPE_ACTION; 15 + 13 16 /* 14 17 15 18 $types[] = DifferentialTransaction::TYPE_INLINE; 16 19 $types[] = DifferentialTransaction::TYPE_UPDATE; 17 - $types[] = DifferentialTransaction::TYPE_ACTION; 18 20 */ 19 21 20 22 return $types; ··· 29 31 return $object->getViewPolicy(); 30 32 case PhabricatorTransactions::TYPE_EDIT_POLICY: 31 33 return $object->getEditPolicy(); 34 + case DifferentialTransaction::TYPE_ACTION: 35 + return null; 32 36 } 33 37 34 38 return parent::getCustomTransactionOldValue($object, $xaction); ··· 41 45 switch ($xaction->getTransactionType()) { 42 46 case PhabricatorTransactions::TYPE_VIEW_POLICY: 43 47 case PhabricatorTransactions::TYPE_EDIT_POLICY: 48 + case DifferentialTransaction::TYPE_ACTION: 44 49 return $xaction->getNewValue(); 45 50 } 46 51 47 52 return parent::getCustomTransactionNewValue($object, $xaction); 48 53 } 49 54 55 + protected function transactionHasEffect( 56 + PhabricatorLiskDAO $object, 57 + PhabricatorApplicationTransaction $xaction) { 58 + 59 + switch ($xaction->getTransactionType()) { 60 + } 61 + 62 + return parent::transactionHasEffect($object, $xaction); 63 + } 64 + 65 + 50 66 protected function applyCustomInternalTransaction( 51 67 PhabricatorLiskDAO $object, 52 68 PhabricatorApplicationTransaction $xaction) { ··· 59 75 $object->setEditPolicy($xaction->getNewValue()); 60 76 return; 61 77 case PhabricatorTransactions::TYPE_SUBSCRIBERS: 78 + case PhabricatorTransactions::TYPE_COMMENT: 62 79 case PhabricatorTransactions::TYPE_EDGE: 63 80 // TODO: When removing reviewers, we may be able to move the revision 64 81 // to "Accepted". 65 82 return; 83 + case DifferentialTransaction::TYPE_ACTION: 84 + // TODO: For now, we're just shipping these through without acting 85 + // on them. 86 + return null; 66 87 } 67 88 68 89 return parent::applyCustomInternalTransaction($object, $xaction); ··· 78 99 return; 79 100 case PhabricatorTransactions::TYPE_SUBSCRIBERS: 80 101 case PhabricatorTransactions::TYPE_EDGE: 102 + case PhabricatorTransactions::TYPE_COMMENT: 103 + case DifferentialTransaction::TYPE_ACTION: 81 104 return; 82 105 } 83 106
+4 -13
src/applications/differential/mail/DifferentialReplyHandler.php
··· 114 114 115 115 switch ($command) { 116 116 case 'unsubscribe': 117 - $this->unsubscribeUser($this->getMailReceiver(), $actor); 117 + id(new PhabricatorSubscriptionsEditor()) 118 + ->setObject($this->getMailReceiver()) 119 + ->unsubscribe(array($actor->getPHID())) 120 + ->save(); 118 121 // TODO: Send the user a confirmation email? 119 122 return null; 120 123 } ··· 161 164 throw $ex; 162 165 } 163 166 } 164 - 165 - private function unsubscribeUser( 166 - DifferentialRevision $revision, 167 - PhabricatorUser $user) { 168 - 169 - $revision->loadRelationships(); 170 - DifferentialRevisionEditor::removeCCAndUpdateRevision( 171 - $revision, 172 - $user->getPHID(), 173 - $user); 174 - } 175 - 176 167 177 168 }
+14
src/applications/differential/storage/DifferentialTransaction.php
··· 115 115 return parent::getColor(); 116 116 } 117 117 118 + public function getNoEffectDescription() { 119 + switch ($this->getTransactionType()) { 120 + case PhabricatorTransactions::TYPE_EDGE: 121 + switch ($this->getMetadataValue('edge:type')) { 122 + case PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER: 123 + return pht( 124 + 'Those reviewers are already reviewing this revision.'); 125 + } 126 + } 127 + 128 + return parent::getNoEffectDescription(); 129 + } 130 + 131 + 118 132 }
+4
src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
··· 164 164 // NOTE: Custom fields have their old value pre-populated when they are 165 165 // built by PhabricatorCustomFieldList. 166 166 return $xaction->getOldValue(); 167 + case PhabricatorTransactions::TYPE_COMMENT: 168 + return null; 167 169 default: 168 170 return $this->getCustomTransactionOldValue($object, $xaction); 169 171 } ··· 184 186 case PhabricatorTransactions::TYPE_CUSTOMFIELD: 185 187 $field = $this->getCustomFieldForTransaction($object, $xaction); 186 188 return $field->getNewValueFromApplicationTransactions($xaction); 189 + case PhabricatorTransactions::TYPE_COMMENT: 190 + return null; 187 191 default: 188 192 return $this->getCustomTransactionNewValue($object, $xaction); 189 193 }
+1
src/applications/transactions/exception/PhabricatorApplicationTransactionNoEffectException.php
··· 12 12 13 13 $this->transactions = $transactions; 14 14 $this->anyEffect = $any_effect; 15 + $this->hasComment = $has_comment; 15 16 16 17 $message = array(); 17 18 $message[] = 'Transactions have no effect:';