Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14087953
D13626.id32919.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
48 KB
Referenced Files
None
Subscribers
None
D13626.id32919.diff
View Options
diff --git a/resources/sql/autopatches/20150712.badges.1.sql b/resources/sql/autopatches/20150712.badges.1.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20150712.badges.1.sql
@@ -0,0 +1,52 @@
+CREATE TABLE {$NAMESPACE}_badges.badges_badge (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ phid VARBINARY(64) NOT NULL,
+ name VARCHAR(255) NOT NULL COLLATE {$COLLATE_TEXT},
+ flavor VARCHAR(255) NOT NULL COLLATE {$COLLATE_TEXT},
+ description LONGTEXT NOT NULL,
+ icon VARCHAR(255) NOT NULL,
+ quality VARCHAR(255) NOT NULL,
+ status VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT},
+ dateCreated INT UNSIGNED NOT NULL,
+ dateModified INT UNSIGNED NOT NULL,
+ viewPolicy VARBINARY(64) NOT NULL,
+ editPolicy VARBINARY(64) NOT NULL,
+ UNIQUE KEY `key_phid` (phid)
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
+
+CREATE TABLE {$NAMESPACE}_badges.badges_transaction (
+ id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ phid VARBINARY(64) NOT NULL,
+ authorPHID VARBINARY(64) NOT NULL,
+ objectPHID VARBINARY(64) NOT NULL,
+ viewPolicy VARBINARY(64) NOT NULL,
+ editPolicy VARBINARY(64) NOT NULL,
+ commentPHID VARBINARY(64),
+ commentVersion INT UNSIGNED NOT NULL,
+ transactionType VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT},
+ oldValue LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
+ newValue LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
+ contentSource LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
+ metadata LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
+ dateCreated INT UNSIGNED NOT NULL,
+ dateModified INT UNSIGNED NOT NULL,
+ UNIQUE KEY `key_phid` (phid),
+ KEY `key_object` (objectPHID)
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
+
+CREATE TABLE {$NAMESPACE}_badges.edge (
+ src VARBINARY(64) NOT NULL,
+ type INT UNSIGNED NOT NULL,
+ dst VARBINARY(64) NOT NULL,
+ dateCreated INT UNSIGNED NOT NULL,
+ seq INT UNSIGNED NOT NULL,
+ dataID INT UNSIGNED,
+ PRIMARY KEY (src, type, dst),
+ KEY `src` (src, type, dateCreated, seq),
+ UNIQUE KEY `key_dst` (dst, type, src)
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
+
+CREATE TABLE {$NAMESPACE}_badges.edgedata (
+ id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ data LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT}
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
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
@@ -176,6 +176,10 @@
'AuditConduitAPIMethod' => 'applications/audit/conduit/AuditConduitAPIMethod.php',
'AuditQueryConduitAPIMethod' => 'applications/audit/conduit/AuditQueryConduitAPIMethod.php',
'AuthManageProvidersCapability' => 'applications/auth/capability/AuthManageProvidersCapability.php',
+ 'BadgesController' => 'applications/badges/controller/BadgesController.php',
+ 'BadgesEditController' => 'applications/badges/controller/BadgesEditController.php',
+ 'BadgesListController' => 'applications/badges/controller/BadgesListController.php',
+ 'BadgesViewController' => 'applications/badges/controller/BadgesViewController.php',
'CalendarTimeUtil' => 'applications/calendar/util/CalendarTimeUtil.php',
'CalendarTimeUtilTestCase' => 'applications/calendar/__tests__/CalendarTimeUtilTestCase.php',
'CelerityAPI' => 'applications/celerity/CelerityAPI.php',
@@ -1600,6 +1604,20 @@
'PhabricatorAuthValidateController' => 'applications/auth/controller/PhabricatorAuthValidateController.php',
'PhabricatorAuthenticationConfigOptions' => 'applications/config/option/PhabricatorAuthenticationConfigOptions.php',
'PhabricatorAutoEventListener' => 'infrastructure/events/PhabricatorAutoEventListener.php',
+ 'PhabricatorBadge' => 'applications/badges/storage/PhabricatorBadge.php',
+ 'PhabricatorBadgesApplication' => 'applications/badges/application/PhabricatorBadgesApplication.php',
+ 'PhabricatorBadgesCreateCapability' => 'applications/badges/capability/PhabricatorBadgesCreateCapability.php',
+ 'PhabricatorBadgesDAO' => 'applications/badges/storage/PhabricatorBadgesDAO.php',
+ 'PhabricatorBadgesDefaultEditCapability' => 'applications/badges/capability/PhabricatorBadgesDefaultEditCapability.php',
+ 'PhabricatorBadgesDefaultViewCapability' => 'applications/badges/capability/PhabricatorBadgesDefaultViewCapability.php',
+ 'PhabricatorBadgesEditor' => 'applications/badges/editor/PhabricatorBadgesEditor.php',
+ 'PhabricatorBadgesInterface' => 'applications/badges/interface/PhabricatorBadgesInterface.php',
+ 'PhabricatorBadgesPHIDType' => 'applications/badges/phid/PhabricatorBadgesPHIDType.php',
+ 'PhabricatorBadgesQuery' => 'applications/badges/query/PhabricatorBadgesQuery.php',
+ 'PhabricatorBadgesSchemaSpec' => 'applications/badges/storage/PhabricatorBadgesSchemaSpec.php',
+ 'PhabricatorBadgesSearchEngine' => 'applications/badges/query/PhabricatorBadgesSearchEngine.php',
+ 'PhabricatorBadgesTransaction' => 'applications/badges/storage/PhabricatorBadgesTransaction.php',
+ 'PhabricatorBadgesTransactionQuery' => 'applications/badges/query/PhabricatorBadgesTransactionQuery.php',
'PhabricatorBarePageUIExample' => 'applications/uiexample/examples/PhabricatorBarePageUIExample.php',
'PhabricatorBarePageView' => 'view/page/PhabricatorBarePageView.php',
'PhabricatorBaseURISetupCheck' => 'applications/config/check/PhabricatorBaseURISetupCheck.php',
@@ -3653,6 +3671,10 @@
'AuditConduitAPIMethod' => 'ConduitAPIMethod',
'AuditQueryConduitAPIMethod' => 'AuditConduitAPIMethod',
'AuthManageProvidersCapability' => 'PhabricatorPolicyCapability',
+ 'BadgesController' => 'PhabricatorController',
+ 'BadgesEditController' => 'BadgesController',
+ 'BadgesListController' => 'BadgesController',
+ 'BadgesViewController' => 'BadgesController',
'CalendarTimeUtil' => 'Phobject',
'CalendarTimeUtilTestCase' => 'PhabricatorTestCase',
'CelerityAPI' => 'Phobject',
@@ -5286,6 +5308,25 @@
'PhabricatorAuthValidateController' => 'PhabricatorAuthController',
'PhabricatorAuthenticationConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorAutoEventListener' => 'PhabricatorEventListener',
+ 'PhabricatorBadge' => array(
+ 'PhabricatorBadgesDAO',
+ 'PhabricatorPolicyInterface',
+ 'PhabricatorApplicationTransactionInterface',
+ 'PhabricatorDestructibleInterface',
+ ),
+ 'PhabricatorBadgesApplication' => 'PhabricatorApplication',
+ 'PhabricatorBadgesCreateCapability' => 'PhabricatorPolicyCapability',
+ 'PhabricatorBadgesDAO' => 'PhabricatorLiskDAO',
+ 'PhabricatorBadgesDefaultEditCapability' => 'PhabricatorPolicyCapability',
+ 'PhabricatorBadgesDefaultViewCapability' => 'PhabricatorPolicyCapability',
+ 'PhabricatorBadgesEditor' => 'PhabricatorApplicationTransactionEditor',
+ 'PhabricatorBadgesInterface' => 'PhabricatorPHIDInterface',
+ 'PhabricatorBadgesPHIDType' => 'PhabricatorPHIDType',
+ 'PhabricatorBadgesQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+ 'PhabricatorBadgesSchemaSpec' => 'PhabricatorConfigSchemaSpec',
+ 'PhabricatorBadgesSearchEngine' => 'PhabricatorApplicationSearchEngine',
+ 'PhabricatorBadgesTransaction' => 'PhabricatorApplicationTransaction',
+ 'PhabricatorBadgesTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorBarePageUIExample' => 'PhabricatorUIExample',
'PhabricatorBarePageView' => 'AphrontPageView',
'PhabricatorBaseURISetupCheck' => 'PhabricatorSetupCheck',
diff --git a/src/applications/badges/application/PhabricatorBadgesApplication.php b/src/applications/badges/application/PhabricatorBadgesApplication.php
new file mode 100644
--- /dev/null
+++ b/src/applications/badges/application/PhabricatorBadgesApplication.php
@@ -0,0 +1,66 @@
+<?php
+
+final class PhabricatorBadgesApplication extends PhabricatorApplication {
+
+ public function getName() {
+ return pht('Badges');
+ }
+
+ public function getBaseURI() {
+ return '/badges/';
+ }
+
+ public function getShortDescription() {
+ return pht('Achievements and Notority');
+ }
+
+ public function getFontIcon() {
+ return 'fa-trophy';
+ }
+
+ public function getFlavorText() {
+ return pht('Build developer self esteem through gamification.');
+ }
+
+ public function getApplicationGroup() {
+ return self::GROUP_UTILITIES;
+ }
+
+ public function canUninstall() {
+ return true;
+ }
+
+ public function isPrototype() {
+ return true;
+ }
+
+ public function getRoutes() {
+ return array(
+ '/badges/' => array(
+ '(?:query/(?P<queryKey>[^/]+)/)?' => 'BadgesListController',
+ 'create/' => 'BadgesEditController',
+ 'edit/(?:(?P<id>\d+)/)?' => 'BadgesEditController',
+ 'view/(?:(?P<id>\d+)/)?' => 'BadgesViewController',
+ 'members/(?:(?P<id>\d+)/)?(?:query/(?P<queryKey>[^/]+)/)?'
+ => 'BadgesMemberListController',
+ ),
+ );
+ }
+
+ protected function getCustomCapabilities() {
+ return array(
+ PhabricatorBadgesCreateCapability::CAPABILITY => array(
+ 'default' => PhabricatorPolicies::POLICY_ADMIN,
+ 'caption' => pht('Default create policy for badges.'),
+ ),
+ PhabricatorBadgesDefaultEditCapability::CAPABILITY => array(
+ 'default' => PhabricatorPolicies::POLICY_ADMIN,
+ 'caption' => pht('Default edit policy for badges.'),
+ ),
+ PhabricatorBadgesDefaultViewCapability::CAPABILITY => array(
+ 'caption' => pht('Default view policy for badges.'),
+ ),
+ );
+ }
+
+}
diff --git a/src/applications/badges/capability/PhabricatorBadgesCreateCapability.php b/src/applications/badges/capability/PhabricatorBadgesCreateCapability.php
new file mode 100644
--- /dev/null
+++ b/src/applications/badges/capability/PhabricatorBadgesCreateCapability.php
@@ -0,0 +1,16 @@
+<?php
+
+final class PhabricatorBadgesCreateCapability
+ extends PhabricatorPolicyCapability {
+
+ const CAPABILITY = 'badges.default.create';
+
+ public function getCapabilityName() {
+ return pht('Can Create Badges');
+ }
+
+ public function describeCapabilityRejection() {
+ return pht('You do not have permission to create badges.');
+ }
+
+}
diff --git a/src/applications/badges/capability/PhabricatorBadgesDefaultEditCapability.php b/src/applications/badges/capability/PhabricatorBadgesDefaultEditCapability.php
new file mode 100644
--- /dev/null
+++ b/src/applications/badges/capability/PhabricatorBadgesDefaultEditCapability.php
@@ -0,0 +1,16 @@
+<?php
+
+final class PhabricatorBadgesDefaultEditCapability
+ extends PhabricatorPolicyCapability {
+
+ const CAPABILITY = 'badges.default.edit';
+
+ public function getCapabilityName() {
+ return pht('Can Edit Badges');
+ }
+
+ public function describeCapabilityRejection() {
+ return pht('You do not have permission to edit badges.');
+ }
+
+}
diff --git a/src/applications/badges/capability/PhabricatorBadgesDefaultViewCapability.php b/src/applications/badges/capability/PhabricatorBadgesDefaultViewCapability.php
new file mode 100644
--- /dev/null
+++ b/src/applications/badges/capability/PhabricatorBadgesDefaultViewCapability.php
@@ -0,0 +1,16 @@
+<?php
+
+final class PhabricatorBadgesDefaultViewCapability extends
+ PhabricatorPolicyCapability {
+
+ const CAPABILITY = 'badges.default.view';
+
+ public function getCapabilityName() {
+ return pht('Default View Policy');
+ }
+
+ public function shouldAllowPublicPolicySetting() {
+ return true;
+ }
+
+}
diff --git a/src/applications/badges/controller/BadgesController.php b/src/applications/badges/controller/BadgesController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/badges/controller/BadgesController.php
@@ -0,0 +1,3 @@
+<?php
+
+abstract class BadgesController extends PhabricatorController {}
diff --git a/src/applications/badges/controller/BadgesEditController.php b/src/applications/badges/controller/BadgesEditController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/badges/controller/BadgesEditController.php
@@ -0,0 +1,220 @@
+<?php
+
+final class BadgesEditController
+ extends BadgesController {
+
+ private $id;
+
+ public function willProcessRequest(array $data) {
+ $this->id = idx($data, 'id');
+ }
+
+ public function processRequest() {
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ if ($this->id) {
+ $badge = id(new PhabricatorBadgesQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($this->id))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->executeOne();
+ if (!$badge) {
+ return new Aphront404Response();
+ }
+ $is_new = false;
+ } else {
+ $badge = PhabricatorBadge::initializeNewBadge($viewer);
+ $is_new = true;
+ }
+
+ if ($is_new) {
+ $title = pht('Create Badge');
+ $button_text = pht('Create Badge');
+ $cancel_uri = $this->getApplicationURI();
+ } else {
+ $title = pht(
+ 'Edit %s',
+ $badge->getName());
+ $button_text = pht('Save Changes');
+ $cancel_uri = $this->getApplicationURI().'view/'.$this->id.'/';
+ }
+
+ $e_name = true;
+ $v_name = $badge->getName();
+
+ $e_icon = true;
+ $v_icon = $badge->getIcon();
+
+ $v_flav = $badge->getFlavor();
+ $v_desc = $badge->getDescription();
+ $v_qual = $badge->getQuality();
+ $v_stat = $badge->getStatus();
+
+ $validation_exception = null;
+ if ($request->isFormPost()) {
+ $v_name = $request->getStr('name');
+ $v_flav = $request->getStr('flavor');
+ $v_desc = $request->getStr('description');
+ $v_icon = $request->getStr('icon');
+ $v_stat = $request->getStr('status');
+ $v_qual = $request->getStr('quality');
+
+ $v_view = $request->getStr('viewPolicy');
+ $v_edit = $request->getStr('editPolicy');
+
+ $type_name = PhabricatorBadgesTransaction::TYPE_NAME;
+ $type_flav = PhabricatorBadgesTransaction::TYPE_FLAVOR;
+ $type_desc = PhabricatorBadgesTransaction::TYPE_DESCRIPTION;
+ $type_icon = PhabricatorBadgesTransaction::TYPE_ICON;
+ $type_qual = PhabricatorBadgesTransaction::TYPE_QUALITY;
+ $type_stat = PhabricatorBadgesTransaction::TYPE_STATUS;
+
+ $type_view = PhabricatorTransactions::TYPE_VIEW_POLICY;
+ $type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY;
+
+ $xactions = array();
+
+ $xactions[] = id(new PhabricatorBadgesTransaction())
+ ->setTransactionType($type_name)
+ ->setNewValue($v_name);
+
+ $xactions[] = id(new PhabricatorBadgesTransaction())
+ ->setTransactionType($type_flav)
+ ->setNewValue($v_flav);
+
+ $xactions[] = id(new PhabricatorBadgesTransaction())
+ ->setTransactionType($type_desc)
+ ->setNewValue($v_desc);
+
+ $xactions[] = id(new PhabricatorBadgesTransaction())
+ ->setTransactionType($type_icon)
+ ->setNewValue($v_icon);
+
+ $xactions[] = id(new PhabricatorBadgesTransaction())
+ ->setTransactionType($type_qual)
+ ->setNewValue($v_qual);
+
+ $xactions[] = id(new PhabricatorBadgesTransaction())
+ ->setTransactionType($type_stat)
+ ->setNewValue($v_stat);
+
+ $xactions[] = id(new PhabricatorBadgesTransaction())
+ ->setTransactionType($type_view)
+ ->setNewValue($v_view);
+
+ $xactions[] = id(new PhabricatorBadgesTransaction())
+ ->setTransactionType($type_edit)
+ ->setNewValue($v_edit);
+
+ $editor = id(new PhabricatorBadgesEditor())
+ ->setActor($viewer)
+ ->setContentSourceFromRequest($request)
+ ->setContinueOnNoEffect(true);
+
+ try {
+ $editor->applyTransactions($badge, $xactions);
+
+ return id(new AphrontRedirectResponse())
+ ->setURI('/badges/');
+ } catch (PhabricatorApplicationTransactionValidationException $ex) {
+ $validation_exception = $ex;
+
+ $e_name = $ex->getShortMessage($type_name);
+ $e_desc = $ex->getShortMessage($type_desc);
+
+ $badge->setViewPolicy($v_view);
+ $badge->setEditPolicy($v_edit);
+ }
+ }
+
+ $policies = id(new PhabricatorPolicyQuery())
+ ->setViewer($viewer)
+ ->setObject($badge)
+ ->execute();
+
+ $form = id(new AphrontFormView())
+ ->setUser($viewer)
+ ->appendChild(
+ id(new AphrontFormTextControl())
+ ->setName('name')
+ ->setLabel(pht('Name'))
+ ->setValue($v_name)
+ ->setError($e_name))
+ ->appendChild(
+ id(new AphrontFormTextControl())
+ ->setName('flavor')
+ ->setLabel(pht('Flavor Text'))
+ ->setValue($v_flav))
+ ->appendChild(
+ id(new AphrontFormSelectControl())
+ ->setUser($viewer)
+ ->setName('icon')
+ ->setLabel(pht('Icon'))
+ ->setValue($v_icon)
+ ->setOptions($badge->getIconNameMap()))
+ ->appendChild(
+ id(new AphrontFormSelectControl())
+ ->setName('quality')
+ ->setLabel(pht('Quality'))
+ ->setValue($v_qual)
+ ->setOptions($badge->getQualityNameMap()))
+ ->appendChild(
+ id(new AphrontFormSelectControl())
+ ->setLabel(pht('Status'))
+ ->setName('status')
+ ->setValue($v_stat)
+ ->setOptions($badge->getStatusNameMap()))
+ ->appendChild(
+ id(new PhabricatorRemarkupControl())
+ ->setUser($viewer)
+ ->setName('description')
+ ->setLabel(pht('Description'))
+ ->setValue($v_desc))
+ ->appendChild(
+ id(new AphrontFormPolicyControl())
+ ->setName('viewPolicy')
+ ->setPolicyObject($badge)
+ ->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
+ ->setPolicies($policies))
+ ->appendChild(
+ id(new AphrontFormPolicyControl())
+ ->setName('editPolicy')
+ ->setPolicyObject($badge)
+ ->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
+ ->setPolicies($policies))
+ ->appendChild(
+ id(new AphrontFormSubmitControl())
+ ->setValue($button_text)
+ ->addCancelButton($cancel_uri));
+
+ $crumbs = $this->buildApplicationCrumbs();
+ if ($is_new) {
+ $crumbs->addTextCrumb(pht('Create Badge'));
+ } else {
+ $crumbs->addTextCrumb(
+ $badge->getName(),
+ '/badges/view/'.$badge->getID().'/');
+ $crumbs->addTextCrumb(pht('Edit'));
+ }
+
+ $box = id(new PHUIObjectBoxView())
+ ->setValidationException($validation_exception)
+ ->setHeaderText($title)
+ ->appendChild($form);
+
+ return $this->buildApplicationPage(
+ array(
+ $crumbs,
+ $box,
+ ),
+ array(
+ 'title' => $title,
+ ));
+ }
+
+}
diff --git a/src/applications/badges/controller/BadgesListController.php b/src/applications/badges/controller/BadgesListController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/badges/controller/BadgesListController.php
@@ -0,0 +1,57 @@
+<?php
+
+final class BadgesListController
+ extends BadgesController {
+
+ private $queryKey;
+
+ public function shouldAllowPublic() {
+ return true;
+ }
+
+ public function willProcessRequest(array $data) {
+ $this->queryKey = idx($data, 'queryKey');
+ }
+
+ public function processRequest() {
+ $controller = id(new PhabricatorApplicationSearchController())
+ ->setQueryKey($this->queryKey)
+ ->setSearchEngine(new PhabricatorBadgesSearchEngine())
+ ->setNavigation($this->buildSideNavView());
+
+ return $this->delegateToController($controller);
+ }
+
+ public function buildSideNavView() {
+ $user = $this->getRequest()->getUser();
+
+ $nav = new AphrontSideNavFilterView();
+ $nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
+
+ id(new PhabricatorBadgesSearchEngine())
+ ->setViewer($user)
+ ->addNavigationItems($nav->getMenu());
+
+ $nav->selectFilter(null);
+
+ return $nav;
+ }
+
+ protected function buildApplicationCrumbs() {
+ $crumbs = parent::buildApplicationCrumbs();
+
+ $can_create = $this->hasApplicationCapability(
+ PhabricatorBadgesCreateCapability::CAPABILITY);
+
+ $crumbs->addAction(
+ id(new PHUIListItemView())
+ ->setName(pht('Create Badge'))
+ ->setHref($this->getApplicationURI('create/'))
+ ->setIcon('fa-plus-square')
+ ->setDisabled(!$can_create)
+ ->setWorkflow(!$can_create));
+
+ return $crumbs;
+ }
+
+}
diff --git a/src/applications/badges/controller/BadgesViewController.php b/src/applications/badges/controller/BadgesViewController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/badges/controller/BadgesViewController.php
@@ -0,0 +1,152 @@
+<?php
+
+final class BadgesViewController
+ extends BadgesController {
+
+ private $id;
+
+ public function shouldAllowPublic() {
+ return true;
+ }
+
+ public function willProcessRequest(array $data) {
+ $this->id = $data['id'];
+ }
+
+ public function processRequest() {
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ $badge = id(new PhabricatorBadgesQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($this->id))
+ ->executeOne();
+ if (!$badge) {
+ return new Aphront404Response();
+ }
+
+ $crumbs = $this->buildApplicationCrumbs();
+ $crumbs->addTextCrumb($badge->getName());
+ $title = $badge->getName();
+
+ if ($badge->isClosed()) {
+ $status_icon = 'fa-ban';
+ $status_color = 'dark';
+ } else {
+ $status_icon = 'fa-check';
+ $status_color = 'bluegrey';
+ }
+ $status_name = idx(
+ PhabricatorBadge::getStatusNameMap(),
+ $badge->getStatus());
+
+ $header = id(new PHUIHeaderView())
+ ->setHeader($badge->getName())
+ ->setUser($viewer)
+ ->setPolicyObject($badge)
+ ->setStatus($status_icon, $status_color, $status_name);
+
+ $properties = $this->buildPropertyListView($badge);
+ $actions = $this->buildActionListView($badge);
+ $properties->setActionList($actions);
+
+ $box = id(new PHUIObjectBoxView())
+ ->setHeader($header)
+ ->addPropertyList($properties);
+
+ $timeline = $this->buildTransactionTimeline(
+ $badge,
+ new PhabricatorBadgesTransactionQuery());
+ $timeline
+ ->setShouldTerminate(true);
+
+ return $this->buildApplicationPage(
+ array(
+ $crumbs,
+ $box,
+ $timeline,
+ ),
+ array(
+ 'title' => $title,
+ 'pageObjects' => array($badge->getPHID()),
+ ));
+ }
+
+ private function buildPropertyListView(PhabricatorBadge $badge) {
+ $viewer = $this->getRequest()->getUser();
+
+ $view = id(new PHUIPropertyListView())
+ ->setUser($viewer)
+ ->setObject($badge);
+
+ $quality = idx($badge->getQualityNameMap(), $badge->getQuality());
+
+ $view->addProperty(
+ pht('Quality'),
+ $quality);
+
+ $view->addProperty(
+ pht('Icon'),
+ $badge->getIcon());
+
+ $view->addProperty(
+ pht('Flavor'),
+ $badge->getFlavor());
+
+ $view->invokeWillRenderEvent();
+
+ $description = $badge->getDescription();
+ if (strlen($description)) {
+ $description = PhabricatorMarkupEngine::renderOneObject(
+ id(new PhabricatorMarkupOneOff())->setContent($description),
+ 'default',
+ $viewer);
+
+ $view->addSectionHeader(pht('Description'));
+ $view->addTextContent($description);
+ }
+
+ return $view;
+ }
+
+ private function buildActionListView(PhabricatorBadge $badge) {
+ $viewer = $this->getRequest()->getUser();
+ $id = $badge->getID();
+
+ $can_edit = PhabricatorPolicyFilter::hasCapability(
+ $viewer,
+ $badge,
+ PhabricatorPolicyCapability::CAN_EDIT);
+
+ $view = id(new PhabricatorActionListView())
+ ->setUser($viewer)
+ ->setObject($badge);
+
+ $view->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('Edit Badge'))
+ ->setIcon('fa-pencil')
+ ->setDisabled(!$can_edit)
+ ->setWorkflow(!$can_edit)
+ ->setHref($this->getApplicationURI("/edit/{$id}/")));
+
+ if ($badge->isClosed()) {
+ $close_name = pht('Activate Badge');
+ $close_icon = 'fa-check';
+ } else {
+ $close_name = pht('Archive Badge');
+ $close_icon = 'fa-times';
+ }
+
+ $view->addAction(
+ id(new PhabricatorActionView())
+ ->setName($close_name)
+ ->setIcon($close_icon)
+ ->setDisabled(!$can_edit)
+ ->setWorkflow(true)
+ ->setHref($this->getApplicationURI("/close/{$id}/")));
+
+ return $view;
+ }
+
+}
diff --git a/src/applications/badges/editor/PhabricatorBadgesEditor.php b/src/applications/badges/editor/PhabricatorBadgesEditor.php
new file mode 100644
--- /dev/null
+++ b/src/applications/badges/editor/PhabricatorBadgesEditor.php
@@ -0,0 +1,150 @@
+<?php
+
+final class PhabricatorBadgesEditor
+ extends PhabricatorApplicationTransactionEditor {
+
+ public function getEditorApplicationClass() {
+ return 'PhabricatorBadgesApplication';
+ }
+
+ public function getEditorObjectsDescription() {
+ return pht('Badges');
+ }
+
+ public function getTransactionTypes() {
+ $types = parent::getTransactionTypes();
+
+ $types[] = PhabricatorBadgesTransaction::TYPE_NAME;
+ $types[] = PhabricatorBadgesTransaction::TYPE_FLAVOR;
+ $types[] = PhabricatorBadgesTransaction::TYPE_DESCRIPTION;
+ $types[] = PhabricatorBadgesTransaction::TYPE_ICON;
+ $types[] = PhabricatorBadgesTransaction::TYPE_STATUS;
+ $types[] = PhabricatorBadgesTransaction::TYPE_QUALITY;
+
+ $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
+ $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
+
+ return $types;
+ }
+
+ protected function getCustomTransactionOldValue(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+ switch ($xaction->getTransactionType()) {
+ case PhabricatorBadgesTransaction::TYPE_NAME:
+ return $object->getName();
+ case PhabricatorBadgesTransaction::TYPE_FLAVOR:
+ return $object->getFlavor();
+ case PhabricatorBadgesTransaction::TYPE_DESCRIPTION:
+ return $object->getDescription();
+ case PhabricatorBadgesTransaction::TYPE_ICON:
+ return $object->getIcon();
+ case PhabricatorBadgesTransaction::TYPE_QUALITY:
+ return $object->getIcon();
+ case PhabricatorBadgesTransaction::TYPE_STATUS:
+ return $object->getStatus();
+ }
+
+ return parent::getCustomTransactionOldValue($object, $xaction);
+ }
+
+ protected function getCustomTransactionNewValue(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ switch ($xaction->getTransactionType()) {
+ case PhabricatorBadgesTransaction::TYPE_NAME:
+ case PhabricatorBadgesTransaction::TYPE_FLAVOR:
+ case PhabricatorBadgesTransaction::TYPE_DESCRIPTION:
+ case PhabricatorBadgesTransaction::TYPE_ICON:
+ case PhabricatorBadgesTransaction::TYPE_STATUS:
+ case PhabricatorBadgesTransaction::TYPE_QUALITY:
+ return $xaction->getNewValue();
+ }
+
+ return parent::getCustomTransactionNewValue($object, $xaction);
+ }
+
+ protected function applyCustomInternalTransaction(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ $type = $xaction->getTransactionType();
+ switch ($type) {
+ case PhabricatorBadgesTransaction::TYPE_NAME:
+ $object->setName($xaction->getNewValue());
+ return;
+ case PhabricatorBadgesTransaction::TYPE_FLAVOR:
+ $object->setFlavor($xaction->getNewValue());
+ return;
+ case PhabricatorBadgesTransaction::TYPE_DESCRIPTION:
+ $object->setDescription($xaction->getNewValue());
+ return;
+ case PhabricatorBadgesTransaction::TYPE_ICON:
+ $object->setIcon($xaction->getNewValue());
+ return;
+ case PhabricatorBadgesTransaction::TYPE_QUALITY:
+ $object->setQuality($xaction->getNewValue());
+ return;
+ case PhabricatorBadgesTransaction::TYPE_STATUS:
+ $object->setStatus($xaction->getNewValue());
+ return;
+ }
+
+ return parent::applyCustomInternalTransaction($object, $xaction);
+ }
+
+ protected function applyCustomExternalTransaction(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ $type = $xaction->getTransactionType();
+ switch ($type) {
+ case PhabricatorBadgesTransaction::TYPE_NAME:
+ case PhabricatorBadgesTransaction::TYPE_FLAVOR:
+ case PhabricatorBadgesTransaction::TYPE_DESCRIPTION:
+ case PhabricatorBadgesTransaction::TYPE_ICON:
+ case PhabricatorBadgesTransaction::TYPE_STATUS:
+ case PhabricatorBadgesTransaction::TYPE_QUALITY:
+ return;
+ }
+
+ return parent::applyCustomExternalTransaction($object, $xaction);
+ }
+
+ protected function validateTransaction(
+ PhabricatorLiskDAO $object,
+ $type,
+ array $xactions) {
+
+ $errors = parent::validateTransaction($object, $type, $xactions);
+
+ switch ($type) {
+ case PhabricatorBadgesTransaction::TYPE_NAME:
+ $missing = $this->validateIsEmptyTextField(
+ $object->getName(),
+ $xactions);
+
+ if ($missing) {
+ $error = new PhabricatorApplicationTransactionValidationError(
+ $type,
+ pht('Required'),
+ pht('Badge name is required.'),
+ nonempty(last($xactions), null));
+
+ $error->setIsMissingFieldError(true);
+ $errors[] = $error;
+ }
+ break;
+ }
+
+ return $errors;
+ }
+
+ protected function shouldPublishFeedStory(
+ PhabricatorLiskDAO $object,
+ array $xactions) {
+ return true;
+ }
+
+}
diff --git a/src/applications/badges/interface/PhabricatorBadgesInterface.php b/src/applications/badges/interface/PhabricatorBadgesInterface.php
new file mode 100644
--- /dev/null
+++ b/src/applications/badges/interface/PhabricatorBadgesInterface.php
@@ -0,0 +1,3 @@
+<?php
+
+interface PhabricatorBadgesInterface extends PhabricatorPHIDInterface {}
diff --git a/src/applications/badges/phid/PhabricatorBadgesPHIDType.php b/src/applications/badges/phid/PhabricatorBadgesPHIDType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/badges/phid/PhabricatorBadgesPHIDType.php
@@ -0,0 +1,73 @@
+<?php
+
+final class PhabricatorBadgesPHIDType extends PhabricatorPHIDType {
+
+ const TYPECONST = 'BDGE';
+
+ public function getTypeName() {
+ return pht('Badge');
+ }
+
+ public function newObject() {
+ return new PhabricatorBadge();
+ }
+
+ public function getPHIDTypeApplicationClass() {
+ return 'PhabricatorBadgesApplication';
+ }
+
+ protected function buildQueryForObjects(
+ PhabricatorObjectQuery $query,
+ array $phids) {
+
+ return id(new PhabricatorBadgesQuery())
+ ->withPHIDs($phids);
+ }
+
+ public function loadHandles(
+ PhabricatorHandleQuery $query,
+ array $handles,
+ array $objects) {
+
+ foreach ($handles as $phid => $handle) {
+ $badge = $objects[$phid];
+
+ $id = $badge->getID();
+ $name = $badge->getName();
+
+ if ($badge->isClosed()) {
+ $handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
+ }
+
+ $handle->setName($name);
+ $handle->setFullName("{$name}");
+ $handle->setURI("/badges/view/{$id}/");
+ }
+ }
+
+ public function loadNamedObjects(
+ PhabricatorObjectQuery $query,
+ array $names) {
+
+ $id_map = array();
+ foreach ($names as $name) {
+ $id = (int)substr($name, 1);
+ $id_map[$id][] = $name;
+ }
+
+ $objects = id(new PhabricatorBadgesQuery())
+ ->setViewer($query->getViewer())
+ ->withIDs(array_keys($id_map))
+ ->execute();
+
+ $results = array();
+ foreach ($objects as $id => $object) {
+ foreach (idx($id_map, $id, array()) as $name) {
+ $results[$name] = $object;
+ }
+ }
+
+ return $results;
+ }
+
+}
diff --git a/src/applications/badges/query/PhabricatorBadgesQuery.php b/src/applications/badges/query/PhabricatorBadgesQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/badges/query/PhabricatorBadgesQuery.php
@@ -0,0 +1,90 @@
+<?php
+
+final class PhabricatorBadgesQuery
+ extends PhabricatorCursorPagedPolicyAwareQuery {
+
+ private $ids;
+ private $phids;
+ private $qualities;
+ private $statuses;
+
+ public function withIDs(array $ids) {
+ $this->ids = $ids;
+ return $this;
+ }
+
+ public function withPHIDs(array $phids) {
+ $this->phids = $phids;
+ return $this;
+ }
+
+ public function withQualiyies(array $qualities) {
+ $this->qualities = $qualities;
+ return $this;
+ }
+
+ public function withStatuses(array $statuses) {
+ $this->statuses = $statuses;
+ return $this;
+ }
+
+ protected function loadPage() {
+ $table = new PhabricatorBadge();
+ $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);
+ }
+
+ protected function didFilterPage(array $badges) {
+ return $badges;
+ }
+
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ $where = array();
+
+ $where[] = $this->buildPagingClause($conn_r);
+
+ if ($this->ids !== null) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'id IN (%Ld)',
+ $this->ids);
+ }
+
+ if ($this->phids !== null) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'phid IN (%Ls)',
+ $this->phids);
+ }
+
+ if ($this->qualities !== null) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'quality IN (%Ls)',
+ $this->qualities);
+ }
+
+ if ($this->statuses !== null) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'status IN (%Ls)',
+ $this->statuses);
+ }
+
+ return $this->formatWhereClause($where);
+ }
+
+ public function getQueryApplicationClass() {
+ return 'PhabricatorBadgesApplication';
+ }
+
+}
diff --git a/src/applications/badges/query/PhabricatorBadgesSearchEngine.php b/src/applications/badges/query/PhabricatorBadgesSearchEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/badges/query/PhabricatorBadgesSearchEngine.php
@@ -0,0 +1,129 @@
+<?php
+
+final class PhabricatorBadgesSearchEngine
+ extends PhabricatorApplicationSearchEngine {
+
+ public function getResultTypeDescription() {
+ return pht('Badge');
+ }
+
+ public function getApplicationClassName() {
+ return 'PhabricatorBadgesApplication';
+ }
+
+ public function buildSavedQueryFromRequest(AphrontRequest $request) {
+ $saved = new PhabricatorSavedQuery();
+
+ $saved->setParameter(
+ 'statuses',
+ $this->readListFromRequest($request, 'statuses'));
+
+ return $saved;
+ }
+
+ public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
+ $query = new PhabricatorBadgesQuery();
+
+ $statuses = $saved->getParameter('statuses');
+ if ($statuses) {
+ $query->withStatuses($statuses);
+ }
+
+ return $query;
+ }
+
+ public function buildSearchForm(
+ AphrontFormView $form,
+ PhabricatorSavedQuery $saved) {
+
+ $statuses = $saved->getParameter('statuses', array());
+ $statuses = array_fuse($statuses);
+
+ $status_map = PhabricatorBadge::getStatusNameMap();
+ $status_control = id(new AphrontFormCheckboxControl())
+ ->setLabel(pht('Statuses'));
+ foreach ($status_map as $status => $name) {
+ $status_control->addCheckbox(
+ 'statuses[]',
+ $status,
+ $name,
+ isset($statuses[$status]));
+ }
+ }
+
+ protected function getURI($path) {
+ return '/badges/'.$path;
+ }
+
+ protected function getBuiltinQueryNames() {
+ $names = array();
+
+ $names['open'] = pht('Active Badges');
+ $names['all'] = pht('All Badges');
+
+ 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(
+ PhabricatorBadge::STATUS_OPEN,
+ ));
+ }
+
+ return parent::buildSavedQueryFromBuiltin($query_key);
+ }
+
+ protected function getRequiredHandlePHIDsForResultList(
+ array $badges,
+ PhabricatorSavedQuery $query) {
+
+ $phids = array();
+
+ return $phids;
+ }
+
+ protected function renderResultList(
+ array $badges,
+ PhabricatorSavedQuery $query,
+ array $handles) {
+ assert_instances_of($badges, 'PhabricatorBadge');
+
+ $viewer = $this->requireViewer();
+
+ $list = id(new PHUIObjectItemListView());
+ foreach ($badges as $badge) {
+
+ $quality = idx($badge->getQualityNameMap(), $badge->getQuality());
+
+ $item = id(new PHUIObjectItemView())
+ ->setHeader($badge->getName())
+ ->setStatusIcon($badge->getIcon().' '.$badge->getQuality())
+ ->setHref('/badges/view/'.$badge->getID().'/')
+ ->addAttribute($quality)
+ ->addAttribute($badge->getFlavor());
+
+ if ($badge->isClosed()) {
+ $item->setDisabled(true);
+ }
+
+ $list->addItem($item);
+ }
+
+ $result = new PhabricatorApplicationSearchResultView();
+ $result->setObjectList($list);
+ $result->setNoDataString(pht('No badges found.'));
+
+ return $result;
+
+ }
+
+}
diff --git a/src/applications/badges/query/PhabricatorBadgesTransactionQuery.php b/src/applications/badges/query/PhabricatorBadgesTransactionQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/badges/query/PhabricatorBadgesTransactionQuery.php
@@ -0,0 +1,10 @@
+<?php
+
+final class PhabricatorBadgesTransactionQuery
+ extends PhabricatorApplicationTransactionQuery {
+
+ public function getTemplateApplicationTransaction() {
+ return new PhabricatorBadgesTransaction();
+ }
+
+}
diff --git a/src/applications/badges/storage/PhabricatorBadge.php b/src/applications/badges/storage/PhabricatorBadge.php
new file mode 100644
--- /dev/null
+++ b/src/applications/badges/storage/PhabricatorBadge.php
@@ -0,0 +1,187 @@
+<?php
+
+final class PhabricatorBadge extends PhabricatorBadgesDAO
+ implements
+ PhabricatorPolicyInterface,
+ PhabricatorApplicationTransactionInterface,
+ PhabricatorDestructibleInterface {
+
+ protected $name;
+ protected $flavor;
+ protected $description;
+ protected $icon;
+ protected $quality;
+ protected $viewPolicy;
+ protected $editPolicy;
+ protected $status;
+
+ const STATUS_OPEN = 'open';
+ const STATUS_CLOSED = 'closed';
+
+ const POOR = 'grey';
+ const COMMON = 'white';
+ const UNCOMMON = 'green';
+ const RARE = 'blue';
+ const EPIC = 'indigo';
+ const LEGENDARY = 'orange';
+ const HEIRLOOM = 'yellow';
+
+ const ICON_STAR = 'fa-star';
+ const ICON_PERSON = 'fa-user';
+ const ICON_BUG = 'fa-bug';
+ const ICON_BOOK = 'fa-book';
+ const ICON_ROCKET = 'fa-rocket';
+ const ICON_HELP = 'fa-bouy';
+
+ public static function getStatusNameMap() {
+ return array(
+ self::STATUS_OPEN => pht('Active'),
+ self::STATUS_CLOSED => pht('Archived'),
+ );
+ }
+
+ public static function getQualityNameMap() {
+ return array(
+ self::POOR => pht('Poor'),
+ self::COMMON => pht('Common'),
+ self::UNCOMMON => pht('Uncommon'),
+ self::RARE => pht('Rare'),
+ self::EPIC => pht('Epic'),
+ self::LEGENDARY => pht('Legendary'),
+ self::HEIRLOOM => pht('Heirloom'),
+ );
+ }
+
+ public static function getIconNameMap() {
+ return array(
+ self::ICON_STAR => pht('Star'),
+ self::ICON_PERSON => pht('Person'),
+ self::ICON_BUG => pht('Bug'),
+ self::ICON_BOOK => pht('Book'),
+ self::ICON_ROCKET => pht('Rocket'),
+ self::ICON_HELP => pht('Bouy'),
+ );
+ }
+
+ public static function initializeNewBadge(PhabricatorUser $actor) {
+ $app = id(new PhabricatorApplicationQuery())
+ ->setViewer($actor)
+ ->withClasses(array('PhabricatorBadgesApplication'))
+ ->executeOne();
+
+ $view_policy =
+ $app->getPolicy(PhabricatorBadgesDefaultViewCapability::CAPABILITY);
+
+ $edit_policy =
+ $app->getPolicy(PhabricatorBadgesDefaultEditCapability::CAPABILITY);
+
+ return id(new PhabricatorBadge())
+ ->setName('')
+ ->setViewPolicy($view_policy)
+ ->setEditPolicy($edit_policy)
+ ->setStatus(self::STATUS_OPEN);
+ }
+
+ protected function getConfiguration() {
+ return array(
+ self::CONFIG_AUX_PHID => true,
+ self::CONFIG_COLUMN_SCHEMA => array(
+ 'name' => 'text255',
+ 'flavor' => 'text255',
+ 'description' => 'text',
+ 'icon' => 'text255',
+ 'quality' => 'text255',
+ 'status' => 'text32',
+ ),
+ ) + parent::getConfiguration();
+ }
+
+ public function generatePHID() {
+ return
+ PhabricatorPHID::generateNewPHID(PhabricatorBadgesPHIDType::TYPECONST);
+ }
+
+ public function isClosed() {
+ return ($this->getStatus() == self::STATUS_CLOSED);
+ }
+
+
+/* -( PhabricatorPolicyInterface )----------------------------------------- */
+
+
+ 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 $viewer) {
+ return false;
+ }
+
+ public function describeAutomaticCapability($capability) {
+ return null;
+ }
+
+
+/* -( PhabricatorApplicationTransactionInterface )------------------------- */
+
+
+ public function getApplicationTransactionEditor() {
+ return new PhabricatorBadgesEditor();
+ }
+
+ public function getApplicationTransactionObject() {
+ return $this;
+ }
+
+ public function getApplicationTransactionTemplate() {
+ return new PhabricatorBadgesTransaction();
+ }
+
+ public function willRenderTimeline(
+ PhabricatorApplicationTransactionView $timeline,
+ AphrontRequest $request) {
+
+ return $timeline;
+ }
+
+
+/* -( PhabricatorSubscribableInterface )----------------------------------- */
+
+
+ public function isAutomaticallySubscribed($phid) {
+ return false;
+ }
+
+ public function shouldShowSubscribersProperty() {
+ return false;
+ }
+
+ public function shouldAllowSubscription($phid) {
+ return false;
+ }
+
+
+/* -( PhabricatorDestructibleInterface )----------------------------------- */
+
+
+ public function destroyObjectPermanently(
+ PhabricatorDestructionEngine $engine) {
+
+ $this->openTransaction();
+ $this->delete();
+ $this->saveTransaction();
+ }
+
+}
diff --git a/src/applications/badges/storage/PhabricatorBadgesDAO.php b/src/applications/badges/storage/PhabricatorBadgesDAO.php
new file mode 100644
--- /dev/null
+++ b/src/applications/badges/storage/PhabricatorBadgesDAO.php
@@ -0,0 +1,9 @@
+<?php
+
+abstract class PhabricatorBadgesDAO extends PhabricatorLiskDAO {
+
+ public function getApplicationName() {
+ return 'badges';
+ }
+
+}
diff --git a/src/applications/badges/storage/PhabricatorBadgesSchemaSpec.php b/src/applications/badges/storage/PhabricatorBadgesSchemaSpec.php
new file mode 100644
--- /dev/null
+++ b/src/applications/badges/storage/PhabricatorBadgesSchemaSpec.php
@@ -0,0 +1,10 @@
+<?php
+
+final class PhabricatorBadgesSchemaSpec
+ extends PhabricatorConfigSchemaSpec {
+
+ public function buildSchemata() {
+ $this->buildEdgeSchemata(new PhabricatorBadge());
+ }
+
+}
diff --git a/src/applications/badges/storage/PhabricatorBadgesTransaction.php b/src/applications/badges/storage/PhabricatorBadgesTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/badges/storage/PhabricatorBadgesTransaction.php
@@ -0,0 +1,139 @@
+<?php
+
+final class PhabricatorBadgesTransaction
+ extends PhabricatorApplicationTransaction {
+
+ const TYPE_NAME = 'badges:name';
+ const TYPE_DESCRIPTION = 'badges:description';
+ const TYPE_QUALITY = 'badges:quality';
+ const TYPE_ICON = 'badges:icon';
+ const TYPE_STATUS = 'badges:status';
+ const TYPE_FLAVOR = 'badges:flavor';
+
+ public function getApplicationName() {
+ return 'badges';
+ }
+
+ public function getApplicationTransactionType() {
+ return PhabricatorBadgesPHIDType::TYPECONST;
+ }
+
+ public function getApplicationTransactionCommentObject() {
+ return null;
+ }
+
+ 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 badge.',
+ $this->renderHandleLink($author_phid));
+ } else {
+ return pht(
+ '%s renamed this badge from "%s" to "%s".',
+ $this->renderHandleLink($author_phid),
+ $old,
+ $new);
+ }
+ 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_ICON:
+ return pht(
+ '%s updated the icon for %s.',
+ $this->renderHandleLink($author_phid),
+ $this->renderHandleLink($object_phid));
+ case self::TYPE_QUALITY:
+ return pht(
+ '%s updated the quality level for %s.',
+ $this->renderHandleLink($author_phid),
+ $this->renderHandleLink($object_phid));
+ case self::TYPE_DESCRIPTION:
+ return pht(
+ '%s updated the description for %s.',
+ $this->renderHandleLink($author_phid),
+ $this->renderHandleLink($object_phid));
+ case self::TYPE_STATUS:
+ switch ($new) {
+ case PhabricatorBadge::STATUS_OPEN:
+ return pht(
+ '%s activated %s.',
+ $this->renderHandleLink($author_phid),
+ $this->renderHandleLink($object_phid));
+ case PhabricatorBadge::STATUS_CLOSED:
+ return pht(
+ '%s archived %s.',
+ $this->renderHandleLink($author_phid),
+ $this->renderHandleLink($object_phid));
+ }
+ break;
+ }
+
+ return parent::getTitleForFeed();
+ }
+
+
+ public function shouldHide() {
+ $old = $this->getOldValue();
+ switch ($this->getTransactionType()) {
+ case self::TYPE_DESCRIPTION:
+ return ($old === null);
+ }
+ return parent::shouldHide();
+ }
+
+ public function hasChangeDetails() {
+ switch ($this->getTransactionType()) {
+ case self::TYPE_DESCRIPTION:
+ return ($this->getOldValue() !== null);
+ }
+
+ return parent::hasChangeDetails();
+ }
+
+ public function renderChangeDetails(PhabricatorUser $viewer) {
+ return $this->renderTextCorpusChangeDetails(
+ $viewer,
+ $this->getOldValue(),
+ $this->getNewValue());
+ }
+}
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
@@ -11,7 +11,7 @@
}
public function getFontIcon() {
- return 'fa-trophy';
+ return 'fa-heart';
}
public function getTitleGlyph() {
diff --git a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
--- a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
+++ b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
@@ -106,6 +106,7 @@
'db.almanac' => array(),
'db.multimeter' => array(),
'db.spaces' => array(),
+ 'db.badges' => array(),
'0000.legacy.sql' => array(
'legacy' => 0,
),
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Nov 25, 12:47 AM (20 h, 48 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6784439
Default Alt Text
D13626.id32919.diff (48 KB)
Attached To
Mode
D13626: Badges v0.1
Attached
Detach File
Event Timeline
Log In to Comment