Skip to content

Commit cc7ae60

Browse files
author
epriestley
committedJul 1, 2016
Make the revision graph view more flexible
Summary: Ref T4788. This separates the revision graph view into a base class with core logic and a revision class with Differential-specific logic, so I can subclass it in Maniphest, etc., and try using it in other applications to show similar graphs. Not sure if we'll stick with it, but even if we don't this makes the code a bit cleaner and gets custom rendering logic out of the RevisionViewController, which is nice. Test Plan: Viewed revisions, saw the stack UI completely unchanged. Reviewers: chad Reviewed By: chad Maniphest Tasks: T4788 Differential Revision: https://secure.phabricator.com/D16213
1 parent 791a4ff commit cc7ae60

File tree

5 files changed

+259
-210
lines changed

5 files changed

+259
-210
lines changed
 

‎src/__phutil_library_map__.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,7 @@
521521
'DifferentialRevisionDependsOnRevisionEdgeType' => 'applications/differential/edge/DifferentialRevisionDependsOnRevisionEdgeType.php',
522522
'DifferentialRevisionEditController' => 'applications/differential/controller/DifferentialRevisionEditController.php',
523523
'DifferentialRevisionFulltextEngine' => 'applications/differential/search/DifferentialRevisionFulltextEngine.php',
524+
'DifferentialRevisionGraph' => 'infrastructure/graph/DifferentialRevisionGraph.php',
524525
'DifferentialRevisionHasChildRelationship' => 'applications/differential/relationships/DifferentialRevisionHasChildRelationship.php',
525526
'DifferentialRevisionHasCommitEdgeType' => 'applications/differential/edge/DifferentialRevisionHasCommitEdgeType.php',
526527
'DifferentialRevisionHasCommitRelationship' => 'applications/differential/relationships/DifferentialRevisionHasCommitRelationship.php',
@@ -556,7 +557,6 @@
556557
'DifferentialRevisionViewController' => 'applications/differential/controller/DifferentialRevisionViewController.php',
557558
'DifferentialSchemaSpec' => 'applications/differential/storage/DifferentialSchemaSpec.php',
558559
'DifferentialSetDiffPropertyConduitAPIMethod' => 'applications/differential/conduit/DifferentialSetDiffPropertyConduitAPIMethod.php',
559-
'DifferentialStackGraph' => 'applications/differential/edge/DifferentialStackGraph.php',
560560
'DifferentialStoredCustomField' => 'applications/differential/customfield/DifferentialStoredCustomField.php',
561561
'DifferentialSubscribersField' => 'applications/differential/customfield/DifferentialSubscribersField.php',
562562
'DifferentialSummaryField' => 'applications/differential/customfield/DifferentialSummaryField.php',
@@ -2868,6 +2868,7 @@
28682868
'PhabricatorOAuthServerTokenController' => 'applications/oauthserver/controller/PhabricatorOAuthServerTokenController.php',
28692869
'PhabricatorOAuthServerTransaction' => 'applications/oauthserver/storage/PhabricatorOAuthServerTransaction.php',
28702870
'PhabricatorOAuthServerTransactionQuery' => 'applications/oauthserver/query/PhabricatorOAuthServerTransactionQuery.php',
2871+
'PhabricatorObjectGraph' => 'infrastructure/graph/PhabricatorObjectGraph.php',
28712872
'PhabricatorObjectHandle' => 'applications/phid/PhabricatorObjectHandle.php',
28722873
'PhabricatorObjectHasAsanaSubtaskEdgeType' => 'applications/doorkeeper/edge/PhabricatorObjectHasAsanaSubtaskEdgeType.php',
28732874
'PhabricatorObjectHasAsanaTaskEdgeType' => 'applications/doorkeeper/edge/PhabricatorObjectHasAsanaTaskEdgeType.php',
@@ -4895,6 +4896,7 @@
48954896
'DifferentialRevisionDependsOnRevisionEdgeType' => 'PhabricatorEdgeType',
48964897
'DifferentialRevisionEditController' => 'DifferentialController',
48974898
'DifferentialRevisionFulltextEngine' => 'PhabricatorFulltextEngine',
4899+
'DifferentialRevisionGraph' => 'PhabricatorObjectGraph',
48984900
'DifferentialRevisionHasChildRelationship' => 'DifferentialRevisionRelationship',
48994901
'DifferentialRevisionHasCommitEdgeType' => 'PhabricatorEdgeType',
49004902
'DifferentialRevisionHasCommitRelationship' => 'DifferentialRevisionRelationship',
@@ -4930,7 +4932,6 @@
49304932
'DifferentialRevisionViewController' => 'DifferentialController',
49314933
'DifferentialSchemaSpec' => 'PhabricatorConfigSchemaSpec',
49324934
'DifferentialSetDiffPropertyConduitAPIMethod' => 'DifferentialConduitAPIMethod',
4933-
'DifferentialStackGraph' => 'AbstractDirectedGraph',
49344935
'DifferentialStoredCustomField' => 'DifferentialCustomField',
49354936
'DifferentialSubscribersField' => 'DifferentialCoreCustomField',
49364937
'DifferentialSummaryField' => 'DifferentialCoreCustomField',
@@ -7582,6 +7583,7 @@
75827583
'PhabricatorOAuthServerTokenController' => 'PhabricatorOAuthServerController',
75837584
'PhabricatorOAuthServerTransaction' => 'PhabricatorApplicationTransaction',
75847585
'PhabricatorOAuthServerTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
7586+
'PhabricatorObjectGraph' => 'AbstractDirectedGraph',
75857587
'PhabricatorObjectHandle' => array(
75867588
'Phobject',
75877589
'PhabricatorPolicyInterface',

‎src/applications/differential/controller/DifferentialRevisionViewController.php

+21-150
Original file line numberDiff line numberDiff line change
@@ -341,12 +341,29 @@ public function handleRequest(AphrontRequest $request) {
341341
->setKey('commits')
342342
->appendChild($local_table));
343343

344-
$stack_graph = id(new DifferentialStackGraph())
345-
->setSeedRevision($revision)
344+
$stack_graph = id(new DifferentialRevisionGraph())
345+
->setViewer($viewer)
346+
->setSeedPHID($revision->getPHID())
346347
->loadGraph();
347348
if (!$stack_graph->isEmpty()) {
348-
$stack_view = $this->renderStackView($revision, $stack_graph);
349-
list($stack_name, $stack_color, $stack_table) = $stack_view;
349+
$stack_table = $stack_graph->newGraphTable();
350+
351+
$parent_type = DifferentialRevisionDependsOnRevisionEdgeType::EDGECONST;
352+
$reachable = $stack_graph->getReachableObjects($parent_type);
353+
354+
foreach ($reachable as $key => $reachable_revision) {
355+
if ($reachable_revision->isClosed()) {
356+
unset($reachable[$key]);
357+
}
358+
}
359+
360+
if ($reachable) {
361+
$stack_name = pht('Stack (%s Open)', phutil_count($reachable));
362+
$stack_color = PHUIListItemView::STATUS_FAIL;
363+
} else {
364+
$stack_name = pht('Stack');
365+
$stack_color = null;
366+
}
350367

351368
$tab_group->addTab(
352369
id(new PHUITabView())
@@ -1212,150 +1229,4 @@ private function buildUnitMessagesView(
12121229
->setShowViewAll(true);
12131230
}
12141231

1215-
1216-
private function renderStackView(
1217-
DifferentialRevision $current,
1218-
DifferentialStackGraph $graph) {
1219-
1220-
$ancestry = $graph->getParentEdges();
1221-
$viewer = $this->getViewer();
1222-
1223-
$revisions = id(new DifferentialRevisionQuery())
1224-
->setViewer($viewer)
1225-
->withPHIDs(array_keys($ancestry))
1226-
->execute();
1227-
$revisions = mpull($revisions, null, 'getPHID');
1228-
1229-
$order = id(new PhutilDirectedScalarGraph())
1230-
->addNodes($ancestry)
1231-
->getTopographicallySortedNodes();
1232-
1233-
$ancestry = array_select_keys($ancestry, $order);
1234-
1235-
$traces = id(new PHUIDiffGraphView())
1236-
->renderGraph($ancestry);
1237-
1238-
// Load author handles, and also revision handles for any revisions which
1239-
// we failed to load (they might be policy restricted).
1240-
$handle_phids = mpull($revisions, 'getAuthorPHID');
1241-
foreach ($order as $phid) {
1242-
if (empty($revisions[$phid])) {
1243-
$handle_phids[] = $phid;
1244-
}
1245-
}
1246-
$handles = $viewer->loadHandles($handle_phids);
1247-
1248-
$rows = array();
1249-
$rowc = array();
1250-
1251-
$ii = 0;
1252-
$seen = false;
1253-
foreach ($ancestry as $phid => $ignored) {
1254-
$revision = idx($revisions, $phid);
1255-
if ($revision) {
1256-
$status_icon = $revision->getStatusIcon();
1257-
$status_name = $revision->getStatusDisplayName();
1258-
1259-
$status = array(
1260-
id(new PHUIIconView())->setIcon($status_icon),
1261-
' ',
1262-
$status_name,
1263-
);
1264-
1265-
$author = $viewer->renderHandle($revision->getAuthorPHID());
1266-
$title = phutil_tag(
1267-
'a',
1268-
array(
1269-
'href' => $revision->getURI(),
1270-
),
1271-
array(
1272-
$revision->getMonogram(),
1273-
' ',
1274-
$revision->getTitle(),
1275-
));
1276-
} else {
1277-
$status = null;
1278-
$author = null;
1279-
$title = $viewer->renderHandle($phid);
1280-
}
1281-
1282-
$rows[] = array(
1283-
$traces[$ii++],
1284-
$status,
1285-
$author,
1286-
$title,
1287-
);
1288-
1289-
if ($phid == $current->getPHID()) {
1290-
$rowc[] = 'highlighted';
1291-
} else {
1292-
$rowc[] = null;
1293-
}
1294-
}
1295-
1296-
$stack_table = id(new AphrontTableView($rows))
1297-
->setHeaders(
1298-
array(
1299-
null,
1300-
pht('Status'),
1301-
pht('Author'),
1302-
pht('Revision'),
1303-
))
1304-
->setRowClasses($rowc)
1305-
->setColumnClasses(
1306-
array(
1307-
'threads',
1308-
null,
1309-
null,
1310-
'wide',
1311-
));
1312-
1313-
// Count how many revisions this one depends on that are not yet closed.
1314-
$seen = array();
1315-
$look = array($current->getPHID());
1316-
while ($look) {
1317-
$phid = array_pop($look);
1318-
1319-
$parents = idx($ancestry, $phid, array());
1320-
foreach ($parents as $parent) {
1321-
if (isset($seen[$parent])) {
1322-
continue;
1323-
}
1324-
1325-
$seen[$parent] = $parent;
1326-
$look[] = $parent;
1327-
}
1328-
}
1329-
1330-
$blocking_count = 0;
1331-
foreach ($seen as $parent) {
1332-
if ($parent == $current->getPHID()) {
1333-
continue;
1334-
}
1335-
1336-
$revision = idx($revisions, $parent);
1337-
if (!$revision) {
1338-
continue;
1339-
}
1340-
1341-
if ($revision->isClosed()) {
1342-
continue;
1343-
}
1344-
1345-
$blocking_count++;
1346-
}
1347-
1348-
if (!$blocking_count) {
1349-
$stack_name = pht('Stack');
1350-
$stack_color = null;
1351-
} else {
1352-
$stack_name = pht(
1353-
'Stack (%s Open)',
1354-
new PhutilNumber($blocking_count));
1355-
$stack_color = PHUIListItemView::STATUS_FAIL;
1356-
}
1357-
1358-
return array($stack_name, $stack_color, $stack_table);
1359-
}
1360-
13611232
}

‎src/applications/differential/edge/DifferentialStackGraph.php

-58
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
final class DifferentialRevisionGraph
4+
extends PhabricatorObjectGraph {
5+
6+
protected function getEdgeTypes() {
7+
return array(
8+
DifferentialRevisionDependsOnRevisionEdgeType::EDGECONST,
9+
DifferentialRevisionDependedOnByRevisionEdgeType::EDGECONST,
10+
);
11+
}
12+
13+
protected function getParentEdgeType() {
14+
return DifferentialRevisionDependsOnRevisionEdgeType::EDGECONST;
15+
}
16+
17+
protected function newQuery() {
18+
return new DifferentialRevisionQuery();
19+
}
20+
21+
protected function newTableRow($phid, $object, $trace) {
22+
$viewer = $this->getViewer();
23+
24+
if ($object) {
25+
$status_icon = $object->getStatusIcon();
26+
$status_name = $object->getStatusDisplayName();
27+
28+
$status = array(
29+
id(new PHUIIconView())->setIcon($status_icon),
30+
' ',
31+
$status_name,
32+
);
33+
34+
$author = $viewer->renderHandle($object->getAuthorPHID());
35+
$link = phutil_tag(
36+
'a',
37+
array(
38+
'href' => $object->getURI(),
39+
),
40+
array(
41+
$object->getMonogram(),
42+
' ',
43+
$object->getTitle(),
44+
));
45+
} else {
46+
$status = null;
47+
$author = null;
48+
$link = $viewer->renderHandle($phid);
49+
}
50+
51+
return array(
52+
$trace,
53+
$status,
54+
$author,
55+
$link,
56+
);
57+
}
58+
59+
protected function newTable(AphrontTableView $table) {
60+
return $table
61+
->setHeaders(
62+
array(
63+
null,
64+
pht('Status'),
65+
pht('Author'),
66+
pht('Revision'),
67+
))
68+
->setColumnClasses(
69+
array(
70+
'threads',
71+
null,
72+
null,
73+
'wide',
74+
));
75+
}
76+
77+
}

0 commit comments

Comments
 (0)
Failed to load comments.