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 ArrayIterator;
18: use Cake\Collection\Collection;
19: use Cake\Collection\CollectionInterface;
20:
21: /**
22: * Creates an iterator from another iterator that will modify each of the values
23: * by converting them using a callback function.
24: */
25: class ReplaceIterator extends Collection
26: {
27:
28: /**
29: * The callback function to be used to transform values
30: *
31: * @var callable
32: */
33: protected $_callback;
34:
35: /**
36: * A reference to the internal iterator this object is wrapping.
37: *
38: * @var \Iterator
39: */
40: protected $_innerIterator;
41:
42: /**
43: * Creates an iterator from another iterator that will modify each of the values
44: * by converting them using a callback function.
45: *
46: * Each time the callback is executed it will receive the value of the element
47: * in the current iteration, the key of the element and the passed $items iterator
48: * as arguments, in that order.
49: *
50: * @param array|\Traversable $items The items to be filtered.
51: * @param callable $callback Callback.
52: */
53: public function __construct($items, callable $callback)
54: {
55: $this->_callback = $callback;
56: parent::__construct($items);
57: $this->_innerIterator = $this->getInnerIterator();
58: }
59:
60: /**
61: * Returns the value returned by the callback after passing the current value in
62: * the iteration
63: *
64: * @return mixed
65: */
66: public function current()
67: {
68: $callback = $this->_callback;
69:
70: return $callback(parent::current(), $this->key(), $this->_innerIterator);
71: }
72:
73: /**
74: * {@inheritDoc}
75: *
76: * We perform here some strictness analysis so that the
77: * iterator logic is bypassed entirely.
78: *
79: * @return \Iterator
80: */
81: public function unwrap()
82: {
83: $iterator = $this->_innerIterator;
84:
85: if ($iterator instanceof CollectionInterface) {
86: $iterator = $iterator->unwrap();
87: }
88:
89: if (get_class($iterator) !== ArrayIterator::class) {
90: return $this;
91: }
92:
93: // ArrayIterator can be traversed strictly.
94: // Let's do that for performance gains
95:
96: $callback = $this->_callback;
97: $res = [];
98:
99: foreach ($iterator as $k => $v) {
100: $res[$k] = $callback($v, $k, $iterator);
101: }
102:
103: return new ArrayIterator($res);
104: }
105: }
106: