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()->warning(Logger::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