Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F93177480
PhabricatorObjectGraph.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Nov 26, 19:17
Size
5 KB
Mime Type
text/x-php
Expires
Thu, Nov 28, 19:17 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
22587230
Attached To
rPH Phabricator
PhabricatorObjectGraph.php
View Options
<?php
abstract
class
PhabricatorObjectGraph
extends
AbstractDirectedGraph
{
private
$viewer
;
private
$edges
=
array
();
private
$edgeReach
=
array
();
private
$seedPHID
;
private
$objects
;
private
$loadEntireGraph
=
false
;
private
$limit
;
public
function
setViewer
(
PhabricatorUser
$viewer
)
{
$this
->
viewer
=
$viewer
;
return
$this
;
}
public
function
getViewer
()
{
if
(!
$this
->
viewer
)
{
throw
new
PhutilInvalidStateException
(
'setViewer'
);
}
return
$this
->
viewer
;
}
public
function
setLimit
(
$limit
)
{
$this
->
limit
=
$limit
;
return
$this
;
}
public
function
getLimit
()
{
return
$this
->
limit
;
}
abstract
protected
function
getEdgeTypes
();
abstract
protected
function
getParentEdgeType
();
abstract
protected
function
newQuery
();
abstract
protected
function
newTableRow
(
$phid
,
$object
,
$trace
);
abstract
protected
function
newTable
(
AphrontTableView
$table
);
abstract
protected
function
isClosed
(
$object
);
final
public
function
setSeedPHID
(
$phid
)
{
$this
->
seedPHID
=
$phid
;
$this
->
edgeReach
[
$phid
]
=
array_fill_keys
(
$this
->
getEdgeTypes
(),
true
);
return
$this
->
addNodes
(
array
(
'<seed>'
=>
array
(
$phid
),
));
}
final
public
function
isEmpty
()
{
return
(
count
(
$this
->
getNodes
())
<=
2
);
}
final
public
function
isOverLimit
()
{
$limit
=
$this
->
getLimit
();
if
(!
$limit
)
{
return
false
;
}
return
(
count
(
$this
->
edgeReach
)
>
$limit
);
}
final
public
function
getEdges
(
$type
)
{
$edges
=
idx
(
$this
->
edges
,
$type
,
array
());
// Remove any nodes which we never reached. We can get these when loading
// only part of the graph: for example, they point at other subtasks of
// parents or other parents of subtasks.
$nodes
=
$this
->
getNodes
();
foreach
(
$edges
as
$src
=>
$dsts
)
{
foreach
(
$dsts
as
$key
=>
$dst
)
{
if
(!
isset
(
$nodes
[
$dst
]))
{
unset
(
$edges
[
$src
][
$key
]);
}
}
}
return
$edges
;
}
final
public
function
setLoadEntireGraph
(
$load_entire_graph
)
{
$this
->
loadEntireGraph
=
$load_entire_graph
;
return
$this
;
}
final
public
function
getLoadEntireGraph
()
{
return
$this
->
loadEntireGraph
;
}
final
protected
function
loadEdges
(
array
$nodes
)
{
if
(
$this
->
isOverLimit
())
{
return
array_fill_keys
(
$nodes
,
array
());
}
$edge_types
=
$this
->
getEdgeTypes
();
$query
=
id
(
new
PhabricatorEdgeQuery
())
->
withSourcePHIDs
(
$nodes
)
->
withEdgeTypes
(
$edge_types
);
$query
->
execute
();
$whole_graph
=
$this
->
getLoadEntireGraph
();
$map
=
array
();
foreach
(
$nodes
as
$node
)
{
$map
[
$node
]
=
array
();
foreach
(
$edge_types
as
$edge_type
)
{
$dst_phids
=
$query
->
getDestinationPHIDs
(
array
(
$node
),
array
(
$edge_type
));
$this
->
edges
[
$edge_type
][
$node
]
=
$dst_phids
;
foreach
(
$dst_phids
as
$dst_phid
)
{
if
(
$whole_graph
||
isset
(
$this
->
edgeReach
[
$node
][
$edge_type
]))
{
$map
[
$node
][]
=
$dst_phid
;
}
$this
->
edgeReach
[
$dst_phid
][
$edge_type
]
=
true
;
}
}
$map
[
$node
]
=
array_values
(
array_fuse
(
$map
[
$node
]));
}
return
$map
;
}
final
public
function
newGraphTable
()
{
$viewer
=
$this
->
getViewer
();
$ancestry
=
$this
->
getEdges
(
$this
->
getParentEdgeType
());
$objects
=
$this
->
newQuery
()
->
setViewer
(
$viewer
)
->
withPHIDs
(
array_keys
(
$ancestry
))
->
execute
();
$objects
=
mpull
(
$objects
,
null
,
'getPHID'
);
$order
=
id
(
new
PhutilDirectedScalarGraph
())
->
addNodes
(
$ancestry
)
->
getTopographicallySortedNodes
();
$ancestry
=
array_select_keys
(
$ancestry
,
$order
);
$traces
=
id
(
new
PHUIDiffGraphView
())
->
renderGraph
(
$ancestry
);
$ii
=
0
;
$rows
=
array
();
$rowc
=
array
();
foreach
(
$ancestry
as
$phid
=>
$ignored
)
{
$object
=
idx
(
$objects
,
$phid
);
$rows
[]
=
$this
->
newTableRow
(
$phid
,
$object
,
$traces
[
$ii
++]);
$classes
=
array
();
if
(
$phid
==
$this
->
seedPHID
)
{
$classes
[]
=
'highlighted'
;
}
if
(
$object
)
{
if
(
$this
->
isClosed
(
$object
))
{
$classes
[]
=
'closed'
;
}
}
if
(
$classes
)
{
$classes
=
implode
(
' '
,
$classes
);
}
else
{
$classes
=
null
;
}
$rowc
[]
=
$classes
;
}
$table
=
id
(
new
AphrontTableView
(
$rows
))
->
setClassName
(
'object-graph-table'
)
->
setRowClasses
(
$rowc
);
$this
->
objects
=
$objects
;
return
$this
->
newTable
(
$table
);
}
final
public
function
getReachableObjects
(
$edge_type
)
{
if
(
$this
->
objects
===
null
)
{
throw
new
PhutilInvalidStateException
(
'newGraphTable'
);
}
$graph
=
$this
->
getEdges
(
$edge_type
);
$seen
=
array
();
$look
=
array
(
$this
->
seedPHID
);
while
(
$look
)
{
$phid
=
array_pop
(
$look
);
$parents
=
idx
(
$graph
,
$phid
,
array
());
foreach
(
$parents
as
$parent
)
{
if
(
isset
(
$seen
[
$parent
]))
{
continue
;
}
$seen
[
$parent
]
=
$parent
;
$look
[]
=
$parent
;
}
}
$reachable
=
array
();
foreach
(
$seen
as
$phid
)
{
if
(
$phid
==
$this
->
seedPHID
)
{
continue
;
}
$object
=
idx
(
$this
->
objects
,
$phid
);
if
(!
$object
)
{
continue
;
}
$reachable
[]
=
$object
;
}
return
$reachable
;
}
}
Event Timeline
Log In to Comment