1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Latte\Runtime;
9:
10: use Latte;
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 \Traversable) {
42: if ($iterator instanceof \IteratorAggregate) {
43: $iterator = $iterator->getIterator();
44:
45: } elseif (!$iterator instanceof \Iterator) {
46: $iterator = new \IteratorIterator($iterator);
47: }
48:
49: } else {
50: throw new \InvalidArgumentException(sprintf('Invalid argument passed to foreach; array or Traversable expected, %s given.', is_object($iterator) ? get_class($iterator) : gettype($iterator)));
51: }
52:
53: parent::__construct($iterator, 0);
54: }
55:
56:
57: 58: 59: 60: 61:
62: public function isFirst($width = NULL)
63: {
64: return $this->counter === 1 || ($width && $this->counter !== 0 && (($this->counter - 1) % $width) === 0);
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: public function isEmpty()
84: {
85: return $this->counter === 0;
86: }
87:
88:
89: 90: 91: 92:
93: public function isOdd()
94: {
95: return $this->counter % 2 === 1;
96: }
97:
98:
99: 100: 101: 102:
103: public function isEven()
104: {
105: return $this->counter % 2 === 0;
106: }
107:
108:
109: 110: 111: 112:
113: public function getCounter()
114: {
115: return $this->counter;
116: }
117:
118:
119: 120: 121: 122:
123: public function count()
124: {
125: $inner = $this->getInnerIterator();
126: if ($inner instanceof \Countable) {
127: return $inner->count();
128:
129: } else {
130: throw new \LogicException('Iterator is not countable.');
131: }
132: }
133:
134:
135: 136: 137: 138:
139: public function next()
140: {
141: parent::next();
142: if (parent::valid()) {
143: $this->counter++;
144: }
145: }
146:
147:
148: 149: 150: 151:
152: public function rewind()
153: {
154: parent::rewind();
155: $this->counter = parent::valid() ? 1 : 0;
156: }
157:
158:
159: 160: 161: 162:
163: public function getNextKey()
164: {
165: return $this->getInnerIterator()->key();
166: }
167:
168:
169: 170: 171: 172:
173: public function getNextValue()
174: {
175: return $this->getInnerIterator()->current();
176: }
177:
178:
179:
180:
181:
182: 183: 184: 185:
186: public function __call($name, $args)
187: {
188: throw new \LogicException(sprintf('Call to undefined method %s::%s().', get_class($this), $name));
189: }
190:
191:
192: 193: 194: 195:
196: public function &__get($name)
197: {
198: if (method_exists($this, $m = 'get' . $name) || method_exists($this, $m = 'is' . $name)) {
199: $ret = $this->$m();
200: return $ret;
201: }
202: throw new \LogicException(sprintf('Cannot read an undeclared property %s::$%s.', get_class($this), $name));
203: }
204:
205:
206: 207: 208: 209:
210: public function __set($name, $value)
211: {
212: throw new \LogicException(sprintf('Cannot write to an undeclared property %s::$%s.', get_class($this), $name));
213: }
214:
215:
216: 217: 218: 219:
220: public function __isset($name)
221: {
222: return method_exists($this, 'get' . $name) || method_exists($this, 'is' . $name);
223: }
224:
225:
226: 227: 228: 229:
230: public function __unset($name)
231: {
232: throw new \LogicException(sprintf('Cannot unset the property %s::$%s.', get_class($this), $name));
233: }
234:
235: }
236: