Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Graph.php
Go to the documentation of this file.
1 <?php
6 namespace Magento\Framework\Data;
7 
11 class Graph
12 {
16  const DIRECTIONAL = 1;
17 
18  const INVERSE = 2;
19 
20  const NON_DIRECTIONAL = 3;
21 
25  protected $_nodes = [];
26 
32  protected $_from = [];
33 
39  protected $_to = [];
40 
47  public function __construct(array $nodes, array $relations)
48  {
49  foreach ($nodes as $node) {
50  $this->_assertNode($node, false);
51  $this->_nodes[$node] = $node;
52  }
53  foreach ($relations as $pair) {
54  list($fromNode, $toNode) = $pair;
55  $this->addRelation($fromNode, $toNode);
56  }
57  }
58 
67  public function addRelation($fromNode, $toNode)
68  {
69  if ($fromNode == $toNode) {
70  throw new \InvalidArgumentException("Graph node '{$fromNode}' is linked to itself.");
71  }
72  $this->_assertNode($fromNode, true);
73  $this->_assertNode($toNode, true);
74  $this->_from[$fromNode][$toNode] = $toNode;
75  $this->_to[$toNode][$fromNode] = $fromNode;
76  return $this;
77  }
78 
86  public function getRelations($mode = self::DIRECTIONAL)
87  {
88  switch ($mode) {
89  case self::DIRECTIONAL:
90  return $this->_from;
91  case self::INVERSE:
92  return $this->_to;
94  $graph = $this->_from;
95  foreach ($this->_to as $idTo => $relations) {
96  foreach ($relations as $idFrom) {
97  $graph[$idTo][$idFrom] = $idFrom;
98  }
99  }
100  return $graph;
101  default:
102  throw new \InvalidArgumentException("Unknown search mode: '{$mode}'");
103  }
104  }
105 
116  public function findCycle($node = null, $firstOnly = true)
117  {
118  $nodes = null === $node ? $this->_nodes : [$node];
119  $results = [];
120  foreach ($nodes as $node) {
121  $result = $this->dfs($node, $node);
122  if ($result) {
123  if ($firstOnly) {
124  return $result;
125  } else {
126  $results[] = $result;
127  }
128  }
129  }
130  return $results;
131  }
132 
143  public function findPathsToReachableNodes($rootNode, $mode = self::DIRECTIONAL)
144  {
145  $graph = $this->getRelations($mode);
146  $paths = [];
147  $queue = [$rootNode];
148  $visited = [$rootNode => $rootNode];
149  $paths[$rootNode] = [$rootNode];
150  while (!empty($queue)) {
151  $node = array_shift($queue);
152  if (!empty($graph[$node])) {
153  foreach ($graph[$node] as $child) {
154  if (!isset($visited[$child])) {
155  $paths[$child] = $paths[$node];
156  $paths[$child][] = $child;
157  $visited[$child] = $child;
158  $queue[] = $child;
159  }
160  }
161  }
162  }
163  return $paths;
164  }
165 
177  public function dfs($fromNode, $toNode, $mode = self::DIRECTIONAL)
178  {
179  $this->_assertNode($fromNode, true);
180  $this->_assertNode($toNode, true);
181  return $this->_dfs($fromNode, $toNode, $this->getRelations($mode));
182  }
183 
195  protected function _dfs($fromNode, $toNode, $graph, &$visited = [], $stack = [])
196  {
197  $stack[] = $fromNode;
198  $visited[$fromNode] = $fromNode;
199  if (isset($graph[$fromNode][$toNode])) {
200  $stack[] = $toNode;
201  return $stack;
202  }
203  if (isset($graph[$fromNode])) {
204  foreach ($graph[$fromNode] as $node) {
205  if (!isset($visited[$node])) {
206  $result = $this->_dfs($node, $toNode, $graph, $visited, $stack);
207  if ($result) {
208  return $result;
209  }
210  }
211  }
212  }
213  return [];
214  }
215 
224  protected function _assertNode($node, $mustExist)
225  {
226  if (isset($this->_nodes[$node])) {
227  if (!$mustExist) {
228  throw new \InvalidArgumentException("Graph node '{$node}' already exists'.");
229  }
230  } else {
231  if ($mustExist) {
232  throw new \InvalidArgumentException("Graph node '{$node}' does not exist.");
233  }
234  }
235  }
236 }
dfs($fromNode, $toNode, $mode=self::DIRECTIONAL)
Definition: Graph.php:177
findPathsToReachableNodes($rootNode, $mode=self::DIRECTIONAL)
Definition: Graph.php:143
$queue
Definition: queue.php:21
$results
Definition: popup.phtml:13
__construct(array $nodes, array $relations)
Definition: Graph.php:47
_dfs($fromNode, $toNode, $graph, &$visited=[], $stack=[])
Definition: Graph.php:195
_assertNode($node, $mustExist)
Definition: Graph.php:224
if($exist=($block->getProductCollection() && $block->getProductCollection() ->getSize())) $mode
Definition: grid.phtml:15
findCycle($node=null, $firstOnly=true)
Definition: Graph.php:116
getRelations($mode=self::DIRECTIONAL)
Definition: Graph.php:86
$paths
Definition: _bootstrap.php:83
addRelation($fromNode, $toNode)
Definition: Graph.php:67