1<?php 2 3namespace ipl\Orm; 4 5use ArrayIterator; 6use Iterator; 7use Traversable; 8 9class ResultSet implements Iterator 10{ 11 protected $cache; 12 13 protected $generator; 14 15 protected $limit; 16 17 protected $position; 18 19 public function __construct(Traversable $traversable, $limit = null) 20 { 21 $this->cache = new ArrayIterator(); 22 $this->generator = $this->yieldTraversable($traversable); 23 $this->limit = $limit; 24 } 25 26 public function hasMore() 27 { 28 return $this->generator->valid(); 29 } 30 31 public function hasResult() 32 { 33 return $this->generator->valid(); 34 } 35 36 public function current() 37 { 38 if ($this->position === null) { 39 $this->advance(); 40 } 41 42 return $this->cache->current(); 43 } 44 45 public function next() 46 { 47 $this->cache->next(); 48 49 if (! $this->cache->valid()) { 50 $this->generator->next(); 51 $this->advance(); 52 } 53 } 54 55 public function key() 56 { 57 if ($this->position === null) { 58 $this->advance(); 59 } 60 61 return $this->cache->key(); 62 } 63 64 public function valid() 65 { 66 if ($this->limit !== null && $this->position === $this->limit) { 67 return false; 68 } 69 70 return $this->cache->valid() || $this->generator->valid(); 71 } 72 73 public function rewind() 74 { 75 $this->cache->rewind(); 76 77 if ($this->position === null) { 78 $this->advance(); 79 } else { 80 $this->position = 0; 81 } 82 } 83 84 protected function advance() 85 { 86 if (! $this->generator->valid()) { 87 return; 88 } 89 90 $this->cache[$this->generator->key()] = $this->generator->current(); 91 92 // Only required on PHP 5.6, 7+ does it automatically 93 $this->cache->seek($this->generator->key()); 94 95 if ($this->position === null) { 96 $this->position = 0; 97 } else { 98 $this->position += 1; 99 } 100 } 101 102 protected function yieldTraversable(Traversable $traversable) 103 { 104 foreach ($traversable as $key => $value) { 105 yield $key => $value; 106 } 107 } 108} 109