2011-07-17 20:06:02 +02:00
|
|
|
<?php
|
|
|
|
|
2014-07-10 00:12:48 +02:00
|
|
|
final class PhrictionDiffController extends PhrictionController {
|
2011-07-17 20:06:02 +02:00
|
|
|
|
|
|
|
private $id;
|
|
|
|
|
2014-11-08 00:36:58 +01:00
|
|
|
public function shouldAllowPublic() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-07-17 20:06:02 +02:00
|
|
|
public function willProcessRequest(array $data) {
|
|
|
|
$this->id = $data['id'];
|
|
|
|
}
|
|
|
|
|
|
|
|
public function processRequest() {
|
|
|
|
$request = $this->getRequest();
|
|
|
|
$user = $request->getUser();
|
|
|
|
|
2014-05-19 21:41:12 +02:00
|
|
|
$document = id(new PhrictionDocumentQuery())
|
|
|
|
->setViewer($user)
|
|
|
|
->withIDs(array($this->id))
|
|
|
|
->needContent(true)
|
|
|
|
->executeOne();
|
2011-07-17 20:06:02 +02:00
|
|
|
if (!$document) {
|
|
|
|
return new Aphront404Response();
|
|
|
|
}
|
|
|
|
|
2014-05-19 21:41:12 +02:00
|
|
|
$current = $document->getContent();
|
2011-07-17 20:06:02 +02:00
|
|
|
|
|
|
|
$l = $request->getInt('l');
|
|
|
|
$r = $request->getInt('r');
|
|
|
|
|
|
|
|
$ref = $request->getStr('ref');
|
|
|
|
if ($ref) {
|
|
|
|
list($l, $r) = explode(',', $ref);
|
|
|
|
}
|
|
|
|
|
|
|
|
$content = id(new PhrictionContent())->loadAllWhere(
|
|
|
|
'documentID = %d AND version IN (%Ld)',
|
|
|
|
$document->getID(),
|
|
|
|
array($l, $r));
|
|
|
|
$content = mpull($content, null, 'getVersion');
|
|
|
|
|
|
|
|
$content_l = idx($content, $l, null);
|
|
|
|
$content_r = idx($content, $r, null);
|
|
|
|
|
|
|
|
if (!$content_l || !$content_r) {
|
|
|
|
return new Aphront404Response();
|
|
|
|
}
|
|
|
|
|
|
|
|
$text_l = $content_l->getContent();
|
|
|
|
$text_r = $content_r->getContent();
|
|
|
|
|
2013-02-28 18:17:58 +01:00
|
|
|
$text_l = phutil_utf8_hard_wrap($text_l, 80);
|
2013-03-03 20:37:45 +01:00
|
|
|
$text_l = implode("\n", $text_l);
|
2013-02-28 18:17:58 +01:00
|
|
|
$text_r = phutil_utf8_hard_wrap($text_r, 80);
|
2013-03-03 20:37:45 +01:00
|
|
|
$text_r = implode("\n", $text_r);
|
2011-07-17 20:06:02 +02:00
|
|
|
|
|
|
|
$engine = new PhabricatorDifferenceEngine();
|
|
|
|
$changeset = $engine->generateChangesetFromFileContent($text_l, $text_r);
|
|
|
|
|
2015-03-05 23:02:45 +01:00
|
|
|
$changeset->setFilename($content_r->getTitle());
|
|
|
|
|
2011-07-17 20:06:02 +02:00
|
|
|
$changeset->setOldProperties(
|
|
|
|
array(
|
|
|
|
'Title' => $content_l->getTitle(),
|
|
|
|
));
|
|
|
|
$changeset->setNewProperties(
|
|
|
|
array(
|
|
|
|
'Title' => $content_r->getTitle(),
|
|
|
|
));
|
|
|
|
|
|
|
|
$whitespace_mode = DifferentialChangesetParser::WHITESPACE_SHOW_ALL;
|
|
|
|
|
2015-03-08 14:02:47 +01:00
|
|
|
$parser = id(new DifferentialChangesetParser())
|
|
|
|
->setUser($user)
|
|
|
|
->setChangeset($changeset)
|
|
|
|
->setRenderingReference("{$l},{$r}");
|
|
|
|
|
|
|
|
$parser->readParametersFromRequest($request);
|
2011-07-17 20:06:02 +02:00
|
|
|
$parser->setWhitespaceMode($whitespace_mode);
|
|
|
|
|
2012-12-09 02:35:34 +01:00
|
|
|
$engine = new PhabricatorMarkupEngine();
|
|
|
|
$engine->setViewer($user);
|
|
|
|
$engine->process();
|
|
|
|
$parser->setMarkupEngine($engine);
|
|
|
|
|
2011-07-17 20:06:02 +02:00
|
|
|
$spec = $request->getStr('range');
|
|
|
|
list($range_s, $range_e, $mask) =
|
|
|
|
DifferentialChangesetParser::parseRangeSpecification($spec);
|
2015-03-05 23:02:45 +01:00
|
|
|
|
2015-03-08 14:02:47 +01:00
|
|
|
$parser->setRange($range_s, $range_e);
|
|
|
|
$parser->setMask($mask);
|
2011-07-17 20:06:02 +02:00
|
|
|
|
|
|
|
if ($request->isAjax()) {
|
2012-03-13 05:39:05 +01:00
|
|
|
return id(new PhabricatorChangesetResponse())
|
2015-03-08 14:02:47 +01:00
|
|
|
->setRenderedChangeset($parser->renderChangeset());
|
2011-07-17 20:06:02 +02:00
|
|
|
}
|
|
|
|
|
2015-03-08 14:02:47 +01:00
|
|
|
$changes = id(new DifferentialChangesetListView())
|
2015-03-05 23:02:45 +01:00
|
|
|
->setUser($this->getViewer())
|
2015-03-08 14:02:47 +01:00
|
|
|
->setChangesets(array($changeset))
|
|
|
|
->setVisibleChangesets(array($changeset))
|
|
|
|
->setRenderingReferences(array("{$l},{$r}"))
|
Make "Show Context" persist rendering, whitespace, encoding, etc
Summary:
Ref T2009. Currently, we do not persist view parameters when making context rendering requests.
The big one is the renderer (1up vs 2up). This makes context on unified diffs come in with too many columns.
However, it impacts other parameters too. For example, at HEAD, if you change highlighting to "rainbow" and then load more context, the context uses the original highlighter instead of the rainbow highlighter.
This moves context loads into ChangesetViewManager, which maintains view parameters and can provide them correctly.
- This removes "ref"; it is no longer required, as the ChangesetViewManager tracks it.
- This removes URI management from `behavior-show-more`; it is no longer required, since the ChangesetViewManager knows how to render.
- This removes "whitespace" since this is handled properly by the view manager.
Test Plan:
- Used "Show Top" / "Show All" / "Show Bottom" in 1-up and 2-up views.
- Changed file highlighting to rainbow, loaded stuff, saw rainbow stick.
- Used "Show Entire File" in 1-up and 2-up views.
- Saw loading chrome.
- No loading chrome normally.
- Made inlines, verified `copyRows()` code runs.
- Poked around Diffusion -- it is missing some parameter handling, but works OK.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T2009
Differential Revision: https://secure.phabricator.com/D11977
2015-03-05 23:03:00 +01:00
|
|
|
->setRenderURI('/phriction/diff/'.$document->getID().'/')
|
2015-03-08 14:02:47 +01:00
|
|
|
->setTitle(pht('Changes'))
|
|
|
|
->setParser($parser);
|
2015-03-05 23:02:45 +01:00
|
|
|
|
2011-07-17 20:06:02 +02:00
|
|
|
require_celerity_resource('phriction-document-css');
|
|
|
|
|
|
|
|
$slug = $document->getSlug();
|
|
|
|
|
|
|
|
$revert_l = $this->renderRevertButton($content_l, $current);
|
|
|
|
$revert_r = $this->renderRevertButton($content_r, $current);
|
|
|
|
|
2013-03-13 23:15:58 +01:00
|
|
|
$crumbs = $this->buildApplicationCrumbs();
|
|
|
|
$crumb_views = $this->renderBreadcrumbs($slug);
|
|
|
|
foreach ($crumb_views as $view) {
|
|
|
|
$crumbs->addCrumb($view);
|
|
|
|
}
|
|
|
|
|
2013-12-19 02:47:34 +01:00
|
|
|
$crumbs->addTextCrumb(
|
|
|
|
pht('History'),
|
|
|
|
PhrictionDocument::getSlugURI($slug, 'history'));
|
2013-03-13 23:15:58 +01:00
|
|
|
|
2014-06-09 20:36:49 +02:00
|
|
|
$title = pht('Version %s vs %s', $l, $r);
|
2013-03-13 23:15:58 +01:00
|
|
|
|
2013-09-17 18:12:37 +02:00
|
|
|
$header = id(new PHUIHeaderView())
|
2015-05-31 21:15:15 +02:00
|
|
|
->setHeader($title)
|
|
|
|
->setTall(true);
|
2013-03-13 23:15:58 +01:00
|
|
|
|
2013-12-19 02:47:34 +01:00
|
|
|
$crumbs->addTextCrumb($title, $request->getRequestURI());
|
2013-03-13 23:15:58 +01:00
|
|
|
|
2011-07-17 20:06:02 +02:00
|
|
|
|
|
|
|
$comparison_table = $this->renderComparisonTable(
|
|
|
|
array(
|
|
|
|
$content_r,
|
|
|
|
$content_l,
|
|
|
|
));
|
|
|
|
|
|
|
|
$navigation_table = null;
|
|
|
|
if ($l + 1 == $r) {
|
|
|
|
$nav_l = ($l > 1);
|
|
|
|
$nav_r = ($r != $current->getVersion());
|
|
|
|
|
|
|
|
$uri = $request->getRequestURI();
|
|
|
|
|
|
|
|
if ($nav_l) {
|
2013-01-18 03:57:09 +01:00
|
|
|
$link_l = phutil_tag(
|
2011-07-17 20:06:02 +02:00
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => $uri->alter('l', $l - 1)->alter('r', $r - 1),
|
[Redesign] Add Table, Collapse support to ObjectBox
Summary: Converts most all tables to be directly set via `setTable` to an ObjectBox. I think this path is more flexible design wise, as we can change the box based on children, and not just CSS. We also already do this with PropertyList, Forms, ObjectList, and Header. `setCollapsed` is added to ObjectBox to all children objects to bleed to the edges (like diffs).
Test Plan: I did a grep of `appendChild($table)` as well as searches for `PHUIObjectBoxView`, also with manual opening of hundreds of files. I'm sure I missed 5-8 places. If you just appendChild($table) nothing breaks, it just looks a little funny.
Reviewers: epriestley, btrahan
Subscribers: Korvin, epriestley
Differential Revision: https://secure.phabricator.com/D12955
2015-05-20 21:43:34 +02:00
|
|
|
'class' => 'button simple',
|
2011-07-17 20:06:02 +02:00
|
|
|
),
|
2013-02-08 18:54:27 +01:00
|
|
|
pht("\xC2\xAB Previous Change"));
|
2011-07-17 20:06:02 +02:00
|
|
|
} else {
|
2013-10-30 00:06:13 +01:00
|
|
|
$link_l = phutil_tag(
|
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => '#',
|
|
|
|
'class' => 'button grey disabled',
|
|
|
|
),
|
|
|
|
pht('Original Change'));
|
2011-07-17 20:06:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$link_r = null;
|
|
|
|
if ($nav_r) {
|
2013-01-18 03:57:09 +01:00
|
|
|
$link_r = phutil_tag(
|
2011-07-17 20:06:02 +02:00
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => $uri->alter('l', $l + 1)->alter('r', $r + 1),
|
[Redesign] Add Table, Collapse support to ObjectBox
Summary: Converts most all tables to be directly set via `setTable` to an ObjectBox. I think this path is more flexible design wise, as we can change the box based on children, and not just CSS. We also already do this with PropertyList, Forms, ObjectList, and Header. `setCollapsed` is added to ObjectBox to all children objects to bleed to the edges (like diffs).
Test Plan: I did a grep of `appendChild($table)` as well as searches for `PHUIObjectBoxView`, also with manual opening of hundreds of files. I'm sure I missed 5-8 places. If you just appendChild($table) nothing breaks, it just looks a little funny.
Reviewers: epriestley, btrahan
Subscribers: Korvin, epriestley
Differential Revision: https://secure.phabricator.com/D12955
2015-05-20 21:43:34 +02:00
|
|
|
'class' => 'button simple',
|
2011-07-17 20:06:02 +02:00
|
|
|
),
|
2013-02-08 18:54:27 +01:00
|
|
|
pht("Next Change \xC2\xBB"));
|
2011-07-17 20:06:02 +02:00
|
|
|
} else {
|
2013-10-30 00:06:13 +01:00
|
|
|
$link_r = phutil_tag(
|
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => '#',
|
|
|
|
'class' => 'button grey disabled',
|
|
|
|
),
|
|
|
|
pht('Most Recent Change'));
|
2011-07-17 20:06:02 +02:00
|
|
|
}
|
|
|
|
|
2013-11-11 18:23:23 +01:00
|
|
|
$navigation_table = phutil_tag(
|
|
|
|
'table',
|
|
|
|
array('class' => 'phriction-history-nav-table'),
|
|
|
|
phutil_tag('tr', array(), array(
|
|
|
|
phutil_tag('td', array('class' => 'nav-prev'), $link_l),
|
|
|
|
phutil_tag('td', array('class' => 'nav-next'), $link_r),
|
|
|
|
)));
|
2011-07-17 20:06:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-02-13 23:50:15 +01:00
|
|
|
$output = hsprintf(
|
2014-03-30 20:18:49 +02:00
|
|
|
'<div class="phriction-document-history-diff">'.
|
2013-10-30 00:06:13 +01:00
|
|
|
'%s%s'.
|
2011-07-17 20:06:02 +02:00
|
|
|
'<table class="phriction-revert-table">'.
|
2013-02-13 23:50:15 +01:00
|
|
|
'<tr><td>%s</td><td>%s</td>'.
|
2011-07-17 20:06:02 +02:00
|
|
|
'</table>'.
|
2013-02-13 23:50:15 +01:00
|
|
|
'</div>',
|
|
|
|
$comparison_table->render(),
|
|
|
|
$navigation_table,
|
|
|
|
$revert_l,
|
2015-03-08 14:02:47 +01:00
|
|
|
$revert_r);
|
2011-07-17 20:06:02 +02:00
|
|
|
|
2013-03-13 23:15:58 +01:00
|
|
|
|
2013-10-30 00:06:13 +01:00
|
|
|
$object_box = id(new PHUIObjectBoxView())
|
|
|
|
->setHeader($header)
|
|
|
|
->appendChild($output);
|
|
|
|
|
2013-03-13 23:15:58 +01:00
|
|
|
return $this->buildApplicationPage(
|
2011-07-17 20:06:02 +02:00
|
|
|
array(
|
|
|
|
$crumbs,
|
2013-10-30 00:06:13 +01:00
|
|
|
$object_box,
|
2015-03-08 14:02:47 +01:00
|
|
|
$changes,
|
2011-07-17 20:06:02 +02:00
|
|
|
),
|
|
|
|
array(
|
2013-02-08 18:54:27 +01:00
|
|
|
'title' => pht('Document History'),
|
2011-07-17 20:06:02 +02:00
|
|
|
));
|
2013-03-13 23:15:58 +01:00
|
|
|
|
2011-07-17 20:06:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private function renderRevertButton(
|
|
|
|
PhrictionContent $content,
|
|
|
|
PhrictionContent $current) {
|
|
|
|
|
|
|
|
$document_id = $content->getDocumentID();
|
|
|
|
$version = $content->getVersion();
|
|
|
|
|
2013-03-22 22:42:25 +01:00
|
|
|
$hidden_statuses = array(
|
|
|
|
PhrictionChangeType::CHANGE_DELETE => true, // Silly
|
|
|
|
PhrictionChangeType::CHANGE_MOVE_AWAY => true, // Plain silly
|
|
|
|
PhrictionChangeType::CHANGE_STUB => true, // Utterly silly
|
|
|
|
);
|
|
|
|
if (isset($hidden_statuses[$content->getChangeType()])) {
|
|
|
|
// Don't show an edit/revert button for changes which deleted, moved or
|
|
|
|
// stubbed the content since it's silly.
|
2011-12-17 18:19:08 +01:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2011-07-17 20:06:02 +02:00
|
|
|
if ($content->getID() == $current->getID()) {
|
2013-01-18 03:57:09 +01:00
|
|
|
return phutil_tag(
|
2011-07-17 20:06:02 +02:00
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => '/phriction/edit/'.$document_id.'/',
|
2015-05-28 23:04:54 +02:00
|
|
|
'class' => 'button simple',
|
2011-07-17 20:06:02 +02:00
|
|
|
),
|
2013-02-08 18:54:27 +01:00
|
|
|
pht('Edit Current Version'));
|
2011-07-17 20:06:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-01-18 09:32:58 +01:00
|
|
|
return phutil_tag(
|
2011-07-17 20:06:02 +02:00
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => '/phriction/edit/'.$document_id.'/?revert='.$version,
|
2015-05-28 23:04:54 +02:00
|
|
|
'class' => 'button simple',
|
2011-07-17 20:06:02 +02:00
|
|
|
),
|
2013-02-09 02:29:15 +01:00
|
|
|
pht('Revert to Version %s...', $version));
|
2011-07-17 20:06:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private function renderComparisonTable(array $content) {
|
2012-04-03 21:10:45 +02:00
|
|
|
assert_instances_of($content, 'PhrictionContent');
|
2011-07-17 20:06:02 +02:00
|
|
|
|
|
|
|
$user = $this->getRequest()->getUser();
|
|
|
|
|
|
|
|
$phids = mpull($content, 'getAuthorPHID');
|
2012-09-05 04:02:56 +02:00
|
|
|
$handles = $this->loadViewerHandles($phids);
|
2011-07-17 20:06:02 +02:00
|
|
|
|
2013-09-09 23:14:34 +02:00
|
|
|
$list = new PHUIObjectItemListView();
|
2013-03-22 22:42:25 +01:00
|
|
|
|
|
|
|
$first = true;
|
2011-07-17 20:06:02 +02:00
|
|
|
foreach ($content as $c) {
|
2013-03-22 22:42:25 +01:00
|
|
|
$author = $handles[$c->getAuthorPHID()]->renderLink();
|
2013-09-09 23:14:34 +02:00
|
|
|
$item = id(new PHUIObjectItemView())
|
2013-03-22 22:42:25 +01:00
|
|
|
->setHeader(pht('%s by %s, %s',
|
|
|
|
PhrictionChangeType::getChangeTypeLabel($c->getChangeType()),
|
|
|
|
$author,
|
|
|
|
pht('Version %s', $c->getVersion())))
|
|
|
|
->addAttribute(pht('%s %s',
|
|
|
|
phabricator_date($c->getDateCreated(), $user),
|
|
|
|
phabricator_time($c->getDateCreated(), $user)));
|
|
|
|
|
|
|
|
if ($c->getDescription()) {
|
|
|
|
$item->addAttribute($c->getDescription());
|
|
|
|
}
|
2011-07-17 20:06:02 +02:00
|
|
|
|
2013-03-22 22:42:25 +01:00
|
|
|
if ($first == true) {
|
2015-05-28 23:04:54 +02:00
|
|
|
$item->setStatusIcon('fa-file green');
|
2013-03-22 22:42:25 +01:00
|
|
|
$first = false;
|
|
|
|
} else {
|
2015-05-28 23:04:54 +02:00
|
|
|
$item->setStatusIcon('fa-file red');
|
2013-03-22 22:42:25 +01:00
|
|
|
}
|
2011-07-17 20:06:02 +02:00
|
|
|
|
2013-03-22 22:42:25 +01:00
|
|
|
$list->addItem($item);
|
|
|
|
}
|
2011-07-17 20:06:02 +02:00
|
|
|
|
2013-03-22 22:42:25 +01:00
|
|
|
return $list;
|
2011-07-17 20:06:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|