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

Notify users when an object they created gets awarded a token

Summary:
- Publish feed/notification.
- I think this is too lightweight for an email?
- We don't tell them which token right now. Laziness? Or intentional aura of mystery?!
- For tasks, notify both author and current owner.
- Fixes T2562.

Test Plan: {F33187}

Reviewers: chad

Reviewed By: chad

CC: aran

Maniphest Tasks: T2562

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

+111 -16
+2
src/__phutil_library_map__.php
··· 1348 1348 'PhabricatorTokenGiven' => 'applications/tokens/storage/PhabricatorTokenGiven.php', 1349 1349 'PhabricatorTokenGivenController' => 'applications/tokens/controller/PhabricatorTokenGivenController.php', 1350 1350 'PhabricatorTokenGivenEditor' => 'applications/tokens/editor/PhabricatorTokenGivenEditor.php', 1351 + 'PhabricatorTokenGivenFeedStory' => 'applications/tokens/feed/PhabricatorTokenGivenFeedStory.php', 1351 1352 'PhabricatorTokenGivenQuery' => 'applications/tokens/query/PhabricatorTokenGivenQuery.php', 1352 1353 'PhabricatorTokenQuery' => 'applications/tokens/query/PhabricatorTokenQuery.php', 1353 1354 'PhabricatorTokenReceiverInterface' => 'applications/tokens/interface/PhabricatorTokenReceiverInterface.php', ··· 2808 2809 ), 2809 2810 'PhabricatorTokenGivenController' => 'PhabricatorTokenController', 2810 2811 'PhabricatorTokenGivenEditor' => 'PhabricatorEditor', 2812 + 'PhabricatorTokenGivenFeedStory' => 'PhabricatorFeedStory', 2811 2813 'PhabricatorTokenGivenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 2812 2814 'PhabricatorTokenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 2813 2815 'PhabricatorTokenUIEventListener' => 'PhutilEventListener',
+6
src/applications/differential/storage/DifferentialRevision.php
··· 327 327 return false; 328 328 } 329 329 330 + public function getUsersToNotifyOfTokenGiven() { 331 + return array( 332 + $this->getAuthorPHID(), 333 + ); 334 + } 335 + 330 336 }
+13
src/applications/maniphest/storage/ManiphestTask.php
··· 283 283 return false; 284 284 } 285 285 286 + 287 + /* -( PhabricatorTokenReceiverInterface )---------------------------------- */ 288 + 289 + public function getUsersToNotifyOfTokenGiven() { 290 + // Sort of ambiguous who this was intended for; just let them both know. 291 + return array_filter( 292 + array_unique( 293 + array( 294 + $this->getAuthorPHID(), 295 + $this->getOwnerPHID(), 296 + ))); 297 + } 298 + 286 299 }
+9
src/applications/pholio/storage/PholioMock.php
··· 137 137 } 138 138 139 139 140 + /* -( PhabricatorTokenReceiverInterface )---------------------------------- */ 141 + 142 + 143 + public function getUsersToNotifyOfTokenGiven() { 144 + return array( 145 + $this->getAuthorPHID(), 146 + ); 147 + } 148 + 140 149 }
+38 -15
src/applications/tokens/editor/PhabricatorTokenGivenEditor.php
··· 5 5 6 6 public function addToken($object_phid, $token_phid) { 7 7 $token = $this->validateToken($token_phid); 8 - $handle = $this->validateObject($object_phid); 8 + $object = $this->validateObject($object_phid); 9 9 10 10 $actor = $this->requireActor(); 11 11 12 12 $token_given = id(new PhabricatorTokenGiven()) 13 13 ->setAuthorPHID($actor->getPHID()) 14 - ->setObjectPHID($handle->getPHID()) 14 + ->setObjectPHID($object->getPHID()) 15 15 ->setTokenPHID($token->getPHID()); 16 16 17 17 $token_given->openTransaction(); 18 18 19 - $this->executeDeleteToken($handle); 19 + $this->executeDeleteToken($object); 20 20 21 21 $token_given->save(); 22 22 ··· 25 25 'INSERT INTO %T (objectPHID, tokenCount) VALUES (%s, 1) 26 26 ON DUPLICATE KEY UPDATE tokenCount = tokenCount + 1', 27 27 id(new PhabricatorTokenCount())->getTableName(), 28 - $handle->getPHID()); 28 + $object->getPHID()); 29 29 30 30 $token_given->saveTransaction(); 31 31 32 + $subscribed_phids = $object->getUsersToNotifyOfTokenGiven(); 33 + if ($subscribed_phids) { 34 + $related_phids = $subscribed_phids; 35 + $related_phids[] = $actor->getPHID(); 36 + 37 + $story_type = 'PhabricatorTokenGivenFeedStory'; 38 + $story_data = array( 39 + 'authorPHID' => $actor->getPHID(), 40 + 'tokenPHID' => $token->getPHID(), 41 + 'objectPHID' => $object->getPHID(), 42 + ); 43 + 44 + id(new PhabricatorFeedStoryPublisher()) 45 + ->setStoryType($story_type) 46 + ->setStoryData($story_data) 47 + ->setStoryTime(time()) 48 + ->setStoryAuthorPHID($actor->getPHID()) 49 + ->setRelatedPHIDs($related_phids) 50 + ->setPrimaryObjectPHID($object->getPHID()) 51 + ->setSubscribedPHIDs($subscribed_phids) 52 + ->publish(); 53 + } 54 + 32 55 return $token_given; 33 56 } 34 57 35 58 public function deleteToken($object_phid) { 36 - $handle = $this->validateObject($object_phid); 37 - 38 - return $this->executeDeleteToken($handle); 59 + $object = $this->validateObject($object_phid); 60 + return $this->executeDeleteToken($object); 39 61 } 40 62 41 - private function executeDeleteToken(PhabricatorObjectHandle $handle) { 63 + private function executeDeleteToken($object) { 42 64 $actor = $this->requireActor(); 43 65 44 66 $token_given = id(new PhabricatorTokenGiven())->loadOneWhere( 45 67 'authorPHID = %s AND objectPHID = %s', 46 68 $actor->getPHID(), 47 - $handle->getPHID()); 69 + $object->getPHID()); 48 70 if (!$token_given) { 49 71 return; 50 72 } ··· 58 80 'INSERT INTO %T (objectPHID, tokenCount) VALUES (%s, 0) 59 81 ON DUPLICATE KEY UPDATE tokenCount = tokenCount - 1', 60 82 id(new PhabricatorTokenCount())->getTableName(), 61 - $handle->getPHID()); 83 + $object->getPHID()); 62 84 63 85 $token_given->saveTransaction(); 64 86 } ··· 77 99 } 78 100 79 101 private function validateObject($object_phid) { 80 - $handle = PhabricatorObjectHandleData::loadOneHandle( 81 - $object_phid, 82 - $this->requireActor()); 102 + $objects = id(new PhabricatorObjectHandleData(array($object_phid))) 103 + ->setViewer($this->requireActor()) 104 + ->loadObjects(); 105 + $object = head($objects); 83 106 84 - if (!$handle->isComplete()) { 107 + if (!$object) { 85 108 throw new Exception("No such object!"); 86 109 } 87 110 88 - return $handle; 111 + return $object; 89 112 } 90 113 91 114 }
+1 -1
src/applications/tokens/event/PhabricatorTokenUIEventListener.php
··· 44 44 ->setUser($user) 45 45 ->setWorkflow(true) 46 46 ->setHref('/token/give/'.$object->getPHID().'/') 47 - ->setName(pht('Give Token')) 47 + ->setName(pht('Award Token')) 48 48 ->setIcon('like'); 49 49 } else { 50 50 $token_action = id(new PhabricatorActionView())
+40
src/applications/tokens/feed/PhabricatorTokenGivenFeedStory.php
··· 1 + <?php 2 + 3 + final class PhabricatorTokenGivenFeedStory 4 + extends PhabricatorFeedStory { 5 + 6 + public function getPrimaryObjectPHID() { 7 + return $this->getValue('objectPHID'); 8 + } 9 + 10 + public function getRequiredHandlePHIDs() { 11 + $phids = array(); 12 + $phids[] = $this->getValue('objectPHID'); 13 + $phids[] = $this->getValue('authorPHID'); 14 + return $phids; 15 + } 16 + 17 + public function renderView() { 18 + $view = new PhabricatorFeedStoryView(); 19 + $view->setViewed($this->getHasViewed()); 20 + 21 + $href = $this->getHandle($this->getPrimaryObjectPHID())->getURI(); 22 + $view->setHref($view); 23 + 24 + $title = pht( 25 + '%s awarded %s a token.', 26 + $this->linkTo($this->getValue('authorPHID')), 27 + $this->linkTo($this->getValue('objectPHID'))); 28 + 29 + $view->setTitle($title); 30 + $view->setOneLineStory(true); 31 + 32 + return $view; 33 + } 34 + 35 + public function renderText() { 36 + // TODO: This is grotesque; the feed notification handler relies on it. 37 + return strip_tags($this->renderView()->render()); 38 + } 39 + 40 + }
+2
src/applications/tokens/interface/PhabricatorTokenReceiverInterface.php
··· 2 2 3 3 interface PhabricatorTokenReceiverInterface { 4 4 5 + public function getUsersToNotifyOfTokenGiven(); 6 + 5 7 }