Page MenuHomePhabricator

D16178.id38919.diff
No OneTemporary

D16178.id38919.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -3599,11 +3599,15 @@
'PhabricatorTimezoneSetupCheck' => 'applications/config/check/PhabricatorTimezoneSetupCheck.php',
'PhabricatorTitleGlyphsSetting' => 'applications/settings/setting/PhabricatorTitleGlyphsSetting.php',
'PhabricatorToken' => 'applications/tokens/storage/PhabricatorToken.php',
+ 'PhabricatorTokenArchiveController' => 'applications/tokens/controller/PhabricatorTokenArchiveController.php',
'PhabricatorTokenController' => 'applications/tokens/controller/PhabricatorTokenController.php',
'PhabricatorTokenCount' => 'applications/tokens/storage/PhabricatorTokenCount.php',
'PhabricatorTokenCountQuery' => 'applications/tokens/query/PhabricatorTokenCountQuery.php',
'PhabricatorTokenDAO' => 'applications/tokens/storage/PhabricatorTokenDAO.php',
'PhabricatorTokenDestructionEngineExtension' => 'applications/tokens/engineextension/PhabricatorTokenDestructionEngineExtension.php',
+ 'PhabricatorTokenEditController' => 'applications/tokens/controller/PhabricatorTokenEditController.php',
+ 'PhabricatorTokenEditEngine' => 'applications/tokens/editor/PhabricatorTokenEditEngine.php',
+ 'PhabricatorTokenEditor' => 'applications/tokens/editor/PhabricatorTokenEditor.php',
'PhabricatorTokenGiveController' => 'applications/tokens/controller/PhabricatorTokenGiveController.php',
'PhabricatorTokenGiven' => 'applications/tokens/storage/PhabricatorTokenGiven.php',
'PhabricatorTokenGivenController' => 'applications/tokens/controller/PhabricatorTokenGivenController.php',
@@ -3611,15 +3615,26 @@
'PhabricatorTokenGivenFeedStory' => 'applications/tokens/feed/PhabricatorTokenGivenFeedStory.php',
'PhabricatorTokenGivenQuery' => 'applications/tokens/query/PhabricatorTokenGivenQuery.php',
'PhabricatorTokenLeaderController' => 'applications/tokens/controller/PhabricatorTokenLeaderController.php',
+ 'PhabricatorTokenListController' => 'applications/tokens/controller/PhabricatorTokenListController.php',
'PhabricatorTokenQuery' => 'applications/tokens/query/PhabricatorTokenQuery.php',
'PhabricatorTokenReceiverInterface' => 'applications/tokens/interface/PhabricatorTokenReceiverInterface.php',
'PhabricatorTokenReceiverQuery' => 'applications/tokens/query/PhabricatorTokenReceiverQuery.php',
- 'PhabricatorTokenTokenPHIDType' => 'applications/tokens/phid/PhabricatorTokenTokenPHIDType.php',
+ 'PhabricatorTokenSearchEngine' => 'applications/tokens/query/PhabricatorTokenSearchEngine.php',
'PhabricatorTokenUIEventListener' => 'applications/tokens/event/PhabricatorTokenUIEventListener.php',
+ 'PhabricatorTokenViewController' => 'applications/tokens/controller/PhabricatorTokenViewController.php',
'PhabricatorTokenizerEditField' => 'applications/transactions/editfield/PhabricatorTokenizerEditField.php',
'PhabricatorTokensApplication' => 'applications/tokens/application/PhabricatorTokensApplication.php',
+ 'PhabricatorTokensCreateCapability' => 'applications/tokens/capability/PhabricatorTokensCreateCapability.php',
'PhabricatorTokensCurtainExtension' => 'applications/tokens/engineextension/PhabricatorTokensCurtainExtension.php',
+ 'PhabricatorTokensDefaultEditCapability' => 'applications/tokens/capability/PhabricatorTokensDefaultEditCapability.php',
+ 'PhabricatorTokensMailReceiver' => 'applications/tokens/mail/PhabricatorTokensMailReceiver.php',
+ 'PhabricatorTokensReplyHandler' => 'applications/tokens/mail/PhabricatorTokensReplyHandler.php',
'PhabricatorTokensSettingsPanel' => 'applications/settings/panel/PhabricatorTokensSettingsPanel.php',
+ 'PhabricatorTokensToken' => 'applications/tokens/storage/PhabricatorTokensToken.php',
+ 'PhabricatorTokensTokenPHIDType' => 'applications/tokens/phid/PhabricatorTokensTokenPHIDType.php',
+ 'PhabricatorTokensTransaction' => 'applications/tokens/storage/PhabricatorTokensTransaction.php',
+ 'PhabricatorTokensTransactionComment' => 'applications/tokens/storage/PhabricatorTokensTransactionComment.php',
+ 'PhabricatorTokensTransactionQuery' => 'applications/tokens/query/PhabricatorTokensTransactionQuery.php',
'PhabricatorTooltipUIExample' => 'applications/uiexample/examples/PhabricatorTooltipUIExample.php',
'PhabricatorTransactionChange' => 'applications/transactions/data/PhabricatorTransactionChange.php',
'PhabricatorTransactionRemarkupChange' => 'applications/transactions/data/PhabricatorTransactionRemarkupChange.php',
@@ -8440,11 +8455,15 @@
'PhabricatorTokenDAO',
'PhabricatorPolicyInterface',
),
+ 'PhabricatorTokenArchiveController' => 'PhabricatorTokenController',
'PhabricatorTokenController' => 'PhabricatorController',
'PhabricatorTokenCount' => 'PhabricatorTokenDAO',
'PhabricatorTokenCountQuery' => 'PhabricatorOffsetPagedQuery',
'PhabricatorTokenDAO' => 'PhabricatorLiskDAO',
'PhabricatorTokenDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension',
+ 'PhabricatorTokenEditController' => 'PhabricatorTokenController',
+ 'PhabricatorTokenEditEngine' => 'PhabricatorEditEngine',
+ 'PhabricatorTokenEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorTokenGiveController' => 'PhabricatorTokenController',
'PhabricatorTokenGiven' => array(
'PhabricatorTokenDAO',
@@ -8455,14 +8474,31 @@
'PhabricatorTokenGivenFeedStory' => 'PhabricatorFeedStory',
'PhabricatorTokenGivenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorTokenLeaderController' => 'PhabricatorTokenController',
+ 'PhabricatorTokenListController' => 'PhabricatorTokenController',
'PhabricatorTokenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorTokenReceiverQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
- 'PhabricatorTokenTokenPHIDType' => 'PhabricatorPHIDType',
+ 'PhabricatorTokenSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorTokenUIEventListener' => 'PhabricatorEventListener',
+ 'PhabricatorTokenViewController' => 'PhabricatorTokenController',
'PhabricatorTokenizerEditField' => 'PhabricatorPHIDListEditField',
'PhabricatorTokensApplication' => 'PhabricatorApplication',
+ 'PhabricatorTokensCreateCapability' => 'PhabricatorPolicyCapability',
'PhabricatorTokensCurtainExtension' => 'PHUICurtainExtension',
+ 'PhabricatorTokensDefaultEditCapability' => 'PhabricatorPolicyCapability',
+ 'PhabricatorTokensMailReceiver' => 'PhabricatorObjectMailReceiver',
+ 'PhabricatorTokensReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
'PhabricatorTokensSettingsPanel' => 'PhabricatorSettingsPanel',
+ 'PhabricatorTokensToken' => array(
+ 'PhameDAO',
+ 'PhabricatorPolicyInterface',
+ 'PhabricatorDestructibleInterface',
+ 'PhabricatorApplicationTransactionInterface',
+ 'PhabricatorConduitResultInterface',
+ ),
+ 'PhabricatorTokensTokenPHIDType' => 'PhabricatorPHIDType',
+ 'PhabricatorTokensTransaction' => 'PhabricatorApplicationTransaction',
+ 'PhabricatorTokensTransactionComment' => 'PhabricatorApplicationTransactionComment',
+ 'PhabricatorTokensTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorTooltipUIExample' => 'PhabricatorUIExample',
'PhabricatorTransactionChange' => 'Phobject',
'PhabricatorTransactionRemarkupChange' => 'PhabricatorTransactionChange',
diff --git a/src/applications/tokens/application/PhabricatorTokensApplication.php b/src/applications/tokens/application/PhabricatorTokensApplication.php
--- a/src/applications/tokens/application/PhabricatorTokensApplication.php
+++ b/src/applications/tokens/application/PhabricatorTokensApplication.php
@@ -7,7 +7,7 @@
}
public function getBaseURI() {
- return '/token/';
+ return '/tokens/';
}
public function getIcon() {
@@ -28,11 +28,33 @@
public function getRoutes() {
return array(
- '/token/' => array(
- '' => 'PhabricatorTokenGivenController',
- 'given/' => 'PhabricatorTokenGivenController',
- 'give/(?<phid>[^/]+)/' => 'PhabricatorTokenGiveController',
- 'leaders/' => 'PhabricatorTokenLeaderController',
+ '/tokens/' => array(
+ '(?:query/(?P<queryKey>[^/]+)/)?'
+ => 'PhabricatorTokenListController',
+ 'given/' =>
+ 'PhabricatorTokenGivenController',
+ 'give/(?<phid>[^/]+)/' =>
+ 'PhabricatorTokenGiveController',
+ 'leaders/' =>
+ 'PhabricatorTokenLeaderController',
+ 'view/(?:(?P<id>\d+)/)?'
+ => 'PhabricatorTokenViewController',
+ $this->getEditRoutePattern('edit/')
+ => 'PhabaricatorTokenEditController',
+ ),
+ );
+ }
+
+ protected function getCustomCapabilities() {
+ return array(
+ PhabricatorTokensCreateCapability::CAPABILITY => array(
+ 'default' => PhabricatorPolicies::POLICY_ADMIN,
+ 'caption' => pht('Default create policy for tokens.'),
+ ),
+ PhabricatorTokensDefaultEditCapability::CAPABILITY => array(
+ 'default' => PhabricatorPolicies::POLICY_ADMIN,
+ 'caption' => pht('Default edit policy for tokens.'),
+ 'template' => PhabricatorTokensTokenPHIDType::TYPECONST,
),
);
}
diff --git a/src/applications/tokens/capability/PhabricatorTokensCreateCapability.php b/src/applications/tokens/capability/PhabricatorTokensCreateCapability.php
new file mode 100644
--- /dev/null
+++ b/src/applications/tokens/capability/PhabricatorTokensCreateCapability.php
@@ -0,0 +1,16 @@
+<?php
+
+final class PhabricatorTokensCreateCapability
+ extends PhabricatorPolicyCapability {
+
+ const CAPABILITY = 'tokens.default.create';
+
+ public function getCapabilityName() {
+ return pht('Can Create Tokens');
+ }
+
+ public function describeCapabilityRejection() {
+ return pht('You do not have permission to create tokens.');
+ }
+
+}
diff --git a/src/applications/tokens/capability/PhabricatorTokensDefaultEditCapability.php b/src/applications/tokens/capability/PhabricatorTokensDefaultEditCapability.php
new file mode 100644
--- /dev/null
+++ b/src/applications/tokens/capability/PhabricatorTokensDefaultEditCapability.php
@@ -0,0 +1,12 @@
+<?php
+
+final class PhabricatorTokensDefaultEditCapability
+ extends PhabricatorPolicyCapability {
+
+ const CAPABILITY = 'tokens.default.edit';
+
+ public function getCapabilityName() {
+ return pht('Default Edit Tokens');
+ }
+
+}
diff --git a/src/applications/tokens/controller/PhabricatorTokenArchiveController.php b/src/applications/tokens/controller/PhabricatorTokenArchiveController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/tokens/controller/PhabricatorTokenArchiveController.php
@@ -0,0 +1,67 @@
+<?php
+
+final class PhabricatorTokenArchiveController
+ extends PhabricatorTokenController {
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $request->getViewer();
+ $id = $request->getURIData('id');
+
+ $token = id(new PhabricatorTokenQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($id))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->executeOne();
+ if (!$token) {
+ return new Aphront404Response();
+ }
+
+ $view_uri = $this->getApplicationURI('view/'.$token->getID().'/');
+
+ if ($request->isFormPost()) {
+ if ($token->isArchived()) {
+ $new_status = PhabricatorTokensToken::STATUS_ACTIVE;
+ } else {
+ $new_status = PhabricatorTokensToken::STATUS_ARCHIVED;
+ }
+
+ $xactions = array();
+
+ $xactions[] = id(new PhabricatorTokensTransaction())
+ ->setTransactionType(PhabricatorTokensTransaction::TYPE_STATUS)
+ ->setNewValue($new_status);
+
+ id(new PhabricatorTokenEditor())
+ ->setActor($viewer)
+ ->setContentSourceFromRequest($request)
+ ->setContinueOnNoEffect(true)
+ ->setContinueOnMissingFields(true)
+ ->applyTransactions($token, $xactions);
+
+ return id(new AphrontRedirectResponse())->setURI($view_uri);
+ }
+
+ if ($token->isArchived()) {
+ $title = pht('Activate Token');
+ $body = pht('This token will immediately be available for '.
+ 'general tomfoolery.');
+ $button = pht('Activate Token');
+ } else {
+ $title = pht('Archive Token');
+ $body = pht(
+ 'Really? You want to just "get rid" of this token? Kinda harsh.');
+ $button = pht('Archive Token');
+ }
+
+ return $this->newDialog()
+ ->setTitle($title)
+ ->appendChild($body)
+ ->addCancelButton($view_uri)
+ ->addSubmitButton($button);
+ }
+
+}
diff --git a/src/applications/tokens/controller/PhabricatorTokenController.php b/src/applications/tokens/controller/PhabricatorTokenController.php
--- a/src/applications/tokens/controller/PhabricatorTokenController.php
+++ b/src/applications/tokens/controller/PhabricatorTokenController.php
@@ -1,25 +1,4 @@
<?php
-abstract class PhabricatorTokenController extends PhabricatorController {
+abstract class PhabricatorTokenController extends PhabricatorController {}
- protected function buildSideNav() {
- $nav = new AphrontSideNavFilterView();
- $nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
-
- $nav->addLabel(pht('Tokens'));
- $nav->addFilter('given/', pht('Tokens Given'));
- $nav->addFilter('leaders/', pht('Leader Board'));
-
- return $nav;
- }
-
- public function buildApplicationMenu() {
- return $this->buildSideNav()->getMenu();
- }
-
- protected function buildApplicationCrumbs() {
- $crumbs = parent::buildApplicationCrumbs();
- return $crumbs;
- }
-
-}
diff --git a/src/applications/tokens/controller/PhabricatorTokenEditController.php b/src/applications/tokens/controller/PhabricatorTokenEditController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/tokens/controller/PhabricatorTokenEditController.php
@@ -0,0 +1,11 @@
+<?php
+
+final class PhabricatorTokenEditController extends PhabricatorTokenController {
+
+ public function handleRequest(AphrontRequest $request) {
+ return id(new PhabricatorTokenEditEngine())
+ ->setController($this)
+ ->buildResponse();
+ }
+
+}
diff --git a/src/applications/tokens/controller/PhabricatorTokenListController.php b/src/applications/tokens/controller/PhabricatorTokenListController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/tokens/controller/PhabricatorTokenListController.php
@@ -0,0 +1,26 @@
+<?php
+
+final class PhabricatorTokenListController
+ extends PhabricatorTokenController {
+
+ public function shouldAllowPublic() {
+ return true;
+ }
+
+ public function handleRequest(AphrontRequest $request) {
+ return id(new PhabricatorTokenSearchEngine())
+ ->setController($this)
+ ->buildResponse();
+ }
+
+ protected function buildApplicationCrumbs() {
+ $crumbs = parent::buildApplicationCrumbs();
+
+ id(new PhabricatorTokenEditEngine())
+ ->setViewer($this->getViewer())
+ ->addActionToCrumbs($crumbs);
+
+ return $crumbs;
+ }
+
+}
diff --git a/src/applications/tokens/controller/PhabricatorTokenViewController.php b/src/applications/tokens/controller/PhabricatorTokenViewController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/tokens/controller/PhabricatorTokenViewController.php
@@ -0,0 +1,124 @@
+<?php
+
+final class PhabricatorTokenViewController
+ extends PhabricatorTokenController {
+
+ public function shouldAllowPublic() {
+ return true;
+ }
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $request->getViewer();
+ $id = $request->getURIData('id');
+
+ $token = id(new PhabricatorTokenQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($id))
+ ->executeOne();
+ if (!$token) {
+ return new Aphront404Response();
+ }
+
+ $crumbs = $this->buildApplicationCrumbs();
+ $crumbs->addTextCrumb($token->getName());
+ $crumbs->setBorder(true);
+ $title = $token->getName();
+
+ if ($token->isArchived()) {
+ $status_icon = 'fa-ban';
+ $status_color = 'dark';
+ } else {
+ $status_icon = 'fa-check';
+ $status_color = 'bluegrey';
+ }
+ $status_name = idx(
+ PhabricatorTokensToken::getStatusNameMap(),
+ $token->getStatus());
+
+ $header = id(new PHUIHeaderView())
+ ->setHeader($token->getName())
+ ->setUser($viewer)
+ ->setPolicyObject($token)
+ ->setStatus($status_icon, $status_color, $status_name)
+ ->setHeaderIcon('fa-trophy');
+
+ $curtain = $this->buildCurtain($token);
+ $details = $this->buildDetailsView($token);
+
+ $timeline = $this->buildTransactionTimeline(
+ $token,
+ new PhabricatorTokensTransactionQuery());
+
+ $comment_view = id(new PhabricatorTokenEditEngine())
+ ->setViewer($viewer)
+ ->buildEditEngineCommentView($token);
+
+ $view = id(new PHUITwoColumnView())
+ ->setHeader($header)
+ ->setCurtain($curtain)
+ ->setMainColumn(array(
+ $timeline,
+ $comment_view,
+ ))
+ ->addPropertySection(pht('Description'), $details);
+
+ return $this->newPage()
+ ->setTitle($title)
+ ->setCrumbs($crumbs)
+ ->setPageObjectPHIDs(array($token->getPHID()))
+ ->appendChild($view);
+ }
+
+ private function buildDetailsView(
+ PhabricatorBadgesBadge $token) {
+ $viewer = $this->getViewer();
+
+ $view = id(new PHUIPropertyListView())
+ ->setUser($viewer);
+
+ return $view;
+ }
+
+ private function buildCurtain(PhabricatorTokensToken $token) {
+ $viewer = $this->getViewer();
+
+ $can_edit = PhabricatorPolicyFilter::hasCapability(
+ $viewer,
+ $token,
+ PhabricatorPolicyCapability::CAN_EDIT);
+
+ $id = $token->getID();
+ $edit_uri = $this->getApplicationURI("/edit/{$id}/");
+ $archive_uri = $this->getApplicationURI("/archive/{$id}/");
+
+ $curtain = $this->newCurtainView($token);
+
+ $curtain->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('Edit Token'))
+ ->setIcon('fa-pencil')
+ ->setDisabled(!$can_edit)
+ ->setHref($edit_uri));
+
+ if ($token->isArchived()) {
+ $curtain->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('Activate Token'))
+ ->setIcon('fa-check')
+ ->setDisabled(!$can_edit)
+ ->setWorkflow($can_edit)
+ ->setHref($archive_uri));
+ } else {
+ $curtain->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('Archive Token'))
+ ->setIcon('fa-ban')
+ ->setDisabled(!$can_edit)
+ ->setWorkflow($can_edit)
+ ->setHref($archive_uri));
+ }
+
+ return $curtain;
+ }
+
+}
diff --git a/src/applications/tokens/editor/PhabricatorTokenEditEngine.php b/src/applications/tokens/editor/PhabricatorTokenEditEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/tokens/editor/PhabricatorTokenEditEngine.php
@@ -0,0 +1,90 @@
+<?php
+
+final class PhabricatorTokenEditEngine
+ extends PhabricatorEditEngine {
+
+ const ENGINECONST = 'phabricator.tokens.token';
+
+ public function getEngineName() {
+ return pht('Tokens');
+ }
+
+ public function getEngineApplicationClass() {
+ return 'PhabricatorTokensApplication';
+ }
+
+ public function getSummaryHeader() {
+ return pht('Configure Tokens Forms');
+ }
+
+ public function getSummaryText() {
+ return pht('Configure how tokens are created and edited.');
+ }
+
+ protected function newEditableObject() {
+ return PhabricatorToken::initializeNewToken($this->getViewer());
+ }
+
+ protected function newObjectQuery() {
+ return id(new PhabricatorTokenQuery());
+ }
+
+ protected function getObjectCreateTitleText($object) {
+ return pht('Create New Token');
+ }
+
+ protected function getObjectEditTitleText($object) {
+ return pht('Edit %s', $object->getName());
+ }
+
+ protected function getObjectEditShortText($object) {
+ return $object->getName();
+ }
+
+ protected function getObjectCreateShortText() {
+ return pht('Create Token');
+ }
+
+ protected function getObjectName() {
+ return pht('Token');
+ }
+
+ protected function getObjectCreateCancelURI($object) {
+ return $this->getApplication()->getApplicationURI('token/');
+ }
+
+ protected function getEditorURI() {
+ return $this->getApplication()->getApplicationURI('token/edit/');
+ }
+
+ protected function getObjectViewURI($object) {
+ return $object->getManageURI();
+ }
+
+ protected function getCreateNewObjectPolicy() {
+ return $this->getApplication()->getPolicy(
+ PhabricatorTokensCreateCapability::CAPABILITY);
+ }
+
+ protected function buildCustomEditFields($object) {
+ return array(
+ id(new PhabricatorTextEditField())
+ ->setKey('name')
+ ->setLabel(pht('Name'))
+ ->setDescription(pht('Token name.'))
+ ->setConduitDescription(pht('Retitle the token.'))
+ ->setConduitTypeDescription(pht('New token name.'))
+ ->setTransactionType(PhabricatorTokensTransaction::TYPE_NAME)
+ ->setValue($object->getName()),
+ id(new PhabricatorTextEditField())
+ ->setKey('flavor')
+ ->setLabel(pht('Flavor'))
+ ->setDescription(pht('Token flavor text.'))
+ ->setConduitDescription(pht('Change the token flavor.'))
+ ->setConduitTypeDescription(pht('New token flavor.'))
+ ->setTransactionType(PhabricatorTokensTransaction::TYPE_FLAVOR)
+ ->setValue($object->getFlavor()),
+ );
+ }
+
+}
diff --git a/src/applications/tokens/editor/PhabricatorTokenEditor.php b/src/applications/tokens/editor/PhabricatorTokenEditor.php
new file mode 100644
--- /dev/null
+++ b/src/applications/tokens/editor/PhabricatorTokenEditor.php
@@ -0,0 +1,188 @@
+<?php
+
+final class PhabricatorTokenEditor
+ extends PhabricatorApplicationTransactionEditor {
+
+ public function getEditorApplicationClass() {
+ return 'PhabricatorTokensApplication';
+ }
+
+ public function getEditorObjectsDescription() {
+ return pht('Phabricator Tokens');
+ }
+
+ public function getTransactionTypes() {
+ $types = parent::getTransactionTypes();
+
+ $types[] = PhabricatorTokensTransaction::TYPE_NAME;
+ $types[] = PhabricatorTokensTransaction::TYPE_FLAVOR;
+ $types[] = PhabricatorTokensTransaction::TYPE_STATUS;
+ $types[] = PhabricatorTokensTransaction::TYPE_IMAGE;
+ $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
+
+ return $types;
+ }
+
+ protected function getCustomTransactionOldValue(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ switch ($xaction->getTransactionType()) {
+ case PhabricatorTokensTransaction::TYPE_NAME:
+ return $object->getName();
+ case PhabricatorTokensTransaction::TYPE_FLAVOR:
+ return $object->getFlavor();
+ case PhabricatorTokensTransaction::TYPE_STATUS:
+ return $object->getStatus();
+ case PhabricatorTokensTransaction::TYPE_IMAGE:
+ return $object->getImage();
+ }
+ }
+
+ protected function getCustomTransactionNewValue(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ switch ($xaction->getTransactionType()) {
+ case PhabricatorTokensTransaction::TYPE_NAME:
+ case PhabricatorTokensTransaction::TYPE_FLAVOR:
+ case PhabricatorTokensTransaction::TYPE_STATUS:
+ case PhabricatorTokensTransaction::TYPE_IMAGE:
+ return $xaction->getNewValue();
+ }
+ }
+
+ protected function applyCustomInternalTransaction(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ switch ($xaction->getTransactionType()) {
+ case PhabricatorTokensTransaction::TYPE_NAME:
+ return $object->setName($xaction->getNewValue());
+ case PhabricatorTokensTransaction::TYPE_FLAVOR:
+ return $object->setFlavor($xaction->getNewValue());
+ case PhabricatorTokensTransaction::TYPE_STATUS:
+ return $object->setStatus($xaction->getNewValue());
+ case PhabricatorTokensTransaction::TYPE_IMAGE:
+ return $object->setImage($xaction->getNewValue());
+ }
+
+ return parent::applyCustomInternalTransaction($object, $xaction);
+ }
+
+ protected function applyCustomExternalTransaction(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ switch ($xaction->getTransactionType()) {
+ case PhabricatorTokensTransaction::TYPE_NAME:
+ case PhabricatorTokensTransaction::TYPE_FLAVOR:
+ case PhabricatorTokensTransaction::TYPE_STATUS:
+ case PhabricatorTokensTransaction::TYPE_IMAGE:
+ return;
+ }
+
+ return parent::applyCustomExternalTransaction($object, $xaction);
+ }
+
+ protected function validateTransaction(
+ PhabricatorLiskDAO $object,
+ $type,
+ array $xactions) {
+
+ $errors = parent::validateTransaction($object, $type, $xactions);
+
+ switch ($type) {
+ case PhabricatorTokensTransaction::TYPE_NAME:
+ $missing = $this->validateIsEmptyTextField(
+ $object->getName(),
+ $xactions);
+
+ if ($missing) {
+ $error = new PhabricatorApplicationTransactionValidationError(
+ $type,
+ pht('Required'),
+ pht('Name is required.'),
+ nonempty(last($xactions), null));
+
+ $error->setIsMissingFieldError(true);
+ $errors[] = $error;
+ }
+ break;
+ }
+ return $errors;
+ }
+
+ protected function shouldSendMail(
+ PhabricatorLiskDAO $object,
+ array $xactions) {
+ return true;
+ }
+
+ protected function shouldPublishFeedStory(
+ PhabricatorLiskDAO $object,
+ array $xactions) {
+ return true;
+ }
+
+ protected function getMailTo(PhabricatorLiskDAO $object) {
+ $phids = array();
+ $phids[] = $this->requireActor()->getPHID();
+ $phids[] = $object->getCreatorPHID();
+
+ return $phids;
+ }
+
+ protected function buildMailTemplate(PhabricatorLiskDAO $object) {
+ $phid = $object->getPHID();
+ $name = $object->getName();
+
+ return id(new PhabricatorMetaMTAMail())
+ ->setSubject($name)
+ ->addHeader('Thread-Topic', $phid);
+ }
+
+ protected function buildReplyHandler(PhabricatorLiskDAO $object) {
+ return id(new PhabricatorTokensReplyHandler())
+ ->setMailReceiver($object);
+ }
+
+ protected function buildMailBody(
+ PhabricatorLiskDAO $object,
+ array $xactions) {
+
+ $body = parent::buildMailBody($object, $xactions);
+
+ $body->addLinkSection(
+ pht('TOKEN DETAIL'),
+ PhabricatorEnv::getProductionURI($object->getViewURI()));
+
+ return $body;
+ }
+
+ public function getMailTagsMap() {
+ return array(
+ PhabricatorTokensTransaction::MAILTAG_DETAILS =>
+ pht("A token's details change."),
+ PhabricatorTokensTransaction::MAILTAG_SUBSCRIBERS =>
+ pht("A token's subscribers change."),
+ PhabricatorTokensTransaction::MAILTAG_OTHER =>
+ pht('Other token activity not listed above occurs.'),
+ );
+ }
+
+ protected function getMailSubjectPrefix() {
+ return '[Tokens]';
+ }
+
+ protected function supportsSearch() {
+ return false;
+ }
+
+ protected function shouldApplyHeraldRules(
+ PhabricatorLiskDAO $object,
+ array $xactions) {
+ return false;
+ }
+
+}
diff --git a/src/applications/tokens/mail/PhabricatorTokensMailReceiver.php b/src/applications/tokens/mail/PhabricatorTokensMailReceiver.php
new file mode 100644
--- /dev/null
+++ b/src/applications/tokens/mail/PhabricatorTokensMailReceiver.php
@@ -0,0 +1,28 @@
+<?php
+
+final class PhabricatorTokensMailReceiver
+ extends PhabricatorObjectMailReceiver {
+
+ public function isEnabled() {
+ return PhabricatorApplication::isClassInstalled(
+ 'PhabricatorTokensApplication');
+ }
+
+ protected function getObjectPattern() {
+ return 'TOKN[1-9]\d*';
+ }
+
+ protected function loadObject($pattern, PhabricatorUser $viewer) {
+ $id = (int)substr($pattern, 4);
+
+ return id(new PhabricatorTokenQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($id))
+ ->executeOne();
+ }
+
+ protected function getTransactionReplyHandler() {
+ return new PhabricatorTokensReplyHandler();
+ }
+
+}
diff --git a/src/applications/tokens/mail/PhabricatorTokensReplyHandler.php b/src/applications/tokens/mail/PhabricatorTokensReplyHandler.php
new file mode 100644
--- /dev/null
+++ b/src/applications/tokens/mail/PhabricatorTokensReplyHandler.php
@@ -0,0 +1,16 @@
+<?php
+
+final class PhabricatorTokensReplyHandler
+ extends PhabricatorApplicationTransactionReplyHandler {
+
+ public function validateMailReceiver($mail_receiver) {
+ if (!($mail_receiver instanceof PhabricatorTokensToken)) {
+ throw new Exception(pht('Mail receiver is not a %s!', 'Tokens'));
+ }
+ }
+
+ public function getObjectPrefix() {
+ return 'TOKN';
+ }
+
+}
diff --git a/src/applications/tokens/phid/PhabricatorTokenTokenPHIDType.php b/src/applications/tokens/phid/PhabricatorTokensTokenPHIDType.php
rename from src/applications/tokens/phid/PhabricatorTokenTokenPHIDType.php
rename to src/applications/tokens/phid/PhabricatorTokensTokenPHIDType.php
--- a/src/applications/tokens/phid/PhabricatorTokenTokenPHIDType.php
+++ b/src/applications/tokens/phid/PhabricatorTokensTokenPHIDType.php
@@ -1,6 +1,6 @@
<?php
-final class PhabricatorTokenTokenPHIDType extends PhabricatorPHIDType {
+final class PhabricatorTokensTokenPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'TOKN';
@@ -9,7 +9,7 @@
}
public function newObject() {
- return new PhabricatorToken();
+ return new PhabricatorTokensToken();
}
public function getPHIDTypeApplicationClass() {
diff --git a/src/applications/tokens/query/PhabricatorTokenQuery.php b/src/applications/tokens/query/PhabricatorTokenQuery.php
--- a/src/applications/tokens/query/PhabricatorTokenQuery.php
+++ b/src/applications/tokens/query/PhabricatorTokenQuery.php
@@ -3,13 +3,27 @@
final class PhabricatorTokenQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
+ private $ids;
private $phids;
+ private $statuses;
+
+ private $needImages;
+
+ public function withIDs(array $ids) {
+ $this->ids = $ids;
+ return $this;
+ }
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
+ public function withStatuses(array $statuses) {
+ $this->statuses = $statuses;
+ return $this;
+ }
+
protected function loadPage() {
$tokens = $this->getBuiltinTokens();
@@ -45,7 +59,7 @@
array('misc-4', pht('The World Burns')),
);
- $type = PhabricatorTokenTokenPHIDType::TYPECONST;
+ $type = PhabricatorTokensTokenPHIDType::TYPECONST;
$tokens = array();
foreach ($specs as $id => $spec) {
diff --git a/src/applications/tokens/query/PhabricatorTokenSearchEngine.php b/src/applications/tokens/query/PhabricatorTokenSearchEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/tokens/query/PhabricatorTokenSearchEngine.php
@@ -0,0 +1,131 @@
+<?php
+
+final class PhabricatorTokenSearchEngine
+ extends PhabricatorApplicationSearchEngine {
+
+ public function getResultTypeDescription() {
+ return pht('Token');
+ }
+
+ public function getApplicationClassName() {
+ return 'PhabricatorTokensApplication';
+ }
+
+ public function newQuery() {
+ return new PhabricatorTokenQuery();
+ }
+
+ protected function buildCustomSearchFields() {
+ return array(
+ id(new PhabricatorSearchCheckboxesField())
+ ->setKey('statuses')
+ ->setLabel(pht('Status'))
+ ->setOptions(
+ id(new PhabricatorTokensToken())
+ ->getStatusNameMap()),
+ );
+ }
+
+ protected function buildQueryFromParameters(array $map) {
+ $query = $this->newQuery();
+
+ if ($map['statuses']) {
+ $query->withStatuses($map['statuses']);
+ }
+
+ return $query;
+ }
+
+ protected function getURI($path) {
+ return '/tokens/'.$path;
+ }
+
+ protected function getBuiltinQueryNames() {
+ $names = array();
+
+ $names['open'] = pht('Active Tokens');
+ $names['all'] = pht('All Tokens');
+
+ return $names;
+ }
+
+ public function buildSavedQueryFromBuiltin($query_key) {
+ $query = $this->newSavedQuery();
+ $query->setQueryKey($query_key);
+
+ switch ($query_key) {
+ case 'all':
+ return $query;
+ case 'open':
+ return $query->setParameter(
+ 'statuses',
+ array(
+ PhabricatorBadgesBadge::STATUS_ACTIVE,
+ ));
+ }
+
+ return parent::buildSavedQueryFromBuiltin($query_key);
+ }
+
+ protected function getRequiredHandlePHIDsForResultList(
+ array $tokens,
+ PhabricatorSavedQuery $query) {
+
+ $phids = array();
+
+ return $phids;
+ }
+
+ protected function renderResultList(
+ array $tokens,
+ PhabricatorSavedQuery $query,
+ array $handles) {
+ assert_instances_of($tokens, 'PhabricatorTokensToken');
+
+ $viewer = $this->requireViewer();
+
+ $list = id(new PHUIObjectItemListView());
+ foreach ($tokens as $token) {
+
+ $item = id(new PHUIObjectItemView())
+ ->setHeader($token->getName())
+ ->setHref('/tokens/view/'.$token->getID().'/')
+ ->addAttribute($token->getFlavor());
+
+ if ($token->isArchived()) {
+ $item->setDisabled(true);
+ $item->addIcon('fa-ban', pht('Archived'));
+ }
+
+ $list->addItem($item);
+ }
+
+ $result = new PhabricatorApplicationSearchResultView();
+ $result->setObjectList($list);
+ $result->setNoDataString(pht('No tokens found.'));
+
+ return $result;
+
+ }
+
+ protected function getNewUserBody() {
+ $create_button = id(new PHUIButtonView())
+ ->setTag('a')
+ ->setText(pht('Create a Token'))
+ ->setHref('/tokens/edit/')
+ ->setColor(PHUIButtonView::GREEN);
+
+ $icon = $this->getApplication()->getIcon();
+ $app_name = $this->getApplication()->getName();
+ $view = id(new PHUIBigInfoView())
+ ->setIcon($icon)
+ ->setTitle(pht('Welcome to %s', $app_name))
+ ->setDescription(
+ pht('Tokens let you award and distinguish objects and comments '.
+ 'throughout your instance.'))
+ ->addAction($create_button);
+
+ return $view;
+ }
+
+}
diff --git a/src/applications/tokens/query/PhabricatorTokensTransactionQuery.php b/src/applications/tokens/query/PhabricatorTokensTransactionQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/tokens/query/PhabricatorTokensTransactionQuery.php
@@ -0,0 +1,10 @@
+<?php
+
+final class PhabricatorTokensTransactionQuery
+ extends PhabricatorApplicationTransactionQuery {
+
+ public function getTemplateApplicationTransaction() {
+ return new PhabricatorTokensTransaction();
+ }
+
+}
diff --git a/src/applications/tokens/storage/PhabricatorTokensToken.php b/src/applications/tokens/storage/PhabricatorTokensToken.php
new file mode 100644
--- /dev/null
+++ b/src/applications/tokens/storage/PhabricatorTokensToken.php
@@ -0,0 +1,216 @@
+<?php
+
+final class PhabricatorTokensToken extends PhameDAO
+ implements
+ PhabricatorPolicyInterface,
+ PhabricatorDestructibleInterface,
+ PhabricatorApplicationTransactionInterface,
+ PhabricatorConduitResultInterface {
+
+ protected $name;
+ protected $flavor;
+ protected $status;
+ protected $creatorPHID;
+ protected $mailKey;
+
+ private $tokenImagePHID = self::ATTACHABLE;
+
+ const STATUS_ACTIVE = 'active';
+ const STATUS_ARCHIVED = 'archived';
+
+ protected function getConfiguration() {
+ return array(
+ self::CONFIG_AUX_PHID => true,
+ self::CONFIG_SERIALIZATION => array(
+ 'configData' => self::SERIALIZATION_JSON,
+ ),
+ self::CONFIG_COLUMN_SCHEMA => array(
+ 'name' => 'text64',
+ 'flavor' => 'text128',
+ 'status' => 'text32',
+ 'tokenImagePHID' => 'phid?',
+ 'viewPolicy' => 'policy?',
+ 'editPolicy' => 'policy?',
+ 'mailKey' => 'bytes20',
+ ),
+ ) + parent::getConfiguration();
+ }
+
+ public function generatePHID() {
+ return PhabricatorPHID::generateNewPHID(
+ PhabricatorTokensTokenPHIDType::TYPECONST);
+ }
+
+ public static function initializeNewToken(PhabricatorUser $actor) {
+ $app = id(new PhabricatorApplicationQuery())
+ ->setViewer($actor)
+ ->withClasses(array('PhabricatorTokensApplication'))
+ ->executeOne();
+
+ $view_policy = PhabricatorPolicies::getMostOpenPolicy();
+
+ $edit_policy =
+ $app->getPolicy(PhabricatorBadgesDefaultEditCapability::CAPABILITY);
+
+ $token = id(new self())
+ ->setCreatorPHID($actor->getPHID())
+ ->setStatus(self::STATUS_ACTIVE)
+ ->setViewPolicy($view_policy)
+ ->setEditPolicy($edit_policy);
+ return $token;
+ }
+
+ public function isArchived() {
+ return ($this->getStatus() == self::STATUS_ARCHIVED);
+ }
+
+ public static function getStatusNameMap() {
+ return array(
+ self::STATUS_ACTIVE => pht('Active'),
+ self::STATUS_ARCHIVED => pht('Archived'),
+ );
+ }
+
+ public function getTokenImageURI() {
+ return $this->getTokenImageFile()->getBestURI();
+ }
+
+ public function attachTokenImageFile(PhabricatorFile $file) {
+ $this->tokenImageFile = $file;
+ return $this;
+ }
+
+ public function getTokenImageFile() {
+ return $this->assertAttached($this->tokenImageFile);
+ }
+
+ public function save() {
+ if (!$this->getMailKey()) {
+ $this->setMailKey(Filesystem::readRandomCharacters(20));
+ }
+ return parent::save();
+ }
+
+
+/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
+
+
+ public function getCapabilities() {
+ return array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ );
+ }
+
+
+ public function getPolicy($capability) {
+ switch ($capability) {
+ case PhabricatorPolicyCapability::CAN_VIEW:
+ return $this->getViewPolicy();
+ case PhabricatorPolicyCapability::CAN_EDIT:
+ return $this->getEditPolicy();
+ }
+ }
+
+ public function hasAutomaticCapability($capability, PhabricatorUser $user) {
+ switch ($capability) {
+ case PhabricatorPolicyCapability::CAN_VIEW:
+ return true;
+ break;
+ }
+ return false;
+ }
+
+
+ public function describeAutomaticCapability($capability) {
+ switch ($capability) {
+ case PhabricatorPolicyCapability::CAN_VIEW:
+ return pht(
+ 'Users can always see Tokens.');
+ }
+
+ return null;
+ }
+
+/* -( PhabricatorDestructibleInterface )----------------------------------- */
+
+ public function destroyObjectPermanently(
+ PhabricatorDestructionEngine $engine) {
+
+ $this->openTransaction();
+
+ $tokens = id(new self())
+ ->loadAllWhere('tokenPHID = %s', $this->getPHID());
+ foreach ($tokens as $token) {
+ $token->delete();
+ }
+ $this->delete();
+
+ $this->saveTransaction();
+ }
+
+
+/* -( PhabricatorApplicationTransactionInterface )------------------------- */
+
+
+ public function getApplicationTransactionEditor() {
+ return new PhabricatorTokenEditor();
+ }
+
+ public function getApplicationTransactionObject() {
+ return $this;
+ }
+
+ public function getApplicationTransactionTemplate() {
+ return new PhabricatorTokensTransaction();
+ }
+
+ public function willRenderTimeline(
+ PhabricatorApplicationTransactionView $timeline,
+ AphrontRequest $request) {
+ return $timeline;
+ }
+
+
+/* -( PhabricatorSubscribableInterface Implementation )-------------------- */
+
+
+ public function isAutomaticallySubscribed($phid) {
+ return ($this->creatorPHID == $phid);
+ }
+
+
+/* -( PhabricatorConduitResultInterface )---------------------------------- */
+
+
+ public function getFieldSpecificationsForConduit() {
+ return array(
+ id(new PhabricatorConduitSearchFieldSpecification())
+ ->setKey('name')
+ ->setType('string')
+ ->setDescription(pht('The name of the token.')),
+ id(new PhabricatorConduitSearchFieldSpecification())
+ ->setKey('flavor')
+ ->setType('string')
+ ->setDescription(pht('Token flavor.')),
+ id(new PhabricatorConduitSearchFieldSpecification())
+ ->setKey('status')
+ ->setType('string')
+ ->setDescription(pht('Archived or active status.')),
+ );
+ }
+
+ public function getFieldValuesForConduit() {
+ return array(
+ 'name' => $this->getName(),
+ 'flavor' => $this->getFlavor(),
+ 'status' => $this->getStatus(),
+ );
+ }
+
+ public function getConduitSearchAttachments() {
+ return array();
+ }
+
+
+}
diff --git a/src/applications/tokens/storage/PhabricatorTokensTransaction.php b/src/applications/tokens/storage/PhabricatorTokensTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/tokens/storage/PhabricatorTokensTransaction.php
@@ -0,0 +1,154 @@
+<?php
+
+final class PhabricatorTokensTransaction
+ extends PhabricatorApplicationTransaction {
+
+ const TYPE_NAME = 'tokens.token.name';
+ const TYPE_QUALITY = 'tokens.token.flavor';
+ const TYPE_ICON = 'tokens.token.image';
+ const TYPE_STATUS = 'tokens.token.status';
+
+ const MAILTAG_DETAILS = 'tokens.token.details';
+ const MAILTAG_COMMENT = 'tokens.token.comment';
+ const MAILTAG_OTHER = 'tokens.token.other';
+
+ public function getApplicationName() {
+ return 'tokens';
+ }
+
+ public function getApplicationTransactionType() {
+ return PhabricatorTokensTokenPHIDType::TYPECONST;
+ }
+
+ public function getApplicationTransactionCommentObject() {
+ return new PhabricatorTokensTransactionComment();
+ }
+
+
+ public function getTitle() {
+ $author_phid = $this->getAuthorPHID();
+ $object_phid = $this->getObjectPHID();
+
+ $old = $this->getOldValue();
+ $new = $this->getNewValue();
+
+ $type = $this->getTransactionType();
+ switch ($type) {
+ case self::TYPE_NAME:
+ if ($old === null) {
+ return pht(
+ '%s created this token.',
+ $this->renderHandleLink($author_phid));
+ } else {
+ return pht(
+ '%s renamed this token from "%s" to "%s".',
+ $this->renderHandleLink($author_phid),
+ $old,
+ $new);
+ }
+ break;
+ case self::TYPE_FLAVOR:
+ if ($old === null) {
+ return pht(
+ '%s set the flavor text for this token.',
+ $this->renderHandleLink($author_phid));
+ } else {
+ return pht(
+ '%s updated the flavor text for this token.',
+ $this->renderHandleLink($author_phid));
+ }
+ break;
+ case self::TYPE_STATUS:
+ switch ($new) {
+ case PhabricatorTokensToken::STATUS_ACTIVE:
+ return pht(
+ '%s activated this token.',
+ $this->renderHandleLink($author_phid));
+ case PhabricatorTokensToken::STATUS_ARCHIVED:
+ return pht(
+ '%s archived this token.',
+ $this->renderHandleLink($author_phid));
+ }
+ break;
+ case self::TYPE_IMAGE:
+ return pht(
+ '%s updated the image for this token.',
+ $this->renderHandleLink($author_phid));
+ break;
+ }
+
+ return parent::getTitle();
+ }
+
+ public function getTitleForFeed() {
+ $author_phid = $this->getAuthorPHID();
+ $object_phid = $this->getObjectPHID();
+
+ $old = $this->getOldValue();
+ $new = $this->getNewValue();
+
+ $type = $this->getTransactionType();
+ switch ($type) {
+ case self::TYPE_NAME:
+ if ($old === null) {
+ return pht(
+ '%s created %s.',
+ $this->renderHandleLink($author_phid),
+ $this->renderHandleLink($object_phid));
+
+ } else {
+ return pht(
+ '%s renamed %s.',
+ $this->renderHandleLink($author_phid),
+ $this->renderHandleLink($object_phid));
+ }
+ break;
+ case self::TYPE_FLAVOR:
+ return pht(
+ '%s updated the flavor text for %s.',
+ $this->renderHandleLink($author_phid),
+ $this->renderHandleLink($object_phid));
+ case self::TYPE_IMAGE:
+ return pht(
+ '%s updated the image for %s.',
+ $this->renderHandleLink($author_phid),
+ $this->renderHandleLink($object_phid));
+ case self::TYPE_STATUS:
+ switch ($new) {
+ case PhabricatorTokensToken::STATUS_ACTIVE:
+ return pht(
+ '%s activated %s.',
+ $this->renderHandleLink($author_phid),
+ $this->renderHandleLink($object_phid));
+ case PhabricatorTokensToken::STATUS_ARCHIVED:
+ return pht(
+ '%s archived %s.',
+ $this->renderHandleLink($author_phid),
+ $this->renderHandleLink($object_phid));
+ }
+ break;
+ }
+
+ return parent::getTitleForFeed();
+ }
+
+ public function getMailTags() {
+ $tags = parent::getMailTags();
+
+ switch ($this->getTransactionType()) {
+ case PhabricatorTransactions::TYPE_COMMENT:
+ $tags[] = self::MAILTAG_COMMENT;
+ break;
+ case self::TYPE_NAME:
+ case self::TYPE_FLAVOR:
+ case self::TYPE_IMAGE:
+ $tags[] = self::MAILTAG_DETAILS;
+ break;
+ default:
+ $tags[] = self::MAILTAG_OTHER;
+ break;
+ }
+ return $tags;
+ }
+
+}
diff --git a/src/applications/tokens/storage/PhabricatorTokensTransactionComment.php b/src/applications/tokens/storage/PhabricatorTokensTransactionComment.php
new file mode 100644
--- /dev/null
+++ b/src/applications/tokens/storage/PhabricatorTokensTransactionComment.php
@@ -0,0 +1,10 @@
+<?php
+
+final class PhabricatorTokensTransactionComment
+ extends PhabricatorApplicationTransactionComment {
+
+ public function getApplicationTransactionObject() {
+ return new PhabricatorTokensTransaction();
+ }
+
+}

File Metadata

Mime Type
text/plain
Expires
Sun, Mar 16, 3:45 PM (2 w, 7 h ago)
Storage Engine
amazon-s3
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
phabricator/secure/jh/t7/644god5awfhs5h4o
Default Alt Text
D16178.id38919.diff (45 KB)

Event Timeline