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