1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-10 08:52:39 +01:00

Add Badges to UserCache

Summary: Ref T12270. Builds out a BadgeCache for PhabricatorUser, primarily for Timeline, potentially feed? This should still work if we later let people pick which two, just switch query in BadgeCache.

Test Plan: Give out badges, test timeline for displaying badges from handles and without queries. Revoke a badge, see cache change.

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: Korvin

Maniphest Tasks: T12270

Differential Revision: https://secure.phabricator.com/D17503
This commit is contained in:
Chad Little 2017-03-17 10:32:07 -07:00
parent 65de9e9f5e
commit aef2a39a81
7 changed files with 141 additions and 37 deletions

View file

@ -4067,6 +4067,7 @@ phutil_register_library_map(array(
'PhabricatorUnknownContentSource' => 'infrastructure/contentsource/PhabricatorUnknownContentSource.php', 'PhabricatorUnknownContentSource' => 'infrastructure/contentsource/PhabricatorUnknownContentSource.php',
'PhabricatorUnsubscribedFromObjectEdgeType' => 'applications/transactions/edges/PhabricatorUnsubscribedFromObjectEdgeType.php', 'PhabricatorUnsubscribedFromObjectEdgeType' => 'applications/transactions/edges/PhabricatorUnsubscribedFromObjectEdgeType.php',
'PhabricatorUser' => 'applications/people/storage/PhabricatorUser.php', 'PhabricatorUser' => 'applications/people/storage/PhabricatorUser.php',
'PhabricatorUserBadgesCacheType' => 'applications/people/cache/PhabricatorUserBadgesCacheType.php',
'PhabricatorUserBlurbField' => 'applications/people/customfield/PhabricatorUserBlurbField.php', 'PhabricatorUserBlurbField' => 'applications/people/customfield/PhabricatorUserBlurbField.php',
'PhabricatorUserCache' => 'applications/people/storage/PhabricatorUserCache.php', 'PhabricatorUserCache' => 'applications/people/storage/PhabricatorUserCache.php',
'PhabricatorUserCacheType' => 'applications/people/cache/PhabricatorUserCacheType.php', 'PhabricatorUserCacheType' => 'applications/people/cache/PhabricatorUserCacheType.php',
@ -9415,6 +9416,7 @@ phutil_register_library_map(array(
'PhabricatorFulltextInterface', 'PhabricatorFulltextInterface',
'PhabricatorConduitResultInterface', 'PhabricatorConduitResultInterface',
), ),
'PhabricatorUserBadgesCacheType' => 'PhabricatorUserCacheType',
'PhabricatorUserBlurbField' => 'PhabricatorUserCustomField', 'PhabricatorUserBlurbField' => 'PhabricatorUserCustomField',
'PhabricatorUserCache' => 'PhabricatorUserDAO', 'PhabricatorUserCache' => 'PhabricatorUserDAO',
'PhabricatorUserCacheType' => 'Phobject', 'PhabricatorUserCacheType' => 'Phobject',

View file

@ -118,4 +118,45 @@ final class PhabricatorBadgesEditor
return pht('[Badge]'); return pht('[Badge]');
} }
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
$badge_phid = $object->getPHID();
$user_phids = array();
$clear_everything = false;
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorBadgesBadgeAwardTransaction::TRANSACTIONTYPE:
case PhabricatorBadgesBadgeRevokeTransaction::TRANSACTIONTYPE:
foreach ($xaction->getNewValue() as $user_phid) {
$user_phids[] = $user_phid;
}
break;
default:
$clear_everything = true;
break;
}
}
if ($clear_everything) {
$awards = id(new PhabricatorBadgesAwardQuery())
->setViewer($this->getActor())
->withBadgePHIDs(array($badge_phid))
->execute();
foreach ($awards as $award) {
$user_phids[] = $award->getRecipientPHID();
}
}
if ($user_phids) {
PhabricatorUserCache::clearCaches(
PhabricatorUserBadgesCacheType::KEY_BADGES,
$user_phids);
}
return $xactions;
}
} }

View file

@ -0,0 +1,61 @@
<?php
final class PhabricatorUserBadgesCacheType
extends PhabricatorUserCacheType {
const CACHETYPE = 'badges.award';
const KEY_BADGES = 'user.badge.award.v1';
const BADGE_COUNT = 2;
public function getAutoloadKeys() {
return array(
self::KEY_BADGES,
);
}
public function canManageKey($key) {
return ($key === self::KEY_BADGES);
}
public function getValueFromStorage($value) {
return phutil_json_decode($value);
}
public function newValueForUsers($key, array $users) {
if (!$users) {
return array();
}
$user_phids = mpull($users, 'getPHID');
$results = array();
foreach ($user_phids as $user_phid) {
$awards = id(new PhabricatorBadgesAwardQuery())
->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] = phutil_json_encode($award_data);
}
return $results;
}
}

View file

@ -24,6 +24,7 @@ final class PhabricatorPeopleQuery
private $needProfile; private $needProfile;
private $needProfileImage; private $needProfileImage;
private $needAvailability; private $needAvailability;
private $needBadgeAwards;
private $cacheKeys = array(); private $cacheKeys = array();
public function withIDs(array $ids) { public function withIDs(array $ids) {
@ -145,6 +146,18 @@ final class PhabricatorPeopleQuery
return $this; 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() { public function newResultObject() {
return new PhabricatorUser(); return new PhabricatorUser();
} }

View file

@ -848,6 +848,11 @@ final class PhabricatorUser
return $this->requireCacheData($message_key); return $this->requireCacheData($message_key);
} }
public function getRecentBadgeAwards() {
$badges_key = PhabricatorUserBadgesCacheType::KEY_BADGES;
return $this->requireCacheData($badges_key);
}
public function getFullName() { public function getFullName() {
if (strlen($this->getRealName())) { if (strlen($this->getRealName())) {
return $this->getUsername().' ('.$this->getRealName().')'; return $this->getUsername().' ('.$this->getRealName().')';

View file

@ -525,25 +525,18 @@ class PhabricatorApplicationTransactionCommentView extends AphrontView {
return null; return null;
} }
$awards = id(new PhabricatorBadgesAwardQuery()) // Pull Badges from UserCache
->setViewer($this->getUser()) $badges = $user->getRecentBadgeAwards();
->withRecipientPHIDs(array($user->getPHID()))
->withBadgeStatuses(array(PhabricatorBadgesBadge::STATUS_ACTIVE))
->setLimit(2)
->execute();
$badges = mpull($awards, 'getBadge');
$badge_view = null; $badge_view = null;
if ($badges) { if ($badges) {
$badge_list = array(); $badge_list = array();
foreach ($badges as $badge) { foreach ($badges as $badge) {
$badge_view = id(new PHUIBadgeMiniView()) $badge_view = id(new PHUIBadgeMiniView())
->setIcon($badge->getIcon()) ->setIcon($badge['icon'])
->setQuality($badge->getQuality()) ->setQuality($badge['quality'])
->setHeader($badge->getName()) ->setHeader($badge['name'])
->setTipDirection('E') ->setTipDirection('E')
->setHref('/badges/view/'.$badge->getID()); ->setHref('/badges/view/'.$badge['id'].'/');
$badge_list[] = $badge_view; $badge_list[] = $badge_view;
} }

View file

@ -243,37 +243,26 @@ final class PHUITimelineView extends AphrontView {
return; return;
} }
$users = id(new PhabricatorPeopleQuery())
$awards = id(new PhabricatorBadgesAwardQuery()) ->setViewer($viewer)
->setViewer($this->getViewer()) ->withPHIDs($user_phids)
->withRecipientPHIDs($user_phids) ->needBadgeAwards(true)
->withBadgeStatuses(array(PhabricatorBadgesBadge::STATUS_ACTIVE))
->execute(); ->execute();
$users = mpull($users, null, 'getPHID');
$awards = mgroup($awards, 'getRecipientPHID');
foreach ($events as $event) { foreach ($events as $event) {
$user_phid = $event->getAuthorPHID();
$author_awards = idx($awards, $event->getAuthorPHID(), array()); if (!array_key_exists($user_phid, $users)) {
continue;
$badges = array();
foreach ($author_awards as $award) {
$badge = $award->getBadge();
$badges[$award->getBadgePHID()] = $badge;
} }
$badges = $users[$user_phid]->getRecentBadgeAwards();
// 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) { foreach ($badges as $badge) {
$badge_view = id(new PHUIBadgeMiniView()) $badge_view = id(new PHUIBadgeMiniView())
->setIcon($badge->getIcon()) ->setIcon($badge['icon'])
->setQuality($badge->getQuality()) ->setQuality($badge['quality'])
->setHeader($badge->getName()) ->setHeader($badge['name'])
->setTipDirection('E') ->setTipDirection('E')
->setHref('/badges/view/'.$badge->getID()); ->setHref('/badges/view/'.$badge['id'].'/');
$event->addBadge($badge_view); $event->addBadge($badge_view);
} }
} }