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