Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/view/phui/PHUITimelineView.php
12249 views
1
<?php
2
3
final class PHUITimelineView extends AphrontView {
4
5
private $events = array();
6
private $id;
7
private $shouldTerminate = false;
8
private $shouldAddSpacers = true;
9
private $pager;
10
private $viewData = array();
11
private $quoteTargetID;
12
private $quoteRef;
13
14
public function setID($id) {
15
$this->id = $id;
16
return $this;
17
}
18
19
public function setShouldTerminate($term) {
20
$this->shouldTerminate = $term;
21
return $this;
22
}
23
24
public function setShouldAddSpacers($bool) {
25
$this->shouldAddSpacers = $bool;
26
return $this;
27
}
28
29
public function setPager(AphrontCursorPagerView $pager) {
30
$this->pager = $pager;
31
return $this;
32
}
33
34
public function getPager() {
35
return $this->pager;
36
}
37
38
public function addEvent(PHUITimelineEventView $event) {
39
$this->events[] = $event;
40
return $this;
41
}
42
43
public function setViewData(array $data) {
44
$this->viewData = $data;
45
return $this;
46
}
47
48
public function getViewData() {
49
return $this->viewData;
50
}
51
52
public function setQuoteTargetID($quote_target_id) {
53
$this->quoteTargetID = $quote_target_id;
54
return $this;
55
}
56
57
public function getQuoteTargetID() {
58
return $this->quoteTargetID;
59
}
60
61
public function setQuoteRef($quote_ref) {
62
$this->quoteRef = $quote_ref;
63
return $this;
64
}
65
66
public function getQuoteRef() {
67
return $this->quoteRef;
68
}
69
70
public function render() {
71
if ($this->getPager()) {
72
if ($this->id === null) {
73
$this->id = celerity_generate_unique_node_id();
74
}
75
Javelin::initBehavior(
76
'phabricator-show-older-transactions',
77
array(
78
'timelineID' => $this->id,
79
'viewData' => $this->getViewData(),
80
));
81
}
82
$events = $this->buildEvents();
83
84
return phutil_tag(
85
'div',
86
array(
87
'class' => 'phui-timeline-view',
88
'id' => $this->id,
89
),
90
array(
91
phutil_tag(
92
'h3',
93
array(
94
'class' => 'aural-only',
95
),
96
pht('Event Timeline')),
97
$events,
98
));
99
}
100
101
public function buildEvents() {
102
require_celerity_resource('phui-timeline-view-css');
103
104
$spacer = self::renderSpacer();
105
106
// Track why we're hiding older results.
107
$hide_reason = null;
108
109
$hide = array();
110
$show = array();
111
112
// Bucket timeline events into events we'll hide by default (because they
113
// predate your most recent interaction with the object) and events we'll
114
// show by default.
115
foreach ($this->events as $event) {
116
if ($event->getHideByDefault()) {
117
$hide[] = $event;
118
} else {
119
$show[] = $event;
120
}
121
}
122
123
// If you've never interacted with the object, all the events will be shown
124
// by default. We may still need to paginate if there are a large number
125
// of events.
126
$more = (bool)$hide;
127
128
if ($more) {
129
$hide_reason = 'comment';
130
}
131
132
if ($this->getPager()) {
133
if ($this->getPager()->getHasMoreResults()) {
134
if (!$more) {
135
$hide_reason = 'limit';
136
}
137
$more = true;
138
}
139
}
140
141
$events = array();
142
if ($more && $this->getPager()) {
143
switch ($hide_reason) {
144
case 'comment':
145
$hide_help = pht(
146
'Changes from before your most recent comment are hidden.');
147
break;
148
case 'limit':
149
default:
150
$hide_help = pht(
151
'There are a very large number of changes, so older changes are '.
152
'hidden.');
153
break;
154
}
155
156
$uri = $this->getPager()->getNextPageURI();
157
158
$target_id = $this->getQuoteTargetID();
159
if ($target_id === null) {
160
$uri->removeQueryParam('quoteTargetID');
161
} else {
162
$uri->replaceQueryParam('quoteTargetID', $target_id);
163
}
164
165
$quote_ref = $this->getQuoteRef();
166
if ($quote_ref === null) {
167
$uri->removeQueryParam('quoteRef');
168
} else {
169
$uri->replaceQueryParam('quoteRef', $quote_ref);
170
}
171
172
$events[] = javelin_tag(
173
'div',
174
array(
175
'sigil' => 'show-older-block',
176
'class' => 'phui-timeline-older-transactions-are-hidden',
177
),
178
array(
179
$hide_help,
180
' ',
181
javelin_tag(
182
'a',
183
array(
184
'href' => (string)$uri,
185
'mustcapture' => true,
186
'sigil' => 'show-older-link',
187
),
188
pht('Show Older Changes')),
189
));
190
191
if ($show) {
192
$events[] = $spacer;
193
}
194
}
195
196
if ($show) {
197
$this->prepareBadgeData($show);
198
$events[] = phutil_implode_html($spacer, $show);
199
}
200
201
if ($events) {
202
if ($this->shouldAddSpacers) {
203
$events = array($spacer, $events, $spacer);
204
}
205
} else {
206
$events = array($spacer);
207
}
208
209
if ($this->shouldTerminate) {
210
$events[] = self::renderEnder();
211
}
212
213
return $events;
214
}
215
216
public static function renderSpacer() {
217
return phutil_tag(
218
'div',
219
array(
220
'class' => 'phui-timeline-event-view '.
221
'phui-timeline-spacer',
222
),
223
'');
224
}
225
226
public static function renderEnder() {
227
return phutil_tag(
228
'div',
229
array(
230
'class' => 'phui-timeline-event-view '.
231
'the-worlds-end',
232
),
233
'');
234
}
235
236
private function prepareBadgeData(array $events) {
237
assert_instances_of($events, 'PHUITimelineEventView');
238
239
$viewer = $this->getUser();
240
$can_use_badges = PhabricatorApplication::isClassInstalledForViewer(
241
'PhabricatorBadgesApplication',
242
$viewer);
243
if (!$can_use_badges) {
244
return;
245
}
246
247
$user_phid_type = PhabricatorPeopleUserPHIDType::TYPECONST;
248
249
$user_phids = array();
250
foreach ($events as $key => $event) {
251
$author_phid = $event->getAuthorPHID();
252
if (!$author_phid) {
253
unset($events[$key]);
254
continue;
255
}
256
257
if (phid_get_type($author_phid) != $user_phid_type) {
258
// This is likely an application actor, like "Herald" or "Harbormaster".
259
// They can't have badges.
260
unset($events[$key]);
261
continue;
262
}
263
264
$user_phids[$author_phid] = $author_phid;
265
}
266
267
if (!$user_phids) {
268
return;
269
}
270
271
$users = id(new PhabricatorPeopleQuery())
272
->setViewer($viewer)
273
->withPHIDs($user_phids)
274
->needBadgeAwards(true)
275
->execute();
276
$users = mpull($users, null, 'getPHID');
277
278
foreach ($events as $event) {
279
$user_phid = $event->getAuthorPHID();
280
if (!array_key_exists($user_phid, $users)) {
281
continue;
282
}
283
$badges = $users[$user_phid]->getRecentBadgeAwards();
284
foreach ($badges as $badge) {
285
$badge_view = id(new PHUIBadgeMiniView())
286
->setIcon($badge['icon'])
287
->setQuality($badge['quality'])
288
->setHeader($badge['name'])
289
->setTipDirection('E')
290
->setHref('/badges/view/'.$badge['id'].'/');
291
$event->addBadge($badge_view);
292
}
293
}
294
}
295
296
}
297
298