1 | <?php |
||
13 | class Traverser |
||
14 | { |
||
15 | /** |
||
16 | * If this is used as the visitor type, the visitor is called right BEFORE entering the child node list |
||
17 | * of the node |
||
18 | */ |
||
19 | const BEFORE = 1; |
||
20 | |||
21 | /** |
||
22 | * If this is used as the visitor type, the visitor is called right AFTER the children have been visited. |
||
23 | */ |
||
24 | const AFTER = 2; |
||
25 | |||
26 | /** |
||
27 | * The tree to traverse |
||
28 | * |
||
29 | * @var array |
||
30 | */ |
||
31 | protected $tree; |
||
32 | |||
33 | /** |
||
34 | * The visitors to apply to the tree |
||
35 | * @var array |
||
36 | */ |
||
37 | protected $visitors; |
||
38 | |||
39 | |||
40 | /** |
||
41 | * Construct the traverser with the specified tree as input. |
||
42 | * |
||
43 | * @param array $tree |
||
44 | */ |
||
45 | public function __construct($tree) |
||
50 | |||
51 | |||
52 | /** |
||
53 | * Add a visitor to the traverser. The node being visited is passed to the second callback to determine whether |
||
54 | * the first callback should be called with the node. The arguments passed to both callbacks are the current node |
||
55 | * and the path to the node. The result of the first callback is used to replace the node in the tree. |
||
56 | * |
||
57 | * Example: |
||
58 | * <code> |
||
59 | * $traverser->addVisitor( |
||
60 | * function($path, $node) { |
||
61 | * $node['i was visited'] = true; |
||
62 | * return $node; |
||
63 | * }, |
||
64 | * function($path, $node) { |
||
65 | * return count($path) == 3 && $path[0] == 'foo' && $path[2] == 'bar'; |
||
66 | * } |
||
67 | * ); |
||
68 | * |
||
69 | * $traverser->traverse( |
||
70 | * array( |
||
71 | * 'foo' => array( |
||
72 | * array( |
||
73 | * 'bar' => array('i should be visited' => true), |
||
74 | * 'baz' => array('i should not be visited' => true) |
||
75 | * ) |
||
76 | * ) |
||
77 | * ) |
||
78 | * ); |
||
79 | * </code> |
||
80 | * |
||
81 | * @param callable $callable |
||
82 | * @param callable $condition |
||
83 | * @param int $when |
||
84 | * @return self |
||
85 | */ |
||
86 | public function addVisitor($callable, $condition, $when = self::BEFORE) |
||
92 | |||
93 | |||
94 | /** |
||
95 | * Traverse the entire tree |
||
96 | * |
||
97 | * @return mixed |
||
98 | */ |
||
99 | public function traverse() |
||
103 | |||
104 | |||
105 | /** |
||
106 | * Recursive traversal implementation |
||
107 | * |
||
108 | * @param mixed $node |
||
109 | * @param array $path |
||
110 | * @return mixed |
||
111 | */ |
||
112 | private function doTraverse($node, $path = array()) |
||
129 | |||
130 | |||
131 | /** |
||
132 | * Visits the node with all visitors at the specified time. |
||
133 | * |
||
134 | * @param array $path |
||
135 | * @param mixed $value |
||
136 | * @param int $when |
||
137 | * @return mixed |
||
138 | * |
||
139 | * @throws \RuntimeException |
||
140 | */ |
||
141 | private function doVisit($path, $value, $when) |
||
159 | } |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.