Path: blob/master/src/applications/diffusion/view/DiffusionCommitGraphView.php
12242 views
<?php12final class DiffusionCommitGraphView3extends DiffusionView {45private $history;6private $commits;7private $isHead;8private $isTail;9private $parents;10private $filterParents;1112private $commitMap;13private $buildableMap;14private $revisionMap;1516private $showAuditors;1718public function setHistory(array $history) {19assert_instances_of($history, 'DiffusionPathChange');20$this->history = $history;21return $this;22}2324public function getHistory() {25return $this->history;26}2728public function setCommits(array $commits) {29assert_instances_of($commits, 'PhabricatorRepositoryCommit');30$this->commits = $commits;31return $this;32}3334public function getCommits() {35return $this->commits;36}3738public function setShowAuditors($show_auditors) {39$this->showAuditors = $show_auditors;40return $this;41}4243public function getShowAuditors() {44return $this->showAuditors;45}4647public function setParents(array $parents) {48$this->parents = $parents;49return $this;50}5152public function getParents() {53return $this->parents;54}5556public function setIsHead($is_head) {57$this->isHead = $is_head;58return $this;59}6061public function getIsHead() {62return $this->isHead;63}6465public function setIsTail($is_tail) {66$this->isTail = $is_tail;67return $this;68}6970public function getIsTail() {71return $this->isTail;72}7374public function setFilterParents($filter_parents) {75$this->filterParents = $filter_parents;76return $this;77}7879public function getFilterParents() {80return $this->filterParents;81}8283private function getRepository() {84$drequest = $this->getDiffusionRequest();8586if (!$drequest) {87return null;88}8990return $drequest->getRepository();91}9293public function newObjectItemListView() {94$list_view = id(new PHUIObjectItemListView());9596$item_views = $this->newObjectItemViews();97foreach ($item_views as $item_view) {98$list_view->addItem($item_view);99}100101return $list_view;102}103104private function newObjectItemViews() {105$viewer = $this->getViewer();106107require_celerity_resource('diffusion-css');108109$show_builds = $this->shouldShowBuilds();110$show_revisions = $this->shouldShowRevisions();111$show_auditors = $this->shouldShowAuditors();112113$phids = array();114115if ($show_revisions) {116$revision_map = $this->getRevisionMap();117foreach ($revision_map as $revisions) {118foreach ($revisions as $revision) {119$phids[] = $revision->getPHID();120}121}122}123124$commits = $this->getCommitMap();125126foreach ($commits as $commit) {127$author_phid = $commit->getAuthorDisplayPHID();128if ($author_phid !== null) {129$phids[] = $author_phid;130}131}132133if ($show_auditors) {134foreach ($commits as $commit) {135$audits = $commit->getAudits();136foreach ($audits as $auditor) {137$phids[] = $auditor->getAuditorPHID();138}139}140}141142$handles = $viewer->loadHandles($phids);143144$views = array();145146$items = $this->newHistoryItems();147foreach ($items as $hash => $item) {148$content = array();149150$commit = $item['commit'];151152$commit_description = $this->getCommitDescription($commit);153$commit_link = $this->getCommitURI($hash);154155$short_hash = $this->getCommitObjectName($hash);156$is_disabled = $this->getCommitIsDisabled($commit);157158$item_view = id(new PHUIObjectItemView())159->setViewer($viewer)160->setHeader($commit_description)161->setObjectName($short_hash)162->setHref($commit_link)163->setDisabled($is_disabled);164165$this->addBrowseAction($item_view, $hash);166167if ($show_builds) {168$this->addBuildAction($item_view, $hash);169}170171$this->addAuditAction($item_view, $hash);172173if ($show_auditors) {174$auditor_list = $item_view->newMapView();175if ($commit) {176$auditors = $this->newAuditorList($commit, $handles);177$auditor_list->newItem()178->setName(pht('Auditors'))179->setValue($auditors);180}181}182183$property_list = $item_view->newMapView();184185if ($commit) {186$author_view = $this->getCommitAuthorView($commit);187if ($author_view) {188$property_list->newItem()189->setName(pht('Author'))190->setValue($author_view);191}192}193194if ($show_revisions) {195if ($commit) {196$revisions = $this->getRevisions($commit);197if ($revisions) {198$list_view = $handles->newSublist(mpull($revisions, 'getPHID'))199->newListView();200201$property_list->newItem()202->setName(pht('Revisions'))203->setValue($list_view);204}205}206}207208$views[$hash] = $item_view;209}210211return $views;212}213214private function newObjectItemRows() {215$viewer = $this->getViewer();216217$items = $this->newHistoryItems();218$views = $this->newObjectItemViews();219220$last_date = null;221$rows = array();222foreach ($items as $hash => $item) {223$item_epoch = $item['epoch'];224$item_date = phabricator_date($item_epoch, $viewer);225if ($item_date !== $last_date) {226$last_date = $item_date;227$header = $item_date;228} else {229$header = null;230}231232$item_view = $views[$hash];233234$list_view = id(new PHUIObjectItemListView())235->setViewer($viewer)236->setFlush(true)237->addItem($item_view);238239if ($header !== null) {240$list_view->setHeader($header);241}242243$rows[] = $list_view;244}245246return $rows;247}248249public function render() {250$rows = $this->newObjectItemRows();251252$graph = $this->newGraphView();253foreach ($rows as $idx => $row) {254$cells = array();255256if ($graph) {257$cells[] = phutil_tag(258'td',259array(260'class' => 'diffusion-commit-graph-path-cell',261),262$graph[$idx]);263}264265$cells[] = phutil_tag(266'td',267array(268'class' => 'diffusion-commit-graph-content-cell',269),270$row);271272$rows[$idx] = phutil_tag('tr', array(), $cells);273}274275$table = phutil_tag(276'table',277array(278'class' => 'diffusion-commit-graph-table',279),280$rows);281282return $table;283}284285private function newGraphView() {286if (!$this->getParents()) {287return null;288}289290$parents = $this->getParents();291292// If we're filtering parents, remove relationships which point to293// commits that are not part of the visible graph. Otherwise, we get294// a big tree of nonsense when viewing release branches like "stable"295// versus "master".296if ($this->getFilterParents()) {297foreach ($parents as $key => $nodes) {298foreach ($nodes as $nkey => $node) {299if (empty($parents[$node])) {300unset($parents[$key][$nkey]);301}302}303}304}305306return id(new PHUIDiffGraphView())307->setIsHead($this->getIsHead())308->setIsTail($this->getIsTail())309->renderGraph($parents);310}311312private function shouldShowBuilds() {313$viewer = $this->getViewer();314315$show_builds = PhabricatorApplication::isClassInstalledForViewer(316'PhabricatorHarbormasterApplication',317$this->getUser());318319return $show_builds;320}321322private function shouldShowRevisions() {323$viewer = $this->getViewer();324325$show_revisions = PhabricatorApplication::isClassInstalledForViewer(326'PhabricatorDifferentialApplication',327$viewer);328329return $show_revisions;330}331332private function shouldShowAuditors() {333return $this->getShowAuditors();334}335336private function newHistoryItems() {337$items = array();338339$history = $this->getHistory();340if ($history !== null) {341foreach ($history as $history_item) {342$commit_hash = $history_item->getCommitIdentifier();343344$items[$commit_hash] = array(345'epoch' => $history_item->getEpoch(),346'hash' => $commit_hash,347'commit' => $this->getCommit($commit_hash),348);349}350} else {351$commits = $this->getCommitMap();352foreach ($commits as $commit) {353$commit_hash = $commit->getCommitIdentifier();354355$items[$commit_hash] = array(356'epoch' => $commit->getEpoch(),357'hash' => $commit_hash,358'commit' => $commit,359);360}361}362363return $items;364}365366private function getCommitDescription($commit) {367if (!$commit) {368return phutil_tag('em', array(), pht("Discovering\xE2\x80\xA6"));369}370371// We can show details once the message and change have been imported.372$partial_import = PhabricatorRepositoryCommit::IMPORTED_MESSAGE |373PhabricatorRepositoryCommit::IMPORTED_CHANGE;374if (!$commit->isPartiallyImported($partial_import)) {375return phutil_tag('em', array(), pht("Importing\xE2\x80\xA6"));376}377378return $commit->getCommitData()->getSummary();379}380381private function getCommitURI($hash) {382$repository = $this->getRepository();383384if ($repository) {385return $repository->getCommitURI($hash);386}387388$commit = $this->getCommit($hash);389if ($commit) {390return $commit->getURI();391}392393return null;394}395396private function getCommitObjectName($hash) {397$repository = $this->getRepository();398399if ($repository) {400return $repository->formatCommitName(401$hash,402$is_local = true);403}404405$commit = $this->getCommit($hash);406if ($commit) {407return $commit->getDisplayName();408}409410return null;411}412413private function getCommitIsDisabled($commit) {414if (!$commit) {415return true;416}417418if ($commit->isUnreachable()) {419return true;420}421422return false;423}424425private function getCommitAuthorView($commit) {426if (!$commit) {427return null;428}429430$viewer = $this->getViewer();431432$author_phid = $commit->getAuthorDisplayPHID();433if ($author_phid) {434return $viewer->loadHandles(array($author_phid))435->newListView();436}437438return $commit->newCommitAuthorView($viewer);439}440441private function getCommit($hash) {442$commit_map = $this->getCommitMap();443return idx($commit_map, $hash);444}445446private function getCommitMap() {447if ($this->commitMap === null) {448$commit_list = $this->newCommitList();449$this->commitMap = mpull($commit_list, null, 'getCommitIdentifier');450}451452return $this->commitMap;453}454455private function addBrowseAction(PHUIObjectItemView $item, $hash) {456$repository = $this->getRepository();457458if (!$repository) {459return;460}461462$drequest = $this->getDiffusionRequest();463$path = $drequest->getPath();464465$uri = $drequest->generateURI(466array(467'action' => 'browse',468'path' => $path,469'commit' => $hash,470));471472$menu_item = $item->newMenuItem()473->setName(pht('Browse Repository'))474->setURI($uri);475476$menu_item->newIcon()477->setIcon('fa-folder-open-o')478->setColor('bluegrey');479}480481private function addBuildAction(PHUIObjectItemView $item, $hash) {482$is_disabled = true;483484$buildable = null;485486$commit = $this->getCommit($hash);487if ($commit) {488$buildable = $this->getBuildable($commit);489}490491if ($buildable) {492$icon = $buildable->getStatusIcon();493$color = $buildable->getStatusColor();494$name = $buildable->getStatusDisplayName();495$uri = $buildable->getURI();496} else {497$icon = 'fa-times';498$color = 'grey';499$name = pht('No Builds');500$uri = null;501}502503$menu_item = $item->newMenuItem()504->setName($name)505->setURI($uri)506->setDisabled(($uri === null));507508$menu_item->newIcon()509->setIcon($icon)510->setColor($color);511}512513private function addAuditAction(PHUIObjectItemView $item_view, $hash) {514$commit = $this->getCommit($hash);515516if ($commit) {517$status = $commit->getAuditStatusObject();518519$text = $status->getName();520$icon = $status->getIcon();521522$is_disabled = $status->isNoAudit();523if ($is_disabled) {524$uri = null;525$color = 'grey';526} else {527$color = $status->getColor();528$uri = $commit->getURI();529}530} else {531$text = pht('No Audit');532$color = 'grey';533$icon = 'fa-times';534$uri = null;535536$is_disabled = true;537}538539$menu_item = $item_view->newMenuItem()540->setName($text)541->setURI($uri)542->setBackgroundColor($color)543->setDisabled($is_disabled);544545$menu_item->newIcon()546->setIcon($icon)547->setColor($color);548}549550private function getBuildable(PhabricatorRepositoryCommit $commit) {551$buildable_map = $this->getBuildableMap();552return idx($buildable_map, $commit->getPHID());553}554555private function getBuildableMap() {556if ($this->buildableMap === null) {557$commits = $this->getCommitMap();558$buildables = $this->loadBuildables($commits);559$this->buildableMap = $buildables;560}561562return $this->buildableMap;563}564565private function getRevisions(PhabricatorRepositoryCommit $commit) {566$revision_map = $this->getRevisionMap();567return idx($revision_map, $commit->getPHID(), array());568}569570private function getRevisionMap() {571if ($this->revisionMap === null) {572$this->revisionMap = $this->newRevisionMap();573}574575return $this->revisionMap;576}577578private function newRevisionMap() {579$viewer = $this->getViewer();580$commits = $this->getCommitMap();581582return DiffusionCommitRevisionQuery::loadRevisionMapForCommits(583$viewer,584$commits);585}586587private function newCommitList() {588$commits = $this->getCommits();589if ($commits !== null) {590return $commits;591}592593$repository = $this->getRepository();594if (!$repository) {595return array();596}597598$history = $this->getHistory();599if ($history === null) {600return array();601}602603$identifiers = array();604foreach ($history as $item) {605$identifiers[] = $item->getCommitIdentifier();606}607608if (!$identifiers) {609return array();610}611612$viewer = $this->getViewer();613614$commits = id(new DiffusionCommitQuery())615->setViewer($viewer)616->withRepository($repository)617->withIdentifiers($identifiers)618->needCommitData(true)619->needIdentities(true)620->execute();621622return $commits;623}624625private function newAuditorList(626PhabricatorRepositoryCommit $commit,627$handles) {628629$auditors = $commit->getAudits();630if (!$auditors) {631return phutil_tag('em', array(), pht('None'));632}633634$auditor_phids = mpull($auditors, 'getAuditorPHID');635$auditor_list = $handles->newSublist($auditor_phids)636->newListView();637638return $auditor_list;639}640641}642643644