Page MenuHomePhabricator

D13908.diff
No OneTemporary

D13908.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1362,6 +1362,8 @@
'PHUIDiffInlineCommentView' => 'infrastructure/diff/view/PHUIDiffInlineCommentView.php',
'PHUIDiffOneUpInlineCommentRowScaffold' => 'infrastructure/diff/view/PHUIDiffOneUpInlineCommentRowScaffold.php',
'PHUIDiffRevealIconView' => 'infrastructure/diff/view/PHUIDiffRevealIconView.php',
+ 'PHUIDiffTableOfContentsItemView' => 'infrastructure/diff/view/PHUIDiffTableOfContentsItemView.php',
+ 'PHUIDiffTableOfContentsListView' => 'infrastructure/diff/view/PHUIDiffTableOfContentsListView.php',
'PHUIDiffTwoUpInlineCommentRowScaffold' => 'infrastructure/diff/view/PHUIDiffTwoUpInlineCommentRowScaffold.php',
'PHUIDocumentExample' => 'applications/uiexample/examples/PHUIDocumentExample.php',
'PHUIDocumentView' => 'view/phui/PHUIDocumentView.php',
@@ -5157,6 +5159,8 @@
'PHUIDiffInlineCommentView' => 'AphrontView',
'PHUIDiffOneUpInlineCommentRowScaffold' => 'PHUIDiffInlineCommentRowScaffold',
'PHUIDiffRevealIconView' => 'AphrontView',
+ 'PHUIDiffTableOfContentsItemView' => 'AphrontView',
+ 'PHUIDiffTableOfContentsListView' => 'AphrontView',
'PHUIDiffTwoUpInlineCommentRowScaffold' => 'PHUIDiffInlineCommentRowScaffold',
'PHUIDocumentExample' => 'PhabricatorUIExample',
'PHUIDocumentView' => 'AphrontTagView',
diff --git a/src/applications/differential/controller/DifferentialRevisionViewController.php b/src/applications/differential/controller/DifferentialRevisionViewController.php
--- a/src/applications/differential/controller/DifferentialRevisionViewController.php
+++ b/src/applications/differential/controller/DifferentialRevisionViewController.php
@@ -349,16 +349,10 @@
$other_view = $this->renderOtherRevisions($other_revisions);
}
- $toc_view = new DifferentialDiffTableOfContentsView();
- $toc_view->setChangesets($changesets);
- $toc_view->setVisibleChangesets($visible_changesets);
- $toc_view->setRenderingReferences($rendering_references);
- $toc_view->setCoverageMap($target->loadCoverageMap($user));
- if ($repository) {
- $toc_view->setRepository($repository);
- }
- $toc_view->setDiff($target);
- $toc_view->setUser($user);
+ $toc_view = $this->buildTableOfContents(
+ $changesets,
+ $visible_changesets,
+ $target->loadCoverageMap($user));
$comment_form = null;
if (!$viewer_is_anonymous) {
@@ -1042,5 +1036,34 @@
return $view;
}
+ private function buildTableOfContents(
+ array $changesets,
+ array $visible_changesets,
+ array $coverage) {
+ $viewer = $this->getViewer();
+
+ $toc_view = id(new PHUIDiffTableOfContentsListView())
+ ->setUser($viewer);
+
+ foreach ($changesets as $changeset_id => $changeset) {
+ $is_visible = isset($visible_changesets[$changeset_id]);
+ $anchor = $changeset->getAnchorName();
+
+ $filename = $changeset->getFilename();
+ $coverage_id = 'differential-mcoverage-'.md5($filename);
+
+ $item = id(new PHUIDiffTableOfContentsItemView())
+ ->setChangeset($changeset)
+ ->setIsVisible($is_visible)
+ ->setAnchor($anchor)
+ ->setCoverage(idx($coverage, $filename))
+ ->setCoverageID($coverage_id);
+
+ $toc_view->addItem($item);
+ }
+
+ return $toc_view;
+ }
+
}
diff --git a/src/infrastructure/diff/view/PHUIDiffTableOfContentsItemView.php b/src/infrastructure/diff/view/PHUIDiffTableOfContentsItemView.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/diff/view/PHUIDiffTableOfContentsItemView.php
@@ -0,0 +1,295 @@
+<?php
+
+final class PHUIDiffTableOfContentsItemView extends AphrontView {
+
+ private $changeset;
+ private $isVisible;
+ private $anchor;
+ private $coverage;
+ private $coverageID;
+
+ public function setChangeset(DifferentialChangeset $changeset) {
+ $this->changeset = $changeset;
+ return $this;
+ }
+
+ public function getChangeset() {
+ return $this->changeset;
+ }
+
+ public function setIsVisible($is_visible) {
+ $this->isVisible = $is_visible;
+ return $this;
+ }
+
+ public function getIsVisible() {
+ return $this->isVisible;
+ }
+
+ public function setAnchor($anchor) {
+ $this->anchor = $anchor;
+ return $this;
+ }
+
+ public function getAnchor() {
+ return $this->anchor;
+ }
+
+ public function setCoverage($coverage) {
+ $this->coverage = $coverage;
+ return $this;
+ }
+
+ public function getCoverage() {
+ return $this->coverage;
+ }
+
+ public function setCoverageID($coverage_id) {
+ $this->coverageID = $coverage_id;
+ return $this;
+ }
+
+ public function getCoverageID() {
+ return $this->coverageID;
+ }
+
+ public function render() {
+ $changeset = $this->getChangeset();
+
+ $cells = array();
+
+ $cells[] = $this->renderPathChangeCharacter();
+ $cells[] = $this->renderPropertyChangeCharacter();
+ $cells[] = $this->renderPropertyChangeDescription();
+
+ $link = $this->renderChangesetLink();
+ $lines = $this->renderChangesetLines();
+ $meta = $this->renderChangesetMetadata();
+
+ $cells[] = array(
+ $link,
+ $lines,
+ $meta,
+ );
+
+ $cells[] = $this->renderCoverage();
+ $cells[] = $this->renderModifiedCoverage();
+
+ return $cells;
+ }
+
+ private function renderPathChangeCharacter() {
+ $changeset = $this->getChangeset();
+ $type = $changeset->getChangeType();
+
+ $color = DifferentialChangeType::getSummaryColorForChangeType($type);
+ $char = DifferentialChangeType::getSummaryCharacterForChangeType($type);
+ $title = DifferentialChangeType::getFullNameForChangeType($type);
+
+ return javelin_tag(
+ 'span',
+ array(
+ 'sigil' => 'has-tip',
+ 'meta' => array(
+ 'tip' => $title,
+ 'align' => 'E',
+ ),
+ 'class' => 'phui-text-'.$color,
+ ),
+ $char);
+ }
+
+ private function renderPropertyChangeCharacter() {
+ $changeset = $this->getChangeset();
+
+ $old = $changeset->getOldProperties();
+ $new = $changeset->getNewProperties();
+
+ if ($old === $new) {
+ return null;
+ }
+
+ return javelin_tag(
+ 'span',
+ array(
+ 'sigil' => 'has-tip',
+ 'meta' => array(
+ 'tip' => pht('Properties Modified'),
+ 'align' => 'E',
+ ),
+ ),
+ 'M');
+ }
+
+ private function renderPropertyChangeDescription() {
+ $changeset = $this->getChangeset();
+
+ $file_type = $changeset->getFileType();
+
+ $desc = DifferentialChangeType::getShortNameForFileType($file_type);
+ if ($desc === null) {
+ return null;
+ }
+
+ return pht('(%s)', $desc);
+ }
+
+ private function renderChangesetLink() {
+ $anchor = $this->getAnchor();
+
+ $changeset = $this->getChangeset();
+ $name = $changeset->getDisplayFilename();
+
+ $change_type = $changeset->getChangeType();
+ if (DifferentialChangeType::isOldLocationChangeType($change_type)) {
+ $away = $changeset->getAwayPaths();
+ if (count($away) == 1) {
+ if ($change_type == DifferentialChangeType::TYPE_MOVE_AWAY) {
+ $right_arrow = "\xE2\x86\x92";
+ $name = $this->renderRename($name, head($away), $right_arrow);
+ }
+ }
+ } else if ($change_type == DifferentialChangeType::TYPE_MOVE_HERE) {
+ $left_arrow = "\xE2\x86\x90";
+ $name = $this->renderRename($name, $changeset->getOldFile(), $left_arrow);
+ }
+
+ return javelin_tag(
+ 'a',
+ array(
+ 'href' => '#'.$anchor,
+ 'sigil' => 'differential-load',
+ 'meta' => array(
+ 'id' => 'diff-'.$anchor,
+ ),
+ ),
+ $name);
+ }
+
+ private function renderChangesetLines() {
+ $changeset = $this->getChangeset();
+
+ $line_count = $changeset->getAffectedLineCount();
+ if (!$line_count) {
+ return null;
+ }
+
+ return ' '.pht('(%d line(s))', $line_count);
+ }
+
+ private function renderCoverage() {
+ $not_applicable = '-';
+
+ $coverage = $this->getCoverage();
+ if (!strlen($coverage)) {
+ return $not_applicable;
+ }
+
+ $covered = substr_count($coverage, 'C');
+ $not_covered = substr_count($coverage, 'U');
+
+ if (!$not_covered && !$covered) {
+ return $not_applicable;
+ }
+
+ return sprintf('%d%%', 100 * ($covered / ($covered + $not_covered)));
+ }
+
+ private function renderModifiedCoverage() {
+ $not_applicable = '-';
+
+ $coverage = $this->getCoverage();
+ if (!strlen($coverage)) {
+ return $not_applicable;
+ }
+
+ if ($this->getIsVisible()) {
+ $label = pht('Loading...');
+ } else {
+ $label = pht('?');
+ }
+
+ return phutil_tag(
+ 'div',
+ array(
+ 'id' => $this->getCoverageID(),
+ 'class' => 'differential-mcoverage-loading',
+ ),
+ $label);
+ }
+
+ private function renderChangesetMetadata() {
+ $changeset = $this->getChangeset();
+ $type = $changeset->getChangeType();
+
+ $meta = array();
+ if (DifferentialChangeType::isOldLocationChangeType($type)) {
+ $away = $changeset->getAwayPaths();
+ if (count($away) > 1) {
+ if ($type == DifferentialChangeType::TYPE_MULTICOPY) {
+ $meta[] = pht('Deleted after being copied to multiple locations:');
+ } else {
+ $meta[] = pht('Copied to multiple locations:');
+ }
+ foreach ($away as $path) {
+ $meta[] = $path;
+ }
+ } else {
+ if ($type == DifferentialChangeType::TYPE_MOVE_AWAY) {
+ // This case is handled when we render the path.
+ } else {
+ $meta[] = pht('Copied to %s', head($away));
+ }
+ }
+ } else if ($type == DifferentialChangeType::TYPE_COPY_HERE) {
+ $meta = pht('Copied from %s', $changeset->getOldFile());
+ }
+
+ if (!$meta) {
+ return null;
+ }
+
+ $meta = phutil_implode_html(phutil_tag('br'), $meta);
+
+ return phutil_tag(
+ 'div',
+ array(
+ 'class' => 'differential-toc-meta',
+ ),
+ $meta);
+ }
+
+ private function renderRename($self, $other, $arrow) {
+ $old = explode('/', $self);
+ $new = explode('/', $other);
+
+ $start = count($old);
+ foreach ($old as $index => $part) {
+ if (!isset($new[$index]) || $part != $new[$index]) {
+ $start = $index;
+ break;
+ }
+ }
+
+ $end = count($old);
+ foreach (array_reverse($old) as $from_end => $part) {
+ $index = count($new) - $from_end - 1;
+ if (!isset($new[$index]) || $part != $new[$index]) {
+ $end = $from_end;
+ break;
+ }
+ }
+
+ $rename =
+ '{'.
+ implode('/', array_slice($old, $start, count($old) - $end - $start)).
+ ' '.$arrow.' '.
+ implode('/', array_slice($new, $start, count($new) - $end - $start)).
+ '}';
+
+ array_splice($new, $start, count($new) - $end - $start, $rename);
+
+ return implode('/', $new);
+ }
+
+}
diff --git a/src/infrastructure/diff/view/PHUIDiffTableOfContentsListView.php b/src/infrastructure/diff/view/PHUIDiffTableOfContentsListView.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/diff/view/PHUIDiffTableOfContentsListView.php
@@ -0,0 +1,80 @@
+<?php
+
+final class PHUIDiffTableOfContentsListView extends AphrontView {
+
+ private $items = array();
+
+ public function addItem(PHUIDiffTableOfContentsItemView $item) {
+ $this->items[] = $item;
+ return $this;
+ }
+
+ public function render() {
+ $this->requireResource('differential-core-view-css');
+ $this->requireResource('differential-table-of-contents-css');
+ $this->requireResource('phui-text-css');
+
+ $items = $this->items;
+
+ $rows = array();
+ foreach ($items as $item) {
+ $rows[] = $item->render();
+ }
+
+ $reveal_link = javelin_tag(
+ 'a',
+ array(
+ 'sigil' => 'differential-reveal-all',
+ 'mustcapture' => true,
+ 'class' => 'button differential-toc-reveal-all',
+ ),
+ pht('Show All Context'));
+
+ $buttons = phutil_tag(
+ 'div',
+ array(
+ 'class' => 'differential-toc-buttons grouped',
+ ),
+ $reveal_link);
+
+ $table = id(new AphrontTableView($rows))
+ ->setHeaders(
+ array(
+ '',
+ '',
+ '',
+ pht('Path'),
+ pht('Coverage (All)'),
+ pht('Coverage (Touched)'),
+ ))
+ ->setColumnClasses(
+ array(
+ 'differential-toc-char center',
+ 'differential-toc-prop center',
+ 'differential-toc-ftype center',
+ 'differential-toc-file wide',
+ 'differential-toc-cov',
+ 'differential-toc-cov',
+ ))
+ ->setDeviceVisibility(
+ array(
+ true,
+ true,
+ true,
+ true,
+ false,
+ false,
+ ));
+
+ $anchor = id(new PhabricatorAnchorView())
+ ->setAnchorName('toc')
+ ->setNavigationMarker(true);
+
+ return id(new PHUIObjectBoxView())
+ ->setHeaderText(pht('Table of Contents'))
+ ->setTable($table)
+ ->appendChild($anchor)
+ ->appendChild($buttons);
+ }
+
+}

File Metadata

Mime Type
text/plain
Expires
Fri, Mar 21, 12:02 AM (1 d, 11 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7714657
Default Alt Text
D13908.diff (13 KB)

Event Timeline