1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13:
14:
15: 16: 17: 18: 19: 20: 21:
22: class TableRow extends Object implements IteratorAggregate, ArrayAccess
23: {
24:
25: private $table;
26:
27:
28: private $data;
29:
30:
31: private $dataRefreshed = FALSE;
32:
33:
34: private $modified = array();
35:
36:
37:
38: public function __construct(array $data, TableSelection $table)
39: {
40: $this->data = $data;
41: $this->table = $table;
42: }
43:
44:
45:
46: 47: 48: 49:
50: public function setTable(TableSelection $table)
51: {
52: $this->table = $table;
53: }
54:
55:
56:
57: 58: 59: 60:
61: public function getTable()
62: {
63: return $this->table;
64: }
65:
66:
67:
68: public function __toString()
69: {
70: try {
71: return (string) $this->getPrimary();
72: } catch (Exception $e) {
73: trigger_error("Exception in " . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR);
74: }
75: }
76:
77:
78:
79: 80: 81:
82: public function toArray()
83: {
84: $this->accessColumn(NULL);
85: return $this->data;
86: }
87:
88:
89:
90: 91: 92: 93: 94:
95: public function getPrimary($need = TRUE)
96: {
97: $primary = $this->table->getPrimary();
98: if (!is_array($primary)) {
99: if (isset($this->data[$primary])) {
100: return $this->data[$primary];
101: } elseif ($need) {
102: throw new InvalidStateException("Row does not contain primary $primary column data.");
103: } else {
104: return NULL;
105: }
106: } else {
107: $primaryVal = array();
108: foreach ($primary as $key) {
109: if (!isset($this->data[$key])) {
110: if ($need) {
111: throw new InvalidStateException("Row does not contain primary $key column data.");
112: } else {
113: return NULL;
114: }
115: }
116: $primaryVal[$key] = $this->data[$key];
117: }
118: return $primaryVal;
119: }
120: }
121:
122:
123:
124: 125: 126: 127: 128:
129: public function getSignature($need = TRUE)
130: {
131: return implode('|', (array) $this->getPrimary($need));
132: }
133:
134:
135:
136: 137: 138: 139: 140: 141:
142: public function ref($key, $throughColumn = NULL)
143: {
144: if (!$throughColumn) {
145: list($key, $throughColumn) = $this->table->getConnection()->getDatabaseReflection()->getBelongsToReference($this->table->getName(), $key);
146: }
147:
148: return $this->getReference($key, $throughColumn);
149: }
150:
151:
152:
153: 154: 155: 156: 157: 158:
159: public function related($key, $throughColumn = NULL)
160: {
161: if (strpos($key, '.') !== FALSE) {
162: list($key, $throughColumn) = explode('.', $key);
163: } elseif (!$throughColumn) {
164: list($key, $throughColumn) = $this->table->getConnection()->getDatabaseReflection()->getHasManyReference($this->table->getName(), $key);
165: }
166:
167: return $this->table->getReferencingTable($key, $throughColumn, $this[$this->table->getPrimary()]);
168: }
169:
170:
171:
172: 173: 174: 175: 176:
177: public function update($data = NULL)
178: {
179: if ($data === NULL) {
180: $data = $this->modified;
181: }
182: return $this->table->getConnection()
183: ->table($this->table->getName())
184: ->find($this->getPrimary())
185: ->update($data);
186: }
187:
188:
189:
190: 191: 192: 193:
194: public function delete()
195: {
196: $res = $this->table->getConnection()
197: ->table($this->table->getName())
198: ->find($this->getPrimary())
199: ->delete();
200:
201: if ($res > 0 && ($signature = $this->getSignature(FALSE))) {
202: unset($this->table[$signature]);
203: }
204:
205: return $res;
206: }
207:
208:
209:
210:
211:
212:
213:
214: public function getIterator()
215: {
216: $this->accessColumn(NULL);
217: return new ArrayIterator($this->data);
218: }
219:
220:
221:
222:
223:
224:
225:
226: 227: 228: 229: 230: 231:
232: public function offsetSet($key, $value)
233: {
234: $this->__set($key, $value);
235: }
236:
237:
238:
239: 240: 241: 242: 243:
244: public function offsetGet($key)
245: {
246: return $this->__get($key);
247: }
248:
249:
250:
251: 252: 253: 254: 255:
256: public function offsetExists($key)
257: {
258: return $this->__isset($key);
259: }
260:
261:
262:
263: 264: 265: 266: 267:
268: public function offsetUnset($key)
269: {
270: $this->__unset($key);
271: }
272:
273:
274:
275: public function __set($key, $value)
276: {
277: $this->data[$key] = $value;
278: $this->modified[$key] = $value;
279: }
280:
281:
282:
283: public function &__get($key)
284: {
285: $this->accessColumn($key);
286: if (array_key_exists($key, $this->data)) {
287: return $this->data[$key];
288: }
289:
290: list($table, $column) = $this->table->getConnection()->getDatabaseReflection()->getBelongsToReference($this->table->getName(), $key);
291: $referenced = $this->getReference($table, $column);
292: if ($referenced !== FALSE) {
293: $this->accessColumn($key, FALSE);
294: return $referenced;
295: }
296:
297: $this->removeAccessColumn($key);
298: throw new MemberAccessException("Cannot read an undeclared column \"$key\".");
299: }
300:
301:
302:
303: public function __isset($key)
304: {
305: $this->accessColumn($key);
306: if (array_key_exists($key, $this->data)) {
307: return isset($this->data[$key]);
308: }
309: $this->removeAccessColumn($key);
310: return FALSE;
311: }
312:
313:
314:
315: public function __unset($key)
316: {
317: unset($this->data[$key]);
318: unset($this->modified[$key]);
319: }
320:
321:
322:
323: protected function accessColumn($key, $selectColumn = TRUE)
324: {
325: if (isset($this->modified[$key])) {
326: return;
327: }
328:
329: $this->table->accessColumn($key, $selectColumn);
330: if ($this->table->getDataRefreshed() && !$this->dataRefreshed) {
331: $this->data = $this->table[$this->getSignature()]->data;
332: $this->dataRefreshed = TRUE;
333: }
334: }
335:
336:
337:
338: protected function removeAccessColumn($key)
339: {
340: $this->table->removeAccessColumn($key);
341: }
342:
343:
344:
345: protected function getReference($table, $column)
346: {
347: $this->accessColumn($column);
348: if (array_key_exists($column, $this->data)) {
349: $value = $this->data[$column];
350: $value = $value instanceof TableRow ? $value->getPrimary() : $value;
351:
352: $referenced = $this->table->getReferencedTable($table, $column, !empty($this->modified[$column]));
353: $referenced = isset($referenced[$value]) ? $referenced[$value] : NULL;
354:
355: if (!empty($this->modified[$column])) {
356: $this->modified[$column] = 0;
357: }
358:
359: return $referenced;
360: }
361:
362: return FALSE;
363: }
364:
365: }
366: