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: use CollectionTrait;
27:
28: /**
29: * A callable to generate the iteration key
30: *
31: * @var callable
32: */
33: protected $_key;
34:
35: /**
36: * A callable to extract the display value
37: *
38: * @var callable
39: */
40: protected $_value;
41:
42: /**
43: * Cached value for the current iteration element
44: *
45: * @var mixed
46: */
47: protected $_current;
48:
49: /**
50: * The string to use for prefixing the values according to their depth in the tree.
51: *
52: * @var string
53: */
54: protected $_spacer;
55:
56: /**
57: * Constructor
58: *
59: * @param \RecursiveIterator $items The iterator to flatten.
60: * @param string|callable $valuePath The property to extract or a callable to return
61: * the display value.
62: * @param string|callable $keyPath The property to use as iteration key or a
63: * callable returning the key value.
64: * @param string $spacer The string to use for prefixing the values according to
65: * their depth in the tree.
66: * @param int $mode Iterator mode.
67: */
68: public function __construct($items, $valuePath, $keyPath, $spacer, $mode = RecursiveIteratorIterator::SELF_FIRST)
69: {
70: parent::__construct($items, $mode);
71: $this->_value = $this->_propertyExtractor($valuePath);
72: $this->_key = $this->_propertyExtractor($keyPath);
73: $this->_spacer = $spacer;
74: }
75:
76: /**
77: * Returns the current iteration key
78: *
79: * @return mixed
80: */
81: public function key()
82: {
83: $extractor = $this->_key;
84:
85: return $extractor($this->_fetchCurrent(), parent::key(), $this);
86: }
87:
88: /**
89: * Returns the current iteration value
90: *
91: * @return string
92: */
93: public function current()
94: {
95: $extractor = $this->_value;
96: $current = $this->_fetchCurrent();
97: $spacer = str_repeat($this->_spacer, $this->getDepth());
98:
99: return $spacer . $extractor($current, parent::key(), $this);
100: }
101:
102: /**
103: * Advances the cursor one position
104: *
105: * @return void
106: */
107: public function next()
108: {
109: parent::next();
110: $this->_current = null;
111: }
112:
113: /**
114: * Returns the current iteration element and caches its value
115: *
116: * @return mixed
117: */
118: protected function _fetchCurrent()
119: {
120: if ($this->_current !== null) {
121: return $this->_current;
122: }
123:
124: return $this->_current = parent::current();
125: }
126: }
127: