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