1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 23:02:42 +01:00

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
This commit is contained in:
epriestley 2013-02-18 17:44:45 -08:00
parent 8d79c7282d
commit a5f031835c
8 changed files with 111 additions and 16 deletions

View file

@ -1348,6 +1348,7 @@ phutil_register_library_map(array(
'PhabricatorTokenGiven' => 'applications/tokens/storage/PhabricatorTokenGiven.php', 'PhabricatorTokenGiven' => 'applications/tokens/storage/PhabricatorTokenGiven.php',
'PhabricatorTokenGivenController' => 'applications/tokens/controller/PhabricatorTokenGivenController.php', 'PhabricatorTokenGivenController' => 'applications/tokens/controller/PhabricatorTokenGivenController.php',
'PhabricatorTokenGivenEditor' => 'applications/tokens/editor/PhabricatorTokenGivenEditor.php', 'PhabricatorTokenGivenEditor' => 'applications/tokens/editor/PhabricatorTokenGivenEditor.php',
'PhabricatorTokenGivenFeedStory' => 'applications/tokens/feed/PhabricatorTokenGivenFeedStory.php',
'PhabricatorTokenGivenQuery' => 'applications/tokens/query/PhabricatorTokenGivenQuery.php', 'PhabricatorTokenGivenQuery' => 'applications/tokens/query/PhabricatorTokenGivenQuery.php',
'PhabricatorTokenQuery' => 'applications/tokens/query/PhabricatorTokenQuery.php', 'PhabricatorTokenQuery' => 'applications/tokens/query/PhabricatorTokenQuery.php',
'PhabricatorTokenReceiverInterface' => 'applications/tokens/interface/PhabricatorTokenReceiverInterface.php', 'PhabricatorTokenReceiverInterface' => 'applications/tokens/interface/PhabricatorTokenReceiverInterface.php',
@ -2808,6 +2809,7 @@ phutil_register_library_map(array(
), ),
'PhabricatorTokenGivenController' => 'PhabricatorTokenController', 'PhabricatorTokenGivenController' => 'PhabricatorTokenController',
'PhabricatorTokenGivenEditor' => 'PhabricatorEditor', 'PhabricatorTokenGivenEditor' => 'PhabricatorEditor',
'PhabricatorTokenGivenFeedStory' => 'PhabricatorFeedStory',
'PhabricatorTokenGivenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorTokenGivenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorTokenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorTokenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorTokenUIEventListener' => 'PhutilEventListener', 'PhabricatorTokenUIEventListener' => 'PhutilEventListener',

View file

@ -327,4 +327,10 @@ final class DifferentialRevision extends DifferentialDAO
return false; return false;
} }
public function getUsersToNotifyOfTokenGiven() {
return array(
$this->getAuthorPHID(),
);
}
} }

View file

@ -283,4 +283,17 @@ final class ManiphestTask extends ManiphestDAO
return false; return false;
} }
/* -( PhabricatorTokenReceiverInterface )---------------------------------- */
public function getUsersToNotifyOfTokenGiven() {
// Sort of ambiguous who this was intended for; just let them both know.
return array_filter(
array_unique(
array(
$this->getAuthorPHID(),
$this->getOwnerPHID(),
)));
}
} }

View file

@ -137,4 +137,13 @@ final class PholioMock extends PholioDAO
} }
/* -( PhabricatorTokenReceiverInterface )---------------------------------- */
public function getUsersToNotifyOfTokenGiven() {
return array(
$this->getAuthorPHID(),
);
}
} }

View file

@ -5,18 +5,18 @@ final class PhabricatorTokenGivenEditor
public function addToken($object_phid, $token_phid) { public function addToken($object_phid, $token_phid) {
$token = $this->validateToken($token_phid); $token = $this->validateToken($token_phid);
$handle = $this->validateObject($object_phid); $object = $this->validateObject($object_phid);
$actor = $this->requireActor(); $actor = $this->requireActor();
$token_given = id(new PhabricatorTokenGiven()) $token_given = id(new PhabricatorTokenGiven())
->setAuthorPHID($actor->getPHID()) ->setAuthorPHID($actor->getPHID())
->setObjectPHID($handle->getPHID()) ->setObjectPHID($object->getPHID())
->setTokenPHID($token->getPHID()); ->setTokenPHID($token->getPHID());
$token_given->openTransaction(); $token_given->openTransaction();
$this->executeDeleteToken($handle); $this->executeDeleteToken($object);
$token_given->save(); $token_given->save();
@ -25,26 +25,48 @@ final class PhabricatorTokenGivenEditor
'INSERT INTO %T (objectPHID, tokenCount) VALUES (%s, 1) 'INSERT INTO %T (objectPHID, tokenCount) VALUES (%s, 1)
ON DUPLICATE KEY UPDATE tokenCount = tokenCount + 1', ON DUPLICATE KEY UPDATE tokenCount = tokenCount + 1',
id(new PhabricatorTokenCount())->getTableName(), id(new PhabricatorTokenCount())->getTableName(),
$handle->getPHID()); $object->getPHID());
$token_given->saveTransaction(); $token_given->saveTransaction();
$subscribed_phids = $object->getUsersToNotifyOfTokenGiven();
if ($subscribed_phids) {
$related_phids = $subscribed_phids;
$related_phids[] = $actor->getPHID();
$story_type = 'PhabricatorTokenGivenFeedStory';
$story_data = array(
'authorPHID' => $actor->getPHID(),
'tokenPHID' => $token->getPHID(),
'objectPHID' => $object->getPHID(),
);
id(new PhabricatorFeedStoryPublisher())
->setStoryType($story_type)
->setStoryData($story_data)
->setStoryTime(time())
->setStoryAuthorPHID($actor->getPHID())
->setRelatedPHIDs($related_phids)
->setPrimaryObjectPHID($object->getPHID())
->setSubscribedPHIDs($subscribed_phids)
->publish();
}
return $token_given; return $token_given;
} }
public function deleteToken($object_phid) { public function deleteToken($object_phid) {
$handle = $this->validateObject($object_phid); $object = $this->validateObject($object_phid);
return $this->executeDeleteToken($object);
return $this->executeDeleteToken($handle);
} }
private function executeDeleteToken(PhabricatorObjectHandle $handle) { private function executeDeleteToken($object) {
$actor = $this->requireActor(); $actor = $this->requireActor();
$token_given = id(new PhabricatorTokenGiven())->loadOneWhere( $token_given = id(new PhabricatorTokenGiven())->loadOneWhere(
'authorPHID = %s AND objectPHID = %s', 'authorPHID = %s AND objectPHID = %s',
$actor->getPHID(), $actor->getPHID(),
$handle->getPHID()); $object->getPHID());
if (!$token_given) { if (!$token_given) {
return; return;
} }
@ -58,7 +80,7 @@ final class PhabricatorTokenGivenEditor
'INSERT INTO %T (objectPHID, tokenCount) VALUES (%s, 0) 'INSERT INTO %T (objectPHID, tokenCount) VALUES (%s, 0)
ON DUPLICATE KEY UPDATE tokenCount = tokenCount - 1', ON DUPLICATE KEY UPDATE tokenCount = tokenCount - 1',
id(new PhabricatorTokenCount())->getTableName(), id(new PhabricatorTokenCount())->getTableName(),
$handle->getPHID()); $object->getPHID());
$token_given->saveTransaction(); $token_given->saveTransaction();
} }
@ -77,15 +99,16 @@ final class PhabricatorTokenGivenEditor
} }
private function validateObject($object_phid) { private function validateObject($object_phid) {
$handle = PhabricatorObjectHandleData::loadOneHandle( $objects = id(new PhabricatorObjectHandleData(array($object_phid)))
$object_phid, ->setViewer($this->requireActor())
$this->requireActor()); ->loadObjects();
$object = head($objects);
if (!$handle->isComplete()) { if (!$object) {
throw new Exception("No such object!"); throw new Exception("No such object!");
} }
return $handle; return $object;
} }
} }

View file

@ -44,7 +44,7 @@ final class PhabricatorTokenUIEventListener
->setUser($user) ->setUser($user)
->setWorkflow(true) ->setWorkflow(true)
->setHref('/token/give/'.$object->getPHID().'/') ->setHref('/token/give/'.$object->getPHID().'/')
->setName(pht('Give Token')) ->setName(pht('Award Token'))
->setIcon('like'); ->setIcon('like');
} else { } else {
$token_action = id(new PhabricatorActionView()) $token_action = id(new PhabricatorActionView())

View file

@ -0,0 +1,40 @@
<?php
final class PhabricatorTokenGivenFeedStory
extends PhabricatorFeedStory {
public function getPrimaryObjectPHID() {
return $this->getValue('objectPHID');
}
public function getRequiredHandlePHIDs() {
$phids = array();
$phids[] = $this->getValue('objectPHID');
$phids[] = $this->getValue('authorPHID');
return $phids;
}
public function renderView() {
$view = new PhabricatorFeedStoryView();
$view->setViewed($this->getHasViewed());
$href = $this->getHandle($this->getPrimaryObjectPHID())->getURI();
$view->setHref($view);
$title = pht(
'%s awarded %s a token.',
$this->linkTo($this->getValue('authorPHID')),
$this->linkTo($this->getValue('objectPHID')));
$view->setTitle($title);
$view->setOneLineStory(true);
return $view;
}
public function renderText() {
// TODO: This is grotesque; the feed notification handler relies on it.
return strip_tags($this->renderView()->render());
}
}

View file

@ -2,4 +2,6 @@
interface PhabricatorTokenReceiverInterface { interface PhabricatorTokenReceiverInterface {
public function getUsersToNotifyOfTokenGiven();
} }