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 RecursiveIterator;
19: use RecursiveIteratorIterator;
20:
21: /**
22: * A Recursive iterator used to flatten nested structures and also exposes
23: * all Collection methods
24: */
25: class TreeIterator extends RecursiveIteratorIterator
26: {
27: use CollectionTrait;
28:
29: /**
30: * The iteration mode
31: *
32: * @var int
33: */
34: protected $_mode;
35:
36: /**
37: * Constructor
38: *
39: * @param \RecursiveIterator $items The iterator to flatten.
40: * @param int $mode Iterator mode.
41: * @param int $flags Iterator flags.
42: */
43: public function __construct(RecursiveIterator $items, $mode = RecursiveIteratorIterator::SELF_FIRST, $flags = 0)
44: {
45: parent::__construct($items, $mode, $flags);
46: $this->_mode = $mode;
47: }
48:
49: /**
50: * Returns another iterator which will return the values ready to be displayed
51: * to a user. It does so by extracting one property from each of the elements
52: * and prefixing it with a spacer so that the relative position in the tree
53: * can be visualized.
54: *
55: * Both $valuePath and $keyPath can be a string with a property name to extract
56: * or a dot separated path of properties that should be followed to get the last
57: * one in the path.
58: *
59: * Alternatively, $valuePath and $keyPath can be callable functions. They will get
60: * the current element as first parameter, the current iteration key as second
61: * parameter, and the iterator instance as third argument.
62: *
63: * ### Example
64: *
65: * ```
66: * $printer = (new Collection($treeStructure))->listNested()->printer('name');
67: * ```
68: *
69: * Using a closure:
70: *
71: * ```
72: * $printer = (new Collection($treeStructure))
73: * ->listNested()
74: * ->printer(function ($item, $key, $iterator) {
75: * return $item->name;
76: * });
77: * ```
78: *
79: * @param string|callable $valuePath The property to extract or a callable to return
80: * the display value
81: * @param string|callable|null $keyPath The property to use as iteration key or a
82: * callable returning the key value.
83: * @param string $spacer The string to use for prefixing the values according to
84: * their depth in the tree
85: * @return \Cake\Collection\Iterator\TreePrinter
86: */
87: public function printer($valuePath, $keyPath = null, $spacer = '__')
88: {
89: if (!$keyPath) {
90: $counter = 0;
91: $keyPath = function () use (&$counter) {
92: return $counter++;
93: };
94: }
95:
96: return new TreePrinter(
97: $this->getInnerIterator(),
98: $valuePath,
99: $keyPath,
100: $spacer,
101: $this->_mode
102: );
103: }
104: }
105: