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.5
13: * @license https://opensource.org/licenses/mit-license.php MIT License
14: */
15: namespace Cake\Collection\Iterator;
16:
17: use Cake\Collection\Collection;
18: use Cake\Collection\CollectionInterface;
19: use Cake\Collection\CollectionTrait;
20: use MultipleIterator;
21: use Serializable;
22:
23: /**
24: * Creates an iterator that returns elements grouped in pairs
25: *
26: * ### Example
27: *
28: * ```
29: * $iterator = new ZipIterator([[1, 2], [3, 4]]);
30: * $iterator->toList(); // Returns [[1, 3], [2, 4]]
31: * ```
32: *
33: * You can also chose a custom function to zip the elements together, such
34: * as doing a sum by index:
35: *
36: * ### Example
37: *
38: * ```
39: * $iterator = new ZipIterator([[1, 2], [3, 4]], function ($a, $b) {
40: * return $a + $b;
41: * });
42: * $iterator->toList(); // Returns [4, 6]
43: * ```
44: */
45: class ZipIterator extends MultipleIterator implements CollectionInterface, Serializable
46: {
47:
48: use CollectionTrait;
49:
50: /**
51: * The function to use for zipping items together
52: *
53: * @var callable
54: */
55: protected $_callback;
56:
57: /**
58: * Contains the original iterator objects that were attached
59: *
60: * @var array
61: */
62: protected $_iterators = [];
63:
64: /**
65: * Creates the iterator to merge together the values by for all the passed
66: * iterators by their corresponding index.
67: *
68: * @param array $sets The list of array or iterators to be zipped.
69: * @param callable|null $callable The function to use for zipping the elements of each iterator.
70: */
71: public function __construct(array $sets, $callable = null)
72: {
73: $sets = array_map(function ($items) {
74: return (new Collection($items))->unwrap();
75: }, $sets);
76:
77: $this->_callback = $callable;
78: parent::__construct(MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_NUMERIC);
79:
80: foreach ($sets as $set) {
81: $this->_iterators[] = $set;
82: $this->attachIterator($set);
83: }
84: }
85:
86: /**
87: * Returns the value resulting out of zipping all the elements for all the
88: * iterators with the same positional index.
89: *
90: * @return mixed
91: */
92: public function current()
93: {
94: if ($this->_callback === null) {
95: return parent::current();
96: }
97:
98: return call_user_func_array($this->_callback, parent::current());
99: }
100:
101: /**
102: * Returns a string representation of this object that can be used
103: * to reconstruct it
104: *
105: * @return string
106: */
107: public function serialize()
108: {
109: return serialize($this->_iterators);
110: }
111:
112: /**
113: * Unserializes the passed string and rebuilds the ZipIterator instance
114: *
115: * @param string $iterators The serialized iterators
116: * @return void
117: */
118: public function unserialize($iterators)
119: {
120: parent::__construct(MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_NUMERIC);
121: $this->_iterators = unserialize($iterators);
122: foreach ($this->_iterators as $it) {
123: $this->attachIterator($it);
124: }
125: }
126: }
127: