Tokens v1
Summary: Features! - Giving tokens. - Taking tokens back. - Not giving tokens. Test Plan: See screenshots. Reviewers: chad, vrana Reviewed By: chad CC: aran, btrahan Maniphest Tasks: T2541 Differential Revision: https://secure.phabricator.com/D4964
This commit is contained in:
@@ -532,6 +532,13 @@ celerity_register_resource_map(array(
|
||||
'disk' => '/rsrc/image/sprite-menu.png',
|
||||
'type' => 'png',
|
||||
),
|
||||
'/rsrc/image/sprite-tokens.png' =>
|
||||
array(
|
||||
'hash' => '67c46fd75c885b76ecbfe46e71a476cc',
|
||||
'uri' => '/res/67c46fd7/rsrc/image/sprite-tokens.png',
|
||||
'disk' => '/rsrc/image/sprite-tokens.png',
|
||||
'type' => 'png',
|
||||
),
|
||||
'/rsrc/image/texture/dark-menu-hover.png' =>
|
||||
array(
|
||||
'hash' => 'a214a732644be34872e895b338b5d639',
|
||||
@@ -2861,7 +2868,7 @@ celerity_register_resource_map(array(
|
||||
),
|
||||
'phabricator-pinboard-view-css' =>
|
||||
array(
|
||||
'uri' => '/res/fdb2470f/rsrc/css/layout/phabricator-pinboard-view.css',
|
||||
'uri' => '/res/b954ccbf/rsrc/css/layout/phabricator-pinboard-view.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
@@ -3336,7 +3343,7 @@ celerity_register_resource_map(array(
|
||||
),
|
||||
'sprite-conpher-css' =>
|
||||
array(
|
||||
'uri' => '/res/89821322/rsrc/css/sprite-conph.css',
|
||||
'uri' => '/res/f640f0c5/rsrc/css/sprite-conph.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
@@ -3370,6 +3377,15 @@ celerity_register_resource_map(array(
|
||||
),
|
||||
'disk' => '/rsrc/css/sprite-menu.css',
|
||||
),
|
||||
'sprite-tokens-css' =>
|
||||
array(
|
||||
'uri' => '/res/9ae0de5b/rsrc/css/sprite-tokens.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/sprite-tokens.css',
|
||||
),
|
||||
'stripe-core' =>
|
||||
array(
|
||||
'uri' => '/res/3b0f0ad4/rsrc/js/stripe/stripe_core.js',
|
||||
@@ -3397,6 +3413,15 @@ celerity_register_resource_map(array(
|
||||
),
|
||||
'disk' => '/rsrc/css/core/syntax.css',
|
||||
),
|
||||
'tokens-css' =>
|
||||
array(
|
||||
'uri' => '/res/c1f6113c/rsrc/css/application/tokens/tokens.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/tokens/tokens.css',
|
||||
),
|
||||
), array(
|
||||
'packages' =>
|
||||
array(
|
||||
|
||||
@@ -182,6 +182,10 @@ phutil_register_library_map(array(
|
||||
'ConduitAPI_repository_create_Method' => 'applications/repository/conduit/ConduitAPI_repository_create_Method.php',
|
||||
'ConduitAPI_repository_query_Method' => 'applications/repository/conduit/ConduitAPI_repository_query_Method.php',
|
||||
'ConduitAPI_slowvote_info_Method' => 'applications/slowvote/conduit/ConduitAPI_slowvote_info_Method.php',
|
||||
'ConduitAPI_token_Method' => 'applications/tokens/conduit/ConduitAPI_token_Method.php',
|
||||
'ConduitAPI_token_give_Method' => 'applications/tokens/conduit/ConduitAPI_token_give_Method.php',
|
||||
'ConduitAPI_token_given_Method' => 'applications/tokens/conduit/ConduitAPI_token_given_Method.php',
|
||||
'ConduitAPI_token_query_Method' => 'applications/tokens/conduit/ConduitAPI_token_query_Method.php',
|
||||
'ConduitAPI_user_Method' => 'applications/people/conduit/ConduitAPI_user_Method.php',
|
||||
'ConduitAPI_user_addstatus_Method' => 'applications/people/conduit/ConduitAPI_user_addstatus_Method.php',
|
||||
'ConduitAPI_user_disable_Method' => 'applications/people/conduit/ConduitAPI_user_disable_Method.php',
|
||||
@@ -664,6 +668,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorApplicationSlowvote' => 'applications/slowvote/application/PhabricatorApplicationSlowvote.php',
|
||||
'PhabricatorApplicationStatusView' => 'applications/meta/view/PhabricatorApplicationStatusView.php',
|
||||
'PhabricatorApplicationSubscriptions' => 'applications/subscriptions/application/PhabricatorApplicationSubscriptions.php',
|
||||
'PhabricatorApplicationTokens' => 'applications/tokens/application/PhabricatorApplicationTokens.php',
|
||||
'PhabricatorApplicationTransaction' => 'applications/transactions/storage/PhabricatorApplicationTransaction.php',
|
||||
'PhabricatorApplicationTransactionComment' => 'applications/transactions/storage/PhabricatorApplicationTransactionComment.php',
|
||||
'PhabricatorApplicationTransactionCommentEditController' => 'applications/transactions/controller/PhabricatorApplicationTransactionCommentEditController.php',
|
||||
@@ -1323,6 +1328,18 @@ phutil_register_library_map(array(
|
||||
'PhabricatorTimelineIterator' => 'infrastructure/daemon/timeline/cursor/PhabricatorTimelineIterator.php',
|
||||
'PhabricatorTimelineView' => 'view/layout/PhabricatorTimelineView.php',
|
||||
'PhabricatorTimer' => 'applications/countdown/storage/PhabricatorTimer.php',
|
||||
'PhabricatorToken' => 'applications/tokens/storage/PhabricatorToken.php',
|
||||
'PhabricatorTokenController' => 'applications/tokens/controller/PhabricatorTokenController.php',
|
||||
'PhabricatorTokenCount' => 'applications/tokens/storage/PhabricatorTokenCount.php',
|
||||
'PhabricatorTokenDAO' => 'applications/tokens/storage/PhabricatorTokenDAO.php',
|
||||
'PhabricatorTokenGiveController' => 'applications/tokens/controller/PhabricatorTokenGiveController.php',
|
||||
'PhabricatorTokenGiven' => 'applications/tokens/storage/PhabricatorTokenGiven.php',
|
||||
'PhabricatorTokenGivenController' => 'applications/tokens/controller/PhabricatorTokenGivenController.php',
|
||||
'PhabricatorTokenGivenEditor' => 'applications/tokens/editor/PhabricatorTokenGivenEditor.php',
|
||||
'PhabricatorTokenGivenQuery' => 'applications/tokens/query/PhabricatorTokenGivenQuery.php',
|
||||
'PhabricatorTokenQuery' => 'applications/tokens/query/PhabricatorTokenQuery.php',
|
||||
'PhabricatorTokenReceiverInterface' => 'applications/tokens/interface/PhabricatorTokenReceiverInterface.php',
|
||||
'PhabricatorTokenUIEventListener' => 'applications/tokens/event/PhabricatorTokenUIEventListener.php',
|
||||
'PhabricatorTransactionView' => 'view/layout/PhabricatorTransactionView.php',
|
||||
'PhabricatorTransactions' => 'applications/transactions/constants/PhabricatorTransactions.php',
|
||||
'PhabricatorTransformedFile' => 'applications/files/storage/PhabricatorTransformedFile.php',
|
||||
@@ -1683,6 +1700,10 @@ phutil_register_library_map(array(
|
||||
'ConduitAPI_repository_create_Method' => 'ConduitAPI_repository_Method',
|
||||
'ConduitAPI_repository_query_Method' => 'ConduitAPI_repository_Method',
|
||||
'ConduitAPI_slowvote_info_Method' => 'ConduitAPIMethod',
|
||||
'ConduitAPI_token_Method' => 'ConduitAPIMethod',
|
||||
'ConduitAPI_token_give_Method' => 'ConduitAPI_token_Method',
|
||||
'ConduitAPI_token_given_Method' => 'ConduitAPI_token_Method',
|
||||
'ConduitAPI_token_query_Method' => 'ConduitAPI_token_Method',
|
||||
'ConduitAPI_user_Method' => 'ConduitAPIMethod',
|
||||
'ConduitAPI_user_addstatus_Method' => 'ConduitAPI_user_Method',
|
||||
'ConduitAPI_user_disable_Method' => 'ConduitAPI_user_Method',
|
||||
@@ -1817,7 +1838,12 @@ phutil_register_library_map(array(
|
||||
'DifferentialReviewedByFieldSpecification' => 'DifferentialFieldSpecification',
|
||||
'DifferentialReviewerStatsTestCase' => 'PhabricatorTestCase',
|
||||
'DifferentialReviewersFieldSpecification' => 'DifferentialFieldSpecification',
|
||||
'DifferentialRevision' => 'DifferentialDAO',
|
||||
'DifferentialRevision' =>
|
||||
array(
|
||||
0 => 'DifferentialDAO',
|
||||
1 => 'PhabricatorTokenReceiverInterface',
|
||||
2 => 'PhabricatorPolicyInterface',
|
||||
),
|
||||
'DifferentialRevisionCommentListView' => 'AphrontView',
|
||||
'DifferentialRevisionCommentView' => 'AphrontView',
|
||||
'DifferentialRevisionDetailView' => 'AphrontView',
|
||||
@@ -2112,6 +2138,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorApplicationSlowvote' => 'PhabricatorApplication',
|
||||
'PhabricatorApplicationStatusView' => 'AphrontView',
|
||||
'PhabricatorApplicationSubscriptions' => 'PhabricatorApplication',
|
||||
'PhabricatorApplicationTokens' => 'PhabricatorApplication',
|
||||
'PhabricatorApplicationTransaction' =>
|
||||
array(
|
||||
0 => 'PhabricatorLiskDAO',
|
||||
@@ -2741,6 +2768,25 @@ phutil_register_library_map(array(
|
||||
'PhabricatorTimelineIterator' => 'Iterator',
|
||||
'PhabricatorTimelineView' => 'AphrontView',
|
||||
'PhabricatorTimer' => 'PhabricatorCountdownDAO',
|
||||
'PhabricatorToken' =>
|
||||
array(
|
||||
0 => 'PhabricatorTokenDAO',
|
||||
1 => 'PhabricatorPolicyInterface',
|
||||
),
|
||||
'PhabricatorTokenController' => 'PhabricatorController',
|
||||
'PhabricatorTokenCount' => 'PhabricatorTokenDAO',
|
||||
'PhabricatorTokenDAO' => 'PhabricatorLiskDAO',
|
||||
'PhabricatorTokenGiveController' => 'PhabricatorTokenController',
|
||||
'PhabricatorTokenGiven' =>
|
||||
array(
|
||||
0 => 'PhabricatorTokenDAO',
|
||||
1 => 'PhabricatorPolicyInterface',
|
||||
),
|
||||
'PhabricatorTokenGivenController' => 'PhabricatorTokenController',
|
||||
'PhabricatorTokenGivenEditor' => 'PhabricatorEditor',
|
||||
'PhabricatorTokenGivenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorTokenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorTokenUIEventListener' => 'PhutilEventListener',
|
||||
'PhabricatorTransactionView' => 'AphrontView',
|
||||
'PhabricatorTransformedFile' => 'PhabricatorFileDAO',
|
||||
'PhabricatorTranslationsConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||
@@ -2853,6 +2899,7 @@ phutil_register_library_map(array(
|
||||
1 => 'PhabricatorMarkupInterface',
|
||||
2 => 'PhabricatorPolicyInterface',
|
||||
3 => 'PhabricatorSubscribableInterface',
|
||||
4 => 'PhabricatorTokenReceiverInterface',
|
||||
),
|
||||
'PholioMockCommentController' => 'PholioController',
|
||||
'PholioMockEditController' => 'PholioController',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
final class DifferentialRevision extends DifferentialDAO {
|
||||
final class DifferentialRevision extends DifferentialDAO
|
||||
implements PhabricatorTokenReceiverInterface, PhabricatorPolicyInterface {
|
||||
|
||||
protected $title;
|
||||
protected $originalTitle;
|
||||
@@ -311,4 +312,19 @@ final class DifferentialRevision extends DifferentialDAO {
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCapabilities() {
|
||||
return array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
);
|
||||
}
|
||||
|
||||
public function getPolicy($capability) {
|
||||
return PhabricatorPolicies::POLICY_USER;
|
||||
}
|
||||
|
||||
public function hasAutomaticCapability($capability, PhabricatorUser $user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -58,7 +58,10 @@ final class DifferentialRevisionDetailView extends AphrontView {
|
||||
$actions->addAction($obj);
|
||||
}
|
||||
|
||||
$properties = new PhabricatorPropertyListView();
|
||||
$properties = id(new PhabricatorPropertyListView())
|
||||
->setUser($user)
|
||||
->setObject($revision);
|
||||
|
||||
$status = $revision->getStatus();
|
||||
$local_vcs = $this->getDiff()->getSourceControlSystem();
|
||||
|
||||
|
||||
@@ -424,7 +424,9 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
||||
|
||||
$viewer = $this->getRequest()->getUser();
|
||||
|
||||
$view = new PhabricatorPropertyListView();
|
||||
$view = id(new PhabricatorPropertyListView())
|
||||
->setUser($viewer)
|
||||
->setObject($task);
|
||||
|
||||
$view->addProperty(
|
||||
pht('Assigned To'),
|
||||
@@ -511,6 +513,8 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
||||
$file_view->render());
|
||||
}
|
||||
|
||||
$view->invokeWillRenderEvent();
|
||||
|
||||
if (strlen($task->getDescription())) {
|
||||
$view->addSectionHeader(pht('Description'));
|
||||
$view->addTextContent(
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
* @group maniphest
|
||||
*/
|
||||
final class ManiphestTask extends ManiphestDAO
|
||||
implements PhabricatorMarkupInterface {
|
||||
implements
|
||||
PhabricatorMarkupInterface,
|
||||
PhabricatorPolicyInterface,
|
||||
PhabricatorTokenReceiverInterface {
|
||||
|
||||
const MARKUP_FIELD_DESCRIPTION = 'markup:desc';
|
||||
|
||||
@@ -261,4 +264,23 @@ final class ManiphestTask extends ManiphestDAO
|
||||
return (bool)$this->getID();
|
||||
}
|
||||
|
||||
|
||||
/* -( Policy Interface )--------------------------------------------------- */
|
||||
|
||||
|
||||
public function getCapabilities() {
|
||||
return array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
);
|
||||
}
|
||||
|
||||
public function getPolicy($capability) {
|
||||
return PhabricatorPolicies::POLICY_USER;
|
||||
}
|
||||
|
||||
public function hasAutomaticCapability($capability, PhabricatorUser $user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -122,7 +122,9 @@ final class PholioMockViewController extends PholioController {
|
||||
|
||||
$user = $this->getRequest()->getUser();
|
||||
|
||||
$properties = new PhabricatorPropertyListView();
|
||||
$properties = id(new PhabricatorPropertyListView())
|
||||
->setUser($user)
|
||||
->setObject($mock);
|
||||
|
||||
$properties->addProperty(
|
||||
pht('Author'),
|
||||
@@ -154,6 +156,8 @@ final class PholioMockViewController extends PholioController {
|
||||
pht('Subscribers'),
|
||||
$sub_view);
|
||||
|
||||
$properties->invokeWillRenderEvent();
|
||||
|
||||
$properties->addTextContent(
|
||||
$engine->getOutput($mock, PholioMock::MARKUP_FIELD_DESCRIPTION));
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@ final class PholioMock extends PholioDAO
|
||||
implements
|
||||
PhabricatorMarkupInterface,
|
||||
PhabricatorPolicyInterface,
|
||||
PhabricatorSubscribableInterface {
|
||||
PhabricatorSubscribableInterface,
|
||||
PhabricatorTokenReceiverInterface {
|
||||
|
||||
const MARKUP_FIELD_DESCRIPTION = 'markup:description';
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
final class PhabricatorApplicationTokens extends PhabricatorApplication {
|
||||
|
||||
public function getName() {
|
||||
return pht('Tokens');
|
||||
}
|
||||
|
||||
public function isBeta() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getBaseURI() {
|
||||
return '/token/';
|
||||
}
|
||||
|
||||
public function getTitleGlyph() {
|
||||
return "\xE2\x99\xA6";
|
||||
}
|
||||
|
||||
public function getShortDescription() {
|
||||
return pht('Acquire Trinkets');
|
||||
}
|
||||
|
||||
public function getApplicationGroup() {
|
||||
return self::GROUP_UTILITIES;
|
||||
}
|
||||
|
||||
public function getRoutes() {
|
||||
return array(
|
||||
'/token/' => array(
|
||||
'' => 'PhabricatorTokenGivenController',
|
||||
'given/' => 'PhabricatorTokenGivenController',
|
||||
'give/(?<phid>[^/]+)/' => 'PhabricatorTokenGiveController',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function getEventListeners() {
|
||||
return array(
|
||||
new PhabricatorTokenUIEventListener(),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
41
src/applications/tokens/conduit/ConduitAPI_token_Method.php
Normal file
41
src/applications/tokens/conduit/ConduitAPI_token_Method.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
abstract class ConduitAPI_token_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodStatus() {
|
||||
return self::METHOD_STATUS_UNSTABLE;
|
||||
}
|
||||
|
||||
public function buildTokenDicts(array $tokens) {
|
||||
assert_instances_of($tokens, 'PhabricatorToken');
|
||||
|
||||
$list = array();
|
||||
foreach ($tokens as $token) {
|
||||
$list[] = array(
|
||||
'id' => $token->getID(),
|
||||
'name' => $token->getName(),
|
||||
'phid' => $token->getPHID(),
|
||||
);
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function buildTokenGivenDicts(array $tokens_given) {
|
||||
assert_instances_of($tokens_given, 'PhabricatorTokenGiven');
|
||||
|
||||
$list = array();
|
||||
foreach ($tokens_given as $given) {
|
||||
$list[] = array(
|
||||
'authorPHID' => $given->getAuthorPHID(),
|
||||
'objectPHID' => $given->getObjectPHID(),
|
||||
'tokenPHID' => $given->getTokenPHID(),
|
||||
'dateCreated' => $given->getDateCreated(),
|
||||
);
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
final class ConduitAPI_token_give_Method extends ConduitAPI_token_Method {
|
||||
|
||||
public function getMethodDescription() {
|
||||
return pht('Give or change a token.');
|
||||
}
|
||||
|
||||
public function defineParamTypes() {
|
||||
return array(
|
||||
'tokenPHID' => 'phid|null',
|
||||
'objectPHID' => 'phid',
|
||||
);
|
||||
}
|
||||
|
||||
public function defineErrorTypes() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function defineReturnType() {
|
||||
return 'void';
|
||||
}
|
||||
|
||||
public function execute(ConduitAPIRequest $request) {
|
||||
$editor = id(new PhabricatorTokenGivenEditor())
|
||||
->setActor($request->getUser());
|
||||
|
||||
if ($request->getValue('tokenPHID')) {
|
||||
$editor->addToken(
|
||||
$request->getValue('objectPHID'),
|
||||
$request->getValue('tokenPHID'));
|
||||
} else {
|
||||
$editor->deleteToken($request->getValue('objectPHID'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
final class ConduitAPI_token_given_Method extends ConduitAPI_token_Method {
|
||||
|
||||
public function getMethodDescription() {
|
||||
return pht('Query tokens given to objects.');
|
||||
}
|
||||
|
||||
public function defineParamTypes() {
|
||||
return array(
|
||||
'authorPHIDs' => 'list<phid>',
|
||||
'objectPHIDs' => 'list<phid>',
|
||||
'tokenPHIDs' => 'list<phid>',
|
||||
);
|
||||
}
|
||||
|
||||
public function defineErrorTypes() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function defineReturnType() {
|
||||
return 'list<dict>';
|
||||
}
|
||||
|
||||
public function execute(ConduitAPIRequest $request) {
|
||||
$query = id(new PhabricatorTokenGivenQuery())
|
||||
->setViewer($request->getUser());
|
||||
|
||||
$author_phids = $request->getValue('authorPHIDs');
|
||||
if ($author_phids) {
|
||||
$query->withAuthorPHIDs($author_phids);
|
||||
}
|
||||
|
||||
$object_phids = $request->getValue('objectPHIDs');
|
||||
if ($object_phids) {
|
||||
$query->withObjectPHIDs($object_phids);
|
||||
}
|
||||
|
||||
$token_phids = $request->getValue('tokenPHIDs');
|
||||
if ($token_phids) {
|
||||
$query->withTokenPHIDs($token_phids);
|
||||
}
|
||||
|
||||
$given = $query->execute();
|
||||
|
||||
return $this->buildTokenGivenDicts($given);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
final class ConduitAPI_token_query_Method extends ConduitAPI_token_Method {
|
||||
|
||||
public function getMethodDescription() {
|
||||
return pht('Query tokens.');
|
||||
}
|
||||
|
||||
public function defineParamTypes() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function defineReturnType() {
|
||||
return 'list<dict>';
|
||||
}
|
||||
|
||||
public function defineErrorTypes() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function execute(ConduitAPIRequest $request) {
|
||||
$query = id(new PhabricatorTokenQuery())
|
||||
->setViewer($request->getUser());
|
||||
|
||||
$tokens = $query->execute();
|
||||
|
||||
return $this->buildTokenDicts($tokens);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
abstract class PhabricatorTokenController extends PhabricatorController {
|
||||
|
||||
|
||||
protected function buildSideNav() {
|
||||
$nav = new AphrontSideNavFilterView();
|
||||
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
|
||||
|
||||
$nav->addFilter('given/', pht('Tokens Given'));
|
||||
|
||||
return $nav;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
final class PhabricatorTokenGiveController extends PhabricatorTokenController {
|
||||
|
||||
private $phid;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->phid = $data['phid'];
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
$handle = PhabricatorObjectHandleData::loadOneHandle($this->phid, $user);
|
||||
if (!$handle->isComplete()) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$current = id(new PhabricatorTokenGivenQuery())
|
||||
->setViewer($user)
|
||||
->withAuthorPHIDs(array($user->getPHID()))
|
||||
->withObjectPHIDs(array($handle->getPHID()))
|
||||
->execute();
|
||||
|
||||
if ($current) {
|
||||
$is_give = false;
|
||||
$title = pht('Rescind Token');
|
||||
} else {
|
||||
$is_give = true;
|
||||
$title = pht('Give Token');
|
||||
}
|
||||
|
||||
$done_uri = $handle->getURI();
|
||||
if ($request->isDialogFormPost()) {
|
||||
if ($is_give) {
|
||||
$token_phid = $request->getStr('tokenPHID');
|
||||
$editor = id(new PhabricatorTokenGivenEditor())
|
||||
->setActor($user)
|
||||
->addToken($handle->getPHID(), $token_phid);
|
||||
} else {
|
||||
$editor = id(new PhabricatorTokenGivenEditor())
|
||||
->setActor($user)
|
||||
->deleteToken($handle->getPHID());
|
||||
}
|
||||
|
||||
return id(new AphrontReloadResponse())->setURI($done_uri);
|
||||
}
|
||||
|
||||
if ($is_give) {
|
||||
$dialog = $this->buildGiveTokenDialog();
|
||||
} else {
|
||||
$dialog = $this->buildRescindTokenDialog(head($current));
|
||||
}
|
||||
|
||||
$dialog->setUser($user);
|
||||
$dialog->addCancelButton($done_uri);
|
||||
|
||||
return id(new AphrontDialogResponse())->setDialog($dialog);
|
||||
}
|
||||
|
||||
private function buildGiveTokenDialog() {
|
||||
$user = $this->getRequest()->getUser();
|
||||
|
||||
$tokens = id(new PhabricatorTokenQuery())
|
||||
->setViewer($user)
|
||||
->execute();
|
||||
|
||||
$buttons = array();
|
||||
$ii = 0;
|
||||
foreach ($tokens as $token) {
|
||||
$buttons[] = javelin_tag(
|
||||
'button',
|
||||
array(
|
||||
'class' => 'token-button',
|
||||
'name' => 'tokenPHID',
|
||||
'value' => $token->getPHID(),
|
||||
'type' => 'submit',
|
||||
'sigil' => 'has-tooltip',
|
||||
'meta' => array(
|
||||
'tip' => $token->getName(),
|
||||
)
|
||||
),
|
||||
$token->renderIcon());
|
||||
if ((++$ii % 4) == 0) {
|
||||
$buttons[] = phutil_tag('br');
|
||||
}
|
||||
}
|
||||
|
||||
$buttons = phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'token-grid',
|
||||
),
|
||||
$buttons);
|
||||
|
||||
$dialog = new AphrontDialogView();
|
||||
$dialog->setTitle(pht('Give Token'));
|
||||
$dialog->appendChild($buttons);
|
||||
|
||||
return $dialog;
|
||||
}
|
||||
|
||||
private function buildRescindTokenDialog(PhabricatorTokenGiven $token_given) {
|
||||
$dialog = new AphrontDialogView();
|
||||
$dialog->setTitle(pht('Rescind Token'));
|
||||
|
||||
$dialog->appendChild(
|
||||
pht('Really rescind this lovely token?'));
|
||||
|
||||
$dialog->addSubmitButton(pht('Rescind Token'));
|
||||
|
||||
return $dialog;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
final class PhabricatorTokenGivenController extends PhabricatorTokenController {
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
$pager = id(new AphrontCursorPagerView())
|
||||
->setURI(new PhutilURI($this->getApplicationURI('/given/')));
|
||||
|
||||
$tokens_given = id(new PhabricatorTokenGivenQuery())
|
||||
->setViewer($user)
|
||||
->setLimit(100)
|
||||
->executeWithCursorPager($pager);
|
||||
|
||||
$handles = array();
|
||||
if ($tokens_given) {
|
||||
$object_phids = mpull($tokens_given, 'getObjectPHID');
|
||||
$user_phids = mpull($tokens_given, 'getAuthorPHID');
|
||||
$handle_phids = array_merge($object_phids, $user_phids);
|
||||
$handles = id(new PhabricatorObjectHandleData($handle_phids))
|
||||
->setViewer($user)
|
||||
->loadHandles();
|
||||
}
|
||||
|
||||
$tokens = array();
|
||||
if ($tokens_given) {
|
||||
$token_phids = mpull($tokens_given, 'getTokenPHID');
|
||||
$tokens = id(new PhabricatorTokenQuery())
|
||||
->setViewer($user)
|
||||
->withPHIDs($token_phids)
|
||||
->execute();
|
||||
$tokens = mpull($tokens, null, 'getPHID');
|
||||
}
|
||||
|
||||
$list = new PhabricatorObjectItemListView();
|
||||
foreach ($tokens_given as $token_given) {
|
||||
$handle = $handles[$token_given->getObjectPHID()];
|
||||
$token = idx($tokens, $token_given->getTokenPHID());
|
||||
|
||||
$item = id(new PhabricatorObjectItemView());
|
||||
$item->setHeader($handle->getFullName());
|
||||
$item->setHref($handle->getURI());
|
||||
|
||||
$item->addAttribute($token->renderIcon());
|
||||
|
||||
$item->addAttribute(
|
||||
pht(
|
||||
'Given by %s on %s',
|
||||
$handles[$token_given->getAuthorPHID()]->renderLink(),
|
||||
phabricator_date($token_given->getDateCreated(), $user)));
|
||||
|
||||
$list->addItem($item);
|
||||
}
|
||||
|
||||
$title = pht('Tokens Given');
|
||||
|
||||
$nav = $this->buildSideNav();
|
||||
$nav->setCrumbs(
|
||||
$this->buildApplicationCrumbs()
|
||||
->addCrumb(
|
||||
id(new PhabricatorCrumbView())
|
||||
->setName($title)));
|
||||
$nav->selectFilter('given/');
|
||||
|
||||
$nav->appendChild($list);
|
||||
$nav->appendChild($pager);
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
$nav,
|
||||
array(
|
||||
'title' => $title,
|
||||
'device' => true,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
final class PhabricatorTokenGivenEditor
|
||||
extends PhabricatorEditor {
|
||||
|
||||
public function addToken($object_phid, $token_phid) {
|
||||
$token = $this->validateToken($token_phid);
|
||||
$handle = $this->validateObject($object_phid);
|
||||
|
||||
$actor = $this->requireActor();
|
||||
|
||||
$token_given = id(new PhabricatorTokenGiven())
|
||||
->setAuthorPHID($actor->getPHID())
|
||||
->setObjectPHID($handle->getPHID())
|
||||
->setTokenPHID($token->getPHID());
|
||||
|
||||
$token_given->openTransaction();
|
||||
|
||||
$this->executeDeleteToken($handle);
|
||||
|
||||
$token_given->save();
|
||||
|
||||
queryfx(
|
||||
$token_given->establishConnection('w'),
|
||||
'INSERT INTO %T (objectPHID, tokenCount) VALUES (%s, 1)
|
||||
ON DUPLICATE KEY UPDATE tokenCount = tokenCount + 1',
|
||||
id(new PhabricatorTokenCount())->getTableName(),
|
||||
$handle->getPHID());
|
||||
|
||||
$token_given->saveTransaction();
|
||||
|
||||
return $token_given;
|
||||
}
|
||||
|
||||
public function deleteToken($object_phid) {
|
||||
$handle = $this->validateObject($object_phid);
|
||||
|
||||
return $this->executeDeleteToken($handle);
|
||||
}
|
||||
|
||||
private function executeDeleteToken(PhabricatorObjectHandle $handle) {
|
||||
$actor = $this->requireActor();
|
||||
|
||||
$token_given = id(new PhabricatorTokenGiven())->loadOneWhere(
|
||||
'authorPHID = %s AND objectPHID = %s',
|
||||
$actor->getPHID(),
|
||||
$handle->getPHID());
|
||||
if (!$token_given) {
|
||||
return;
|
||||
}
|
||||
|
||||
$token_given->openTransaction();
|
||||
|
||||
$token_given->delete();
|
||||
|
||||
queryfx(
|
||||
$token_given->establishConnection('w'),
|
||||
'INSERT INTO %T (objectPHID, tokenCount) VALUES (%s, 0)
|
||||
ON DUPLICATE KEY UPDATE tokenCount = tokenCount - 1',
|
||||
id(new PhabricatorTokenCount())->getTableName(),
|
||||
$handle->getPHID());
|
||||
|
||||
$token_given->saveTransaction();
|
||||
}
|
||||
|
||||
private function validateToken($token_phid) {
|
||||
$tokens = id(new PhabricatorTokenQuery())
|
||||
->setViewer($this->requireActor())
|
||||
->withPHIDs(array($token_phid))
|
||||
->execute();
|
||||
|
||||
if (empty($tokens)) {
|
||||
throw new Exception("No such token!");
|
||||
}
|
||||
|
||||
return head($tokens);
|
||||
}
|
||||
|
||||
private function validateObject($object_phid) {
|
||||
$handle = PhabricatorObjectHandleData::loadOneHandle(
|
||||
$object_phid,
|
||||
$this->requireActor());
|
||||
|
||||
if (!$handle->isComplete()) {
|
||||
throw new Exception("No such object!");
|
||||
}
|
||||
|
||||
return $handle;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
final class PhabricatorTokenUIEventListener
|
||||
extends PhutilEventListener {
|
||||
|
||||
public function register() {
|
||||
$this->listen(PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS);
|
||||
$this->listen(PhabricatorEventType::TYPE_UI_WILLRENDERPROPERTIES);
|
||||
}
|
||||
|
||||
public function handleEvent(PhutilEvent $event) {
|
||||
switch ($event->getType()) {
|
||||
case PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS:
|
||||
$this->handleActionEvent($event);
|
||||
break;
|
||||
case PhabricatorEventType::TYPE_UI_WILLRENDERPROPERTIES:
|
||||
$this->handlePropertyEvent($event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private function handleActionEvent($event) {
|
||||
$user = $event->getUser();
|
||||
$object = $event->getValue('object');
|
||||
|
||||
if (!$object || !$object->getPHID()) {
|
||||
// No object, or the object has no PHID yet..
|
||||
return;
|
||||
}
|
||||
|
||||
if (!($object instanceof PhabricatorTokenReceiverInterface)) {
|
||||
// This object isn't a token receiver.
|
||||
return;
|
||||
}
|
||||
|
||||
$current = id(new PhabricatorTokenGivenQuery())
|
||||
->setViewer($user)
|
||||
->withAuthorPHIDs(array($user->getPHID()))
|
||||
->withObjectPHIDs(array($object->getPHID()))
|
||||
->execute();
|
||||
|
||||
if (!$current) {
|
||||
$token_action = id(new PhabricatorActionView())
|
||||
->setUser($user)
|
||||
->setWorkflow(true)
|
||||
->setHref('/token/give/'.$object->getPHID().'/')
|
||||
->setName(pht('Give Token'))
|
||||
->setIcon('like');
|
||||
} else {
|
||||
$token_action = id(new PhabricatorActionView())
|
||||
->setUser($user)
|
||||
->setWorkflow(true)
|
||||
->setHref('/token/give/'.$object->getPHID().'/')
|
||||
->setName(pht('Rescind Token'))
|
||||
->setIcon('dislike');
|
||||
}
|
||||
|
||||
$actions = $event->getValue('actions');
|
||||
$actions[] = $token_action;
|
||||
$event->setValue('actions', $actions);
|
||||
}
|
||||
|
||||
private function handlePropertyEvent($event) {
|
||||
$user = $event->getUser();
|
||||
$object = $event->getValue('object');
|
||||
|
||||
if (!$object || !$object->getPHID()) {
|
||||
// No object, or the object has no PHID yet..
|
||||
return;
|
||||
}
|
||||
|
||||
if (!($object instanceof PhabricatorTokenReceiverInterface)) {
|
||||
// This object isn't a token receiver.
|
||||
return;
|
||||
}
|
||||
|
||||
$limit = 1;
|
||||
|
||||
$tokens_given = id(new PhabricatorTokenGivenQuery())
|
||||
->setViewer($user)
|
||||
->withObjectPHIDs(array($object->getPHID()))
|
||||
->execute();
|
||||
|
||||
if (!$tokens_given) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tokens = id(new PhabricatorTokenQuery())
|
||||
->setViewer($user)
|
||||
->withPHIDs(mpull($tokens_given, 'getTokenPHID'))
|
||||
->execute();
|
||||
$tokens = mpull($tokens, null, 'getPHID');
|
||||
|
||||
$author_phids = mpull($tokens_given, 'getAuthorPHID');
|
||||
$handles = id(new PhabricatorObjectHandleData($author_phids))
|
||||
->loadHandles();
|
||||
|
||||
$list = array();
|
||||
foreach ($tokens_given as $token_given) {
|
||||
if (!idx($tokens, $token_given->getTokenPHID())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$token = $tokens[$token_given->getTokenPHID()];
|
||||
|
||||
$list[] = javelin_tag(
|
||||
'span',
|
||||
array(
|
||||
'sigil' => 'has-tooltip',
|
||||
'meta' => array(
|
||||
'tip' => $handles[$token_given->getAuthorPHID()]->getName(),
|
||||
),
|
||||
),
|
||||
$token->renderIcon());
|
||||
}
|
||||
|
||||
$view = $event->getValue('view');
|
||||
$view->addProperty(pht('Tokens'), $list);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
interface PhabricatorTokenReceiverInterface {
|
||||
|
||||
}
|
||||
89
src/applications/tokens/query/PhabricatorTokenGivenQuery.php
Normal file
89
src/applications/tokens/query/PhabricatorTokenGivenQuery.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
final class PhabricatorTokenGivenQuery
|
||||
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
|
||||
private $authorPHIDs;
|
||||
private $objectPHIDs;
|
||||
private $tokenPHIDs;
|
||||
|
||||
public function withTokenPHIDs(array $token_phids) {
|
||||
$this->tokenPHIDs = $token_phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withObjectPHIDs(array $object_phids) {
|
||||
$this->objectPHIDs = $object_phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withAuthorPHIDs(array $author_phids) {
|
||||
$this->authorPHIDs = $author_phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function loadPage() {
|
||||
$table = new PhabricatorTokenGiven();
|
||||
$conn_r = $table->establishConnection('r');
|
||||
|
||||
$rows = queryfx_all(
|
||||
$conn_r,
|
||||
'SELECT * FROM %T %Q %Q %Q',
|
||||
$table->getTableName(),
|
||||
$this->buildWhereClause($conn_r),
|
||||
$this->buildOrderClause($conn_r),
|
||||
$this->buildLimitClause($conn_r));
|
||||
|
||||
return $table->loadAllFromArray($rows);
|
||||
}
|
||||
|
||||
private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
||||
$where = array();
|
||||
|
||||
if ($this->authorPHIDs) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'authorPHID IN (%Ls)',
|
||||
$this->authorPHIDs);
|
||||
}
|
||||
|
||||
if ($this->objectPHIDs) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'objectPHID IN (%Ls)',
|
||||
$this->objectPHIDs);
|
||||
}
|
||||
|
||||
if ($this->tokenPHIDs) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'tokenPHID IN (%Ls)',
|
||||
$this->tokenPHIDs);
|
||||
}
|
||||
|
||||
return $this->formatWhereClause($where);
|
||||
}
|
||||
|
||||
public function willFilterPage(array $results) {
|
||||
$object_phids = array_filter(mpull($results, 'getObjectPHID'));
|
||||
if (!$object_phids) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$objects = id(new PhabricatorObjectHandleData($object_phids))
|
||||
->setViewer($this->getViewer())
|
||||
->loadObjects();
|
||||
|
||||
foreach ($results as $key => $result) {
|
||||
$phid = $result->getObjectPHID();
|
||||
if (empty($objects[$phid])) {
|
||||
unset($results[$key]);
|
||||
} else {
|
||||
$result->attachObject($objects[$phid]);
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
}
|
||||
62
src/applications/tokens/query/PhabricatorTokenQuery.php
Normal file
62
src/applications/tokens/query/PhabricatorTokenQuery.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
final class PhabricatorTokenQuery
|
||||
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
|
||||
private $phids;
|
||||
|
||||
public function withPHIDs(array $phids) {
|
||||
$this->phids = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function loadPage() {
|
||||
$tokens = $this->getBuiltinTokens();
|
||||
|
||||
if ($this->phids) {
|
||||
$map = array_fill_keys($this->phids, true);
|
||||
foreach ($tokens as $key => $token) {
|
||||
if (empty($map[$token->getPHID()])) {
|
||||
unset($tokens[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
private function getBuiltinTokens() {
|
||||
$specs = array(
|
||||
array('like-1', pht('Like')),
|
||||
array('like-2', pht('Dislike')),
|
||||
array('heart-1', pht('Love')),
|
||||
array('heart-2', pht('Heartbreak')),
|
||||
array('medal-1', pht('Orange Medal')),
|
||||
array('medal-2', pht('Grey Medal')),
|
||||
array('medal-3', pht('Yellow Medal')),
|
||||
array('medal-4', pht('Manufacturing Defect?')),
|
||||
array('coin-1', pht('Haypence')),
|
||||
array('coin-2', pht('Piece of Eight')),
|
||||
array('coin-3', pht('Doubloon')),
|
||||
array('coin-4', pht('Mountain of Wealth')),
|
||||
array('misc-1', pht('Pterodactyl')),
|
||||
array('misc-2', pht('Evil Spooky Haunted Tree')),
|
||||
array('misc-3', pht('Baby Tequila')),
|
||||
array('misc-4', pht('The World Burns')),
|
||||
);
|
||||
|
||||
$tokens = array();
|
||||
foreach ($specs as $id => $spec) {
|
||||
list($image, $name) = $spec;
|
||||
|
||||
$token = id(new PhabricatorToken())
|
||||
->setID($id)
|
||||
->setName($name)
|
||||
->setPHID('PHID-TOKN-'.$image);
|
||||
$tokens[] = $token;
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
}
|
||||
46
src/applications/tokens/storage/PhabricatorToken.php
Normal file
46
src/applications/tokens/storage/PhabricatorToken.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
final class PhabricatorToken extends PhabricatorTokenDAO
|
||||
implements PhabricatorPolicyInterface {
|
||||
|
||||
protected $phid;
|
||||
protected $name;
|
||||
protected $filePHID;
|
||||
|
||||
public function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_AUX_PHID => true,
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
public function getCapabilities() {
|
||||
return array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
);
|
||||
}
|
||||
|
||||
public function getPolicy($capability) {
|
||||
return PhabricatorPolicies::POLICY_USER;
|
||||
}
|
||||
|
||||
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function renderIcon() {
|
||||
// TODO: Maybe move to a View class?
|
||||
|
||||
require_celerity_resource('sprite-tokens-css');
|
||||
require_celerity_resource('tokens-css');
|
||||
|
||||
$sprite = substr($this->getPHID(), 10);
|
||||
|
||||
return phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'sprite-tokens token-icon token-'.$sprite,
|
||||
),
|
||||
'');
|
||||
}
|
||||
|
||||
}
|
||||
15
src/applications/tokens/storage/PhabricatorTokenCount.php
Normal file
15
src/applications/tokens/storage/PhabricatorTokenCount.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
final class PhabricatorTokenCount extends PhabricatorTokenDAO {
|
||||
|
||||
protected $objectPHID;
|
||||
protected $tokenCount;
|
||||
|
||||
public function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_IDS => self::IDS_MANUAL,
|
||||
self::CONFIG_TIMESTAMPS => false,
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
}
|
||||
9
src/applications/tokens/storage/PhabricatorTokenDAO.php
Normal file
9
src/applications/tokens/storage/PhabricatorTokenDAO.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
abstract class PhabricatorTokenDAO extends PhabricatorLiskDAO {
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'token';
|
||||
}
|
||||
|
||||
}
|
||||
54
src/applications/tokens/storage/PhabricatorTokenGiven.php
Normal file
54
src/applications/tokens/storage/PhabricatorTokenGiven.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
final class PhabricatorTokenGiven extends PhabricatorTokenDAO
|
||||
implements PhabricatorPolicyInterface {
|
||||
|
||||
protected $authorPHID;
|
||||
protected $objectPHID;
|
||||
protected $tokenPHID;
|
||||
|
||||
private $object;
|
||||
|
||||
public function attachObject(PhabricatorTokenReceiverInterface $object) {
|
||||
$this->object = $object;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getObject() {
|
||||
if ($this->object === null) {
|
||||
throw new Exception("Call attachObject() before getObject()!");
|
||||
}
|
||||
return $this->object;
|
||||
}
|
||||
|
||||
public function getCapabilities() {
|
||||
return array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
);
|
||||
}
|
||||
|
||||
public function getPolicy($capability) {
|
||||
switch ($capability) {
|
||||
case PhabricatorPolicyCapability::CAN_VIEW:
|
||||
return $this->getObject()->getPolicy($capability);
|
||||
default:
|
||||
return PhabricatorPolicies::POLICY_NOONE;
|
||||
}
|
||||
}
|
||||
|
||||
public function hasAutomaticCapability($capability, PhabricatorUser $user) {
|
||||
switch ($capability) {
|
||||
case PhabricatorPolicyCapability::CAN_VIEW:
|
||||
return $this->getObject()->hasAutomaticCapability(
|
||||
$capability,
|
||||
$user);
|
||||
default:
|
||||
if ($user->getPHID() == $this->authorPHID) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -176,6 +176,33 @@ final class CeleritySpriteGenerator {
|
||||
return $sheet;
|
||||
}
|
||||
|
||||
public function buildTokenSheet() {
|
||||
$tokens = $this->getDirectoryList('tokens_1x');
|
||||
|
||||
$template = id(new PhutilSprite())
|
||||
->setSourceSize(16, 16);
|
||||
|
||||
$sprites = array();
|
||||
foreach ($tokens as $token) {
|
||||
$path = $this->getPath('tokens_1x/'.$token.'.png');
|
||||
|
||||
$sprite = id(clone $template)
|
||||
->setName('token-'.$token)
|
||||
->setTargetCSS('.token-'.$token)
|
||||
->setSourceFile($path, 1);
|
||||
|
||||
$sprites[] = $sprite;
|
||||
}
|
||||
|
||||
$sheet = $this->buildSheet('tokens', false);
|
||||
foreach ($sprites as $sprite) {
|
||||
$sheet->addSprite($sprite);
|
||||
}
|
||||
|
||||
return $sheet;
|
||||
}
|
||||
|
||||
|
||||
public function buildConpherenceSheet() {
|
||||
$icons = $this->getDirectoryList('conpher_1x');
|
||||
$scales = array(
|
||||
@@ -186,7 +213,7 @@ final class CeleritySpriteGenerator {
|
||||
->setSourceSize(32, 32);
|
||||
|
||||
$sprites = array();
|
||||
foreach ($icons as $icon) {
|
||||
foreach ($icons as $icon) {
|
||||
$color = preg_match('/_on/', $icon) ? 'on' : 'off';
|
||||
|
||||
$prefix = 'conpher_';
|
||||
|
||||
@@ -29,6 +29,7 @@ final class PhabricatorEventType extends PhutilEventType {
|
||||
const TYPE_UI_WILLRENDEROBJECTS = 'ui.willRenderObjects';
|
||||
const TYPE_UI_DDIDRENDEROBJECT = 'ui.didRenderObject';
|
||||
const TYPE_UI_DIDRENDEROBJECTS = 'ui.didRenderObjects';
|
||||
const TYPE_UI_WILLRENDERPROPERTIES = 'ui.willRenderProperties';
|
||||
|
||||
const TYPE_PEOPLE_DIDRENDERMENU = 'people.didRenderMenu';
|
||||
}
|
||||
|
||||
@@ -163,6 +163,14 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
|
||||
'type' => 'db',
|
||||
'name' => 'conpherence',
|
||||
),
|
||||
'db.config' => array(
|
||||
'type' => 'db',
|
||||
'name' => 'config',
|
||||
),
|
||||
'db.token' => array(
|
||||
'type' => 'db',
|
||||
'name' => 'token',
|
||||
),
|
||||
'0000.legacy.sql' => array(
|
||||
'type' => 'sql',
|
||||
'name' => $this->getPatchPath('0000.legacy.sql'),
|
||||
@@ -1068,10 +1076,6 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
|
||||
'type' => 'sql',
|
||||
'name' => $this->getPatchPath('20121220.generalcache.sql'),
|
||||
),
|
||||
'db.config' => array(
|
||||
'type' => 'db',
|
||||
'name' => 'config',
|
||||
),
|
||||
'20121226.config.sql' => array(
|
||||
'type' => 'sql',
|
||||
'name' => $this->getPatchPath('20121226.config.sql'),
|
||||
@@ -1117,6 +1121,10 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
|
||||
'type' => 'sql',
|
||||
'name' => $this->getPatchPath('20130214.chatlogchannelid.sql'),
|
||||
),
|
||||
'20130214.token.sql' => array(
|
||||
'type' => 'sql',
|
||||
'name' => $this->getPatchPath('20130214.token.sql'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,18 @@ final class PhabricatorPropertyListView extends AphrontView {
|
||||
|
||||
private $parts = array();
|
||||
private $hasKeyboardShortcuts;
|
||||
private $object;
|
||||
private $invokedWillRenderEvent;
|
||||
|
||||
protected function canAppendChild() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function setObject($object) {
|
||||
$this->object = $object;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setHasKeyboardShortcuts($has_keyboard_shortcuts) {
|
||||
$this->hasKeyboardShortcuts = $has_keyboard_shortcuts;
|
||||
return $this;
|
||||
@@ -52,7 +59,25 @@ final class PhabricatorPropertyListView extends AphrontView {
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function invokeWillRenderEvent() {
|
||||
if ($this->object && $this->getUser() && !$this->invokedWillRenderEvent) {
|
||||
$event = new PhabricatorEvent(
|
||||
PhabricatorEventType::TYPE_UI_WILLRENDERPROPERTIES,
|
||||
array(
|
||||
'object' => $this->object,
|
||||
'view' => $this,
|
||||
));
|
||||
$event->setUser($this->getUser());
|
||||
PhutilEventEngine::dispatchEvent($event);
|
||||
}
|
||||
$this->invokedWillRenderEvent = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function render() {
|
||||
$this->invokeWillRenderEvent();
|
||||
|
||||
require_celerity_resource('phabricator-property-list-view-css');
|
||||
|
||||
$items = array();
|
||||
|
||||
Reference in New Issue
Block a user