1 | <?php |
||
271 | class SS_Map_Iterator implements Iterator { |
||
272 | |||
273 | protected $items; |
||
274 | protected $keyField, $titleField; |
||
275 | |||
276 | protected $firstItemIdx = 0; |
||
277 | |||
278 | protected $endItemIdx; |
||
279 | |||
280 | protected $firstItems = array(); |
||
281 | protected $lastItems = array(); |
||
282 | |||
283 | protected $excludedItems = array(); |
||
284 | |||
285 | /** |
||
286 | * @param Iterator $items The iterator to build this map from |
||
287 | * @param string $keyField The field to use for the keys |
||
288 | * @param string $titleField The field to use for the values |
||
289 | * @param array $fristItems An optional map of items to show first |
||
290 | * @param array $lastItems An optional map of items to show last |
||
291 | */ |
||
292 | public function __construct(Iterator $items, $keyField, $titleField, $firstItems = null, $lastItems = null) { |
||
293 | $this->items = $items; |
||
294 | $this->keyField = $keyField; |
||
295 | $this->titleField = $titleField; |
||
296 | $this->endItemIdx = null; |
||
297 | |||
298 | if($firstItems) { |
||
299 | foreach($firstItems as $k => $v) { |
||
300 | $this->firstItems[] = array($k,$v); |
||
301 | $this->excludedItems[] = $k; |
||
302 | } |
||
303 | } |
||
304 | |||
305 | if($lastItems) { |
||
306 | foreach($lastItems as $k => $v) { |
||
307 | $this->lastItems[] = array($k, $v); |
||
308 | $this->excludedItems[] = $k; |
||
309 | } |
||
310 | } |
||
311 | |||
312 | } |
||
313 | |||
314 | /** |
||
315 | * Rewind the Iterator to the first element. |
||
316 | * |
||
317 | * @return mixed |
||
318 | */ |
||
319 | public function rewind() { |
||
320 | $this->firstItemIdx = 0; |
||
321 | $this->endItemIdx = null; |
||
322 | |||
323 | $rewoundItem = $this->items->rewind(); |
||
324 | |||
325 | if(isset($this->firstItems[$this->firstItemIdx])) { |
||
326 | return $this->firstItems[$this->firstItemIdx][1]; |
||
327 | } else { |
||
328 | if($rewoundItem) { |
||
329 | if($rewoundItem->hasMethod($this->titleField)) { |
||
330 | return $rewoundItem->{$this->titleField}(); |
||
331 | } |
||
332 | |||
333 | return $rewoundItem->{$this->titleField}; |
||
334 | } else if(!$this->items->valid() && $this->lastItems) { |
||
335 | $this->endItemIdx = 0; |
||
336 | |||
337 | return $this->lastItems[0][1]; |
||
338 | } |
||
339 | } |
||
340 | } |
||
341 | |||
342 | /** |
||
343 | * Return the current element. |
||
344 | * |
||
345 | * @return mixed |
||
346 | */ |
||
347 | public function current() { |
||
348 | if(($this->endItemIdx !== null) && isset($this->lastItems[$this->endItemIdx])) { |
||
349 | return $this->lastItems[$this->endItemIdx][1]; |
||
350 | } else if(isset($this->firstItems[$this->firstItemIdx])) { |
||
351 | return $this->firstItems[$this->firstItemIdx][1]; |
||
352 | } else { |
||
353 | if($this->items->current()->hasMethod($this->titleField)) { |
||
354 | return $this->items->current()->{$this->titleField}(); |
||
355 | } |
||
356 | |||
357 | return $this->items->current()->{$this->titleField}; |
||
358 | } |
||
359 | } |
||
360 | |||
361 | /** |
||
362 | * Return the key of the current element. |
||
363 | * |
||
364 | * @return string |
||
365 | */ |
||
366 | public function key() { |
||
367 | if(($this->endItemIdx !== null) && isset($this->lastItems[$this->endItemIdx])) { |
||
368 | return $this->lastItems[$this->endItemIdx][0]; |
||
369 | } else if(isset($this->firstItems[$this->firstItemIdx])) { |
||
370 | return $this->firstItems[$this->firstItemIdx][0]; |
||
371 | } else { |
||
372 | return $this->items->current()->{$this->keyField}; |
||
373 | } |
||
374 | } |
||
375 | |||
376 | /** |
||
377 | * Move forward to next element. |
||
378 | * |
||
379 | * @return mixed |
||
380 | */ |
||
381 | public function next() { |
||
382 | $this->firstItemIdx++; |
||
383 | |||
384 | if(isset($this->firstItems[$this->firstItemIdx])) { |
||
385 | return $this->firstItems[$this->firstItemIdx][1]; |
||
386 | } else { |
||
387 | if(!isset($this->firstItems[$this->firstItemIdx-1])) { |
||
388 | $this->items->next(); |
||
389 | } |
||
390 | |||
391 | if($this->excludedItems) { |
||
392 | while(($c = $this->items->current()) && in_array($c->{$this->keyField}, $this->excludedItems, true)) { |
||
393 | $this->items->next(); |
||
394 | } |
||
395 | } |
||
396 | } |
||
397 | |||
398 | if(!$this->items->valid()) { |
||
399 | // iterator has passed the preface items, off the end of the items |
||
400 | // list. Track through the end items to go through to the next |
||
401 | if($this->endItemIdx === null) { |
||
402 | $this->endItemIdx = -1; |
||
403 | } |
||
404 | |||
405 | $this->endItemIdx++; |
||
406 | |||
407 | if(isset($this->lastItems[$this->endItemIdx])) { |
||
408 | return $this->lastItems[$this->endItemIdx]; |
||
409 | } |
||
410 | |||
411 | return false; |
||
412 | } |
||
413 | } |
||
414 | |||
415 | /** |
||
416 | * Checks if current position is valid. |
||
417 | * |
||
418 | * @return boolean |
||
419 | */ |
||
420 | public function valid() { |
||
421 | return ( |
||
422 | (isset($this->firstItems[$this->firstItemIdx])) || |
||
423 | (($this->endItemIdx !== null) && isset($this->lastItems[$this->endItemIdx])) || |
||
424 | $this->items->valid() |
||
425 | ); |
||
426 | } |
||
427 | } |
||
428 |