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