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

Partially modernize Doorkeeper/Asana bridge

Summary: Fixes T6201. This stuff didn't fully get updated for ApplicationTransactions. Get it working again (notably, make inline comment text publish) and clean it up a little bit.

Test Plan:
- Published a Differential feed story into Asana with comment text.
- Pulbished a Diffusion feed story into Asana with comment text.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T6201

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

+121 -215
-12
src/applications/differential/doorkeeper/DifferentialDoorkeeperRevisionFeedStoryPublisher.php
··· 86 86 return pht('%s Review Request', $prefix); 87 87 } 88 88 89 - public function getStoryText($object) { 90 - $implied_context = $this->getRenderWithImpliedContext(); 91 - 92 - $story = $this->getFeedStory(); 93 - if ($story instanceof PhabricatorFeedStoryDifferential) { 94 - $text = $story->renderForAsanaBridge($implied_context); 95 - } else { 96 - $text = $story->renderText(); 97 - } 98 - return $text; 99 - } 100 - 101 89 private function getTitlePrefix(DifferentialRevision $revision) { 102 90 $prefix_key = 'metamta.differential.subject-prefix'; 103 91 return PhabricatorEnv::getEnvConfig($prefix_key);
+54
src/applications/differential/storage/DifferentialTransaction.php
··· 596 596 return parent::getNoEffectDescription(); 597 597 } 598 598 599 + public function renderAsTextForDoorkeeper( 600 + DoorkeeperFeedStoryPublisher $publisher, 601 + PhabricatorFeedStory $story, 602 + array $xactions) { 603 + 604 + $body = parent::renderAsTextForDoorkeeper($publisher, $story, $xactions); 605 + 606 + $inlines = array(); 607 + foreach ($xactions as $xaction) { 608 + if ($xaction->getTransactionType() == self::TYPE_INLINE) { 609 + $inlines[] = $xaction; 610 + } 611 + } 612 + 613 + // TODO: This is a bit gross, but far less bad than it used to be. It 614 + // could be further cleaned up at some point. 615 + 616 + if ($inlines) { 617 + $engine = PhabricatorMarkupEngine::newMarkupEngine(array()) 618 + ->setConfig('viewer', new PhabricatorUser()) 619 + ->setMode(PhutilRemarkupEngine::MODE_TEXT); 620 + 621 + $body .= "\n\n"; 622 + $body .= pht('Inline Comments'); 623 + $body .= "\n"; 624 + 625 + $changeset_ids = array(); 626 + foreach ($inlines as $inline) { 627 + $changeset_ids[] = $inline->getComment()->getChangesetID(); 628 + } 629 + 630 + $changesets = id(new DifferentialChangeset())->loadAllWhere( 631 + 'id IN (%Ld)', 632 + $changeset_ids); 633 + 634 + foreach ($inlines as $inline) { 635 + $comment = $inline->getComment(); 636 + $changeset = idx($changesets, $comment->getChangesetID()); 637 + if (!$changeset) { 638 + continue; 639 + } 640 + 641 + $filename = $changeset->getDisplayFilename(); 642 + $linenumber = $comment->getLineNumber(); 643 + $inline_text = $engine->markupText($comment->getContent()); 644 + $inline_text = rtrim($inline_text); 645 + 646 + $body .= "{$filename}:{$linenumber} {$inline_text}\n"; 647 + } 648 + } 649 + 650 + return $body; 651 + } 652 + 599 653 600 654 }
-12
src/applications/diffusion/doorkeeper/DiffusionDoorkeeperCommitFeedStoryPublisher.php
··· 180 180 return pht('%s Audit', $prefix); 181 181 } 182 182 183 - public function getStoryText($object) { 184 - $implied_context = $this->getRenderWithImpliedContext(); 185 - 186 - $story = $this->getFeedStory(); 187 - if ($story instanceof PhabricatorFeedStoryAudit) { 188 - $text = $story->renderForAsanaBridge($implied_context); 189 - } else { 190 - $text = $story->renderText(); 191 - } 192 - return $text; 193 - } 194 - 195 183 private function getTitlePrefix(PhabricatorRepositoryCommit $commit) { 196 184 $prefix_key = 'metamta.diffusion.subject-prefix'; 197 185 return PhabricatorEnv::getEnvConfig($prefix_key);
+5 -1
src/applications/doorkeeper/engine/DoorkeeperFeedStoryPublisher.php
··· 81 81 return $object; 82 82 } 83 83 84 + 85 + public function getStoryText($object) { 86 + return $this->getFeedStory()->renderAsTextForDoorkeeper($this); 87 + } 88 + 84 89 abstract public function isStoryAboutObjectCreation($object); 85 90 abstract public function isStoryAboutObjectClosure($object); 86 91 abstract public function getOwnerPHID($object); ··· 92 97 abstract public function getObjectDescription($object); 93 98 abstract public function isObjectClosed($object); 94 99 abstract public function getResponsibilityTitle($object); 95 - abstract public function getStoryText($object); 96 100 97 101 }
-1
src/applications/feed/constants/PhabricatorFeedStoryTypeConstants.php
··· 4 4 extends PhabricatorFeedConstants { 5 5 6 6 const STORY_PHRICTION = 'PhabricatorFeedStoryPhriction'; 7 - const STORY_AUDIT = 'PhabricatorFeedStoryAudit'; 8 7 const STORY_COMMIT = 'PhabricatorFeedStoryCommit'; 9 8 10 9 }
+11
src/applications/feed/story/PhabricatorFeedStory.php
··· 251 251 } 252 252 253 253 abstract public function renderView(); 254 + public function renderAsTextForDoorkeeper( 255 + DoorkeeperFeedStoryPublisher $publisher) { 256 + 257 + // TODO: This (and text rendering) should be properly abstract and 258 + // universal. However, this is far less bad than it used to be, and we 259 + // need to clean up more old feed code to really make this reasonable. 260 + 261 + return pht( 262 + '(Unable to render story of class %s for Doorkeeper.)', 263 + get_class($this)); 264 + } 254 265 255 266 public function getRequiredHandlePHIDs() { 256 267 return array();
-34
src/applications/feed/story/PhabricatorFeedStoryAudit.php
··· 47 47 return $text; 48 48 } 49 49 50 - 51 - // TODO: At some point, make feed rendering not terrible and remove this 52 - // hacky mess. 53 - public function renderForAsanaBridge($implied_context = false) { 54 - $data = $this->getStoryData(); 55 - $comment = $data->getValue('content'); 56 - 57 - $author_name = $this->getHandle($this->getAuthorPHID())->getName(); 58 - $action = $this->getValue('action'); 59 - $verb = PhabricatorAuditActionConstants::getActionPastTenseVerb($action); 60 - 61 - $commit_phid = $this->getPrimaryObjectPHID(); 62 - $commit_name = $this->getHandle($commit_phid)->getFullName(); 63 - 64 - if ($implied_context) { 65 - $title = "{$author_name} {$verb} this commit."; 66 - } else { 67 - $title = "{$author_name} {$verb} commit {$commit_name}."; 68 - } 69 - 70 - if (strlen($comment)) { 71 - $engine = PhabricatorMarkupEngine::newMarkupEngine(array()) 72 - ->setConfig('viewer', new PhabricatorUser()) 73 - ->setMode(PhutilRemarkupEngine::MODE_TEXT); 74 - 75 - $comment = $engine->markupText($comment); 76 - 77 - $title .= "\n\n"; 78 - $title .= $comment; 79 - } 80 - 81 - return $title; 82 - } 83 - 84 50 }
-155
src/applications/feed/story/PhabricatorFeedStoryDifferential.php
··· 235 235 ); 236 236 } 237 237 238 - // TODO: At some point, make feed rendering not terrible and remove this 239 - // hacky mess. 240 - public function renderForAsanaBridge($implied_context = false) { 241 - $data = $this->getStoryData(); 242 - $comment = $data->getValue('feedback_content'); 243 - 244 - $author_name = $this->getHandle($this->getAuthorPHID())->getName(); 245 - $action = $this->getValue('action'); 246 - 247 - $engine = PhabricatorMarkupEngine::newMarkupEngine(array()) 248 - ->setConfig('viewer', new PhabricatorUser()) 249 - ->setMode(PhutilRemarkupEngine::MODE_TEXT); 250 - 251 - $revision_phid = $this->getPrimaryObjectPHID(); 252 - $revision_name = $this->getHandle($revision_phid)->getFullName(); 253 - 254 - if ($implied_context) { 255 - $title = DifferentialAction::getBasicStoryText( 256 - $action, $author_name); 257 - } else { 258 - switch ($action) { 259 - case DifferentialAction::ACTION_COMMENT: 260 - $title = pht('%s commented on revision %s', 261 - $author_name, $revision_name); 262 - break; 263 - case DifferentialAction::ACTION_ACCEPT: 264 - $title = pht('%s accepted revision %s', 265 - $author_name, $revision_name); 266 - break; 267 - case DifferentialAction::ACTION_REJECT: 268 - $title = pht('%s requested changes to revision %s', 269 - $author_name, $revision_name); 270 - break; 271 - case DifferentialAction::ACTION_RETHINK: 272 - $title = pht('%s planned changes to revision %s', 273 - $author_name, $revision_name); 274 - break; 275 - case DifferentialAction::ACTION_ABANDON: 276 - $title = pht('%s abandoned revision %s', 277 - $author_name, $revision_name); 278 - break; 279 - case DifferentialAction::ACTION_CLOSE: 280 - $title = pht('%s closed revision %s', 281 - $author_name, $revision_name); 282 - break; 283 - case DifferentialAction::ACTION_REQUEST: 284 - $title = pht('%s requested a review of revision %s', 285 - $author_name, $revision_name); 286 - break; 287 - case DifferentialAction::ACTION_RECLAIM: 288 - $title = pht('%s reclaimed revision %s', 289 - $author_name, $revision_name); 290 - break; 291 - case DifferentialAction::ACTION_UPDATE: 292 - $title = pht('%s updated revision %s', 293 - $author_name, $revision_name); 294 - break; 295 - case DifferentialAction::ACTION_RESIGN: 296 - $title = pht('%s resigned from revision %s', 297 - $author_name, $revision_name); 298 - break; 299 - case DifferentialAction::ACTION_SUMMARIZE: 300 - $title = pht('%s summarized revision %s', 301 - $author_name, $revision_name); 302 - break; 303 - case DifferentialAction::ACTION_TESTPLAN: 304 - $title = pht('%s explained the test plan for revision %s', 305 - $author_name, $revision_name); 306 - break; 307 - case DifferentialAction::ACTION_CREATE: 308 - $title = pht('%s created revision %s', 309 - $author_name, $revision_name); 310 - break; 311 - case DifferentialAction::ACTION_ADDREVIEWERS: 312 - $title = pht('%s added reviewers to revision %s', 313 - $author_name, $revision_name); 314 - break; 315 - case DifferentialAction::ACTION_ADDCCS: 316 - $title = pht('%s added CCs to revision %s', 317 - $author_name, $revision_name); 318 - break; 319 - case DifferentialAction::ACTION_CLAIM: 320 - $title = pht('%s commandeered revision %s', 321 - $author_name, $revision_name); 322 - break; 323 - case DifferentialAction::ACTION_REOPEN: 324 - $title = pht('%s reopened revision %s', 325 - $author_name, $revision_name); 326 - break; 327 - case DifferentialTransaction::TYPE_INLINE: 328 - $title = pht('%s added inline comments to %s', 329 - $author_name, $revision_name); 330 - break; 331 - default: 332 - $title = pht('%s edited revision %s', 333 - $author_name, $revision_name); 334 - break; 335 - } 336 - } 337 - 338 - if (strlen($comment)) { 339 - $comment = $engine->markupText($comment); 340 - 341 - $title .= "\n\n"; 342 - $title .= $comment; 343 - } 344 - 345 - // Roughly render inlines into the comment. 346 - $xaction_phids = $data->getValue('temporaryTransactionPHIDs'); 347 - if ($xaction_phids) { 348 - $inlines = id(new DifferentialTransactionQuery()) 349 - ->setViewer(PhabricatorUser::getOmnipotentUser()) 350 - ->withPHIDs($xaction_phids) 351 - ->needComments(true) 352 - ->withTransactionTypes( 353 - array( 354 - DifferentialTransaction::TYPE_INLINE, 355 - )) 356 - ->execute(); 357 - if ($inlines) { 358 - $title .= "\n\n"; 359 - $title .= pht('Inline Comments'); 360 - $title .= "\n"; 361 - 362 - $changeset_ids = array(); 363 - foreach ($inlines as $inline) { 364 - $changeset_ids[] = $inline->getComment()->getChangesetID(); 365 - } 366 - 367 - $changesets = id(new DifferentialChangeset())->loadAllWhere( 368 - 'id IN (%Ld)', 369 - $changeset_ids); 370 - 371 - foreach ($inlines as $inline) { 372 - $comment = $inline->getComment(); 373 - $changeset = idx($changesets, $comment->getChangesetID()); 374 - if (!$changeset) { 375 - continue; 376 - } 377 - 378 - $filename = $changeset->getDisplayFilename(); 379 - $linenumber = $comment->getLineNumber(); 380 - $inline_text = $engine->markupText($comment->getContent()); 381 - $inline_text = rtrim($inline_text); 382 - 383 - $title .= "{$filename}:{$linenumber} {$inline_text}\n"; 384 - } 385 - } 386 - } 387 - 388 - 389 - return $title; 390 - } 391 - 392 - 393 238 }
+13
src/applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php
··· 104 104 return $text; 105 105 } 106 106 107 + public function renderAsTextForDoorkeeper( 108 + DoorkeeperFeedStoryPublisher $publisher) { 109 + 110 + $xactions = array(); 111 + $xaction_phids = $this->getValue('transactionPHIDs'); 112 + foreach ($xaction_phids as $xaction_phid) { 113 + $xactions[] = $this->getObject($xaction_phid); 114 + } 115 + 116 + $primary = $this->getPrimaryTransaction(); 117 + return $primary->renderAsTextForDoorkeeper($publisher, $this, $xactions); 118 + } 119 + 107 120 }
+38
src/applications/transactions/storage/PhabricatorApplicationTransaction.php
··· 1078 1078 return null; 1079 1079 } 1080 1080 1081 + public function renderAsTextForDoorkeeper( 1082 + DoorkeeperFeedStoryPublisher $publisher, 1083 + PhabricatorFeedStory $story, 1084 + array $xactions) { 1085 + 1086 + $text = array(); 1087 + $body = array(); 1088 + 1089 + foreach ($xactions as $xaction) { 1090 + $xaction_body = $xaction->getBodyForMail(); 1091 + if ($xaction_body !== null) { 1092 + $body[] = $xaction_body; 1093 + } 1094 + 1095 + if ($xaction->shouldHideForMail($xactions)) { 1096 + continue; 1097 + } 1098 + 1099 + $old_target = $xaction->getRenderingTarget(); 1100 + $new_target = PhabricatorApplicationTransaction::TARGET_TEXT; 1101 + $xaction->setRenderingTarget($new_target); 1102 + 1103 + if ($publisher->getRenderWithImpliedContext()) { 1104 + $text[] = $xaction->getTitle(); 1105 + } else { 1106 + $text[] = $xaction->getTitleForFeed($story); 1107 + } 1108 + 1109 + $xaction->setRenderingTarget($old_target); 1110 + } 1111 + 1112 + $text = implode("\n", $text); 1113 + $body = implode("\n\n", $body); 1114 + 1115 + return rtrim($text."\n\n".$body); 1116 + } 1117 + 1118 + 1081 1119 1082 1120 /* -( PhabricatorPolicyInterface Implementation )-------------------------- */ 1083 1121