mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-13 00:56:15 +01:00
255 lines
6.5 KiB
PHP
255 lines
6.5 KiB
PHP
|
<?php
|
||
|
|
||
|
final class DiffusionBlameController extends DiffusionController {
|
||
|
|
||
|
public function shouldAllowPublic() {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public function handleRequest(AphrontRequest $request) {
|
||
|
$response = $this->loadDiffusionContext();
|
||
|
if ($response) {
|
||
|
return $response;
|
||
|
}
|
||
|
|
||
|
$viewer = $this->getViewer();
|
||
|
$drequest = $this->getDiffusionRequest();
|
||
|
$repository = $drequest->getRepository();
|
||
|
|
||
|
$blame = $this->loadBlame();
|
||
|
|
||
|
$identifiers = array_fuse($blame);
|
||
|
if ($identifiers) {
|
||
|
$commits = id(new DiffusionCommitQuery())
|
||
|
->setViewer($viewer)
|
||
|
->withRepository($repository)
|
||
|
->withIdentifiers($identifiers)
|
||
|
->execute();
|
||
|
$commits = mpull($commits, null, 'getCommitIdentifier');
|
||
|
} else {
|
||
|
$commits = array();
|
||
|
}
|
||
|
|
||
|
$commit_map = mpull($commits, 'getCommitIdentifier', 'getPHID');
|
||
|
|
||
|
$revisions = array();
|
||
|
$revision_map = array();
|
||
|
if ($commits) {
|
||
|
$revision_ids = id(new DifferentialRevision())
|
||
|
->loadIDsByCommitPHIDs(array_keys($commit_map));
|
||
|
if ($revision_ids) {
|
||
|
$revisions = id(new DifferentialRevisionQuery())
|
||
|
->setViewer($viewer)
|
||
|
->withIDs($revision_ids)
|
||
|
->execute();
|
||
|
$revisions = mpull($revisions, null, 'getID');
|
||
|
}
|
||
|
|
||
|
foreach ($revision_ids as $commit_phid => $revision_id) {
|
||
|
// If the viewer can't actually see this revision, skip it.
|
||
|
if (!isset($revisions[$revision_id])) {
|
||
|
continue;
|
||
|
}
|
||
|
$revision_map[$commit_map[$commit_phid]] = $revision_id;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$base_href = (string)$drequest->generateURI(
|
||
|
array(
|
||
|
'action' => 'browse',
|
||
|
'stable' => true,
|
||
|
));
|
||
|
|
||
|
$skip_text = pht('Skip Past This Commit');
|
||
|
$skip_icon = id(new PHUIIconView())
|
||
|
->setIcon('fa-backward');
|
||
|
|
||
|
Javelin::initBehavior('phabricator-tooltips');
|
||
|
|
||
|
$handle_phids = array();
|
||
|
foreach ($commits as $commit) {
|
||
|
$author_phid = $commit->getAuthorPHID();
|
||
|
if ($author_phid) {
|
||
|
$handle_phids[] = $author_phid;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
foreach ($revisions as $revision) {
|
||
|
$handle_phids[] = $revision->getAuthorPHID();
|
||
|
}
|
||
|
|
||
|
$handles = $viewer->loadHandles($handle_phids);
|
||
|
|
||
|
$map = array();
|
||
|
foreach ($identifiers as $identifier) {
|
||
|
$revision_id = idx($revision_map, $identifier);
|
||
|
if ($revision_id) {
|
||
|
$revision = idx($revisions, $revision_id);
|
||
|
} else {
|
||
|
$revision = null;
|
||
|
}
|
||
|
|
||
|
$skip_href = $base_href.'?before='.$identifier;
|
||
|
|
||
|
$skip_link = javelin_tag(
|
||
|
'a',
|
||
|
array(
|
||
|
'href' => $skip_href,
|
||
|
'sigil' => 'has-tooltip',
|
||
|
'meta' => array(
|
||
|
'tip' => $skip_text,
|
||
|
'align' => 'E',
|
||
|
'size' => 300,
|
||
|
),
|
||
|
),
|
||
|
$skip_icon);
|
||
|
|
||
|
$commit = $commits[$identifier];
|
||
|
|
||
|
$author_phid = $commit->getAuthorPHID();
|
||
|
if (!$author_phid && $revision) {
|
||
|
$author_phid = $revision->getAuthorPHID();
|
||
|
}
|
||
|
|
||
|
if (!$author_phid) {
|
||
|
// This means we couldn't identify an author for the commit or the
|
||
|
// revision. We just render a blank for alignment.
|
||
|
$author_style = null;
|
||
|
$author_href = null;
|
||
|
$author_sigil = null;
|
||
|
$author_meta = null;
|
||
|
} else {
|
||
|
$author_src = $handles[$author_phid]->getImageURI();
|
||
|
$author_style = 'background-image: url('.$author_src.');';
|
||
|
$author_href = $handles[$author_phid]->getURI();
|
||
|
$author_sigil = 'has-tooltip';
|
||
|
$author_meta = array(
|
||
|
'tip' => $handles[$author_phid]->getName(),
|
||
|
'align' => 'E',
|
||
|
);
|
||
|
}
|
||
|
|
||
|
$author_link = javelin_tag(
|
||
|
$author_href ? 'a' : 'span',
|
||
|
array(
|
||
|
'class' => 'phabricator-source-blame-author',
|
||
|
'style' => $author_style,
|
||
|
'href' => $author_href,
|
||
|
'sigil' => $author_sigil,
|
||
|
'meta' => $author_meta,
|
||
|
));
|
||
|
|
||
|
$commit_link = javelin_tag(
|
||
|
'a',
|
||
|
array(
|
||
|
'href' => $commit->getURI(),
|
||
|
'sigil' => 'has-tooltip',
|
||
|
'meta' => array(
|
||
|
'tip' => $this->renderCommitTooltip($commit, $handles),
|
||
|
'align' => 'E',
|
||
|
'size' => 600,
|
||
|
),
|
||
|
),
|
||
|
$commit->getLocalName());
|
||
|
|
||
|
$info = array(
|
||
|
$author_link,
|
||
|
$commit_link,
|
||
|
);
|
||
|
|
||
|
if ($revision) {
|
||
|
$revision_link = phutil_tag(
|
||
|
'a',
|
||
|
array(
|
||
|
'href' => $revision->getURI(),
|
||
|
'sigil' => 'has-tooltip',
|
||
|
'meta' => array(
|
||
|
'tip' => $this->renderRevisionTooltip($revision, $handles),
|
||
|
'align' => 'E',
|
||
|
'size' => 600,
|
||
|
),
|
||
|
),
|
||
|
$revision->getMonogram());
|
||
|
|
||
|
|
||
|
$info = array(
|
||
|
$info,
|
||
|
' / ',
|
||
|
$revision_link,
|
||
|
);
|
||
|
}
|
||
|
|
||
|
$data = array(
|
||
|
'skip' => $skip_link,
|
||
|
'info' => hsprintf('%s', $info),
|
||
|
);
|
||
|
|
||
|
$map[$identifier] = $data;
|
||
|
}
|
||
|
|
||
|
return id(new AphrontAjaxResponse())->setContent(
|
||
|
array(
|
||
|
'blame' => $blame,
|
||
|
'map' => $map,
|
||
|
));
|
||
|
}
|
||
|
|
||
|
private function loadBlame() {
|
||
|
$drequest = $this->getDiffusionRequest();
|
||
|
|
||
|
$commit = $drequest->getCommit();
|
||
|
$path = $drequest->getPath();
|
||
|
|
||
|
$blame_timeout = 15;
|
||
|
|
||
|
$blame = $this->callConduitWithDiffusionRequest(
|
||
|
'diffusion.blame',
|
||
|
array(
|
||
|
'commit' => $commit,
|
||
|
'paths' => array($path),
|
||
|
'timeout' => $blame_timeout,
|
||
|
));
|
||
|
|
||
|
return idx($blame, $path, array());
|
||
|
}
|
||
|
|
||
|
private function renderRevisionTooltip(
|
||
|
DifferentialRevision $revision,
|
||
|
$handles) {
|
||
|
$viewer = $this->getViewer();
|
||
|
|
||
|
$date = phabricator_date($revision->getDateModified(), $viewer);
|
||
|
$monogram = $revision->getMonogram();
|
||
|
$title = $revision->getTitle();
|
||
|
$header = "{$monogram} {$title}";
|
||
|
|
||
|
$author = $handles[$revision->getAuthorPHID()]->getName();
|
||
|
|
||
|
return "{$header}\n{$date} \xC2\xB7 {$author}";
|
||
|
}
|
||
|
|
||
|
private function renderCommitTooltip(
|
||
|
PhabricatorRepositoryCommit $commit,
|
||
|
$handles) {
|
||
|
|
||
|
$viewer = $this->getViewer();
|
||
|
|
||
|
$date = phabricator_date($commit->getEpoch(), $viewer);
|
||
|
$summary = trim($commit->getSummary());
|
||
|
|
||
|
$author_phid = $commit->getAuthorPHID();
|
||
|
if ($author_phid && isset($handles[$author_phid])) {
|
||
|
$author_name = $handles[$author_phid]->getName();
|
||
|
} else {
|
||
|
$author_name = null;
|
||
|
}
|
||
|
|
||
|
if ($author_name) {
|
||
|
return "{$summary}\n{$date} \xC2\xB7 {$author_name}";
|
||
|
} else {
|
||
|
return "{$summary}\n{$date}";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|