Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/view/phui/PHUIHeaderView.php
12249 views
1
<?php
2
3
final class PHUIHeaderView extends AphrontTagView {
4
5
const PROPERTY_STATUS = 1;
6
7
private $header;
8
private $tags = array();
9
private $image;
10
private $imageURL = null;
11
private $imageEditURL = null;
12
private $subheader;
13
private $headerIcon;
14
private $noBackground;
15
private $bleedHeader;
16
private $profileHeader;
17
private $tall;
18
private $properties = array();
19
private $actionLinks = array();
20
private $buttonBar = null;
21
private $policyObject;
22
private $epoch;
23
private $actionItems = array();
24
private $href;
25
private $actionList;
26
private $actionListID;
27
28
public function setHeader($header) {
29
$this->header = $header;
30
return $this;
31
}
32
33
public function setNoBackground($nada) {
34
$this->noBackground = $nada;
35
return $this;
36
}
37
38
public function setTall($tall) {
39
$this->tall = $tall;
40
return $this;
41
}
42
43
public function addTag(PHUITagView $tag) {
44
$this->tags[] = $tag;
45
return $this;
46
}
47
48
public function setImage($uri) {
49
$this->image = $uri;
50
return $this;
51
}
52
53
public function setImageURL($url) {
54
$this->imageURL = $url;
55
return $this;
56
}
57
58
public function setImageEditURL($url) {
59
$this->imageEditURL = $url;
60
return $this;
61
}
62
63
public function setSubheader($subheader) {
64
$this->subheader = $subheader;
65
return $this;
66
}
67
68
public function setBleedHeader($bleed) {
69
$this->bleedHeader = $bleed;
70
return $this;
71
}
72
73
public function setProfileHeader($bighead) {
74
$this->profileHeader = $bighead;
75
return $this;
76
}
77
78
public function setHeaderIcon($icon) {
79
$this->headerIcon = $icon;
80
return $this;
81
}
82
83
public function setActionList(PhabricatorActionListView $list) {
84
$this->actionList = $list;
85
return $this;
86
}
87
88
public function setActionListID($action_list_id) {
89
$this->actionListID = $action_list_id;
90
return $this;
91
}
92
93
public function setPolicyObject(PhabricatorPolicyInterface $object) {
94
$this->policyObject = $object;
95
return $this;
96
}
97
98
public function addProperty($property, $value) {
99
$this->properties[$property] = $value;
100
return $this;
101
}
102
103
public function addActionLink(PHUIButtonView $button) {
104
$this->actionLinks[] = $button;
105
return $this;
106
}
107
108
public function addActionItem($action) {
109
$this->actionItems[] = $action;
110
return $this;
111
}
112
113
public function setButtonBar(PHUIButtonBarView $bb) {
114
$this->buttonBar = $bb;
115
return $this;
116
}
117
118
public function setStatus($icon, $color, $name) {
119
120
// TODO: Normalize "closed/archived" to constants.
121
if ($color == 'dark') {
122
$color = PHUITagView::COLOR_INDIGO;
123
}
124
125
$tag = id(new PHUITagView())
126
->setName($name)
127
->setIcon($icon)
128
->setColor($color)
129
->setType(PHUITagView::TYPE_SHADE);
130
131
return $this->addProperty(self::PROPERTY_STATUS, $tag);
132
}
133
134
public function setEpoch($epoch) {
135
$age = time() - $epoch;
136
$age = floor($age / (60 * 60 * 24));
137
if ($age < 1) {
138
$when = pht('Today');
139
} else if ($age == 1) {
140
$when = pht('Yesterday');
141
} else {
142
$when = pht('%s Day(s) Ago', new PhutilNumber($age));
143
}
144
145
$this->setStatus('fa-clock-o bluegrey', null, pht('Updated %s', $when));
146
return $this;
147
}
148
149
public function setHref($href) {
150
$this->href = $href;
151
return $this;
152
}
153
154
public function getHref() {
155
return $this->href;
156
}
157
158
protected function getTagName() {
159
return 'div';
160
}
161
162
protected function getTagAttributes() {
163
require_celerity_resource('phui-header-view-css');
164
165
$classes = array();
166
$classes[] = 'phui-header-shell';
167
168
if ($this->noBackground) {
169
$classes[] = 'phui-header-no-background';
170
}
171
172
if ($this->bleedHeader) {
173
$classes[] = 'phui-bleed-header';
174
}
175
176
if ($this->profileHeader) {
177
$classes[] = 'phui-profile-header';
178
}
179
180
if ($this->properties || $this->policyObject ||
181
$this->subheader || $this->tall) {
182
$classes[] = 'phui-header-tall';
183
}
184
185
return array(
186
'class' => $classes,
187
);
188
}
189
190
protected function getTagContent() {
191
192
if ($this->actionList || $this->actionListID) {
193
$action_button = id(new PHUIButtonView())
194
->setTag('a')
195
->setText(pht('Actions'))
196
->setHref('#')
197
->setIcon('fa-bars')
198
->addClass('phui-mobile-menu');
199
200
if ($this->actionList) {
201
$action_button->setDropdownMenu($this->actionList);
202
} else if ($this->actionListID) {
203
$action_button->setDropdownMenuID($this->actionListID);
204
}
205
206
$this->addActionLink($action_button);
207
}
208
209
$image = null;
210
if ($this->image) {
211
$image_href = null;
212
if ($this->imageURL) {
213
$image_href = $this->imageURL;
214
} else if ($this->imageEditURL) {
215
$image_href = $this->imageEditURL;
216
}
217
218
$image = phutil_tag(
219
'span',
220
array(
221
'class' => 'phui-header-image',
222
'style' => 'background-image: url('.$this->image.')',
223
));
224
225
if ($image_href) {
226
$edit_view = null;
227
if ($this->imageEditURL) {
228
$edit_view = phutil_tag(
229
'span',
230
array(
231
'class' => 'phui-header-image-edit',
232
),
233
pht('Edit'));
234
}
235
236
$image = phutil_tag(
237
'a',
238
array(
239
'href' => $image_href,
240
'class' => 'phui-header-image-href',
241
),
242
array(
243
$image,
244
$edit_view,
245
));
246
}
247
}
248
249
$viewer = $this->getUser();
250
251
$left = array();
252
$right = array();
253
254
$space_header = null;
255
if ($viewer) {
256
$space_header = id(new PHUISpacesNamespaceContextView())
257
->setUser($viewer)
258
->setObject($this->policyObject);
259
}
260
261
if ($this->actionLinks) {
262
$actions = array();
263
foreach ($this->actionLinks as $button) {
264
if (!$button->getColor()) {
265
$button->setColor(PHUIButtonView::GREY);
266
}
267
$button->addClass(PHUI::MARGIN_SMALL_LEFT);
268
$button->addClass('phui-header-action-link');
269
$actions[] = $button;
270
}
271
$right[] = phutil_tag(
272
'div',
273
array(
274
'class' => 'phui-header-action-links',
275
),
276
$actions);
277
}
278
279
if ($this->buttonBar) {
280
$right[] = phutil_tag(
281
'div',
282
array(
283
'class' => 'phui-header-action-links',
284
),
285
$this->buttonBar);
286
}
287
288
if ($this->actionItems) {
289
$action_list = array();
290
if ($this->actionItems) {
291
foreach ($this->actionItems as $item) {
292
$action_list[] = phutil_tag(
293
'li',
294
array(
295
'class' => 'phui-header-action-item',
296
),
297
$item);
298
}
299
}
300
$right[] = phutil_tag(
301
'ul',
302
array(
303
'class' => 'phui-header-action-list',
304
),
305
$action_list);
306
}
307
308
$icon = null;
309
if ($this->headerIcon) {
310
if ($this->headerIcon instanceof PHUIIconView) {
311
$icon = id(clone $this->headerIcon)
312
->addClass('phui-header-icon');
313
} else {
314
$icon = id(new PHUIIconView())
315
->setIcon($this->headerIcon)
316
->addClass('phui-header-icon');
317
}
318
}
319
320
$header_content = $this->header;
321
322
$href = $this->getHref();
323
if ($href !== null) {
324
$header_content = phutil_tag(
325
'a',
326
array(
327
'href' => $href,
328
),
329
$header_content);
330
}
331
332
$left[] = phutil_tag(
333
'span',
334
array(
335
'class' => 'phui-header-header',
336
),
337
array(
338
$space_header,
339
$icon,
340
$header_content,
341
));
342
343
if ($this->subheader) {
344
$left[] = phutil_tag(
345
'div',
346
array(
347
'class' => 'phui-header-subheader',
348
),
349
array(
350
$this->subheader,
351
));
352
}
353
354
if ($this->properties || $this->policyObject || $this->tags) {
355
$property_list = array();
356
foreach ($this->properties as $type => $property) {
357
switch ($type) {
358
case self::PROPERTY_STATUS:
359
$property_list[] = $property;
360
break;
361
default:
362
throw new Exception(pht('Incorrect Property Passed'));
363
break;
364
}
365
}
366
367
if ($this->policyObject) {
368
$property_list[] = $this->renderPolicyProperty($this->policyObject);
369
}
370
371
if ($this->tags) {
372
$property_list[] = $this->tags;
373
}
374
375
$left[] = phutil_tag(
376
'div',
377
array(
378
'class' => 'phui-header-subheader',
379
),
380
$property_list);
381
}
382
383
// We here at @phabricator
384
$header_image = null;
385
if ($image) {
386
$header_image = phutil_tag(
387
'div',
388
array(
389
'class' => 'phui-header-col1',
390
),
391
$image);
392
}
393
394
// All really love
395
$header_left = phutil_tag(
396
'div',
397
array(
398
'class' => 'phui-header-col2',
399
),
400
$left);
401
402
// Tables and Pokemon.
403
$header_right = phutil_tag(
404
'div',
405
array(
406
'class' => 'phui-header-col3',
407
),
408
$right);
409
410
$header_row = phutil_tag(
411
'div',
412
array(
413
'class' => 'phui-header-row',
414
),
415
array(
416
$header_image,
417
$header_left,
418
$header_right,
419
));
420
421
return phutil_tag(
422
'h1',
423
array(
424
'class' => 'phui-header-view',
425
),
426
$header_row);
427
}
428
429
private function renderPolicyProperty(PhabricatorPolicyInterface $object) {
430
$viewer = $this->getUser();
431
432
$policies = PhabricatorPolicyQuery::loadPolicies($viewer, $object);
433
434
$view_capability = PhabricatorPolicyCapability::CAN_VIEW;
435
$policy = idx($policies, $view_capability);
436
if (!$policy) {
437
return null;
438
}
439
440
// If an object is in a Space with a strictly stronger (more restrictive)
441
// policy, we show the more restrictive policy. This better aligns the
442
// UI hint with the actual behavior.
443
444
// NOTE: We'll do this even if the viewer has access to only one space, and
445
// show them information about the existence of spaces if they click
446
// through.
447
$use_space_policy = false;
448
if ($object instanceof PhabricatorSpacesInterface) {
449
$space_phid = PhabricatorSpacesNamespaceQuery::getObjectSpacePHID(
450
$object);
451
452
$spaces = PhabricatorSpacesNamespaceQuery::getViewerSpaces($viewer);
453
$space = idx($spaces, $space_phid);
454
if ($space) {
455
$space_policies = PhabricatorPolicyQuery::loadPolicies(
456
$viewer,
457
$space);
458
$space_policy = idx($space_policies, $view_capability);
459
if ($space_policy) {
460
if ($space_policy->isStrongerThan($policy)) {
461
$policy = $space_policy;
462
$use_space_policy = true;
463
}
464
}
465
}
466
}
467
468
$container_classes = array();
469
$container_classes[] = 'policy-header-callout';
470
$phid = $object->getPHID();
471
472
$policy_name = array($policy->getShortName());
473
$policy_icon = $policy->getIcon().' bluegrey';
474
475
if ($object instanceof PhabricatorPolicyCodexInterface) {
476
$codex = PhabricatorPolicyCodex::newFromObject($object, $viewer);
477
478
$codex_name = $codex->getPolicyShortName($policy, $view_capability);
479
if ($codex_name !== null) {
480
$policy_name = $codex_name;
481
}
482
483
$codex_icon = $codex->getPolicyIcon($policy, $view_capability);
484
if ($codex_icon !== null) {
485
$policy_icon = $codex_icon;
486
}
487
488
$codex_classes = $codex->getPolicyTagClasses($policy, $view_capability);
489
foreach ($codex_classes as $codex_class) {
490
$container_classes[] = $codex_class;
491
}
492
}
493
494
if (!is_array($policy_name)) {
495
$policy_name = (array)$policy_name;
496
}
497
498
$arrow = id(new PHUIIconView())
499
->setIcon('fa-angle-right')
500
->addClass('policy-tier-separator');
501
502
$policy_name = phutil_implode_html($arrow, $policy_name);
503
504
$icon = id(new PHUIIconView())
505
->setIcon($policy_icon);
506
507
$link = javelin_tag(
508
'a',
509
array(
510
'class' => 'policy-link',
511
'href' => '/policy/explain/'.$phid.'/'.$view_capability.'/',
512
'sigil' => 'workflow',
513
),
514
$policy_name);
515
516
return phutil_tag(
517
'span',
518
array(
519
'class' => implode(' ', $container_classes),
520
),
521
array($icon, $link));
522
}
523
524
}
525
526