Completed
Push — master ( 1e580c...2333a3 )
by Sébastien
02:00
created

MysqlInformationSchema::clearCacheInformation()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 10
ccs 9
cts 9
cp 1
rs 9.4286
cc 3
eloc 6
nc 3
nop 0
crap 3
1
<?php
2
namespace Soluble\Schema\Source;
3
4
use Soluble\Schema\Exception;
5
use Soluble\Schema\Source;
6
use Soluble\Schema\Db\Wrapper\MysqlConnectionAdapter;
7
use ArrayObject;
8
9
class MysqlInformationSchema extends Source\AbstractSchemaSource
10
{
11
    /**
12
     * Schema name
13
     *
14
     * @var string
15
     */
16
    protected $schema;
17
18
    /**
19
     * @var MysqlConnectionAdapter
20
     */
21
    protected $adapter;
22
23
24
    /**
25
     * Whether to include full schema options like comment, collations...
26
     * @var boolean
27
     */
28
    protected $include_options = true;
29
30
    /**
31
     *
32
     * @var array
33
     */
34
    protected static $localCache = array();
35
36
37
    /**
38
     *
39
     * @var boolean
40
     */
41
    protected $useLocalCaching = true;
42
43
    /**
44
     *
45
     * @var array
46
     */
47
    protected static $fullyCachedSchemas = array();
48
49
50
    /**
51
     *
52
     * @var Mysql\MysqlDriverInterface
53
     */
54
    protected $driver;
55
56
    /**
57
     * Constructor
58
     *
59
     * @param \PDO|\mysqli $connection
60
     * @param string|null $schema default schema, taken from adapter if not given
61
     * @throws Exception\InvalidArgumentException for invalid connection
62
     * @throws Exception\InvalidUsageException thrown if no schema can be found.
63
     */
64 23
    public function __construct($connection, $schema = null)
65
    {
66
        try {
67 23
            $this->adapter = new MysqlConnectionAdapter($connection);
68 23
        } catch (Exception\InvalidArgumentException $e) {
69
            $msg = "MysqlInformationSchema requires a valid 'mysqli' or 'pdo:mysql' connection object ({$e->getMessage()}).";
70 3
            throw new Exception\InvalidArgumentException($msg);
71
        }
72
73 23
        if ($schema === null) {
74 23
            $schema = $this->adapter->getCurrentSchema();
75 23
            if ($schema === false || $schema == '') {
76
                $msg = "Database name (schema) parameter missing and no default schema set on connection";
77
                throw new Exception\InvalidUsageException($msg);
78
            }
79 23
        }
80
81 23
        $this->driver = new Mysql\MysqlDriver51($this->adapter, $schema);
82
83 23
        $this->setDefaultSchema($schema);
84 23
    }
85
86
87
    /**
88
     * {@inheritdoc}
89
     */
90 1
    public function getUniqueKeys($table, $include_primary = false)
91
    {
92 1
        $this->loadCacheInformation($table);
93 1
        $uniques = (array) self::$localCache[$this->schema]['tables'][$table]['unique_keys'];
94 1
        if ($include_primary) {
95
            try {
96 1
                $pks = $this->getPrimaryKeys($table);
97 1
                if (count($pks) > 0) {
98 1
                    $uniques = array_merge($uniques, array('PRIMARY' => $pks));
99 1
                }
100 1
            } catch (Exception\NoPrimaryKeyException $e) {
101
                // Ignore exception
102
            }
103 1
        }
104 1
        return $uniques;
105
    }
106
107
108
    /**
109
     * {@inheritdoc}
110
     */
111
    public function getIndexesInformation($table)
112
    {
113
        $this->loadCacheInformation($table);
114
        return self::$localCache[$this->schema]['tables'][$table]['indexes'];
115
    }
116
117
    /**
118
     * {@inheritdoc}
119
     */
120 5
    public function getPrimaryKey($table)
121
    {
122 5
        $pks = $this->getPrimaryKeys($table);
123 2
        if (count($pks) > 1) {
124 1
            $keys = join(',', $pks);
125 1
            throw new Exception\MultiplePrimaryKeyException(__METHOD__ . ". Multiple primary keys found on table '{$this->schema}'.'$table':  $keys");
126
        }
127 4
        return $pks[0];
128
    }
129
130
131
    /**
132
     * {@inheritdoc}
133
     */
134 9
    public function getPrimaryKeys($table)
135
    {
136 9
        $this->loadCacheInformation($table);
137 7
        $pks = self::$localCache[$this->schema]['tables'][$table]['primary_keys'];
138 6
        if (count($pks) == 0) {
139 3
            throw new Exception\NoPrimaryKeyException(__METHOD__ . ". No primary keys found on table  '{$this->schema}'.'$table'.");
140
        }
141 5
        return $pks;
142
    }
143
144
145
    /**
146
     * {@inheritdoc}
147
     */
148 2
    public function getColumnsInformation($table)
149
    {
150 2
        $this->loadCacheInformation($table);
151 2
        return self::$localCache[$this->schema]['tables'][$table]['columns'];
152
    }
153
154
155
    /**
156
     * {@inheritdoc}
157
     */
158 1
    public function getForeignKeys($table)
159
    {
160 1
        $this->loadCacheInformation($table);
161 1
        return self::$localCache[$this->schema]['tables'][$table]['foreign_keys'];
162
    }
163
164
    /**
165
     * {@inheritdoc}
166
     */
167 1
    public function getReferences($table)
168
    {
169 1
        $this->loadCacheInformation($table);
170 1
        return self::$localCache[$this->schema]['tables'][$table]['references'];
171
    }
172
173
    /**
174
     * {@inheritdoc}
175
     */
176 4
    public function getTablesInformation()
177 1
    {
178 4
        $this->loadCacheInformation(null);
179 3
        return self::$localCache[$this->schema]['tables'];
180
    }
181
182
    /**
183
     * Get a table configuration
184
     *
185
     * @throws Exception\ErrorException
186
     * @throws Exception\TableNotFoundException
187
     *
188
     * @param string $table table name
189
     * @param boolean|null $include_options include extended information
190
     * @return ArrayObject
191
     */
192 13
    protected function getTableConfig($table, $include_options = null)
193
    {
194 13
        if ($include_options === null) {
195 13
            $include_options = $this->include_options;
196 13
        }
197
198 13
        $schema = $this->schema;
199
200 13
        if ($this->useLocalCaching &&
201 13
                isset(self::$localCache[$schema]['tables'][$table])) {
202 9
            return self::$localCache[$schema]['tables'][$table];
203
        }
204
205 4
        $config = $this->driver->getSchemaConfig($table, $include_options);
206
207 4
        if (!array_key_exists($table, $config['tables'])) {
208 2
            throw new Exception\TableNotFoundException(__METHOD__ . ". Table '$table' in database schema '{$schema}' not found.");
209
        }
210
211 2
        if ($this->useLocalCaching) {
212 2
            if (!array_key_exists($schema, self::$localCache)) {
213 1
                self::$localCache[$schema] = array();
214 1
            }
215 2
            self::$localCache[$schema] = new ArrayObject(array_merge_recursive((array) self::$localCache[$schema], (array) $config));
216 2
        }
217
218 2
        return $config['tables'][$table];
219
    }
220
221
222
    /**
223
     * Get schema configuration
224
     *
225
     * @throws Exception\ErrorException
226
     * @throws Exception\SchemaNotFoundException
227
     *
228
     * @param boolean|null $include_options include extended information
229
     * @return ArrayObject
230
     */
231 2
    public function getSchemaConfig($include_options = null)
232
    {
233 2
        if ($include_options === null) {
234 2
            $include_options = $this->include_options;
235 2
        }
236 2
        $schema = $this->schema;
237 2
        if ($this->useLocalCaching && in_array($schema, self::$fullyCachedSchemas)) {
238
            return self::$localCache[$schema];
239
        }
240
241 2
        $config = $this->driver->getSchemaConfig($table = null, $include_options);
242 2
        if (count($config['tables']) == 0) {
243 1
            throw new Exception\SchemaNotFoundException(__METHOD__ . " Error: schema '{$schema}' not found or without any table or view");
244
        }
245 1
        if ($this->useLocalCaching) {
246 1
            self::$localCache[$schema] = $config;
247 1
            self::$fullyCachedSchemas[] = $schema;
248 1
        }
249 1
        return $config;
250
    }
251
252
    /**
253
     *
254
     * @param string $table
255
     * @throws Exception\InvalidArgumentException
256
     * @throws Exception\TableNotFoundException
257
     *
258
     */
259 16
    protected function loadCacheInformation($table = null)
260
    {
261 16
        $schema = $this->schema;
262 16
        $this->checkTableArgument($table);
263
264 14
        if (!in_array($schema, self::$fullyCachedSchemas)) {
265 3
            if ($table !== null) {
266 3
                $this->getTableConfig($table);
267 3
            } else {
268
                $this->getSchemaConfig();
269
            }
270 14
        } elseif ($table !== null) {
271
            // Just in case to check if table exists
272 8
            $this->getTableConfig($table);
273 7
        }
274 13
    }
275
276
    /**
277
     * Clear local cache information for the current schema
278
     *
279
     * @throws Exception\InvalidArgumentException
280
     */
281 1
    public function clearCacheInformation()
282
    {
283 1
        $schema = $this->schema;
284 1
        if (array_key_exists($schema, self::$localCache)) {
285 1
            unset(self::$localCache[$schema]);
286 1
            if (($key = array_search($schema, self::$fullyCachedSchemas)) !== false) {
287 1
                unset(self::$fullyCachedSchemas[$key]);
288 1
            }
289 1
        }
290 1
    }
291
}
292