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