1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13:
14:
15: 16: 17: 18: 19: 20: 21:
22: class NDiscoveredReflection extends NObject implements IReflection
23: {
24:
25: protected $cache;
26:
27:
28: protected $cacheStorage;
29:
30:
31: protected $connection;
32:
33:
34: protected $structure = array(
35: 'primary' => array(),
36: 'hasMany' => array(),
37: 'belongsTo' => array(),
38: );
39:
40:
41:
42: 43: 44: 45:
46: public function __construct(ICacheStorage $storage = NULL)
47: {
48: $this->cacheStorage = $storage;
49: }
50:
51:
52:
53: public function setConnection(NConnection $connection)
54: {
55: $this->connection = $connection;
56: if ($this->cacheStorage) {
57: $this->cache = new NCache($this->cacheStorage, 'Nette.Database.' . md5($connection->getDsn()));
58: $this->structure = ($tmp=$this->cache->load('structure')) ? $tmp : $this->structure;
59: }
60: }
61:
62:
63:
64: public function __destruct()
65: {
66: if ($this->cache) {
67: $this->cache->save('structure', $this->structure);
68: }
69: }
70:
71:
72:
73: public function getPrimary($table)
74: {
75: $primary = & $this->structure['primary'][$table];
76: if (isset($primary)) {
77: return $primary;
78: }
79:
80: $columns = $this->connection->getSupplementalDriver()->getColumns($table);
81: $primaryCount = 0;
82: foreach ($columns as $column) {
83: if ($column['primary']) {
84: $primary = $column['name'];
85: $primaryCount++;
86: }
87: }
88:
89: if ($primaryCount !== 1)
90: return NULL;
91:
92: return $primary;
93: }
94:
95:
96:
97: public function getHasManyReference($table, $key, $refresh = TRUE)
98: {
99: $reference = $this->structure['hasMany'];
100: if (!empty($reference[$table])) {
101: foreach ($reference[$table] as $targetTable => $targetColumn) {
102: if (strpos($targetTable, strtolower($key)) !== FALSE) {
103: return array(
104: $targetTable,
105: $targetColumn,
106: );
107: }
108: }
109: }
110:
111: if (!$refresh) {
112: throw new PDOException("No reference found for \${$table}->related({$key}).");
113: }
114:
115: $this->reloadAllForeignKeys();
116: return $this->getHasManyReference($table, $key, FALSE);
117: }
118:
119:
120:
121: public function getBelongsToReference($table, $key, $refresh = TRUE)
122: {
123: $reference = $this->structure['belongsTo'];
124: if (!empty($reference[$table])) {
125: foreach ($reference[$table] as $column => $targetTable) {
126: if (strpos($column, strtolower($key)) !== FALSE) {
127: return array(
128: $targetTable,
129: $column,
130: );
131: }
132: }
133: }
134:
135: if (!$refresh) {
136: throw new PDOException("No reference found for \${$table}->{$key}.");
137: }
138:
139: $this->reloadForeignKeys($table);
140: return $this->getBelongsToReference($table, $key, FALSE);
141: }
142:
143:
144:
145: protected function reloadAllForeignKeys()
146: {
147: foreach ($this->connection->getSupplementalDriver()->getTables() as $table) {
148: if ($table['view'] == FALSE) {
149: $this->reloadForeignKeys($table['name']);
150: }
151: }
152:
153: foreach (array_keys($this->structure['hasMany']) as $table) {
154: uksort($this->structure['hasMany'][$table], create_function('$a, $b', '
155: return strlen($a) - strlen($b);
156: '));
157: }
158: }
159:
160:
161:
162: protected function reloadForeignKeys($table)
163: {
164: foreach ($this->connection->getSupplementalDriver()->getForeignKeys($table) as $row) {
165: $this->structure['belongsTo'][$table][strtolower($row['local'])] = $row['table'];
166: $this->structure['hasMany'][strtolower($row['table'])][$table] = $row['local'];
167: }
168:
169: if (isset($this->structure['belongsTo'][$table])) {
170: uksort($this->structure['belongsTo'][$table], create_function('$a, $b', '
171: return strlen($a) - strlen($b);
172: '));
173: }
174: }
175:
176: }
177: