3 final class DiffusionBlameController
extends DiffusionController
{
5 public function shouldAllowPublic() {
9 public function handleRequest(AphrontRequest
$request) {
10 $response = $this->loadDiffusionContext();
15 $viewer = $this->getViewer();
16 $drequest = $this->getDiffusionRequest();
17 $repository = $drequest->getRepository();
19 $blame = $this->loadBlame();
21 $identifiers = array_fuse($blame);
23 $commits = id(new DiffusionCommitQuery())
25 ->withRepository($repository)
26 ->withIdentifiers($identifiers)
27 ->needIdentities(true)
28 // See PHI1014. If identities haven't been built yet, we may need to
29 // fall back to raw commit data.
30 ->needCommitData(true)
32 $commits = mpull($commits, null, 'getCommitIdentifier');
37 $commit_map = mpull($commits, 'getCommitIdentifier', 'getPHID');
39 $revision_map = DiffusionCommitRevisionQuery
::loadRevisionMapForCommits(
43 $base_href = (string)$drequest->generateURI(
49 $skip_text = pht('Skip Past This Commit');
50 $skip_icon = id(new PHUIIconView())
51 ->setIcon('fa-backward');
53 Javelin
::initBehavior('phabricator-tooltips');
55 $handle_phids = array();
56 foreach ($commits as $commit) {
57 $handle_phids[] = $commit->getAuthorDisplayPHID();
60 foreach ($revision_map as $revisions) {
61 foreach ($revisions as $revision) {
62 $handle_phids[] = $revision->getAuthorPHID();
66 $handles = $viewer->loadHandles($handle_phids);
70 foreach ($identifiers as $identifier) {
71 $skip_href = $base_href.'?before='.$identifier;
73 $skip_link = javelin_tag(
77 'sigil' => 'has-tooltip',
86 // We may not have a commit object for a given identifier if the commit
87 // has not imported yet.
89 // At time of writing, this can also happen if a line was part of the
90 // initial import: blame produces a "^abc123" identifier in Git, which
91 // doesn't correspond to a real commit.
93 $commit = idx($commits, $identifier);
97 $revisions = idx($revision_map, $commit->getPHID());
99 // There may be multiple edges between this commit and revisions in the
100 // database. If there are, just pick one arbitrarily.
102 $revision = head($revisions);
109 $author_phid = $commit->getAuthorDisplayPHID();
113 // This means we couldn't identify an author for the commit or the
114 // revision. We just render a blank for alignment.
115 $author_style = null;
117 $author_sigil = null;
120 $author_src = $handles[$author_phid]->getImageURI();
121 $author_style = 'background-image: url('.$author_src.');';
122 $author_href = $handles[$author_phid]->getURI();
123 $author_sigil = 'has-tooltip';
124 $author_meta = array(
125 'tip' => $handles[$author_phid]->getName(),
131 $author_link = javelin_tag(
132 $author_href ?
'a' : 'span',
134 'class' => 'phabricator-source-blame-author',
135 'style' => $author_style,
136 'href' => $author_href,
137 'sigil' => $author_sigil,
138 'meta' => $author_meta,
142 $commit_link = javelin_tag(
145 'href' => $commit->getURI(),
146 'sigil' => 'has-tooltip',
148 'tip' => $this->renderCommitTooltip($commit, $handles),
153 $commit->getLocalName());
164 $revision_link = javelin_tag(
167 'href' => $revision->getURI(),
168 'sigil' => 'has-tooltip',
170 'tip' => $this->renderRevisionTooltip($revision, $handles),
175 $revision->getMonogram());
185 $epoch = $commit->getEpoch();
193 'skip' => $skip_link,
194 'info' => hsprintf('%s', $info),
198 $map[$identifier] = $data;
201 $epoch_min = min($epochs);
202 $epoch_max = max($epochs);
204 return id(new AphrontAjaxResponse())->setContent(
215 private function loadBlame() {
216 $drequest = $this->getDiffusionRequest();
218 $commit = $drequest->getCommit();
219 $path = $drequest->getPath();
223 $blame = $this->callConduitWithDiffusionRequest(
227 'paths' => array($path),
228 'timeout' => $blame_timeout,
231 return idx($blame, $path, array());
234 private function renderRevisionTooltip(
235 DifferentialRevision
$revision,
237 $viewer = $this->getViewer();
239 $date = phabricator_date($revision->getDateModified(), $viewer);
240 $monogram = $revision->getMonogram();
241 $title = $revision->getTitle();
242 $header = "{$monogram} {$title}";
244 $author = $handles[$revision->getAuthorPHID()]->getName();
246 return "{$header}\n{$date} \xC2\xB7 {$author}";
249 private function renderCommitTooltip(
250 PhabricatorRepositoryCommit
$commit,
253 $viewer = $this->getViewer();
255 $date = phabricator_date($commit->getEpoch(), $viewer);
256 $summary = trim($commit->getSummary());
258 $author_phid = $commit->getAuthorPHID();
259 if ($author_phid && isset($handles[$author_phid])) {
260 $author_name = $handles[$author_phid]->getName();
266 return "{$summary}\n{$date} \xC2\xB7 {$author_name}";
268 return "{$summary}\n{$date}";