Remove product literal strings in "pht()", part 18
[phabricator.git] / src / applications / diffusion / view / DiffusionCommitGraphView.php
blob30c252712c7890692cf36bee4b3c81ac871ddcdd
1 <?php
3 final class DiffusionCommitGraphView
4 extends DiffusionView {
6 private $history;
7 private $commits;
8 private $isHead;
9 private $isTail;
10 private $parents;
11 private $filterParents;
13 private $commitMap;
14 private $buildableMap;
15 private $revisionMap;
17 private $showAuditors;
19 public function setHistory(array $history) {
20 assert_instances_of($history, 'DiffusionPathChange');
21 $this->history = $history;
22 return $this;
25 public function getHistory() {
26 return $this->history;
29 public function setCommits(array $commits) {
30 assert_instances_of($commits, 'PhabricatorRepositoryCommit');
31 $this->commits = $commits;
32 return $this;
35 public function getCommits() {
36 return $this->commits;
39 public function setShowAuditors($show_auditors) {
40 $this->showAuditors = $show_auditors;
41 return $this;
44 public function getShowAuditors() {
45 return $this->showAuditors;
48 public function setParents(array $parents) {
49 $this->parents = $parents;
50 return $this;
53 public function getParents() {
54 return $this->parents;
57 public function setIsHead($is_head) {
58 $this->isHead = $is_head;
59 return $this;
62 public function getIsHead() {
63 return $this->isHead;
66 public function setIsTail($is_tail) {
67 $this->isTail = $is_tail;
68 return $this;
71 public function getIsTail() {
72 return $this->isTail;
75 public function setFilterParents($filter_parents) {
76 $this->filterParents = $filter_parents;
77 return $this;
80 public function getFilterParents() {
81 return $this->filterParents;
84 private function getRepository() {
85 $drequest = $this->getDiffusionRequest();
87 if (!$drequest) {
88 return null;
91 return $drequest->getRepository();
94 public function newObjectItemListView() {
95 $list_view = id(new PHUIObjectItemListView());
97 $item_views = $this->newObjectItemViews();
98 foreach ($item_views as $item_view) {
99 $list_view->addItem($item_view);
102 return $list_view;
105 private function newObjectItemViews() {
106 $viewer = $this->getViewer();
108 require_celerity_resource('diffusion-css');
110 $show_builds = $this->shouldShowBuilds();
111 $show_revisions = $this->shouldShowRevisions();
112 $show_auditors = $this->shouldShowAuditors();
114 $phids = array();
116 if ($show_revisions) {
117 $revision_map = $this->getRevisionMap();
118 foreach ($revision_map as $revisions) {
119 foreach ($revisions as $revision) {
120 $phids[] = $revision->getPHID();
125 $commits = $this->getCommitMap();
127 foreach ($commits as $commit) {
128 $author_phid = $commit->getAuthorDisplayPHID();
129 if ($author_phid !== null) {
130 $phids[] = $author_phid;
134 if ($show_auditors) {
135 foreach ($commits as $commit) {
136 $audits = $commit->getAudits();
137 foreach ($audits as $auditor) {
138 $phids[] = $auditor->getAuditorPHID();
143 $handles = $viewer->loadHandles($phids);
145 $views = array();
147 $items = $this->newHistoryItems();
148 foreach ($items as $hash => $item) {
149 $content = array();
151 $commit = $item['commit'];
153 $commit_description = $this->getCommitDescription($commit);
154 $commit_link = $this->getCommitURI($hash);
156 $short_hash = $this->getCommitObjectName($hash);
157 $is_disabled = $this->getCommitIsDisabled($commit);
159 $item_view = id(new PHUIObjectItemView())
160 ->setViewer($viewer)
161 ->setHeader($commit_description)
162 ->setObjectName($short_hash)
163 ->setHref($commit_link)
164 ->setDisabled($is_disabled);
166 $this->addBrowseAction($item_view, $hash);
168 if ($show_builds) {
169 $this->addBuildAction($item_view, $hash);
172 $this->addAuditAction($item_view, $hash);
174 if ($show_auditors) {
175 $auditor_list = $item_view->newMapView();
176 if ($commit) {
177 $auditors = $this->newAuditorList($commit, $handles);
178 $auditor_list->newItem()
179 ->setName(pht('Auditors'))
180 ->setValue($auditors);
184 $property_list = $item_view->newMapView();
186 if ($commit) {
187 $author_view = $this->getCommitAuthorView($commit);
188 if ($author_view) {
189 $property_list->newItem()
190 ->setName(pht('Author'))
191 ->setValue($author_view);
195 if ($show_revisions) {
196 if ($commit) {
197 $revisions = $this->getRevisions($commit);
198 if ($revisions) {
199 $list_view = $handles->newSublist(mpull($revisions, 'getPHID'))
200 ->newListView();
202 $property_list->newItem()
203 ->setName(pht('Revisions'))
204 ->setValue($list_view);
209 $views[$hash] = $item_view;
212 return $views;
215 private function newObjectItemRows() {
216 $viewer = $this->getViewer();
218 $items = $this->newHistoryItems();
219 $views = $this->newObjectItemViews();
221 $last_date = null;
222 $rows = array();
223 foreach ($items as $hash => $item) {
224 $item_epoch = $item['epoch'];
225 $item_date = phabricator_date($item_epoch, $viewer);
226 if ($item_date !== $last_date) {
227 $last_date = $item_date;
228 $header = $item_date;
229 } else {
230 $header = null;
233 $item_view = $views[$hash];
235 $list_view = id(new PHUIObjectItemListView())
236 ->setViewer($viewer)
237 ->setFlush(true)
238 ->addItem($item_view);
240 if ($header !== null) {
241 $list_view->setHeader($header);
244 $rows[] = $list_view;
247 return $rows;
250 public function render() {
251 $rows = $this->newObjectItemRows();
253 $graph = $this->newGraphView();
254 foreach ($rows as $idx => $row) {
255 $cells = array();
257 if ($graph) {
258 $cells[] = phutil_tag(
259 'td',
260 array(
261 'class' => 'diffusion-commit-graph-path-cell',
263 $graph[$idx]);
266 $cells[] = phutil_tag(
267 'td',
268 array(
269 'class' => 'diffusion-commit-graph-content-cell',
271 $row);
273 $rows[$idx] = phutil_tag('tr', array(), $cells);
276 $table = phutil_tag(
277 'table',
278 array(
279 'class' => 'diffusion-commit-graph-table',
281 $rows);
283 return $table;
286 private function newGraphView() {
287 if (!$this->getParents()) {
288 return null;
291 $parents = $this->getParents();
293 // If we're filtering parents, remove relationships which point to
294 // commits that are not part of the visible graph. Otherwise, we get
295 // a big tree of nonsense when viewing release branches like "stable"
296 // versus "master".
297 if ($this->getFilterParents()) {
298 foreach ($parents as $key => $nodes) {
299 foreach ($nodes as $nkey => $node) {
300 if (empty($parents[$node])) {
301 unset($parents[$key][$nkey]);
307 return id(new PHUIDiffGraphView())
308 ->setIsHead($this->getIsHead())
309 ->setIsTail($this->getIsTail())
310 ->renderGraph($parents);
313 private function shouldShowBuilds() {
314 $viewer = $this->getViewer();
316 $show_builds = PhabricatorApplication::isClassInstalledForViewer(
317 'PhabricatorHarbormasterApplication',
318 $this->getUser());
320 return $show_builds;
323 private function shouldShowRevisions() {
324 $viewer = $this->getViewer();
326 $show_revisions = PhabricatorApplication::isClassInstalledForViewer(
327 'PhabricatorDifferentialApplication',
328 $viewer);
330 return $show_revisions;
333 private function shouldShowAuditors() {
334 return $this->getShowAuditors();
337 private function newHistoryItems() {
338 $items = array();
340 $history = $this->getHistory();
341 if ($history !== null) {
342 foreach ($history as $history_item) {
343 $commit_hash = $history_item->getCommitIdentifier();
345 $items[$commit_hash] = array(
346 'epoch' => $history_item->getEpoch(),
347 'hash' => $commit_hash,
348 'commit' => $this->getCommit($commit_hash),
351 } else {
352 $commits = $this->getCommitMap();
353 foreach ($commits as $commit) {
354 $commit_hash = $commit->getCommitIdentifier();
356 $items[$commit_hash] = array(
357 'epoch' => $commit->getEpoch(),
358 'hash' => $commit_hash,
359 'commit' => $commit,
364 return $items;
367 private function getCommitDescription($commit) {
368 if (!$commit) {
369 return phutil_tag('em', array(), pht("Discovering\xE2\x80\xA6"));
372 // We can show details once the message and change have been imported.
373 $partial_import = PhabricatorRepositoryCommit::IMPORTED_MESSAGE |
374 PhabricatorRepositoryCommit::IMPORTED_CHANGE;
375 if (!$commit->isPartiallyImported($partial_import)) {
376 return phutil_tag('em', array(), pht("Importing\xE2\x80\xA6"));
379 return $commit->getCommitData()->getSummary();
382 private function getCommitURI($hash) {
383 $repository = $this->getRepository();
385 if ($repository) {
386 return $repository->getCommitURI($hash);
389 $commit = $this->getCommit($hash);
390 if ($commit) {
391 return $commit->getURI();
394 return null;
397 private function getCommitObjectName($hash) {
398 $repository = $this->getRepository();
400 if ($repository) {
401 return $repository->formatCommitName(
402 $hash,
403 $is_local = true);
406 $commit = $this->getCommit($hash);
407 if ($commit) {
408 return $commit->getDisplayName();
411 return null;
414 private function getCommitIsDisabled($commit) {
415 if (!$commit) {
416 return true;
419 if ($commit->isUnreachable()) {
420 return true;
423 return false;
426 private function getCommitAuthorView($commit) {
427 if (!$commit) {
428 return null;
431 $viewer = $this->getViewer();
433 $author_phid = $commit->getAuthorDisplayPHID();
434 if ($author_phid) {
435 return $viewer->loadHandles(array($author_phid))
436 ->newListView();
439 return $commit->newCommitAuthorView($viewer);
442 private function getCommit($hash) {
443 $commit_map = $this->getCommitMap();
444 return idx($commit_map, $hash);
447 private function getCommitMap() {
448 if ($this->commitMap === null) {
449 $commit_list = $this->newCommitList();
450 $this->commitMap = mpull($commit_list, null, 'getCommitIdentifier');
453 return $this->commitMap;
456 private function addBrowseAction(PHUIObjectItemView $item, $hash) {
457 $repository = $this->getRepository();
459 if (!$repository) {
460 return;
463 $drequest = $this->getDiffusionRequest();
464 $path = $drequest->getPath();
466 $uri = $drequest->generateURI(
467 array(
468 'action' => 'browse',
469 'path' => $path,
470 'commit' => $hash,
473 $menu_item = $item->newMenuItem()
474 ->setName(pht('Browse Repository'))
475 ->setURI($uri);
477 $menu_item->newIcon()
478 ->setIcon('fa-folder-open-o')
479 ->setColor('bluegrey');
482 private function addBuildAction(PHUIObjectItemView $item, $hash) {
483 $is_disabled = true;
485 $buildable = null;
487 $commit = $this->getCommit($hash);
488 if ($commit) {
489 $buildable = $this->getBuildable($commit);
492 if ($buildable) {
493 $icon = $buildable->getStatusIcon();
494 $color = $buildable->getStatusColor();
495 $name = $buildable->getStatusDisplayName();
496 $uri = $buildable->getURI();
497 } else {
498 $icon = 'fa-times';
499 $color = 'grey';
500 $name = pht('No Builds');
501 $uri = null;
504 $menu_item = $item->newMenuItem()
505 ->setName($name)
506 ->setURI($uri)
507 ->setDisabled(($uri === null));
509 $menu_item->newIcon()
510 ->setIcon($icon)
511 ->setColor($color);
514 private function addAuditAction(PHUIObjectItemView $item_view, $hash) {
515 $commit = $this->getCommit($hash);
517 if ($commit) {
518 $status = $commit->getAuditStatusObject();
520 $text = $status->getName();
521 $icon = $status->getIcon();
523 $is_disabled = $status->isNoAudit();
524 if ($is_disabled) {
525 $uri = null;
526 $color = 'grey';
527 } else {
528 $color = $status->getColor();
529 $uri = $commit->getURI();
531 } else {
532 $text = pht('No Audit');
533 $color = 'grey';
534 $icon = 'fa-times';
535 $uri = null;
537 $is_disabled = true;
540 $menu_item = $item_view->newMenuItem()
541 ->setName($text)
542 ->setURI($uri)
543 ->setBackgroundColor($color)
544 ->setDisabled($is_disabled);
546 $menu_item->newIcon()
547 ->setIcon($icon)
548 ->setColor($color);
551 private function getBuildable(PhabricatorRepositoryCommit $commit) {
552 $buildable_map = $this->getBuildableMap();
553 return idx($buildable_map, $commit->getPHID());
556 private function getBuildableMap() {
557 if ($this->buildableMap === null) {
558 $commits = $this->getCommitMap();
559 $buildables = $this->loadBuildables($commits);
560 $this->buildableMap = $buildables;
563 return $this->buildableMap;
566 private function getRevisions(PhabricatorRepositoryCommit $commit) {
567 $revision_map = $this->getRevisionMap();
568 return idx($revision_map, $commit->getPHID(), array());
571 private function getRevisionMap() {
572 if ($this->revisionMap === null) {
573 $this->revisionMap = $this->newRevisionMap();
576 return $this->revisionMap;
579 private function newRevisionMap() {
580 $viewer = $this->getViewer();
581 $commits = $this->getCommitMap();
583 return DiffusionCommitRevisionQuery::loadRevisionMapForCommits(
584 $viewer,
585 $commits);
588 private function newCommitList() {
589 $commits = $this->getCommits();
590 if ($commits !== null) {
591 return $commits;
594 $repository = $this->getRepository();
595 if (!$repository) {
596 return array();
599 $history = $this->getHistory();
600 if ($history === null) {
601 return array();
604 $identifiers = array();
605 foreach ($history as $item) {
606 $identifiers[] = $item->getCommitIdentifier();
609 if (!$identifiers) {
610 return array();
613 $viewer = $this->getViewer();
615 $commits = id(new DiffusionCommitQuery())
616 ->setViewer($viewer)
617 ->withRepository($repository)
618 ->withIdentifiers($identifiers)
619 ->needCommitData(true)
620 ->needIdentities(true)
621 ->execute();
623 return $commits;
626 private function newAuditorList(
627 PhabricatorRepositoryCommit $commit,
628 $handles) {
630 $auditors = $commit->getAudits();
631 if (!$auditors) {
632 return phutil_tag('em', array(), pht('None'));
635 $auditor_phids = mpull($auditors, 'getAuditorPHID');
636 $auditor_list = $handles->newSublist($auditor_phids)
637 ->newListView();
639 return $auditor_list;