3 final class DiffusionCommitGraphView
4 extends DiffusionView
{
11 private $filterParents;
14 private $buildableMap;
17 private $showAuditors;
19 public function setHistory(array $history) {
20 assert_instances_of($history, 'DiffusionPathChange');
21 $this->history
= $history;
25 public function getHistory() {
26 return $this->history
;
29 public function setCommits(array $commits) {
30 assert_instances_of($commits, 'PhabricatorRepositoryCommit');
31 $this->commits
= $commits;
35 public function getCommits() {
36 return $this->commits
;
39 public function setShowAuditors($show_auditors) {
40 $this->showAuditors
= $show_auditors;
44 public function getShowAuditors() {
45 return $this->showAuditors
;
48 public function setParents(array $parents) {
49 $this->parents
= $parents;
53 public function getParents() {
54 return $this->parents
;
57 public function setIsHead($is_head) {
58 $this->isHead
= $is_head;
62 public function getIsHead() {
66 public function setIsTail($is_tail) {
67 $this->isTail
= $is_tail;
71 public function getIsTail() {
75 public function setFilterParents($filter_parents) {
76 $this->filterParents
= $filter_parents;
80 public function getFilterParents() {
81 return $this->filterParents
;
84 private function getRepository() {
85 $drequest = $this->getDiffusionRequest();
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);
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();
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);
147 $items = $this->newHistoryItems();
148 foreach ($items as $hash => $item) {
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())
161 ->setHeader($commit_description)
162 ->setObjectName($short_hash)
163 ->setHref($commit_link)
164 ->setDisabled($is_disabled);
166 $this->addBrowseAction($item_view, $hash);
169 $this->addBuildAction($item_view, $hash);
172 $this->addAuditAction($item_view, $hash);
174 if ($show_auditors) {
175 $auditor_list = $item_view->newMapView();
177 $auditors = $this->newAuditorList($commit, $handles);
178 $auditor_list->newItem()
179 ->setName(pht('Auditors'))
180 ->setValue($auditors);
184 $property_list = $item_view->newMapView();
187 $author_view = $this->getCommitAuthorView($commit);
189 $property_list->newItem()
190 ->setName(pht('Author'))
191 ->setValue($author_view);
195 if ($show_revisions) {
197 $revisions = $this->getRevisions($commit);
199 $list_view = $handles->newSublist(mpull($revisions, 'getPHID'))
202 $property_list->newItem()
203 ->setName(pht('Revisions'))
204 ->setValue($list_view);
209 $views[$hash] = $item_view;
215 private function newObjectItemRows() {
216 $viewer = $this->getViewer();
218 $items = $this->newHistoryItems();
219 $views = $this->newObjectItemViews();
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;
233 $item_view = $views[$hash];
235 $list_view = id(new PHUIObjectItemListView())
238 ->addItem($item_view);
240 if ($header !== null) {
241 $list_view->setHeader($header);
244 $rows[] = $list_view;
250 public function render() {
251 $rows = $this->newObjectItemRows();
253 $graph = $this->newGraphView();
254 foreach ($rows as $idx => $row) {
258 $cells[] = phutil_tag(
261 'class' => 'diffusion-commit-graph-path-cell',
266 $cells[] = phutil_tag(
269 'class' => 'diffusion-commit-graph-content-cell',
273 $rows[$idx] = phutil_tag('tr', array(), $cells);
279 'class' => 'diffusion-commit-graph-table',
286 private function newGraphView() {
287 if (!$this->getParents()) {
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"
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',
323 private function shouldShowRevisions() {
324 $viewer = $this->getViewer();
326 $show_revisions = PhabricatorApplication
::isClassInstalledForViewer(
327 'PhabricatorDifferentialApplication',
330 return $show_revisions;
333 private function shouldShowAuditors() {
334 return $this->getShowAuditors();
337 private function newHistoryItems() {
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),
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,
367 private function getCommitDescription($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();
386 return $repository->getCommitURI($hash);
389 $commit = $this->getCommit($hash);
391 return $commit->getURI();
397 private function getCommitObjectName($hash) {
398 $repository = $this->getRepository();
401 return $repository->formatCommitName(
406 $commit = $this->getCommit($hash);
408 return $commit->getDisplayName();
414 private function getCommitIsDisabled($commit) {
419 if ($commit->isUnreachable()) {
426 private function getCommitAuthorView($commit) {
431 $viewer = $this->getViewer();
433 $author_phid = $commit->getAuthorDisplayPHID();
435 return $viewer->loadHandles(array($author_phid))
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();
463 $drequest = $this->getDiffusionRequest();
464 $path = $drequest->getPath();
466 $uri = $drequest->generateURI(
468 'action' => 'browse',
473 $menu_item = $item->newMenuItem()
474 ->setName(pht('Browse Repository'))
477 $menu_item->newIcon()
478 ->setIcon('fa-folder-open-o')
479 ->setColor('bluegrey');
482 private function addBuildAction(PHUIObjectItemView
$item, $hash) {
487 $commit = $this->getCommit($hash);
489 $buildable = $this->getBuildable($commit);
493 $icon = $buildable->getStatusIcon();
494 $color = $buildable->getStatusColor();
495 $name = $buildable->getStatusDisplayName();
496 $uri = $buildable->getURI();
500 $name = pht('No Builds');
504 $menu_item = $item->newMenuItem()
507 ->setDisabled(($uri === null));
509 $menu_item->newIcon()
514 private function addAuditAction(PHUIObjectItemView
$item_view, $hash) {
515 $commit = $this->getCommit($hash);
518 $status = $commit->getAuditStatusObject();
520 $text = $status->getName();
521 $icon = $status->getIcon();
523 $is_disabled = $status->isNoAudit();
528 $color = $status->getColor();
529 $uri = $commit->getURI();
532 $text = pht('No Audit');
540 $menu_item = $item_view->newMenuItem()
543 ->setBackgroundColor($color)
544 ->setDisabled($is_disabled);
546 $menu_item->newIcon()
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(
588 private function newCommitList() {
589 $commits = $this->getCommits();
590 if ($commits !== null) {
594 $repository = $this->getRepository();
599 $history = $this->getHistory();
600 if ($history === null) {
604 $identifiers = array();
605 foreach ($history as $item) {
606 $identifiers[] = $item->getCommitIdentifier();
613 $viewer = $this->getViewer();
615 $commits = id(new DiffusionCommitQuery())
617 ->withRepository($repository)
618 ->withIdentifiers($identifiers)
619 ->needCommitData(true)
620 ->needIdentities(true)
626 private function newAuditorList(
627 PhabricatorRepositoryCommit
$commit,
630 $auditors = $commit->getAudits();
632 return phutil_tag('em', array(), pht('None'));
635 $auditor_phids = mpull($auditors, 'getAuditorPHID');
636 $auditor_list = $handles->newSublist($auditor_phids)
639 return $auditor_list;