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