add test
[m6w6/pq-gateway] / lib / pq / Gateway / Rowset.php
1 <?php
2
3 namespace pq\Gateway;
4
5 class Rowset implements \SeekableIterator, \Countable, \JsonSerializable
6 {
7 /**
8 * @var \pq\Gateway\Table
9 */
10 protected $table;
11
12 /**
13 * @var int
14 */
15 protected $index = 0;
16
17 /**
18 * @var array
19 */
20 protected $rows;
21
22 /**
23 * @var mixed
24 */
25 protected $row = "\\pq\\Gateway\\Row";
26
27 /**
28 * @param \pq\Gateway\Table $table
29 * @param \pq\Result $result
30 */
31 function __construct(Table $table, \pq\Result $result = null) {
32 $this->table = $table;
33 $this->hydrate($result);
34 }
35
36 /**
37 * Copy constructor
38 * @param \pq\Result $result
39 * @return \pq\Gateway\Rowset
40 */
41 function __invoke(\pq\Result $result) {
42 $that = clone $this;
43 $that->hydrate($result);
44 return $that;
45 }
46
47 /**
48 *
49 * @param \pq\Result $result
50 * @return array
51 */
52 protected function hydrate(\pq\Result $result = null) {
53 $this->index = 0;
54 $this->rows = array();
55
56 if ($result) {
57 $row = $this->row;
58
59 if (is_callable($row)) {
60 while (($data = $result->fetchRow(\pq\Result::FETCH_ASSOC))) {
61 $this->rows[] = $row($data);
62 }
63 } elseif ($row) {
64 while (($data = $result->fetchRow(\pq\Result::FETCH_ASSOC))) {
65 $this->rows[] = new $row($this->table, $data);
66 }
67 } else {
68 $this->rows = $result->fetchAll(\pq\Result::FETCH_OBJECT);
69 }
70 }
71
72 return $this;
73 }
74
75 /**
76 * Set the row prototype
77 * @param mixed $row
78 * @return \pq\Gateway\Table
79 */
80 function setRowPrototype($row) {
81 $this->row = $row;
82 return $this;
83 }
84
85 /**
86 * @return \pq\Gateway\Table
87 */
88 function getTable() {
89 return $this->table;
90 }
91
92 function create() {
93 array_map(function ($row) {
94 $row->create();
95 }, $this->rows);
96 return $this;
97 }
98
99 function update() {
100 array_map(function ($row) {
101 $row->update();
102 }, $this->rows);
103 return $this;
104 }
105
106 function delete() {
107 array_map(function ($row) {
108 $row->delete();
109 }, $this->rows);
110 return $this;
111 }
112
113 /**
114 * @implements JsonSerilaizable
115 */
116 function jsonSerialize() {
117 return array_map(function($row) {
118 return $row->jsonSerialize();
119 }, $this->rows);
120 }
121
122 /**
123 * @implements \Iterator
124 */
125 function rewind() {
126 $this->index = 0;
127 }
128 /**
129 * @implements \Iterator
130 */
131 function next() {
132 ++$this->index;
133 }
134 /**
135 * @implements \Iterator
136 * @return bool
137 */
138 function valid() {
139 return $this->index < count($this->rows);
140 }
141 /**
142 * @implements \Iterator
143 * @return \pq\Gateway\Row
144 */
145 function current() {
146 return $this->rows[$this->index];
147 }
148 /**
149 * @implements \Iterator
150 * @return int
151 */
152 function key() {
153 return $this->index;
154 }
155
156 /**
157 * @implements SeekableIterator
158 * @param mixed $pos
159 */
160 function seek($pos) {
161 /* only index for now */
162 $this->index = $pos;
163
164 if (!$this->valid()) {
165 throw new \OutOfBoundsException("Invalid seek position ($pos)");
166 }
167 }
168
169 /**
170 * @implements \Countable
171 * @return int
172 */
173 function count() {
174 return count($this->rows);
175 }
176
177 /**
178 * Get the rows of this rowset
179 * @return array
180 */
181 function getRows() {
182 return $this->rows;
183 }
184
185 /**
186 * Filter by callback
187 * @param callable $cb
188 * @return \pq\Gateway\Rowset
189 */
190 function filter(callable $cb) {
191 $rowset = clone $this;
192 $rowset->rows = array_filter($this->rows, $cb);
193 return $rowset;
194 }
195 }