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