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