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\Collection;
18:
19: /**
20: * This iterator will insert values into a property of each of the records returned.
21: * The values to be inserted come out of another traversal object. This is useful
22: * when you have two separate collections and want to merge them together by placing
23: * each of the values from one collection into a property inside the other collection.
24: */
25: class InsertIterator extends Collection
26: {
27: /**
28: * The collection from which to extract the values to be inserted
29: *
30: * @var \Cake\Collection\Collection
31: */
32: protected $_values;
33:
34: /**
35: * Holds whether the values collection is still valid. (has more records)
36: *
37: * @var bool
38: */
39: protected $_validValues = true;
40:
41: /**
42: * An array containing each of the properties to be traversed to reach the
43: * point where the values should be inserted.
44: *
45: * @var array
46: */
47: protected $_path;
48:
49: /**
50: * The property name to which values will be assigned
51: *
52: * @var string
53: */
54: protected $_target;
55:
56: /**
57: * Constructs a new collection that will dynamically add properties to it out of
58: * the values found in $values.
59: *
60: * @param array|\Traversable $into The target collection to which the values will
61: * be inserted at the specified path.
62: * @param string $path A dot separated list of properties that need to be traversed
63: * to insert the value into the target collection.
64: * @param array|\Traversable $values The source collection from which the values will
65: * be inserted at the specified path.
66: */
67: public function __construct($into, $path, $values)
68: {
69: parent::__construct($into);
70:
71: if (!($values instanceof Collection)) {
72: $values = new Collection($values);
73: }
74:
75: $path = explode('.', $path);
76: $target = array_pop($path);
77: $this->_path = $path;
78: $this->_target = $target;
79: $this->_values = $values;
80: }
81:
82: /**
83: * Advances the cursor to the next record
84: *
85: * @return void
86: */
87: public function next()
88: {
89: parent::next();
90: if ($this->_validValues) {
91: $this->_values->next();
92: }
93: $this->_validValues = $this->_values->valid();
94: }
95:
96: /**
97: * Returns the current element in the target collection after inserting
98: * the value from the source collection into the specified path.
99: *
100: * @return mixed
101: */
102: public function current()
103: {
104: $row = parent::current();
105:
106: if (!$this->_validValues) {
107: return $row;
108: }
109:
110: $pointer =& $row;
111: foreach ($this->_path as $step) {
112: if (!isset($pointer[$step])) {
113: return $row;
114: }
115: $pointer =& $pointer[$step];
116: }
117:
118: $pointer[$this->_target] = $this->_values->current();
119:
120: return $row;
121: }
122:
123: /**
124: * Resets the collection pointer.
125: *
126: * @return void
127: */
128: public function rewind()
129: {
130: parent::rewind();
131: $this->_values->rewind();
132: $this->_validValues = $this->_values->valid();
133: }
134: }
135: