Path: blob/master/src/view/phui/PHUITimelineView.php
12249 views
<?php12final class PHUITimelineView extends AphrontView {34private $events = array();5private $id;6private $shouldTerminate = false;7private $shouldAddSpacers = true;8private $pager;9private $viewData = array();10private $quoteTargetID;11private $quoteRef;1213public function setID($id) {14$this->id = $id;15return $this;16}1718public function setShouldTerminate($term) {19$this->shouldTerminate = $term;20return $this;21}2223public function setShouldAddSpacers($bool) {24$this->shouldAddSpacers = $bool;25return $this;26}2728public function setPager(AphrontCursorPagerView $pager) {29$this->pager = $pager;30return $this;31}3233public function getPager() {34return $this->pager;35}3637public function addEvent(PHUITimelineEventView $event) {38$this->events[] = $event;39return $this;40}4142public function setViewData(array $data) {43$this->viewData = $data;44return $this;45}4647public function getViewData() {48return $this->viewData;49}5051public function setQuoteTargetID($quote_target_id) {52$this->quoteTargetID = $quote_target_id;53return $this;54}5556public function getQuoteTargetID() {57return $this->quoteTargetID;58}5960public function setQuoteRef($quote_ref) {61$this->quoteRef = $quote_ref;62return $this;63}6465public function getQuoteRef() {66return $this->quoteRef;67}6869public function render() {70if ($this->getPager()) {71if ($this->id === null) {72$this->id = celerity_generate_unique_node_id();73}74Javelin::initBehavior(75'phabricator-show-older-transactions',76array(77'timelineID' => $this->id,78'viewData' => $this->getViewData(),79));80}81$events = $this->buildEvents();8283return phutil_tag(84'div',85array(86'class' => 'phui-timeline-view',87'id' => $this->id,88),89array(90phutil_tag(91'h3',92array(93'class' => 'aural-only',94),95pht('Event Timeline')),96$events,97));98}99100public function buildEvents() {101require_celerity_resource('phui-timeline-view-css');102103$spacer = self::renderSpacer();104105// Track why we're hiding older results.106$hide_reason = null;107108$hide = array();109$show = array();110111// Bucket timeline events into events we'll hide by default (because they112// predate your most recent interaction with the object) and events we'll113// show by default.114foreach ($this->events as $event) {115if ($event->getHideByDefault()) {116$hide[] = $event;117} else {118$show[] = $event;119}120}121122// If you've never interacted with the object, all the events will be shown123// by default. We may still need to paginate if there are a large number124// of events.125$more = (bool)$hide;126127if ($more) {128$hide_reason = 'comment';129}130131if ($this->getPager()) {132if ($this->getPager()->getHasMoreResults()) {133if (!$more) {134$hide_reason = 'limit';135}136$more = true;137}138}139140$events = array();141if ($more && $this->getPager()) {142switch ($hide_reason) {143case 'comment':144$hide_help = pht(145'Changes from before your most recent comment are hidden.');146break;147case 'limit':148default:149$hide_help = pht(150'There are a very large number of changes, so older changes are '.151'hidden.');152break;153}154155$uri = $this->getPager()->getNextPageURI();156157$target_id = $this->getQuoteTargetID();158if ($target_id === null) {159$uri->removeQueryParam('quoteTargetID');160} else {161$uri->replaceQueryParam('quoteTargetID', $target_id);162}163164$quote_ref = $this->getQuoteRef();165if ($quote_ref === null) {166$uri->removeQueryParam('quoteRef');167} else {168$uri->replaceQueryParam('quoteRef', $quote_ref);169}170171$events[] = javelin_tag(172'div',173array(174'sigil' => 'show-older-block',175'class' => 'phui-timeline-older-transactions-are-hidden',176),177array(178$hide_help,179' ',180javelin_tag(181'a',182array(183'href' => (string)$uri,184'mustcapture' => true,185'sigil' => 'show-older-link',186),187pht('Show Older Changes')),188));189190if ($show) {191$events[] = $spacer;192}193}194195if ($show) {196$this->prepareBadgeData($show);197$events[] = phutil_implode_html($spacer, $show);198}199200if ($events) {201if ($this->shouldAddSpacers) {202$events = array($spacer, $events, $spacer);203}204} else {205$events = array($spacer);206}207208if ($this->shouldTerminate) {209$events[] = self::renderEnder();210}211212return $events;213}214215public static function renderSpacer() {216return phutil_tag(217'div',218array(219'class' => 'phui-timeline-event-view '.220'phui-timeline-spacer',221),222'');223}224225public static function renderEnder() {226return phutil_tag(227'div',228array(229'class' => 'phui-timeline-event-view '.230'the-worlds-end',231),232'');233}234235private function prepareBadgeData(array $events) {236assert_instances_of($events, 'PHUITimelineEventView');237238$viewer = $this->getUser();239$can_use_badges = PhabricatorApplication::isClassInstalledForViewer(240'PhabricatorBadgesApplication',241$viewer);242if (!$can_use_badges) {243return;244}245246$user_phid_type = PhabricatorPeopleUserPHIDType::TYPECONST;247248$user_phids = array();249foreach ($events as $key => $event) {250$author_phid = $event->getAuthorPHID();251if (!$author_phid) {252unset($events[$key]);253continue;254}255256if (phid_get_type($author_phid) != $user_phid_type) {257// This is likely an application actor, like "Herald" or "Harbormaster".258// They can't have badges.259unset($events[$key]);260continue;261}262263$user_phids[$author_phid] = $author_phid;264}265266if (!$user_phids) {267return;268}269270$users = id(new PhabricatorPeopleQuery())271->setViewer($viewer)272->withPHIDs($user_phids)273->needBadgeAwards(true)274->execute();275$users = mpull($users, null, 'getPHID');276277foreach ($events as $event) {278$user_phid = $event->getAuthorPHID();279if (!array_key_exists($user_phid, $users)) {280continue;281}282$badges = $users[$user_phid]->getRecentBadgeAwards();283foreach ($badges as $badge) {284$badge_view = id(new PHUIBadgeMiniView())285->setIcon($badge['icon'])286->setQuality($badge['quality'])287->setHeader($badge['name'])288->setTipDirection('E')289->setHref('/badges/view/'.$badge['id'].'/');290$event->addBadge($badge_view);291}292}293}294295}296297298