flush
[m6w6/pq-gateway] / lib / pq / Gateway / Table.php
1 <?php
2
3 namespace pq\Gateway;
4
5 use \pq\Query\Writer as QueryWriter;
6 use \pq\Query\Executor as QueryExecutor;
7
8 class Table
9 {
10 /**
11 * @var \pq\Connection
12 */
13 public static $defaultConnection;
14
15 /**
16 * @var \pq\Connection
17 */
18 protected $conn;
19
20 /**
21 * @var string
22 */
23 protected $name;
24
25 /**
26 * @var string
27 */
28 protected $rowset = "\\pq\\Gateway\\Rowset";
29
30 /**
31 * @var \pq\Query\WriterIterface
32 */
33 protected $query;
34
35 /**
36 * @var \pq\Query\ExecutorInterface
37 */
38 protected $exec;
39
40 /**
41 * @var array
42 */
43 protected $dependents;
44
45 /**
46 * @param string $name
47 * @param \pq\Connection $conn
48 * @param array $dependents
49 */
50 function __construct($name, \pq\Connection $conn = null, array $dependents = array()) {
51 $this->name = $name;
52 $this->conn = $conn ?: static::$defaultConnection ?: new \pq\Connection;
53 $this->dependents = $dependents;
54 }
55
56 /**
57 * Set the rowset prototype
58 * @param mixed $rowset
59 * @return \pq\Gateway\Table
60 */
61 function setRowsetPrototype($rowset) {
62 $this->rowset = $rowset;
63 return $this;
64 }
65
66 /**
67 * Get the rowset prototype
68 * @return mixed
69 */
70 function getRowsetPrototype() {
71 return $this->rowset;
72 }
73
74 /**
75 * Set the query writer
76 * @param \pq\Query\WriterInterface $query
77 * @return \pq\Gateway\Table
78 */
79 function setQueryWriter(\pq\Query\WriterInterface $query) {
80 $this->query = $query;
81 return $this;
82 }
83
84 /**
85 * Get the query writer
86 * @return \pq\Query\WriterInterface
87 */
88 function getQueryWriter() {
89 if (!$this->query) {
90 $this->query = new QueryWriter;
91 }
92 return $this->query;
93 }
94
95 /**
96 * Set the query executor
97 * @param \pq\Query\ExecutorInterface $exec
98 * @return \pq\Gateway\Table
99 */
100 function setQueryExecutor(\pq\Query\ExecutorInterface $exec) {
101 $this->exec = $exec;
102 return $this;
103 }
104
105 /**
106 * Get the query executor
107 * @return \pq\Query\ExecutorInterface
108 */
109 function getQueryExecutor() {
110 if (!$this->exec) {
111 $this->exec = new QueryExecutor($this->conn);
112 }
113 return $this->exec;
114 }
115
116 /**
117 * @return \pq\Connection
118 */
119 function getConnection() {
120 return $this->conn;
121 }
122
123 /**
124 * @return string
125 */
126 function getName() {
127 return $this->name;
128 }
129
130 /**
131 * Execute the query
132 * @param \pq\Query\WriterInterface $query
133 * @return mixed
134 */
135 protected function execute(QueryWriter $query) {
136 return $this->getQueryExecutor()->execute($query, array($this, "onResult"));
137 }
138
139 /**
140 * Retreives the result of an executed query
141 * @param \pq\Result $result
142 * @return mixed
143 */
144 public function onResult(\pq\Result $result) {
145 if ($result->status != \pq\Result::TUPLES_OK) {
146 return $result;
147 }
148
149 $rowset = $this->getRowsetPrototype();
150 if (is_callable($rowset)) {
151 return $rowset($result);
152 } elseif ($rowset) {
153 return new $rowset($this, $result);
154 }
155
156 return $result;
157 }
158
159 /**
160 * Find rows in the table
161 * @param array $where
162 * @param array|string $order
163 * @param int $limit
164 * @param int $offset
165 * @return mixed
166 */
167 function find(array $where = null, $order = null, $limit = 0, $offset = 0) {
168 $query = $this->getQueryWriter()->reset();
169 $query->write("SELECT * FROM", $this->conn->quoteName($this->name));
170 if ($where) {
171 $query->write("WHERE")->criteria($where);
172 }
173 if ($order) {
174 $query->write("ORDER BY", $order);
175 }
176 if ($limit) {
177 $query->write("LIMIT", $limit);
178 }
179 $query->write("OFFSET", $offset);
180 return $this->execute($query);
181 }
182
183 /**
184 * Get the parent row of a row by foreign key
185 * @param \pq\Gateway\Row $dependent
186 * @param string $name optional fkey name
187 * @param string $order
188 * @param int $limit
189 * @param int $offset
190 * @return mixed
191 */
192 function of(Row $dependent, $name = null, $order = null, $limit = 0, $offset = 0) {
193 if (!$name) {
194 $name = $dependent->getTable()->getName();
195 }
196 return $this->find(array("{$name}_id=" => $dependent->id),
197 $order, $limit, $offset);
198 }
199
200 /**
201 * Get the child rows of a row by foreign key
202 * @param \pq\Gateway\Row $me
203 * @param string $dependent
204 * @param string $order
205 * @param int $limit
206 * @param int $offset
207 * @return mixed
208 * @throws \LogicException
209 */
210 function by(Row $me, $dependent, $order = null, $limit = 0, $offset = 0) {
211 if (!isset($this->dependents[$dependent])) {
212 throw new \LogicException("Unknown dependent table $dependent");
213 }
214
215 $dependentClass = $this->dependents[$dependent];
216 $dependentModel = new $dependentClass($this->conn);
217 return $dependentModel->of($me, null, $order, $limit, $offset);
218 }
219
220 /**
221 * Insert a row into the table
222 * @param array $data
223 * @param string $returning
224 * @return mixed
225 */
226 function create(array $data = null, $returning = "*") {
227 $query = $this->getQueryWriter()->reset();
228 $query->write("INSERT INTO", $this->conn->quoteName($this->name));
229 if ($data) {
230 $first = true;
231 $params = array();
232 foreach ($data as $key => $val) {
233 $query->write($first ? "(" : ",", $key);
234 $params[] = $query->param($val);
235 $first and $first = false;
236 }
237 $query->write(") VALUES (", $params, ")");
238 } else {
239 $query->write("DEFAULT VALUES");
240 }
241
242 if (strlen($returning)) {
243 $query->write("RETURNING", $returning);
244 }
245 return $this->execute($query);
246 }
247
248 /**
249 * Update rows in the table
250 * @param array $where
251 * @param array $data
252 * @param string $returning
253 * @retunr mixed
254 */
255 function update(array $where, array $data, $returning = "*") {
256 $query = $this->getQueryWriter()->reset();
257 $query->write("UPDATE", $this->conn->quoteName($this->name));
258 $first = true;
259 foreach ($data as $key => $val) {
260 $query->write($first ? "SET" : ",", $key, "=", $query->param($val));
261 $first and $first = false;
262 }
263 $query->write("WHERE")->criteria($where);
264 if (strlen($returning)) {
265 $query->write("RETURNING", $returning);
266 }
267 return $this->execute($query);
268 }
269
270 /**
271 * Delete rows from the table
272 * @param array $where
273 * @param string $returning
274 * @return mixed
275 */
276 function delete(array $where, $returning = null) {
277 $query = $this->getQueryWriter()->reset();
278 $query->write("DELETE FROM", $this->conn->quoteName($this->name));
279 $query->write("WHERE")->criteria($where);
280 if (strlen($returning)) {
281 $query->write("RETURNING", $returning);
282 }
283 return $this->execute($query);
284 }
285 }