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

Provide a transaction editor to perform Audit row writes

Summary:
Ref T4896. Replaces more custom stuff with standard stuff. In particular:

- No more fake proxy writes;
- no more fake detection of `@mentions`.

For now, the old code still applies most of the effects and handles feed and email.

Test Plan:
- Added comments.
- Added comments with inline comments.
- Added just inline comments.
- Added comments with Conduit.
- Previewed comments.
- Added CCs explicitly and with `@mentions`.
- Added auditors.
- Accepted a commit.

Reviewers: joshuaspence, btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T4896

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

+182 -112
+2
src/__phutil_library_map__.php
··· 1141 1141 'PhabricatorAuditCommitStatusConstants' => 'applications/audit/constants/PhabricatorAuditCommitStatusConstants.php', 1142 1142 'PhabricatorAuditController' => 'applications/audit/controller/PhabricatorAuditController.php', 1143 1143 'PhabricatorAuditDAO' => 'applications/audit/storage/PhabricatorAuditDAO.php', 1144 + 'PhabricatorAuditEditor' => 'applications/audit/editor/PhabricatorAuditEditor.php', 1144 1145 'PhabricatorAuditInlineComment' => 'applications/audit/storage/PhabricatorAuditInlineComment.php', 1145 1146 'PhabricatorAuditListController' => 'applications/audit/controller/PhabricatorAuditListController.php', 1146 1147 'PhabricatorAuditListView' => 'applications/audit/view/PhabricatorAuditListView.php', ··· 3934 3935 'PhabricatorAuditCommentEditor' => 'PhabricatorEditor', 3935 3936 'PhabricatorAuditController' => 'PhabricatorController', 3936 3937 'PhabricatorAuditDAO' => 'PhabricatorLiskDAO', 3938 + 'PhabricatorAuditEditor' => 'PhabricatorApplicationTransactionEditor', 3937 3939 'PhabricatorAuditInlineComment' => 'PhabricatorInlineCommentInterface', 3938 3940 'PhabricatorAuditListController' => 'PhabricatorAuditController', 3939 3941 'PhabricatorAuditListView' => 'AphrontView',
+7 -7
src/applications/audit/controller/PhabricatorAuditAddCommentController.php
··· 12 12 } 13 13 14 14 $commit_phid = $request->getStr('commit'); 15 - $commit = id(new PhabricatorRepositoryCommit())->loadOneWhere( 16 - 'phid = %s', 17 - $commit_phid); 15 + $commit = id(new DiffusionCommitQuery()) 16 + ->setViewer($user) 17 + ->withPHIDs(array($commit_phid)) 18 + ->executeOne(); 18 19 if (!$commit) { 19 20 return new Aphront404Response(); 20 21 } ··· 36 37 )); 37 38 break; 38 39 case PhabricatorAuditActionConstants::ADD_CCS: 39 - $ccs = $request->getArr('ccs'); 40 40 $comments[] = id(new PhabricatorAuditComment()) 41 - ->setAction(PhabricatorAuditActionConstants::ADD_CCS) 42 - ->setMetadata( 41 + ->setAction(PhabricatorTransactions::TYPE_SUBSCRIBERS) 42 + ->setNewValue( 43 43 array( 44 - PhabricatorAuditComment::METADATA_ADDED_CCS => $ccs, 44 + '+' => $request->getArr('ccs'), 45 45 )); 46 46 break; 47 47 case PhabricatorAuditActionConstants::COMMENT:
+7 -2
src/applications/audit/controller/PhabricatorAuditPreviewController.php
··· 37 37 38 38 $ccs = $request->getStrList('ccs'); 39 39 if ($action == PhabricatorAuditActionConstants::ADD_CCS && $ccs) { 40 - $action_xaction->setTransactionType($action); 41 - $action_xaction->setNewValue(array_fuse($ccs)); 40 + $action_xaction->setTransactionType( 41 + PhabricatorTransactions::TYPE_SUBSCRIBERS); 42 + 43 + // NOTE: This doesn't get processed before use, so just provide fake 44 + // values. 45 + $action_xaction->setOldValue(array()); 46 + $action_xaction->setNewValue($ccs); 42 47 } 43 48 44 49 $xactions[] = $action_xaction;
+26 -69
src/applications/audit/editor/PhabricatorAuditCommentEditor.php
··· 38 38 $commit->getPHID()); 39 39 } 40 40 41 - $content_blocks = array(); 42 - foreach ($comments as $comment) { 43 - $content_blocks[] = $comment->getContent(); 44 - } 45 - 46 - foreach ($inline_comments as $inline) { 47 - $content_blocks[] = $inline->getContent(); 48 - } 49 - 50 - // Find any "@mentions" in the content blocks. 51 - $mention_ccs = PhabricatorMarkupEngine::extractPHIDsFromMentions( 52 - $this->getActor(), 53 - $content_blocks); 54 - if ($mention_ccs) { 55 - $comments[] = id(new PhabricatorAuditComment()) 56 - ->setAction(PhabricatorAuditActionConstants::ADD_CCS) 57 - ->setMetadata( 58 - array( 59 - PhabricatorAuditComment::METADATA_ADDED_CCS => $mention_ccs, 60 - )); 61 - } 62 - 63 41 // When an actor submits an audit comment, we update all the audit requests 64 42 // they have authority over to reflect the most recent status. The general 65 43 // idea here is that if audit has triggered for, e.g., several packages, but ··· 92 70 break; 93 71 } 94 72 } 95 - 96 - $add_self_cc = false; 97 73 98 74 if ($action == PhabricatorAuditActionConstants::CLOSE) { 99 75 if (!PhabricatorEnv::getEnvConfig('audit.can-author-close-audit')) { ··· 181 157 case PhabricatorAuditActionConstants::COMMENT: 182 158 case PhabricatorAuditActionConstants::ADD_AUDITORS: 183 159 case PhabricatorAuditActionConstants::ADD_CCS: 184 - $add_self_cc = true; 185 160 break; 186 161 case PhabricatorAuditActionConstants::ACCEPT: 187 162 $new_status = PhabricatorAuditStatusConstants::ACCEPTED; ··· 208 183 } 209 184 210 185 $auditors = array(); 211 - $ccs = array(); 212 - 213 - if ($add_self_cc) { 214 - $ccs[] = $actor->getPHID(); 215 - } 216 186 217 187 foreach ($comments as $comment) { 218 188 $meta = $comment->getMetadata(); ··· 224 194 foreach ($auditor_phids as $phid) { 225 195 $auditors[] = $phid; 226 196 } 227 - 228 - $cc_phids = idx( 229 - $meta, 230 - PhabricatorAuditComment::METADATA_ADDED_CCS, 231 - array()); 232 - foreach ($cc_phids as $phid) { 233 - $ccs[] = $phid; 234 - } 235 197 } 236 198 237 199 $requests_by_auditor = mpull($requests, null, 'getAuditorPHID'); 238 200 $requests_phids = array_keys($requests_by_auditor); 239 201 240 - $ccs = array_diff($ccs, $requests_phids); 241 202 $auditors = array_diff($auditors, $requests_phids); 242 203 243 204 if ($auditors) { ··· 256 217 $commit->updateAuditStatus($requests); 257 218 $commit->save(); 258 219 259 - if ($ccs) { 260 - id(new PhabricatorSubscriptionsEditor()) 261 - ->setActor($actor) 262 - ->setObject($commit) 263 - ->subscribeExplicit($ccs) 264 - ->save(); 220 + // Convert old comments into real transactions and apply them with a 221 + // normal editor. 222 + 223 + $xactions = array(); 224 + foreach ($comments as $comment) { 225 + $xactions[] = $comment->getTransactionForSave(); 226 + } 227 + 228 + foreach ($inline_comments as $inline) { 229 + $xactions[] = id(new PhabricatorAuditTransaction()) 230 + ->setTransactionType(PhabricatorAuditActionConstants::INLINE) 231 + ->attachComment($inline->getTransactionComment()); 265 232 } 266 233 267 234 $content_source = PhabricatorContentSource::newForSource( 268 235 PhabricatorContentSource::SOURCE_LEGACY, 269 236 array()); 270 237 271 - foreach ($comments as $comment) { 272 - $comment 273 - ->setActorPHID($actor->getPHID()) 274 - ->setTargetPHID($commit->getPHID()) 275 - ->setContentSource($content_source) 276 - ->save(); 277 - } 278 - 279 - foreach ($inline_comments as $inline) { 280 - $xaction = id(new PhabricatorAuditComment()) 281 - ->setProxyComment($inline->getTransactionCommentForSave()) 282 - ->setAction(PhabricatorAuditActionConstants::INLINE) 283 - ->setActorPHID($actor->getPHID()) 284 - ->setTargetPHID($commit->getPHID()) 285 - ->setContentSource($content_source) 286 - ->save(); 287 - 288 - $comments[] = $xaction; 289 - } 238 + $editor = id(new PhabricatorAuditEditor()) 239 + ->setActor($actor) 240 + ->setContinueOnNoEffect(true) 241 + ->setContinueOnMissingFields(true) 242 + ->setContentSource($content_source) 243 + ->applyTransactions($commit, $xactions); 290 244 291 245 $feed_dont_publish_phids = array(); 292 246 foreach ($requests as $request) { ··· 396 350 assert_instances_of($other_comments, 'PhabricatorAuditComment'); 397 351 assert_instances_of($inline_comments, 'PhabricatorInlineCommentInterface'); 398 352 399 - $any_comment = head($comments); 400 - 401 353 $commit = $this->commit; 402 354 403 355 $data = $commit->loadCommitData(); ··· 421 373 PhabricatorAuditActionConstants::ADD_CCS => 'Added CCs', 422 374 PhabricatorAuditActionConstants::ADD_AUDITORS => 'Added Auditors', 423 375 ); 424 - $verb = idx($map, $any_comment->getAction(), 'Commented On'); 376 + if ($comments) { 377 + $any_action = head($comments)->getAction(); 378 + } else { 379 + $any_action = null; 380 + } 381 + $verb = idx($map, $any_action, 'Commented On'); 425 382 426 383 $reply_handler = self::newReplyHandlerForCommit($commit); 427 384 ··· 444 401 $email_to = array(); 445 402 $email_cc = array(); 446 403 447 - $email_to[$any_comment->getActorPHID()] = true; 404 + $email_to[$this->getActor()->getPHID()] = true; 448 405 449 406 $author_phid = $data->getCommitDetail('authorPHID'); 450 407 if ($author_phid) { ··· 493 450 ->setSubject("{$name}: {$summary}") 494 451 ->setSubjectPrefix($prefix) 495 452 ->setVarySubjectPrefix("[{$verb}]") 496 - ->setFrom($any_comment->getActorPHID()) 453 + ->setFrom($this->getActor()->getPHID()) 497 454 ->setThreadID($thread_id, $is_new) 498 455 ->addHeader('Thread-Topic', $thread_topic) 499 456 ->setRelatedPHID($commit->getPHID())
+114
src/applications/audit/editor/PhabricatorAuditEditor.php
··· 1 + <?php 2 + 3 + final class PhabricatorAuditEditor 4 + extends PhabricatorApplicationTransactionEditor { 5 + 6 + public function getTransactionTypes() { 7 + $types = parent::getTransactionTypes(); 8 + 9 + $types[] = PhabricatorTransactions::TYPE_COMMENT; 10 + 11 + // TODO: These will get modernized eventually, but that can happen one 12 + // at a time later on. 13 + $types[] = PhabricatorAuditActionConstants::ACTION; 14 + $types[] = PhabricatorAuditActionConstants::INLINE; 15 + $types[] = PhabricatorAuditActionConstants::ADD_AUDITORS; 16 + 17 + return $types; 18 + } 19 + 20 + protected function transactionHasEffect( 21 + PhabricatorLiskDAO $object, 22 + PhabricatorApplicationTransaction $xaction) { 23 + 24 + switch ($xaction->getTransactionType()) { 25 + case PhabricatorAuditActionConstants::INLINE: 26 + return $xaction->hasComment(); 27 + } 28 + 29 + return parent::transactionHasEffect($object, $xaction); 30 + } 31 + 32 + protected function getCustomTransactionOldValue( 33 + PhabricatorLiskDAO $object, 34 + PhabricatorApplicationTransaction $xaction) { 35 + switch ($xaction->getTransactionType()) { 36 + case PhabricatorAuditActionConstants::ACTION: 37 + case PhabricatorAuditActionConstants::INLINE: 38 + return null; 39 + case PhabricatorAuditActionConstants::ADD_AUDITORS: 40 + // TODO: For now, just record the added PHIDs. Eventually, turn these 41 + // into real edge transactions, probably? 42 + return array(); 43 + } 44 + 45 + return parent::getCustomTransactionOldValue($object, $xaction); 46 + } 47 + 48 + protected function getCustomTransactionNewValue( 49 + PhabricatorLiskDAO $object, 50 + PhabricatorApplicationTransaction $xaction) { 51 + 52 + switch ($xaction->getTransactionType()) { 53 + case PhabricatorAuditActionConstants::ACTION: 54 + case PhabricatorAuditActionConstants::INLINE: 55 + case PhabricatorAuditActionConstants::ADD_AUDITORS: 56 + return $xaction->getNewValue(); 57 + } 58 + 59 + return parent::getCustomTransactionNewValue($object, $xaction); 60 + } 61 + 62 + protected function applyCustomInternalTransaction( 63 + PhabricatorLiskDAO $object, 64 + PhabricatorApplicationTransaction $xaction) { 65 + 66 + switch ($xaction->getTransactionType()) { 67 + case PhabricatorTransactions::TYPE_COMMENT: 68 + case PhabricatorTransactions::TYPE_SUBSCRIBERS: 69 + case PhabricatorAuditActionConstants::ACTION: 70 + case PhabricatorAuditActionConstants::INLINE: 71 + case PhabricatorAuditActionConstants::ADD_AUDITORS: 72 + return; 73 + } 74 + 75 + return parent::applyCustomInternalTransaction($object, $xaction); 76 + } 77 + 78 + protected function applyCustomExternalTransaction( 79 + PhabricatorLiskDAO $object, 80 + PhabricatorApplicationTransaction $xaction) { 81 + 82 + switch ($xaction->getTransactionType()) { 83 + case PhabricatorTransactions::TYPE_COMMENT: 84 + case PhabricatorTransactions::TYPE_SUBSCRIBERS: 85 + case PhabricatorAuditActionConstants::ACTION: 86 + case PhabricatorAuditActionConstants::INLINE: 87 + return; 88 + case PhabricatorAuditActionConstants::ADD_AUDITORS: 89 + // TODO: For now, these are applied externally. 90 + return; 91 + } 92 + 93 + return parent::applyCustomExternalTransaction($object, $xaction); 94 + } 95 + 96 + protected function sortTransactions(array $xactions) { 97 + $xactions = parent::sortTransactions($xactions); 98 + 99 + $head = array(); 100 + $tail = array(); 101 + 102 + foreach ($xactions as $xaction) { 103 + $type = $xaction->getTransactionType(); 104 + if ($type == PhabricatorAuditActionConstants::INLINE) { 105 + $tail[] = $xaction; 106 + } else { 107 + $head[] = $xaction; 108 + } 109 + } 110 + 111 + return array_values(array_merge($head, $tail)); 112 + } 113 + 114 + }
+14 -28
src/applications/audit/storage/PhabricatorAuditComment.php
··· 4 4 implements PhabricatorMarkupInterface { 5 5 6 6 const METADATA_ADDED_AUDITORS = 'added-auditors'; 7 - const METADATA_ADDED_CCS = 'added-ccs'; 8 7 9 8 const MARKUP_FIELD_BODY = 'markup:body'; 10 9 ··· 114 113 switch ($action) { 115 114 case PhabricatorAuditActionConstants::INLINE: 116 115 case PhabricatorAuditActionConstants::ADD_CCS: 116 + case PhabricatorTransactions::TYPE_SUBSCRIBERS: 117 117 case PhabricatorAuditActionConstants::ADD_AUDITORS: 118 118 $this->proxy->setTransactionType($action); 119 119 break; ··· 137 137 return PhabricatorAuditActionConstants::COMMENT; 138 138 case PhabricatorAuditActionConstants::INLINE: 139 139 case PhabricatorAuditActionConstants::ADD_CCS: 140 + case PhabricatorTransactions::TYPE_SUBSCRIBERS: 140 141 case PhabricatorAuditActionConstants::ADD_AUDITORS: 141 142 return $type; 142 143 default: ··· 151 152 152 153 $type = $this->proxy->getTransactionType(); 153 154 switch ($type) { 154 - case PhabricatorAuditActionConstants::ADD_CCS: 155 - $raw_phids = idx($metadata, self::METADATA_ADDED_CCS, array()); 156 - break; 157 155 case PhabricatorAuditActionConstants::ADD_AUDITORS: 158 156 $raw_phids = idx($metadata, self::METADATA_ADDED_AUDITORS, array()); 159 157 break; ··· 161 159 throw new Exception(pht('No metadata expected!')); 162 160 } 163 161 164 - $this->proxy->setOldValue(array()); 165 162 $this->proxy->setNewValue(array_fuse($raw_phids)); 166 163 167 164 return $this; ··· 175 172 $type = $this->proxy->getTransactionType(); 176 173 $new_value = $this->proxy->getNewValue(); 177 174 switch ($type) { 178 - case PhabricatorAuditActionConstants::ADD_CCS: 179 - return array( 180 - self::METADATA_ADDED_CCS => array_keys($new_value), 181 - ); 182 175 case PhabricatorAuditActionConstants::ADD_AUDITORS: 183 176 return array( 184 177 self::METADATA_ADDED_AUDITORS => array_keys($new_value), ··· 189 182 } 190 183 191 184 public function save() { 192 - $this->proxy->openTransaction(); 193 - $this->proxy 194 - ->setViewPolicy('public') 195 - ->setEditPolicy($this->getActorPHID()) 196 - ->save(); 185 + throw new Exception( 186 + pht('This object can no longer be written to directly!')); 187 + } 197 188 198 - if (strlen($this->getContent())) { 199 - $this->getProxyComment() 200 - ->setAuthorPHID($this->getActorPHID()) 201 - ->setViewPolicy('public') 202 - ->setEditPolicy($this->getActorPHID()) 203 - ->setCommentVersion(1) 204 - ->setTransactionPHID($this->proxy->getPHID()) 205 - ->save(); 189 + public function getTransactionForSave() { 190 + $xaction = $this->proxy; 191 + if (strlen($this->getContent())) { 192 + $xaction->attachComment($this->getProxyComment()); 193 + } 206 194 207 - $this->proxy 208 - ->setCommentVersion(1) 209 - ->setCommentPHID($this->getProxyComment()->getPHID()) 210 - ->save(); 211 - } 212 - $this->proxy->saveTransaction(); 195 + return $xaction; 196 + } 213 197 198 + public function setNewValue($value) { 199 + $this->proxy->setNewValue($value); 214 200 return $this; 215 201 } 216 202
+4
src/applications/audit/storage/PhabricatorAuditInlineComment.php
··· 18 18 return $this->proxy->getTransactionPHID(); 19 19 } 20 20 21 + public function getTransactionComment() { 22 + return $this->proxy; 23 + } 24 + 21 25 public function getTransactionCommentForSave() { 22 26 $content_source = PhabricatorContentSource::newForSource( 23 27 PhabricatorContentSource::SOURCE_LEGACY,
+3 -1
src/applications/audit/storage/PhabricatorAuditTransaction.php
··· 83 83 84 84 switch ($type) { 85 85 case PhabricatorAuditActionConstants::INLINE: 86 - break; 86 + return pht( 87 + '%s added inline comments.', 88 + $author_handle); 87 89 case PhabricatorAuditActionConstants::ADD_CCS: 88 90 if ($add && $rem) { 89 91 return pht(
+4 -4
src/applications/diffusion/conduit/DiffusionCreateCommentConduitAPIMethod.php
··· 40 40 41 41 protected function execute(ConduitAPIRequest $request) { 42 42 $commit_phid = $request->getValue('phid'); 43 - $commit = id(new PhabricatorRepositoryCommit())->loadOneWhere( 44 - 'phid = %s', 45 - $commit_phid); 46 - 43 + $commit = id(new DiffusionCommitQuery()) 44 + ->setViewer($request->getUser()) 45 + ->withPHIDs(array($commit_phid)) 46 + ->executeOne(); 47 47 if (!$commit) { 48 48 throw new ConduitException('ERR_BAD_COMMIT'); 49 49 }
+1 -1
src/applications/transactions/editor/PhabricatorApplicationTransactionCommentEditor.php
··· 79 79 if ($xaction->getTransactionType() == $type_comment) { 80 80 if ($comment->getPHID()) { 81 81 throw new Exception( 82 - 'Transaction comment must not yet have a PHID!'); 82 + 'Transaction comment must not yet have a PHID!'); 83 83 } 84 84 } 85 85