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 empty($primary) ? NULL : $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: $primary = '';
91: return NULL;
92: }
93:
94: return $primary;
95: }
96:
97:
98:
99: public function getHasManyReference($table, $key, $refresh = TRUE)
100: {
101: $reference = $this->structure['hasMany'];
102: if (!empty($reference[$table])) {
103: foreach ($reference[$table] as $targetTable => $targetColumn) {
104: if (stripos($targetTable, $key) !== FALSE) {
105: return array(
106: $targetTable,
107: $targetColumn,
108: );
109: }
110: }
111: }
112:
113: if (!$refresh) {
114: throw new PDOException("No reference found for \${$table}->related({$key}).");
115: }
116:
117: $this->reloadAllForeignKeys();
118: return $this->getHasManyReference($table, $key, FALSE);
119: }
120:
121:
122:
123: public function getBelongsToReference($table, $key, $refresh = TRUE)
124: {
125: $reference = $this->structure['belongsTo'];
126: if (!empty($reference[$table])) {
127: foreach ($reference[$table] as $column => $targetTable) {
128: if (stripos($column, $key) !== FALSE) {
129: return array(
130: $targetTable,
131: $column,
132: );
133: }
134: }
135: }
136:
137: if (!$refresh) {
138: throw new PDOException("No reference found for \${$table}->{$key}.");
139: }
140:
141: $this->reloadForeignKeys($table);
142: return $this->getBelongsToReference($table, $key, FALSE);
143: }
144:
145:
146:
147: protected function reloadAllForeignKeys()
148: {
149: foreach ($this->connection->getSupplementalDriver()->getTables() as $table) {
150: if ($table['view'] == FALSE) {
151: $this->reloadForeignKeys($table['name']);
152: }
153: }
154:
155: foreach (array_keys($this->structure['hasMany']) as $table) {
156: uksort($this->structure['hasMany'][$table], create_function('$a, $b', '
157: return strlen($a) - strlen($b);
158: '));
159: }
160: }
161:
162:
163:
164: protected function reloadForeignKeys($table)
165: {
166: foreach ($this->connection->getSupplementalDriver()->getForeignKeys($table) as $row) {
167: $this->structure['belongsTo'][$table][$row['local']] = $row['table'];
168: $this->structure['hasMany'][$row['table']][$table] = $row['local'];
169: }
170:
171: if (isset($this->structure['belongsTo'][$table])) {
172: uksort($this->structure['belongsTo'][$table], create_function('$a, $b', '
173: return strlen($a) - strlen($b);
174: '));
175: }
176: }
177:
178: }
179: