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