@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 feed integration to generic transactions

Summary: Publish feed stories, including from Pholio. Actual stories are somewhat garbage but it's all display-time; I'm going to do a pass on feed in general.

Test Plan: {F26832}

Reviewers: btrahan, chad, vrana

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2104

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

+233 -6
+10 -2
src/__phutil_library_map__.php
··· 602 602 'PhabricatorApplicationTransactionCommentEditor' => 'applications/transactions/editor/PhabricatorApplicationTransactionCommentEditor.php', 603 603 'PhabricatorApplicationTransactionCommentQuery' => 'applications/transactions/query/PhabricatorApplicationTransactionCommentQuery.php', 604 604 'PhabricatorApplicationTransactionEditor' => 'applications/transactions/editor/PhabricatorApplicationTransactionEditor.php', 605 + 'PhabricatorApplicationTransactionFeedStory' => 'applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php', 605 606 'PhabricatorApplicationTransactionQuery' => 'applications/transactions/query/PhabricatorApplicationTransactionQuery.php', 606 607 'PhabricatorApplicationTransactions' => 'applications/transactions/application/PhabricatorApplicationTransactions.php', 607 608 'PhabricatorApplicationUIExamples' => 'applications/uiexample/application/PhabricatorApplicationUIExamples.php', ··· 1320 1321 'phabricator_render_form' => 'infrastructure/javelin/markup.php', 1321 1322 'phabricator_render_form_magic' => 'infrastructure/javelin/markup.php', 1322 1323 'phabricator_time' => 'view/viewutils.php', 1324 + 'phid_get_subtype' => 'applications/phid/utils.php', 1323 1325 'phid_get_type' => 'applications/phid/utils.php', 1324 1326 'phid_group_by_type' => 'applications/phid/utils.php', 1325 1327 'require_celerity_resource' => 'infrastructure/celerity/api.php', ··· 1851 1853 'PhabricatorApplicationSlowvote' => 'PhabricatorApplication', 1852 1854 'PhabricatorApplicationStatusView' => 'AphrontView', 1853 1855 'PhabricatorApplicationSubscriptions' => 'PhabricatorApplication', 1854 - 'PhabricatorApplicationTransaction' => 'PhabricatorLiskDAO', 1856 + 'PhabricatorApplicationTransaction' => 1857 + array( 1858 + 0 => 'PhabricatorLiskDAO', 1859 + 1 => 'PhabricatorPolicyInterface', 1860 + ), 1855 1861 'PhabricatorApplicationTransactionComment' => 1856 1862 array( 1857 1863 0 => 'PhabricatorLiskDAO', 1858 1864 1 => 'PhabricatorMarkupInterface', 1865 + 2 => 'PhabricatorPolicyInterface', 1859 1866 ), 1860 1867 'PhabricatorApplicationTransactionCommentEditor' => 'PhabricatorEditor', 1861 1868 'PhabricatorApplicationTransactionCommentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 1862 1869 'PhabricatorApplicationTransactionEditor' => 'PhabricatorEditor', 1870 + 'PhabricatorApplicationTransactionFeedStory' => 'PhabricatorFeedStory', 1863 1871 'PhabricatorApplicationTransactionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 1864 1872 'PhabricatorApplicationTransactions' => 'PhabricatorApplication', 1865 1873 'PhabricatorApplicationUIExamples' => 'PhabricatorApplication', ··· 2463 2471 'PholioReplyHandler' => 'PhabricatorMailReplyHandler', 2464 2472 'PholioTransaction' => 'PhabricatorApplicationTransaction', 2465 2473 'PholioTransactionComment' => 'PhabricatorApplicationTransactionComment', 2466 - 'PholioTransactionQuery' => 'PhabricatorOffsetPagedQuery', 2474 + 'PholioTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 2467 2475 'PholioTransactionType' => 'PholioConstants', 2468 2476 'PhortuneMonthYearExpiryControl' => 'AphrontFormControl', 2469 2477 'PhortuneStripeBaseController' => 'PhabricatorController',
+23 -1
src/applications/phid/handle/PhabricatorObjectHandleData.php
··· 104 104 $objects[$mock->getPHID()] = $mock; 105 105 } 106 106 break; 107 + case PhabricatorPHIDConstants::PHID_TYPE_XACT: 108 + $subtypes = array(); 109 + foreach ($phids as $phid) { 110 + $subtypes[phid_get_subtype($phid)][] = $phid; 111 + } 112 + $xactions = array(); 113 + foreach ($subtypes as $subtype => $subtype_phids) { 114 + // TODO: Do this magically. 115 + switch ($subtype) { 116 + case PhabricatorPHIDConstants::PHID_TYPE_MOCK: 117 + $results = id(new PholioTransactionQuery()) 118 + ->setViewer($this->viewer) 119 + ->withPHIDs($subtype_phids) 120 + ->execute(); 121 + $xactions += mpull($results, null, 'getPHID'); 122 + break; 123 + } 124 + } 125 + foreach ($xactions as $xaction) { 126 + $objects[$xaction->getPHID()] = $xaction; 127 + } 128 + break; 107 129 } 108 130 } 109 131 ··· 572 594 } else { 573 595 $mock = $mocks[$phid]; 574 596 $handle->setName($mock->getName()); 575 - $handle->setFullName($mock->getName()); 597 + $handle->setFullName('M'.$mock->getID().': '.$mock->getName()); 576 598 $handle->setURI('/M'.$mock->getID()); 577 599 $handle->setComplete(true); 578 600 }
+7
src/applications/phid/utils.php
··· 36 36 } 37 37 return $result; 38 38 } 39 + 40 + function phid_get_subtype($phid) { 41 + if (isset($phid[14]) && ($phid[14] == '-')) { 42 + return substr($phid, 10, 4); 43 + } 44 + return null; 45 + }
+4
src/applications/pholio/editor/PholioMockEditor.php
··· 125 125 return PhabricatorEnv::getEnvConfig('metamta.pholio.subject-prefix'); 126 126 } 127 127 128 + protected function supportsFeed() { 129 + return true; 130 + } 131 + 128 132 }
+105 -3
src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
··· 2 2 3 3 /** 4 4 * @task mail Sending Mail 5 + * @task feed Publishing Feed Stories 5 6 */ 6 7 abstract class PhabricatorApplicationTransactionEditor 7 8 extends PhabricatorEditor { ··· 247 248 } 248 249 249 250 // TODO: Index object. 250 - // TODO: Publish feed/notifications. 251 + 252 + if ($this->supportsFeed()) { 253 + $mailed = array(); 254 + if ($mail) { 255 + $mailed = $mail->buildRecipientList(); 256 + } 257 + $this->publishFeedStory( 258 + $object, 259 + $xactions, 260 + $mailed); 261 + } 251 262 252 263 $this->didApplyTransactions($object, $xactions); 253 264 ··· 550 561 551 562 $mail_tags = $this->getMailTags($object, $xactions); 552 563 553 - $action = $this->getStrongestAction($object, $xactions); 564 + $action = $this->getStrongestAction($object, $xactions)->getActionName(); 554 565 555 566 $template 556 567 ->setFrom($this->requireActor()->getPHID()) ··· 590 601 protected function getStrongestAction( 591 602 PhabricatorLiskDAO $object, 592 603 array $xactions) { 593 - return last(msort($xactions, 'getActionStrength'))->getActionName(); 604 + return last(msort($xactions, 'getActionStrength')); 594 605 } 595 606 596 607 ··· 682 693 return $body; 683 694 } 684 695 696 + 697 + /* -( Publishing Feed Stories )-------------------------------------------- */ 698 + 699 + 700 + /** 701 + * @task feed 702 + */ 703 + protected function supportsFeed() { 704 + return false; 705 + } 706 + 707 + 708 + /** 709 + * @task feed 710 + */ 711 + protected function getFeedStoryType() { 712 + return 'PhabricatorApplicationTransactionFeedStory'; 713 + } 714 + 715 + 716 + /** 717 + * @task feed 718 + */ 719 + protected function getFeedRelatedPHIDs( 720 + PhabricatorLiskDAO $object, 721 + array $xactions) { 722 + 723 + return array( 724 + $object->getPHID(), 725 + $this->requireActor()->getPHID(), 726 + ); 727 + } 728 + 729 + 730 + /** 731 + * @task feed 732 + */ 733 + protected function getFeedNotifyPHIDs( 734 + PhabricatorLiskDAO $object, 735 + array $xactions) { 736 + 737 + return array_merge( 738 + $this->getMailTo($object), 739 + $this->getMailCC($object)); 740 + } 741 + 742 + 743 + /** 744 + * @task feed 745 + */ 746 + protected function getFeedStoryData( 747 + PhabricatorLiskDAO $object, 748 + array $xactions) { 749 + 750 + $xactions = msort($xactions, 'getActionStrength'); 751 + $xactions = array_reverse($xactions); 752 + 753 + return array( 754 + 'objectPHID' => $object->getPHID(), 755 + 'transactionPHIDs' => mpull($xactions, 'getPHID'), 756 + ); 757 + } 758 + 759 + 760 + /** 761 + * @task feed 762 + */ 763 + protected function publishFeedStory( 764 + PhabricatorLiskDAO $object, 765 + array $xactions, 766 + array $mailed_phids) { 767 + 768 + $related_phids = $this->getFeedRelatedPHIDs($object, $xactions); 769 + $subscribed_phids = $this->getFeedNotifyPHIDs($object, $xactions); 770 + 771 + $story_type = $this->getFeedStoryType(); 772 + $story_data = $this->getFeedStoryData($object, $xactions); 773 + 774 + phlog($subscribed_phids); 775 + 776 + id(new PhabricatorFeedStoryPublisher()) 777 + ->setStoryType($story_type) 778 + ->setStoryData($story_data) 779 + ->setStoryTime(time()) 780 + ->setStoryAuthorPHID($this->requireActor()->getPHID()) 781 + ->setRelatedPHIDs($related_phids) 782 + ->setPrimaryObjectPHID($object->getPHID()) 783 + ->setSubscribedPHIDs($subscribed_phids) 784 + ->setMailRecipientPHIDs($mailed_phids) 785 + ->publish(); 786 + } 685 787 686 788 }
+51
src/applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php
··· 1 + <?php 2 + 3 + /** 4 + * @concrete-extensible 5 + */ 6 + class PhabricatorApplicationTransactionFeedStory 7 + extends PhabricatorFeedStory { 8 + 9 + public function getPrimaryObjectPHID() { 10 + return $this->getValue('objectPHID'); 11 + } 12 + 13 + public function getRequiredObjectPHIDs() { 14 + return array( 15 + $this->getPrimaryTransactionPHID(), 16 + ); 17 + } 18 + 19 + public function getRequiredHandlePHIDs() { 20 + $phids = array(); 21 + $phids[] = array($this->getValue('objectPHID')); 22 + $phids[] = $this->getPrimaryTransaction()->getRequiredHandlePHIDs(); 23 + return array_mergev($phids); 24 + } 25 + 26 + protected function getPrimaryTransactionPHID() { 27 + return head($this->getValue('transactionPHIDs')); 28 + } 29 + 30 + protected function getPrimaryTransaction() { 31 + return $this->getObject($this->getPrimaryTransactionPHID()); 32 + } 33 + 34 + public function renderView() { 35 + $view = new PhabricatorFeedStoryView(); 36 + $view->setViewed($this->getHasViewed()); 37 + 38 + $href = $this->getHandle($this->getPrimaryObjectPHID())->getURI(); 39 + $view->setHref($view); 40 + 41 + $xaction_phids = $this->getValue('transactionPHIDs'); 42 + $xaction = $this->getObject(head($xaction_phids)); 43 + 44 + $xaction->setHandles($this->getHandles()); 45 + $view->setTitle($xaction->getTitleForFeed()); 46 + $view->setOneLineStory(true); 47 + 48 + return $view; 49 + } 50 + 51 + }
+33
src/applications/transactions/storage/PhabricatorApplicationTransaction.php
··· 220 220 } 221 221 } 222 222 223 + public function getTitleForFeed() { 224 + $author_phid = $this->getAuthorPHID(); 225 + $object_phid = $this->getObjectPHID(); 226 + 227 + $old = $this->getOldValue(); 228 + $new = $this->getNewValue(); 229 + 230 + switch ($this->getTransactionType()) { 231 + case PhabricatorTransactions::TYPE_COMMENT: 232 + return pht( 233 + '%s added a comment to %s.', 234 + $this->renderHandleLink($author_phid), 235 + $this->renderHandleLink($object_phid)); 236 + case PhabricatorTransactions::TYPE_VIEW_POLICY: 237 + return pht( 238 + '%s changed the visibility for %s.', 239 + $this->renderHandleLink($author_phid), 240 + $this->renderHandleLink($object_phid)); 241 + case PhabricatorTransactions::TYPE_EDIT_POLICY: 242 + return pht( 243 + '%s changed the edit policy for %s.', 244 + $this->renderHandleLink($author_phid), 245 + $this->renderHandleLink($object_phid)); 246 + case PhabricatorTransactions::TYPE_SUBSCRIBERS: 247 + return pht( 248 + '%s updated subscribers of %s.', 249 + $this->renderHandleLink($author_phid), 250 + $this->renderHandleLink($object_phid)); 251 + } 252 + 253 + return $this->getTitle(); 254 + } 255 + 223 256 public function getActionStrength() { 224 257 switch ($this->getTransactionType()) { 225 258 case PhabricatorTransactions::TYPE_COMMENT: