1: <?php
2: /**
3: * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
4: * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
5: *
6: * Licensed under The MIT License
7: * For full copyright and license information, please see the LICENSE.txt
8: * Redistributions of files must retain the above copyright notice.
9: *
10: * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
11: * @link https://cakephp.org CakePHP(tm) Project
12: * @since 3.0.0
13: * @license https://opensource.org/licenses/mit-license.php MIT License
14: */
15: namespace Cake\Collection\Iterator;
16:
17: use Cake\Collection\CollectionTrait;
18: use RecursiveIteratorIterator;
19:
20: /**
21: * Iterator for flattening elements in a tree structure while adding some
22: * visual markers for their relative position in the tree
23: */
24: class TreePrinter extends RecursiveIteratorIterator
25: {
26:
27: use CollectionTrait;
28:
29: /**
30: * A callable to generate the iteration key
31: *
32: * @var callable
33: */
34: protected $_key;
35:
36: /**
37: * A callable to extract the display value
38: *
39: * @var callable
40: */
41: protected $_value;
42:
43: /**
44: * Cached value for the current iteration element
45: *
46: * @var mixed
47: */
48: protected $_current;
49:
50: /**
51: * The string to use for prefixing the values according to their depth in the tree.
52: *
53: * @var string
54: */
55: protected $_spacer;
56:
57: /**
58: * Constructor
59: *
60: * @param \RecursiveIterator $items The iterator to flatten.
61: * @param string|callable $valuePath The property to extract or a callable to return
62: * the display value.
63: * @param string|callable $keyPath The property to use as iteration key or a
64: * callable returning the key value.
65: * @param string $spacer The string to use for prefixing the values according to
66: * their depth in the tree.
67: * @param int $mode Iterator mode.
68: */
69: public function __construct($items, $valuePath, $keyPath, $spacer, $mode = RecursiveIteratorIterator::SELF_FIRST)
70: {
71: parent::__construct($items, $mode);
72: $this->_value = $this->_propertyExtractor($valuePath);
73: $this->_key = $this->_propertyExtractor($keyPath);
74: $this->_spacer = $spacer;
75: }
76:
77: /**
78: * Returns the current iteration key
79: *
80: * @return mixed
81: */
82: public function key()
83: {
84: $extractor = $this->_key;
85:
86: return $extractor($this->_fetchCurrent(), parent::key(), $this);
87: }
88:
89: /**
90: * Returns the current iteration value
91: *
92: * @return string
93: */
94: public function current()
95: {
96: $extractor = $this->_value;
97: $current = $this->_fetchCurrent();
98: $spacer = str_repeat($this->_spacer, $this->getDepth());
99:
100: return $spacer . $extractor($current, parent::key(), $this);
101: }
102:
103: /**
104: * Advances the cursor one position
105: *
106: * @return void
107: */
108: public function next()
109: {
110: parent::next();
111: $this->_current = null;
112: }
113:
114: /**
115: * Returns the current iteration element and caches its value
116: *
117: * @return mixed
118: */
119: protected function _fetchCurrent()
120: {
121: if ($this->_current !== null) {
122: return $this->_current;
123: }
124:
125: return $this->_current = parent::current();
126: }
127: }
128: