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