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