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