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: use CollectionTrait;
48:
49: /**
50: * The function to use for zipping items together
51: *
52: * @var callable|null
53: */
54: protected $_callback;
55:
56: /**
57: * Contains the original iterator objects that were attached
58: *
59: * @var array
60: */
61: protected $_iterators = [];
62:
63: /**
64: * Creates the iterator to merge together the values by for all the passed
65: * iterators by their corresponding index.
66: *
67: * @param array $sets The list of array or iterators to be zipped.
68: * @param callable|null $callable The function to use for zipping the elements of each iterator.
69: */
70: public function __construct(array $sets, $callable = null)
71: {
72: $sets = array_map(function ($items) {
73: return (new Collection($items))->unwrap();
74: }, $sets);
75:
76: $this->_callback = $callable;
77: parent::__construct(MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_NUMERIC);
78:
79: foreach ($sets as $set) {
80: $this->_iterators[] = $set;
81: $this->attachIterator($set);
82: }
83: }
84:
85: /**
86: * Returns the value resulting out of zipping all the elements for all the
87: * iterators with the same positional index.
88: *
89: * @return array|false
90: */
91: public function current()
92: {
93: if ($this->_callback === null) {
94: return parent::current();
95: }
96:
97: return call_user_func_array($this->_callback, parent::current());
98: }
99:
100: /**
101: * Returns a string representation of this object that can be used
102: * to reconstruct it
103: *
104: * @return string
105: */
106: public function serialize()
107: {
108: return serialize($this->_iterators);
109: }
110:
111: /**
112: * Unserializes the passed string and rebuilds the ZipIterator instance
113: *
114: * @param string $iterators The serialized iterators
115: * @return void
116: */
117: public function unserialize($iterators)
118: {
119: parent::__construct(MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_NUMERIC);
120: $this->_iterators = unserialize($iterators);
121: foreach ($this->_iterators as $it) {
122: $this->attachIterator($it);
123: }
124: }
125: }
126: