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