mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-23 07:12:41 +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:
parent
8d79c7282d
commit
a5f031835c
8 changed files with 111 additions and 16 deletions
|
@ -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',
|
||||||
|
|
|
@ -327,4 +327,10 @@ final class DifferentialRevision extends DifferentialDAO
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getUsersToNotifyOfTokenGiven() {
|
||||||
|
return array(
|
||||||
|
$this->getAuthorPHID(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,4 +137,13 @@ final class PholioMock extends PholioDAO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( PhabricatorTokenReceiverInterface )---------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
public function getUsersToNotifyOfTokenGiven() {
|
||||||
|
return array(
|
||||||
|
$this->getAuthorPHID(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,4 +2,6 @@
|
||||||
|
|
||||||
interface PhabricatorTokenReceiverInterface {
|
interface PhabricatorTokenReceiverInterface {
|
||||||
|
|
||||||
|
public function getUsersToNotifyOfTokenGiven();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue