Differences Between: [Versions 310 and 400] [Versions 39 and 400] [Versions 400 and 401]
1 <?php 2 /* 3 * Copyright 2017 MongoDB, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 namespace MongoDB\Model; 19 20 use Countable; 21 use Iterator; 22 use IteratorIterator; 23 use Traversable; 24 use function count; 25 use function current; 26 use function key; 27 use function next; 28 use function reset; 29 30 /** 31 * Iterator for wrapping a Traversable and caching its results. 32 * 33 * By caching results, this iterators allows a Traversable to be counted and 34 * rewound multiple times, even if the wrapped object does not natively support 35 * those operations (e.g. MongoDB\Driver\Cursor). 36 * 37 * @internal 38 */ 39 class CachingIterator implements Countable, Iterator 40 { 41 /** @var array */ 42 private $items = []; 43 44 /** @var IteratorIterator */ 45 private $iterator; 46 47 /** @var boolean */ 48 private $iteratorAdvanced = false; 49 50 /** @var boolean */ 51 private $iteratorExhausted = false; 52 53 /** 54 * Initialize the iterator and stores the first item in the cache. This 55 * effectively rewinds the Traversable and the wrapping IteratorIterator. 56 * Additionally, this mimics behavior of the SPL iterators and allows users 57 * to omit an explicit call * to rewind() before using the other methods. 58 * 59 * @param Traversable $traversable 60 */ 61 public function __construct(Traversable $traversable) 62 { 63 $this->iterator = new IteratorIterator($traversable); 64 65 $this->iterator->rewind(); 66 $this->storeCurrentItem(); 67 } 68 69 /** 70 * @see http://php.net/countable.count 71 * @return integer 72 */ 73 public function count() 74 { 75 $this->exhaustIterator(); 76 77 return count($this->items); 78 } 79 80 /** 81 * @see http://php.net/iterator.current 82 * @return mixed 83 */ 84 public function current() 85 { 86 return current($this->items); 87 } 88 89 /** 90 * @see http://php.net/iterator.key 91 * @return mixed 92 */ 93 public function key() 94 { 95 return key($this->items); 96 } 97 98 /** 99 * @see http://php.net/iterator.next 100 * @return void 101 */ 102 public function next() 103 { 104 if (! $this->iteratorExhausted) { 105 $this->iteratorAdvanced = true; 106 $this->iterator->next(); 107 108 $this->storeCurrentItem(); 109 110 $this->iteratorExhausted = ! $this->iterator->valid(); 111 } 112 113 next($this->items); 114 } 115 116 /** 117 * @see http://php.net/iterator.rewind 118 * @return void 119 */ 120 public function rewind() 121 { 122 /* If the iterator has advanced, exhaust it now so that future iteration 123 * can rely on the cache. 124 */ 125 if ($this->iteratorAdvanced) { 126 $this->exhaustIterator(); 127 } 128 129 reset($this->items); 130 } 131 132 /** 133 * @see http://php.net/iterator.valid 134 * @return boolean 135 */ 136 public function valid() 137 { 138 return $this->key() !== null; 139 } 140 141 /** 142 * Ensures that the inner iterator is fully consumed and cached. 143 */ 144 private function exhaustIterator() 145 { 146 while (! $this->iteratorExhausted) { 147 $this->next(); 148 } 149 } 150 151 /** 152 * Stores the current item in the cache. 153 */ 154 private function storeCurrentItem() 155 { 156 $key = $this->iterator->key(); 157 158 if ($key === null) { 159 return; 160 } 161 162 $this->items[$key] = $this->iterator->current(); 163 } 164 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body