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