2011-01-24 13:18:41 -08:00
|
|
|
<?php
|
|
|
|
|
2012-03-09 15:46:25 -08:00
|
|
|
final class DifferentialDiffViewController extends DifferentialController {
|
2011-01-24 13:18:41 -08:00
|
|
|
|
2014-06-10 07:49:42 -07:00
|
|
|
public function shouldAllowPublic() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-10-11 08:18:42 -07:00
|
|
|
public function handleRequest(AphrontRequest $request) {
|
|
|
|
$viewer = $this->getViewer();
|
|
|
|
$id = $request->getURIData('id');
|
2011-01-30 18:52:29 -08:00
|
|
|
|
2013-07-01 12:38:42 -07:00
|
|
|
$diff = id(new DifferentialDiffQuery())
|
|
|
|
->setViewer($viewer)
|
2015-10-11 08:18:42 -07:00
|
|
|
->withIDs(array($id))
|
2013-07-01 12:38:42 -07:00
|
|
|
->executeOne();
|
2011-01-24 13:18:41 -08:00
|
|
|
if (!$diff) {
|
|
|
|
return new Aphront404Response();
|
|
|
|
}
|
|
|
|
|
2011-05-02 17:44:47 -07:00
|
|
|
if ($diff->getRevisionID()) {
|
2015-02-19 10:55:56 -08:00
|
|
|
return id(new AphrontRedirectResponse())
|
|
|
|
->setURI('/D'.$diff->getRevisionID().'?id='.$diff->getID());
|
|
|
|
}
|
2011-02-03 15:41:58 -08:00
|
|
|
|
2016-12-13 15:39:10 -08:00
|
|
|
if ($request->isFormPost()) {
|
|
|
|
$diff_id = $diff->getID();
|
|
|
|
$revision_id = $request->getInt('revisionID');
|
|
|
|
if ($revision_id) {
|
|
|
|
$attach_uri = "/revision/attach/{$diff_id}/to/{$revision_id}/";
|
|
|
|
} else {
|
|
|
|
$attach_uri = "/revision/attach/{$diff_id}/to/";
|
|
|
|
}
|
|
|
|
$attach_uri = $this->getApplicationURI($attach_uri);
|
|
|
|
|
|
|
|
return id(new AphrontRedirectResponse())
|
|
|
|
->setURI($attach_uri);
|
|
|
|
}
|
|
|
|
|
2015-08-11 06:39:05 -07:00
|
|
|
$diff_phid = $diff->getPHID();
|
|
|
|
$buildables = id(new HarbormasterBuildableQuery())
|
|
|
|
->setViewer($viewer)
|
|
|
|
->withBuildablePHIDs(array($diff_phid))
|
|
|
|
->withManualBuildables(false)
|
|
|
|
->needBuilds(true)
|
|
|
|
->needTargets(true)
|
|
|
|
->execute();
|
|
|
|
$buildables = mpull($buildables, null, 'getBuildablePHID');
|
|
|
|
$diff->attachBuildable(idx($buildables, $diff_phid));
|
|
|
|
|
2015-02-19 10:55:56 -08:00
|
|
|
// TODO: implement optgroup support in AphrontFormSelectControl?
|
|
|
|
$select = array();
|
|
|
|
$select[] = hsprintf('<optgroup label="%s">', pht('Create New Revision'));
|
|
|
|
$select[] = phutil_tag(
|
|
|
|
'option',
|
|
|
|
array('value' => ''),
|
|
|
|
pht('Create a new Revision...'));
|
|
|
|
$select[] = hsprintf('</optgroup>');
|
|
|
|
|
2015-03-23 10:44:33 -07:00
|
|
|
$selected_id = $request->getInt('revisionID');
|
|
|
|
|
2015-03-26 11:11:33 -07:00
|
|
|
$revisions = $this->loadSelectableRevisions($viewer, $selected_id);
|
|
|
|
|
2015-02-19 10:55:56 -08:00
|
|
|
if ($revisions) {
|
|
|
|
$select[] = hsprintf(
|
|
|
|
'<optgroup label="%s">',
|
|
|
|
pht('Update Existing Revision'));
|
|
|
|
foreach ($revisions as $revision) {
|
2015-03-23 10:44:33 -07:00
|
|
|
if ($selected_id == $revision->getID()) {
|
|
|
|
$selected = 'selected';
|
|
|
|
} else {
|
|
|
|
$selected = null;
|
|
|
|
}
|
|
|
|
|
2015-02-19 10:55:56 -08:00
|
|
|
$select[] = phutil_tag(
|
|
|
|
'option',
|
|
|
|
array(
|
|
|
|
'value' => $revision->getID(),
|
2015-03-23 10:44:33 -07:00
|
|
|
'selected' => $selected,
|
2015-02-19 10:55:56 -08:00
|
|
|
),
|
|
|
|
id(new PhutilUTF8StringTruncator())
|
|
|
|
->setMaximumGlyphs(128)
|
|
|
|
->truncateString(
|
|
|
|
'D'.$revision->getID().' '.$revision->getTitle()));
|
2011-05-02 17:44:47 -07:00
|
|
|
}
|
2015-02-19 10:55:56 -08:00
|
|
|
$select[] = hsprintf('</optgroup>');
|
2011-05-02 17:44:47 -07:00
|
|
|
}
|
2011-01-25 15:19:06 -08:00
|
|
|
|
2015-02-19 10:55:56 -08:00
|
|
|
$select = phutil_tag(
|
|
|
|
'select',
|
|
|
|
array('name' => 'revisionID'),
|
|
|
|
$select);
|
|
|
|
|
|
|
|
$form = id(new AphrontFormView())
|
2016-12-13 15:39:10 -08:00
|
|
|
->setViewer($viewer)
|
2015-02-19 10:55:56 -08:00
|
|
|
->appendRemarkupInstructions(
|
|
|
|
pht(
|
|
|
|
'Review the diff for correctness. When you are satisfied, either '.
|
|
|
|
'**create a new revision** or **update an existing revision**.'))
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormMarkupControl())
|
|
|
|
->setLabel(pht('Attach To'))
|
|
|
|
->setValue($select))
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormSubmitControl())
|
|
|
|
->setValue(pht('Continue')));
|
|
|
|
|
2012-11-16 11:48:17 -08:00
|
|
|
$props = id(new DifferentialDiffProperty())->loadAllWhere(
|
2016-12-13 15:39:10 -08:00
|
|
|
'diffID = %d',
|
2012-11-16 11:48:17 -08:00
|
|
|
$diff->getID());
|
|
|
|
$props = mpull($props, 'getData', 'getName');
|
|
|
|
|
2013-09-17 09:12:37 -07:00
|
|
|
$property_head = id(new PHUIHeaderView())
|
2013-07-01 12:37:54 -07:00
|
|
|
->setHeader(pht('Properties'));
|
|
|
|
|
2013-10-11 07:53:56 -07:00
|
|
|
$property_view = new PHUIPropertyListView();
|
2012-11-16 11:48:17 -08:00
|
|
|
|
2011-01-24 13:18:41 -08:00
|
|
|
$changesets = $diff->loadChangesets();
|
|
|
|
$changesets = msort($changesets, 'getSortKey');
|
|
|
|
|
2017-09-29 13:25:55 -07:00
|
|
|
$this->buildPackageMaps($changesets);
|
|
|
|
|
2015-08-15 12:57:20 -07:00
|
|
|
$table_of_contents = $this->buildTableOfContents(
|
|
|
|
$changesets,
|
|
|
|
$changesets,
|
|
|
|
$diff->loadCoverageMap($viewer));
|
2011-01-24 13:18:41 -08:00
|
|
|
|
2011-05-13 12:27:12 -07:00
|
|
|
$refs = array();
|
|
|
|
foreach ($changesets as $changeset) {
|
|
|
|
$refs[$changeset->getID()] = $changeset->getID();
|
|
|
|
}
|
|
|
|
|
2011-01-25 11:57:47 -08:00
|
|
|
$details = id(new DifferentialChangesetListView())
|
2011-05-13 12:27:12 -07:00
|
|
|
->setChangesets($changesets)
|
2012-05-01 12:09:50 -07:00
|
|
|
->setVisibleChangesets($changesets)
|
2012-01-16 11:08:54 -08:00
|
|
|
->setRenderingReferences($refs)
|
2012-04-12 22:08:44 -07:00
|
|
|
->setStandaloneURI('/differential/changeset/')
|
2012-12-12 21:21:56 -08:00
|
|
|
->setDiff($diff)
|
2016-03-13 16:01:05 -07:00
|
|
|
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
2013-01-24 10:46:47 -08:00
|
|
|
->setTitle(pht('Diff %d', $diff->getID()))
|
2012-01-16 11:08:54 -08:00
|
|
|
->setUser($request->getUser());
|
2011-01-24 13:18:41 -08:00
|
|
|
|
2016-03-13 16:01:05 -07:00
|
|
|
$title = pht('Diff %d', $diff->getID());
|
2013-07-01 12:37:54 -07:00
|
|
|
$crumbs = $this->buildApplicationCrumbs();
|
2016-03-13 16:01:05 -07:00
|
|
|
$crumbs->addTextCrumb($title);
|
|
|
|
$crumbs->setBorder(true);
|
|
|
|
|
|
|
|
$header = id(new PHUIHeaderView())
|
|
|
|
->setHeader($title);
|
2013-07-01 12:37:54 -07:00
|
|
|
|
2014-01-13 12:17:37 -08:00
|
|
|
$prop_box = id(new PHUIObjectBoxView())
|
|
|
|
->setHeader($property_head)
|
2016-03-13 16:01:05 -07:00
|
|
|
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
2014-01-13 12:17:37 -08:00
|
|
|
->addPropertyList($property_view)
|
[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 12:43:34 -07:00
|
|
|
->setForm($form);
|
2014-01-13 12:17:37 -08:00
|
|
|
|
2016-03-13 16:01:05 -07:00
|
|
|
$view = id(new PHUITwoColumnView())
|
|
|
|
->setHeader($header)
|
|
|
|
->setMainColumn(array(
|
|
|
|
|
|
|
|
))
|
|
|
|
->setFooter(array(
|
2014-01-13 12:17:37 -08:00
|
|
|
$prop_box,
|
2013-07-01 12:37:54 -07:00
|
|
|
$table_of_contents,
|
|
|
|
$details,
|
2011-01-24 13:18:41 -08:00
|
|
|
));
|
2016-03-13 16:01:05 -07:00
|
|
|
|
|
|
|
$page = $this->newPage()
|
|
|
|
->setTitle(pht('Diff View'))
|
|
|
|
->setCrumbs($crumbs)
|
|
|
|
->appendChild($view);
|
|
|
|
return $page;
|
2011-01-24 13:18:41 -08:00
|
|
|
}
|
|
|
|
|
2015-03-26 11:11:33 -07:00
|
|
|
private function loadSelectableRevisions(
|
|
|
|
PhabricatorUser $viewer,
|
|
|
|
$selected_id) {
|
|
|
|
|
|
|
|
$revisions = id(new DifferentialRevisionQuery())
|
|
|
|
->setViewer($viewer)
|
|
|
|
->withAuthors(array($viewer->getPHID()))
|
2017-08-11 09:18:47 -07:00
|
|
|
->withIsOpen(true)
|
2015-03-26 11:11:33 -07:00
|
|
|
->requireCapabilities(
|
|
|
|
array(
|
|
|
|
PhabricatorPolicyCapability::CAN_VIEW,
|
|
|
|
PhabricatorPolicyCapability::CAN_EDIT,
|
|
|
|
))
|
|
|
|
->execute();
|
|
|
|
$revisions = mpull($revisions, null, 'getID');
|
|
|
|
|
|
|
|
// If a specific revision is selected (for example, because the user is
|
|
|
|
// following the "Update Diff" workflow), but not present in the dropdown,
|
|
|
|
// try to add it to the dropdown even if it is closed. This allows the
|
|
|
|
// workflow to be used to update abandoned revisions.
|
|
|
|
|
|
|
|
if ($selected_id) {
|
|
|
|
if (empty($revisions[$selected_id])) {
|
|
|
|
$selected = id(new DifferentialRevisionQuery())
|
|
|
|
->setViewer($viewer)
|
|
|
|
->withAuthors(array($viewer->getPHID()))
|
|
|
|
->withIDs(array($selected_id))
|
|
|
|
->requireCapabilities(
|
|
|
|
array(
|
|
|
|
PhabricatorPolicyCapability::CAN_VIEW,
|
|
|
|
PhabricatorPolicyCapability::CAN_EDIT,
|
|
|
|
))
|
|
|
|
->execute();
|
|
|
|
$revisions = mpull($selected, null, 'getID') + $revisions;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $revisions;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-24 13:18:41 -08:00
|
|
|
}
|