@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Converting badge recipients from Edge to BadgeAward table

Summary: Ref T8996, Convert badge recipients from Edges to actual BadgeAward objects

Test Plan: Create badge, award it to recipient. Make sure adding/removing recipients works. (Still need to migrate exisiting recipients to new table and need to create activity feed blurbs)

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley, #blessed_reviewers

Subscribers: chad, Korvin

Maniphest Tasks: T8996

Differential Revision: https://secure.phabricator.com/D15014

+296 -74
+10
resources/sql/autopatches/20160102.badges.award.sql
··· 1 + CREATE TABLE {$NAMESPACE}_badges.badges_award ( 2 + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 3 + badgePHID VARBINARY(64) NOT NULL, 4 + recipientPHID VARBINARY(64) NOT NULL, 5 + awarderPHID varbinary(64) NOT NULL, 6 + dateCreated INT UNSIGNED NOT NULL, 7 + dateModified INT UNSIGNED NOT NULL, 8 + UNIQUE KEY `key_badge` (badgePHID, recipientPHID), 9 + KEY `key_recipient` (recipientPHID) 10 + ) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
+6
resources/sql/autopatches/20160323.badgemigrate.sql
··· 1 + /* PhabricatorBadgeHasRecipientEdgeType::TYPECONST = 59 */ 2 + 3 + INSERT IGNORE INTO {$NAMESPACE}_badges.badges_award 4 + (badgePHID, recipientPHID, awarderPHID, dateCreated, dateModified) 5 + SELECT src, dst, 'PHID-VOID-00000000000000000000', dateCreated, dateCreated 6 + FROM {$NAMESPACE}_badges.edge WHERE type = 59;
+8
src/__phutil_library_map__.php
··· 1870 1870 'PhabricatorBadgeHasRecipientEdgeType' => 'applications/badges/edge/PhabricatorBadgeHasRecipientEdgeType.php', 1871 1871 'PhabricatorBadgesApplication' => 'applications/badges/application/PhabricatorBadgesApplication.php', 1872 1872 'PhabricatorBadgesArchiveController' => 'applications/badges/controller/PhabricatorBadgesArchiveController.php', 1873 + 'PhabricatorBadgesAward' => 'applications/badges/storage/PhabricatorBadgesAward.php', 1874 + 'PhabricatorBadgesAwardQuery' => 'applications/badges/query/PhabricatorBadgesAwardQuery.php', 1873 1875 'PhabricatorBadgesBadge' => 'applications/badges/storage/PhabricatorBadgesBadge.php', 1874 1876 'PhabricatorBadgesCommentController' => 'applications/badges/controller/PhabricatorBadgesCommentController.php', 1875 1877 'PhabricatorBadgesController' => 'applications/badges/controller/PhabricatorBadgesController.php', ··· 6231 6233 'PhabricatorBadgeHasRecipientEdgeType' => 'PhabricatorEdgeType', 6232 6234 'PhabricatorBadgesApplication' => 'PhabricatorApplication', 6233 6235 'PhabricatorBadgesArchiveController' => 'PhabricatorBadgesController', 6236 + 'PhabricatorBadgesAward' => array( 6237 + 'PhabricatorBadgesDAO', 6238 + 'PhabricatorDestructibleInterface', 6239 + 'PhabricatorPolicyInterface', 6240 + ), 6241 + 'PhabricatorBadgesAwardQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 6234 6242 'PhabricatorBadgesBadge' => array( 6235 6243 'PhabricatorBadgesDAO', 6236 6244 'PhabricatorPolicyInterface',
-1
src/applications/badges/controller/PhabricatorBadgesEditController.php
··· 2 2 3 3 final class PhabricatorBadgesEditController extends 4 4 PhabricatorBadgesController { 5 - 6 5 public function handleRequest(AphrontRequest $request) { 7 6 return id(new PhabricatorBadgesEditEngine()) 8 7 ->setController($this)
+9 -15
src/applications/badges/controller/PhabricatorBadgesEditRecipientsController.php
··· 6 6 public function handleRequest(AphrontRequest $request) { 7 7 $viewer = $request->getViewer(); 8 8 $id = $request->getURIData('id'); 9 + $xactions = array(); 9 10 10 11 $badge = id(new PhabricatorBadgesQuery()) 11 12 ->setViewer($viewer) ··· 21 22 return new Aphront404Response(); 22 23 } 23 24 24 - $recipient_phids = $badge->getRecipientPHIDs(); 25 25 $view_uri = $this->getApplicationURI('view/'.$badge->getID().'/'); 26 + $awards = $badge->getAwards(); 27 + $recipient_phids = mpull($awards, 'getRecipientPHID'); 26 28 27 29 if ($request->isFormPost()) { 28 - $recipient_spec = array(); 29 - 30 - $remove = $request->getStr('remove'); 31 - if ($remove) { 32 - $recipient_spec['-'] = array_fuse(array($remove)); 33 - } 30 + $award_phids = array(); 34 31 35 32 $add_recipients = $request->getArr('phids'); 36 33 if ($add_recipients) { 37 - $recipient_spec['+'] = array_fuse($add_recipients); 34 + foreach ($add_recipients as $phid) { 35 + $award_phids[] = $phid; 36 + } 38 37 } 39 38 40 - $type_recipient = PhabricatorBadgeHasRecipientEdgeType::EDGECONST; 41 - 42 - $xactions = array(); 43 - 44 39 $xactions[] = id(new PhabricatorBadgesTransaction()) 45 - ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) 46 - ->setMetadataValue('edge:type', $type_recipient) 47 - ->setNewValue($recipient_spec); 40 + ->setTransactionType(PhabricatorBadgesTransaction::TYPE_AWARD) 41 + ->setNewValue($award_phids); 48 42 49 43 $editor = id(new PhabricatorBadgesEditor($badge)) 50 44 ->setActor($viewer)
+4 -10
src/applications/badges/controller/PhabricatorBadgesRemoveRecipientsController.php
··· 21 21 return new Aphront404Response(); 22 22 } 23 23 24 - $recipient_phids = $badge->getRecipientPHIDs(); 24 + $awards = $badge->getAwards(); 25 + $recipient_phids = mpull($awards, 'getRecipientPHID'); 25 26 $remove_phid = $request->getStr('phid'); 26 27 27 28 if (!in_array($remove_phid, $recipient_phids)) { ··· 31 32 $view_uri = $this->getApplicationURI('view/'.$badge->getID().'/'); 32 33 33 34 if ($request->isFormPost()) { 34 - $recipient_spec = array(); 35 - $recipient_spec['-'] = array($remove_phid => $remove_phid); 36 - 37 - $type_recipient = PhabricatorBadgeHasRecipientEdgeType::EDGECONST; 38 - 39 35 $xactions = array(); 40 - 41 36 $xactions[] = id(new PhabricatorBadgesTransaction()) 42 - ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) 43 - ->setMetadataValue('edge:type', $type_recipient) 44 - ->setNewValue($recipient_spec); 37 + ->setTransactionType(PhabricatorBadgesTransaction::TYPE_REVOKE) 38 + ->setNewValue(array($remove_phid)); 45 39 46 40 $editor = id(new PhabricatorBadgesEditor($badge)) 47 41 ->setActor($viewer)
+2 -1
src/applications/badges/controller/PhabricatorBadgesViewController.php
··· 50 50 $badge, 51 51 new PhabricatorBadgesTransactionQuery()); 52 52 53 - $recipient_phids = $badge->getRecipientPHIDs(); 53 + $awards = $badge->getAwards(); 54 + $recipient_phids = mpull($awards, 'getRecipientPHID'); 54 55 $recipient_phids = array_reverse($recipient_phids); 55 56 $handles = $this->loadViewerHandles($recipient_phids); 56 57
+40
src/applications/badges/editor/PhabricatorBadgesEditor.php
··· 20 20 $types[] = PhabricatorBadgesTransaction::TYPE_ICON; 21 21 $types[] = PhabricatorBadgesTransaction::TYPE_STATUS; 22 22 $types[] = PhabricatorBadgesTransaction::TYPE_QUALITY; 23 + $types[] = PhabricatorBadgesTransaction::TYPE_AWARD; 24 + $types[] = PhabricatorBadgesTransaction::TYPE_REVOKE; 23 25 24 26 $types[] = PhabricatorTransactions::TYPE_COMMENT; 25 27 $types[] = PhabricatorTransactions::TYPE_EDGE; ··· 44 46 return $object->getQuality(); 45 47 case PhabricatorBadgesTransaction::TYPE_STATUS: 46 48 return $object->getStatus(); 49 + case PhabricatorBadgesTransaction::TYPE_AWARD: 50 + $award_phids = mpull($object->getAwards(), 'getRecipientPHID'); 51 + return $award_phids; 52 + case PhabricatorBadgesTransaction::TYPE_REVOKE: 53 + return null; 47 54 } 48 55 49 56 return parent::getCustomTransactionOldValue($object, $xaction); ··· 60 67 case PhabricatorBadgesTransaction::TYPE_ICON: 61 68 case PhabricatorBadgesTransaction::TYPE_STATUS: 62 69 case PhabricatorBadgesTransaction::TYPE_QUALITY: 70 + case PhabricatorBadgesTransaction::TYPE_AWARD: 71 + case PhabricatorBadgesTransaction::TYPE_REVOKE: 63 72 return $xaction->getNewValue(); 64 73 } 65 74 ··· 90 99 case PhabricatorBadgesTransaction::TYPE_STATUS: 91 100 $object->setStatus($xaction->getNewValue()); 92 101 return; 102 + case PhabricatorBadgesTransaction::TYPE_AWARD: 103 + case PhabricatorBadgesTransaction::TYPE_REVOKE: 104 + return; 93 105 } 94 106 95 107 return parent::applyCustomInternalTransaction($object, $xaction); ··· 107 119 case PhabricatorBadgesTransaction::TYPE_ICON: 108 120 case PhabricatorBadgesTransaction::TYPE_STATUS: 109 121 case PhabricatorBadgesTransaction::TYPE_QUALITY: 122 + return; 123 + case PhabricatorBadgesTransaction::TYPE_REVOKE: 124 + $revoked_recipient_phids = $xaction->getNewValue(); 125 + $awards = $object->getAwards(); 126 + $awards = mpull($awards, null, 'getRecipientPHID'); 127 + 128 + foreach ($revoked_recipient_phids as $phid) { 129 + $awards[$phid]->delete(); 130 + } 131 + $object->attachAwards($awards); 132 + return; 133 + case PhabricatorBadgesTransaction::TYPE_AWARD: 134 + $recipient_phids = $xaction->getNewValue(); 135 + $awards = $object->getAwards(); 136 + $awards = mpull($awards, null, 'getRecipientPHID'); 137 + 138 + foreach ($recipient_phids as $phid) { 139 + $award = idx($awards, $phid); 140 + if (!$award) { 141 + $award = PhabricatorBadgesAward::initializeNewBadgesAward( 142 + $this->getActor(), 143 + $object, 144 + $phid); 145 + $award->save(); 146 + $awards[] = $award; 147 + } 148 + } 149 + $object->attachAwards($awards); 110 150 return; 111 151 } 112 152
+87
src/applications/badges/query/PhabricatorBadgesAwardQuery.php
··· 1 + <?php 2 + 3 + final class PhabricatorBadgesAwardQuery 4 + extends PhabricatorCursorPagedPolicyAwareQuery { 5 + 6 + private $badgePHIDs; 7 + private $recipientPHIDs; 8 + private $awarderPHIDs; 9 + 10 + 11 + protected function willFilterPage(array $awards) { 12 + $badges = id(new PhabricatorBadgesQuery()) 13 + ->setViewer($this->getViewer()) 14 + ->withRecipientPHIDs(mpull($awards, null, 'getRecipientPHID')) 15 + ->execute(); 16 + 17 + $badges = mpull($badges, null, 'getPHID'); 18 + 19 + foreach ($awards as $key => $award) { 20 + $award_badge = idx($badges, $award->getBadgePHID()); 21 + if ($award_badge === null) { 22 + $this->didRejectResult($award); 23 + unset($awards[$key]); 24 + continue; 25 + } 26 + 27 + $award->attachBadge($award_badge); 28 + } 29 + 30 + return $awards; 31 + } 32 + 33 + public function withBadgePHIDs(array $phids) { 34 + $this->badgePHIDs = $phids; 35 + return $this; 36 + } 37 + 38 + public function withRecipientPHIDs(array $phids) { 39 + $this->recipientPHIDs = $phids; 40 + return $this; 41 + } 42 + 43 + public function withAwarderPHIDs(array $phids) { 44 + $this->awarderPHIDs = $phids; 45 + return $this; 46 + } 47 + 48 + protected function loadPage() { 49 + return $this->loadStandardPage($this->newResultObject()); 50 + } 51 + 52 + public function newResultObject() { 53 + return new PhabricatorBadgesAward(); 54 + } 55 + 56 + protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { 57 + $where = parent::buildWhereClauseParts($conn); 58 + 59 + if ($this->badgePHIDs !== null) { 60 + $where[] = qsprintf( 61 + $conn, 62 + 'badgePHID IN (%Ls)', 63 + $this->badgePHIDs); 64 + } 65 + 66 + if ($this->recipientPHIDs !== null) { 67 + $where[] = qsprintf( 68 + $conn, 69 + 'recipientPHID IN (%Ls)', 70 + $this->recipientPHIDs); 71 + } 72 + 73 + if ($this->awarderPHIDs !== null) { 74 + $where[] = qsprintf( 75 + $conn, 76 + 'awarderPHID IN (%Ls)', 77 + $this->awarderPHIDs); 78 + } 79 + 80 + return $where; 81 + } 82 + 83 + public function getQueryApplicationClass() { 84 + return 'PhabricatorBadgesApplication'; 85 + } 86 + 87 + }
+8 -13
src/applications/badges/query/PhabricatorBadgesQuery.php
··· 50 50 } 51 51 52 52 protected function didFilterPage(array $badges) { 53 + if ($this->needRecipients) { 54 + $query = id(new PhabricatorBadgesAwardQuery()) 55 + ->setViewer($this->getViewer()) 56 + ->withBadgePHIDs(mpull($badges, 'getPHID')) 57 + ->execute(); 53 58 54 - if ($this->needRecipients) { 55 - $edge_query = id(new PhabricatorEdgeQuery()) 56 - ->withSourcePHIDs(mpull($badges, 'getPHID')) 57 - ->withEdgeTypes( 58 - array( 59 - PhabricatorBadgeHasRecipientEdgeType::EDGECONST, 60 - )); 61 - $edge_query->execute(); 59 + $awards = mgroup($query, 'getBadgePHID'); 62 60 63 61 foreach ($badges as $badge) { 64 - $phids = $edge_query->getDestinationPHIDs( 65 - array( 66 - $badge->getPHID(), 67 - )); 68 - $badge->attachRecipientPHIDs($phids); 62 + $badge_awards = idx($awards, $badge->getPHID(), array()); 63 + $badge->attachAwards($badge_awards); 69 64 } 70 65 } 71 66
+83
src/applications/badges/storage/PhabricatorBadgesAward.php
··· 1 + <?php 2 + 3 + final class PhabricatorBadgesAward extends PhabricatorBadgesDAO 4 + implements 5 + PhabricatorDestructibleInterface, 6 + PhabricatorPolicyInterface { 7 + 8 + protected $badgePHID; 9 + protected $recipientPHID; 10 + protected $awarderPHID; 11 + 12 + private $badge = self::ATTACHABLE; 13 + 14 + public static function initializeNewBadgesAward( 15 + PhabricatorUser $actor, 16 + PhabricatorBadgesBadge $badge, 17 + $recipient_phid) { 18 + return id(new self()) 19 + ->setRecipientPHID($recipient_phid) 20 + ->setBadgePHID($badge->getPHID()) 21 + ->setAwarderPHID($actor->getPHID()) 22 + ->attachBadge($badge); 23 + } 24 + 25 + protected function getConfiguration() { 26 + return array( 27 + self::CONFIG_KEY_SCHEMA => array( 28 + 'key_badge' => array( 29 + 'columns' => array('badgePHID', 'recipientPHID'), 30 + 'unique' => true, 31 + ), 32 + 'key_recipient' => array( 33 + 'columns' => array('recipientPHID'), 34 + ), 35 + ), 36 + ) + parent::getConfiguration(); 37 + } 38 + 39 + public function attachBadge(PhabricatorBadgesBadge $badge) { 40 + $this->badge = $badge; 41 + return $this; 42 + } 43 + 44 + public function getBadge() { 45 + return $this->assertAttached($this->badge); 46 + } 47 + 48 + 49 + /* -( PhabricatorDestructibleInterface )----------------------------------- */ 50 + 51 + 52 + public function destroyObjectPermanently( 53 + PhabricatorDestructionEngine $engine) { 54 + 55 + $this->openTransaction(); 56 + $this->delete(); 57 + $this->saveTransaction(); 58 + } 59 + 60 + 61 + /* -( PhabricatorPolicyInterface )----------------------------------------- */ 62 + 63 + 64 + public function getCapabilities() { 65 + return array( 66 + PhabricatorPolicyCapability::CAN_VIEW, 67 + PhabricatorPolicyCapability::CAN_EDIT, 68 + ); 69 + } 70 + 71 + public function getPolicy($capability) { 72 + return $this->getBadge()->getPolicy($capability); 73 + } 74 + 75 + public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { 76 + return false; 77 + } 78 + 79 + public function describeAutomaticCapability($capability) { 80 + return null; 81 + } 82 + 83 + }
+14 -5
src/applications/badges/storage/PhabricatorBadgesBadge.php
··· 19 19 protected $status; 20 20 protected $creatorPHID; 21 21 22 - private $recipientPHIDs = self::ATTACHABLE; 22 + private $awards = self::ATTACHABLE; 23 23 24 24 const STATUS_ACTIVE = 'open'; 25 25 const STATUS_ARCHIVED = 'closed'; ··· 102 102 return ($this->getStatus() == self::STATUS_ARCHIVED); 103 103 } 104 104 105 - public function attachRecipientPHIDs(array $phids) { 106 - $this->recipientPHIDs = $phids; 105 + public function attachAwards(array $awards) { 106 + $this->awards = $awards; 107 107 return $this; 108 108 } 109 109 110 - public function getRecipientPHIDs() { 111 - return $this->assertAttached($this->recipientPHIDs); 110 + public function getAwards() { 111 + return $this->assertAttached($this->awards); 112 112 } 113 113 114 114 public function getViewURI() { ··· 196 196 197 197 public function destroyObjectPermanently( 198 198 PhabricatorDestructionEngine $engine) { 199 + 200 + $awards = id(new PhabricatorBadgesAwardQuery()) 201 + ->setViewer($engine->getViewer()) 202 + ->withBadgePHIDs(array($this->getPHID())) 203 + ->execute(); 204 + 205 + foreach ($awards as $award) { 206 + $engine->destroyObjectPermanently($award); 207 + } 199 208 200 209 $this->openTransaction(); 201 210 $this->delete();
+2
src/applications/badges/storage/PhabricatorBadgesTransaction.php
··· 9 9 const TYPE_ICON = 'badges:icon'; 10 10 const TYPE_STATUS = 'badges:status'; 11 11 const TYPE_FLAVOR = 'badges:flavor'; 12 + const TYPE_AWARD = 'badges:award'; 13 + const TYPE_REVOKE = 'badges:revoke'; 12 14 13 15 const MAILTAG_DETAILS = 'badges:details'; 14 16 const MAILTAG_COMMENT = 'badges:comment';
+9 -12
src/applications/people/query/PhabricatorPeopleQuery.php
··· 155 155 } 156 156 157 157 if ($this->needBadges) { 158 - $edge_query = id(new PhabricatorEdgeQuery()) 159 - ->withSourcePHIDs(mpull($users, 'getPHID')) 160 - ->withEdgeTypes( 161 - array( 162 - PhabricatorRecipientHasBadgeEdgeType::EDGECONST, 163 - )); 164 - $edge_query->execute(); 158 + $awards = id(new PhabricatorBadgesAwardQuery()) 159 + ->setViewer($this->getViewer()) 160 + ->withRecipientPHIDs(mpull($users, 'getPHID')) 161 + ->execute(); 162 + 163 + $awards = mgroup($awards, 'getRecipientPHID'); 165 164 166 165 foreach ($users as $user) { 167 - $phids = $edge_query->getDestinationPHIDs( 168 - array( 169 - $user->getPHID(), 170 - )); 171 - $user->attachBadgePHIDs($phids); 166 + $user_awards = idx($awards, $user->getPHID(), array()); 167 + $badge_phids = mpull($user_awards, 'getBadgePHID'); 168 + $user->attachBadgePHIDs($badge_phids); 172 169 } 173 170 } 174 171
+14 -17
src/view/phui/PHUITimelineView.php
··· 250 250 return; 251 251 } 252 252 253 - $edges = id(new PhabricatorEdgeQuery()) 254 - ->withSourcePHIDs($user_phids) 255 - ->withEdgeTypes(array($badge_edge_type)); 256 - $edges->execute(); 257 253 258 - $badge_phids = $edges->getDestinationPHIDs(); 259 - if (!$badge_phids) { 260 - return; 261 - } 254 + $awards = id(new PhabricatorBadgesAwardQuery()) 255 + ->setViewer($this->getViewer()) 256 + ->withRecipientPHIDs($user_phids) 257 + ->execute(); 262 258 263 - $all_badges = id(new PhabricatorBadgesQuery()) 264 - ->setViewer($viewer) 265 - ->withPHIDs($badge_phids) 266 - ->withStatuses(array(PhabricatorBadgesBadge::STATUS_ACTIVE)) 267 - ->execute(); 268 - $all_badges = mpull($all_badges, null, 'getPHID'); 259 + $awards = mgroup($awards, 'getRecipientPHID'); 269 260 270 261 foreach ($events as $event) { 271 - $author_phid = $event->getAuthorPHID(); 272 - $event_phids = $edges->getDestinationPHIDs(array($author_phid)); 273 - $badges = array_select_keys($all_badges, $event_phids); 262 + $author_awards = idx($awards, $event->getAuthorPHID(), array()); 263 + $badges = array(); 264 + foreach ($author_awards as $award) { 265 + $badge = $award->getBadge(); 266 + if ($badge->getStatus() == PhabricatorBadgesBadge::STATUS_ACTIVE) { 267 + $badges[$award->getBadgePHID()] = $badge; 268 + } 269 + } 274 270 275 271 // TODO: Pick the "best" badges in some smart way. For now, just pick 276 272 // the first two. 277 273 $badges = array_slice($badges, 0, 2); 274 + 278 275 foreach ($badges as $badge) { 279 276 $badge_view = id(new PHUIBadgeMiniView()) 280 277 ->setIcon($badge->getIcon())