1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
17:
18: namespace OpenCloud\Common\Collection;
19:
20: use Iterator;
21: use OpenCloud\Common\Exceptions\InvalidArgumentError;
22: use OpenCloud\Common\Log\Logger;
23:
24: class ResourceIterator extends ArrayCollection implements Iterator
25: {
26: 27: 28:
29: protected $position;
30:
31: 32: 33: 34:
35: protected $resourceParent;
36:
37: 38: 39:
40: protected $options;
41:
42: 43: 44:
45: protected $defaults = array('limit.total' => 1000);
46:
47: 48: 49:
50: protected $required = array();
51:
52: public static function factory($parent, array $options = array(), array $data = array())
53: {
54: $iterator = new static($data);
55:
56: $iterator->setResourceParent($parent)
57: ->setElements($data)
58: ->setOptions($iterator->parseOptions($options))
59: ->rewind();
60:
61: return $iterator;
62: }
63:
64: protected function parseOptions(array $options)
65: {
66: $options = $options + $this->defaults;
67:
68: if ($missing = array_diff($this->required, array_keys($options))) {
69: throw new InvalidArgumentError(sprintf('%s is a required option', implode(',', $missing)));
70: }
71:
72: return $options;
73: }
74:
75: 76: 77: 78:
79: public function setResourceParent($parent)
80: {
81: $this->resourceParent = $parent;
82:
83: return $this;
84: }
85:
86: 87: 88: 89:
90: public function setOptions(array $options)
91: {
92: $this->options = $options;
93:
94: return $this;
95: }
96:
97: 98: 99:
100: public function getOptions()
101: {
102: return $this->options;
103: }
104:
105: 106: 107: 108: 109: 110: 111:
112: public function setOption($key, $value)
113: {
114: $this->options[$key] = $value;
115:
116: return $this;
117: }
118:
119: 120: 121: 122:
123: public function getOption($key)
124: {
125: return (isset($this->options[$key])) ? $this->options[$key] : null;
126: }
127:
128: 129: 130: 131: 132:
133: public function valid()
134: {
135: return $this->offsetExists($this->position) && $this->position < $this->getOption('limit.total');
136: }
137:
138: 139: 140:
141: public function next()
142: {
143: $this->position++;
144:
145: return $this->current();
146: }
147:
148: 149: 150:
151: public function rewind()
152: {
153: $this->position = 0;
154: }
155:
156: 157: 158:
159: public function current()
160: {
161: return $this->constructResource($this->currentElement());
162: }
163:
164: 165: 166:
167: public function currentElement()
168: {
169: return $this->offsetGet($this->key());
170: }
171:
172: 173: 174: 175: 176: 177: 178: 179:
180: public function constructResource($object)
181: {
182: $className = $this->getOption('resourceClass');
183:
184: if (substr_count($className, '\\')) {
185: $array = explode('\\', $className);
186: $className = end($array);
187: }
188:
189: $parent = $this->resourceParent;
190: $getter = sprintf('get%s', ucfirst($className));
191:
192: if (method_exists($parent, $className)) {
193:
194: return call_user_func(array($parent, $className), $object);
195: } elseif (method_exists($parent, $getter)) {
196:
197: return call_user_func(array($parent, $getter), $object);
198: } elseif (method_exists($parent, 'resource')) {
199:
200: return $parent->resource($className, $object);
201: } else {
202: return $object;
203: }
204: }
205:
206: 207: 208: 209: 210:
211: public function key()
212: {
213: return $this->position;
214: }
215:
216: public function getElement($offset)
217: {
218: return (!$this->offsetExists($offset)) ? false : $this->constructResource($this->offsetGet($offset));
219: }
220:
221: 222: 223:
224: public function first()
225: {
226: Logger::newInstance()->deprecated(__METHOD__, 'getElement');
227:
228: return $this->getElement(0);
229: }
230:
231: 232: 233:
234: public function sort()
235: {
236: }
237:
238: public function search($callback)
239: {
240: $return = false;
241:
242: if (!is_callable($callback)) {
243: throw new InvalidArgumentError('The provided argument must be a valid callback');
244: }
245:
246: foreach ($this->elements as $element) {
247: $resource = $this->constructResource($element);
248: if (call_user_func($callback, $resource) === true) {
249: $return = $resource;
250: break;
251: }
252: }
253:
254: return $return;
255: }
256: }
257: