1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Iterators;
9:
10: use Nette;
11: use Nette\Utils\ObjectMixin;
12:
13:
14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
28: class CachingIterator extends \CachingIterator implements \Countable
29: {
30:
31: private $counter = 0;
32:
33:
34: public function __construct($iterator)
35: {
36: if (is_array($iterator) || $iterator instanceof \stdClass) {
37: $iterator = new \ArrayIterator($iterator);
38:
39: } elseif ($iterator instanceof \IteratorAggregate) {
40: do {
41: $iterator = $iterator->getIterator();
42: } while ($iterator instanceof \IteratorAggregate);
43:
44: } elseif ($iterator instanceof \Traversable) {
45: if (!$iterator instanceof \Iterator) {
46: $iterator = new \IteratorIterator($iterator);
47: }
48: } else {
49: throw new Nette\InvalidArgumentException(sprintf('Invalid argument passed to %s; array or Traversable expected, %s given.', __CLASS__, is_object($iterator) ? get_class($iterator) : gettype($iterator)));
50: }
51:
52: parent::__construct($iterator, 0);
53: }
54:
55:
56: 57: 58: 59: 60:
61: public function isFirst($width = NULL)
62: {
63: return $this->counter === 1 || ($width && $this->counter !== 0 && (($this->counter - 1) % $width) === 0);
64: }
65:
66:
67: 68: 69: 70: 71:
72: public function isLast($width = NULL)
73: {
74: return !$this->hasNext() || ($width && ($this->counter % $width) === 0);
75: }
76:
77:
78: 79: 80: 81:
82: public function isEmpty()
83: {
84: return $this->counter === 0;
85: }
86:
87:
88: 89: 90: 91:
92: public function isOdd()
93: {
94: return $this->counter % 2 === 1;
95: }
96:
97:
98: 99: 100: 101:
102: public function isEven()
103: {
104: return $this->counter % 2 === 0;
105: }
106:
107:
108: 109: 110: 111:
112: public function getCounter()
113: {
114: return $this->counter;
115: }
116:
117:
118: 119: 120: 121:
122: public function count()
123: {
124: $inner = $this->getInnerIterator();
125: if ($inner instanceof \Countable) {
126: return $inner->count();
127:
128: } else {
129: throw new Nette\NotSupportedException('Iterator is not countable.');
130: }
131: }
132:
133:
134: 135: 136: 137:
138: public function next()
139: {
140: parent::next();
141: if (parent::valid()) {
142: $this->counter++;
143: }
144: }
145:
146:
147: 148: 149: 150:
151: public function rewind()
152: {
153: parent::rewind();
154: $this->counter = parent::valid() ? 1 : 0;
155: }
156:
157:
158: 159: 160: 161:
162: public function getNextKey()
163: {
164: return $this->getInnerIterator()->key();
165: }
166:
167:
168: 169: 170: 171:
172: public function getNextValue()
173: {
174: return $this->getInnerIterator()->current();
175: }
176:
177:
178:
179:
180:
181: 182: 183: 184: 185: 186: 187:
188: public function __call($name, $args)
189: {
190: return ObjectMixin::call($this, $name, $args);
191: }
192:
193:
194: 195: 196: 197: 198: 199:
200: public function &__get($name)
201: {
202: return ObjectMixin::get($this, $name);
203: }
204:
205:
206: 207: 208: 209: 210: 211: 212:
213: public function __set($name, $value)
214: {
215: ObjectMixin::set($this, $name, $value);
216: }
217:
218:
219: 220: 221: 222: 223:
224: public function __isset($name)
225: {
226: return ObjectMixin::has($this, $name);
227: }
228:
229:
230: 231: 232: 233: 234: 235:
236: public function __unset($name)
237: {
238: ObjectMixin::remove($this, $name);
239: }
240:
241:
242: }
243: