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 @@ -4066,6 +4066,7 @@ 'PhabricatorUnknownContentSource' => 'infrastructure/contentsource/PhabricatorUnknownContentSource.php', 'PhabricatorUnsubscribedFromObjectEdgeType' => 'applications/transactions/edges/PhabricatorUnsubscribedFromObjectEdgeType.php', 'PhabricatorUser' => 'applications/people/storage/PhabricatorUser.php', + 'PhabricatorUserBadgesCacheType' => 'applications/people/cache/PhabricatorUserBadgesCacheType.php', 'PhabricatorUserBlurbField' => 'applications/people/customfield/PhabricatorUserBlurbField.php', 'PhabricatorUserCache' => 'applications/people/storage/PhabricatorUserCache.php', 'PhabricatorUserCacheType' => 'applications/people/cache/PhabricatorUserCacheType.php', @@ -9413,6 +9414,7 @@ 'PhabricatorFulltextInterface', 'PhabricatorConduitResultInterface', ), + 'PhabricatorUserBadgesCacheType' => 'PhabricatorUserCacheType', 'PhabricatorUserBlurbField' => 'PhabricatorUserCustomField', 'PhabricatorUserCache' => 'PhabricatorUserDAO', 'PhabricatorUserCacheType' => 'Phobject', diff --git a/src/applications/people/cache/PhabricatorUserBadgesCacheType.php b/src/applications/people/cache/PhabricatorUserBadgesCacheType.php new file mode 100644 --- /dev/null +++ b/src/applications/people/cache/PhabricatorUserBadgesCacheType.php @@ -0,0 +1,61 @@ +setViewer($this->getViewer()) + ->withRecipientPHIDs(array($user_phid)) + ->withBadgeStatuses(array(PhabricatorBadgesBadge::STATUS_ACTIVE)) + ->setLimit(self::BADGE_COUNT) + ->execute(); + + $award_data = array(); + if ($awards) { + foreach ($awards as $award) { + $badge = $award->getBadge(); + $award_data[] = array( + 'icon' => $badge->getIcon(), + 'name' => $badge->getName(), + 'quality' => $badge->getQuality(), + 'id' => $badge->getID(), + ); + } + } + $results[$user_phid] = json_encode($award_data); + + } + + return $results; + } + +} diff --git a/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php b/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php --- a/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php +++ b/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php @@ -28,7 +28,8 @@ ->withPHIDs($phids) ->needProfile(true) ->needProfileImage(true) - ->needAvailability(true); + ->needAvailability(true) + ->needBadgeAwards(true); } public function loadHandles( @@ -44,6 +45,7 @@ $handle->setURI('/p/'.$user->getUsername().'/'); $handle->setFullName($user->getFullName()); $handle->setImageURI($user->getProfileImageURI()); + $handle->setBadges($user->getRecentBadgeAwards()); if ($user->getIsMailingList()) { $handle->setIcon('fa-envelope-o'); diff --git a/src/applications/people/query/PhabricatorPeopleQuery.php b/src/applications/people/query/PhabricatorPeopleQuery.php --- a/src/applications/people/query/PhabricatorPeopleQuery.php +++ b/src/applications/people/query/PhabricatorPeopleQuery.php @@ -23,6 +23,7 @@ private $needProfile; private $needProfileImage; private $needAvailability; + private $needBadgeAwards; private $cacheKeys = array(); public function withIDs(array $ids) { @@ -139,6 +140,18 @@ return $this; } + public function needBadgeAwards($need) { + $cache_key = PhabricatorUserBadgesCacheType::KEY_BADGES; + + if ($need) { + $this->cacheKeys[$cache_key] = true; + } else { + unset($this->cacheKeys[$cache_key]); + } + + return $this; + } + public function newResultObject() { return new PhabricatorUser(); } diff --git a/src/applications/people/storage/PhabricatorUser.php b/src/applications/people/storage/PhabricatorUser.php --- a/src/applications/people/storage/PhabricatorUser.php +++ b/src/applications/people/storage/PhabricatorUser.php @@ -848,6 +848,11 @@ return $this->requireCacheData($message_key); } + public function getRecentBadgeAwards() { + $badges_key = PhabricatorUserBadgesCacheType::KEY_BADGES; + return $this->requireCacheData($badges_key); + } + public function getFullName() { if (strlen($this->getRealName())) { return $this->getUsername().' ('.$this->getRealName().')'; diff --git a/src/applications/phid/PhabricatorObjectHandle.php b/src/applications/phid/PhabricatorObjectHandle.php --- a/src/applications/phid/PhabricatorObjectHandle.php +++ b/src/applications/phid/PhabricatorObjectHandle.php @@ -24,6 +24,7 @@ private $timestamp; private $status = self::STATUS_OPEN; private $availability = self::AVAILABILITY_FULL; + private $badges; private $complete; private $objectName; private $policyFiltered; @@ -176,6 +177,15 @@ return $this->availability; } + public function setBadges($badges) { + $this->badges = $badges; + return $this; + } + + public function getBadges() { + return $this->badges; + } + public function isDisabled() { return ($this->getAvailability() == self::AVAILABILITY_DISABLED); } diff --git a/src/applications/transactions/view/PhabricatorApplicationTransactionCommentView.php b/src/applications/transactions/view/PhabricatorApplicationTransactionCommentView.php --- a/src/applications/transactions/view/PhabricatorApplicationTransactionCommentView.php +++ b/src/applications/transactions/view/PhabricatorApplicationTransactionCommentView.php @@ -525,25 +525,19 @@ return null; } - $awards = id(new PhabricatorBadgesAwardQuery()) - ->setViewer($this->getUser()) - ->withRecipientPHIDs(array($user->getPHID())) - ->withBadgeStatuses(array(PhabricatorBadgesBadge::STATUS_ACTIVE)) - ->setLimit(2) - ->execute(); - - $badges = mpull($awards, 'getBadge'); - + // Pull Badges from UserCache + $badges = $user->getRecentBadgeAwards(); $badge_view = null; if ($badges) { + $badges = array_slice($badges, 0, 2); $badge_list = array(); foreach ($badges as $badge) { $badge_view = id(new PHUIBadgeMiniView()) - ->setIcon($badge->getIcon()) - ->setQuality($badge->getQuality()) - ->setHeader($badge->getName()) + ->setIcon($badge['icon']) + ->setQuality($badge['quality']) + ->setHeader($badge['name']) ->setTipDirection('E') - ->setHref('/badges/view/'.$badge->getID()); + ->setHref('/badges/view/'.$badge['id'].'/'); $badge_list[] = $badge_view; } diff --git a/src/view/phui/PHUITimelineEventView.php b/src/view/phui/PHUITimelineEventView.php --- a/src/view/phui/PHUITimelineEventView.php +++ b/src/view/phui/PHUITimelineEventView.php @@ -27,7 +27,7 @@ private $reallyMajorEvent; private $hideCommentOptions = false; private $authorPHID; - private $badges = array(); + private $showBadges; public function setAuthorPHID($author_phid) { $this->authorPHID = $author_phid; @@ -161,8 +161,8 @@ return $this; } - public function addBadge(PHUIBadgeMiniView $badge) { - $this->badges[] = $badge; + public function setShowBadges($badge) { + $this->showBadges = $badge; return $this; } @@ -394,17 +394,33 @@ 'href' => $this->userHandle->getURI(), ), ''); - if ($this->badges && $show_badges) { - $flex = new PHUIBadgeBoxView(); - $flex->addItems($this->badges); - $flex->setCollapsed(true); - $badges = phutil_tag( - 'div', - array( - 'class' => 'phui-timeline-badges', - ), - $flex); + } + + // Pull Badges from UserCache + $badges = $this->userHandle->getBadges(); + $badge_view = null; + if ($badges && $show_badges) { + $badges = array_slice($badges, 0, 2); + $badge_list = array(); + foreach ($badges as $badge) { + $badge_view = id(new PHUIBadgeMiniView()) + ->setIcon($badge['icon']) + ->setQuality($badge['quality']) + ->setHeader($badge['name']) + ->setTipDirection('E') + ->setHref('/badges/view/'.$badge['id'].'/'); + + $badge_list[] = $badge_view; } + $flex = new PHUIBadgeBoxView(); + $flex->addItems($badge_list); + $flex->setCollapsed(true); + $badge_view = phutil_tag( + 'div', + array( + 'class' => 'phui-timeline-badges', + ), + $flex); } $content_classes = array(); @@ -446,7 +462,7 @@ array( 'class' => implode(' ', $content_classes), ), - array($image, $badges, $wedge, $content)); + array($image, $badge_view, $wedge, $content)); $outer_classes = $this->classes; $outer_classes[] = 'phui-timeline-shell'; diff --git a/src/view/phui/PHUITimelineView.php b/src/view/phui/PHUITimelineView.php --- a/src/view/phui/PHUITimelineView.php +++ b/src/view/phui/PHUITimelineView.php @@ -218,64 +218,8 @@ if (!$can_use_badges) { return; } - - $user_phid_type = PhabricatorPeopleUserPHIDType::TYPECONST; - - $user_phids = array(); - foreach ($events as $key => $event) { - $author_phid = $event->getAuthorPHID(); - if (!$author_phid) { - unset($events[$key]); - continue; - } - - if (phid_get_type($author_phid) != $user_phid_type) { - // This is likely an application actor, like "Herald" or "Harbormaster". - // They can't have badges. - unset($events[$key]); - continue; - } - - $user_phids[$author_phid] = $author_phid; - } - - if (!$user_phids) { - return; - } - - - $awards = id(new PhabricatorBadgesAwardQuery()) - ->setViewer($this->getViewer()) - ->withRecipientPHIDs($user_phids) - ->withBadgeStatuses(array(PhabricatorBadgesBadge::STATUS_ACTIVE)) - ->execute(); - - $awards = mgroup($awards, 'getRecipientPHID'); - foreach ($events as $event) { - - $author_awards = idx($awards, $event->getAuthorPHID(), array()); - - $badges = array(); - foreach ($author_awards as $award) { - $badge = $award->getBadge(); - $badges[$award->getBadgePHID()] = $badge; - } - - // TODO: Pick the "best" badges in some smart way. For now, just pick - // the first two. - $badges = array_slice($badges, 0, 2); - - foreach ($badges as $badge) { - $badge_view = id(new PHUIBadgeMiniView()) - ->setIcon($badge->getIcon()) - ->setQuality($badge->getQuality()) - ->setHeader($badge->getName()) - ->setTipDirection('E') - ->setHref('/badges/view/'.$badge->getID()); - - $event->addBadge($badge_view); - } + $event->setShowBadges(true); } }