MySQLDriver::getColumns()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Rougin\Describe\Driver;
4
5
use Rougin\Describe\Column;
6
use Rougin\Describe\Exceptions\TableNotFoundException;
7
use Rougin\Describe\Table;
8
9
/**
10
 * MySQL Driver
11
 *
12
 * A database driver extension for MySQL.
13
 * NOTE: Should be renamed to "MySqlDriver" in v2.0.0.
14
 *
15
 * @package Describe
16
 * @author  Rougin Gutib <[email protected]>
17
 */
18
class MySQLDriver implements DriverInterface
19
{
20
    /**
21
     * @var string
22
     */
23
    protected $database;
24
25
    /**
26
     * @var \PDO
27
     */
28
    protected $pdo;
29
30
    /**
31
     * @var string
32
     */
33
    protected $script = '';
34
35
    /**
36
     * Initializes the driver instance.
37
     *
38
     * @param \PDO   $pdo
39
     * @param string $database
40
     */
41 105
    public function __construct(\PDO $pdo, $database)
42
    {
43 105
        $this->database = $database;
44
45 105
        $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
46
47 105
        $this->pdo = $pdo;
48
49 105
        $this->script = 'SELECT COLUMN_NAME as "column", REFERENCED_COLUMN_NAME as ' .
50 35
            '"referenced_column", CONCAT(REFERENCED_TABLE_SCHEMA, ".", ' .
51 35
            'REFERENCED_TABLE_NAME) as "referenced_table" FROM INFORMATION_SCHEMA' .
52 35
            '.KEY_COLUMN_USAGE WHERE CONSTRAINT_SCHEMA = "%s" AND TABLE_NAME = "%s";';
53 105
    }
54
55
    /**
56
     * Returns an array of Column instances from a table.
57
     *
58
     * @param  string $table
59
     * @return \Rougin\Describe\Column[]
60
     */
61 84
    public function columns($table)
62
    {
63 84
        return $this->query($table, 'DESCRIBE ' . $table);
64
    }
65
66
    /**
67
     * Returns an array of Column instances from a table.
68
     * NOTE: To be removed in v2.0.0. Use columns() instead.
69
     *
70
     * @param  string $table
71
     * @return \Rougin\Describe\Column[]
72
     */
73 48
    public function getColumns($table)
74
    {
75 48
        return $this->columns($table);
76
    }
77
78
    /**
79
     * Returns an array of Column instances from a table.
80
     * NOTE: To be removed in v2.0.0. Use getColumns() instead.
81
     *
82
     * @param  string $table
83
     * @return \Rougin\Describe\Column[]
84
     */
85 42
    public function getTable($table)
86
    {
87 42
        return $this->getColumns($table);
88
    }
89
90
    /**
91
     * Returns an array of table names.
92
     * NOTE: To be removed in v2.0.0. Use tables() instead.
93
     *
94
     * @return array
95
     */
96 6
    public function getTableNames()
97
    {
98 6
        return $this->items(false);
99
    }
100
101
    /**
102
     * Returns an array of table names.
103
     * NOTE: To be removed in v2.0.0. Use getTableNames() instead.
104
     *
105
     * @return array
106
     */
107 3
    public function showTables()
108
    {
109 3
        return $this->getTableNames();
110
    }
111
112
    /**
113
     * Returns an array of Table instances.
114
     *
115
     * @return \Rougin\Describe\Table[]
116
     */
117 12
    public function tables()
118
    {
119 12
        return $this->items(true);
120
    }
121
122
    /**
123
     * Prepares the defined columns.
124
     *
125
     * @param  \Rougin\Describe\Column $column
126
     * @param  string                  $table
127
     * @param  mixed                   $row
128
     * @return \Rougin\Describe\Column
129
     */
130 78
    protected function column(Column $column, $table, $row)
131
    {
132 78
        preg_match('/(.*?)\((.*?)\)/', $row->Type, $match);
133
134 78
        $column->setDataType($row->Type);
135
136 78
        $column->setDefaultValue($row->Default);
137
138 78
        $column->setField($row->Field);
139
140 78
        if (isset($match[1]) === true) {
141 78
            $column->setDataType($match[1]);
142
143 78
            $column->setLength($match[2]);
144 26
        }
145
146 78
        $column = $this->properties($row, $column);
147
148 78
        $column = $this->keys($row, $column);
149
150 78
        return $this->foreign($table, $row, $column);
151
    }
152
153
    /**
154
     * Sets the properties of a column if it does exists.
155
     *
156
     * @param  string                  $name
157
     * @param  mixed                   $row
158
     * @param  \Rougin\Describe\Column $column
159
     * @return \Rougin\Describe\Column
160
     */
161 78
    protected function foreign($name, $row, Column $column)
162
    {
163 78
        $query = sprintf($this->script, $this->database, $name);
164
165 78
        $table = $this->pdo->prepare($query);
166
167 78
        $table->execute();
168
169 78
        $table->setFetchMode(\PDO::FETCH_OBJ);
170
171 78
        while ($item = $table->fetch()) {
172 78
            if ($item->column === $row->Field) {
173 78
                $referenced = $this->strip($item->referenced_table);
174
175 78
                $column->setReferencedField($item->referenced_column);
176
177 78
                $column->setReferencedTable($referenced);
178 26
            }
179 26
        }
180
181 78
        return $column;
182
    }
183
184
    /**
185
     * Returns an array of table names or Table instances.
186
     * NOTE: To be removed in v2.0.0. Move to tables() instead.
187
     *
188
     * @param  boolean $instance
189
     * @param  array   $tables
190
     * @return array|\Rougin\Describe\Table[]
191
     */
192 18
    protected function items($instance = false, $tables = array())
193
    {
194 18
        $information = $this->pdo->prepare('SHOW TABLES');
195
196 18
        $information->execute();
197
198 18
        while ($row = $information->fetch()) {
199
            // NOTE: To be removed in v2.0.0. Always return Table instance.
200 18
            $instance && $row[0] = new Table($row[0], $this);
201
202 18
            array_push($tables, $row[0]);
203 6
        }
204
205 18
        return $tables;
206
    }
207
208
    /**
209
     * Sets the key of a column.
210
     *
211
     * @param  mixed                   $row
212
     * @param  \Rougin\Describe\Column $column
213
     * @return \Rougin\Describe\Column
214
     */
215 78
    protected function keys($row, Column $column)
216
    {
217 78
        switch ($row->Key) {
218 78
            case 'PRI':
219 78
                $column->setPrimary(true);
220
221 78
                break;
222
            
223 78
            case 'MUL':
224 78
                $column->setForeign(true);
225
226 78
                break;
227
228 78
            case 'UNI':
229 78
                $column->setUnique(true);
230
231 78
                break;
232 26
        }
233
234 78
        return $column;
235
    }
236
237
    /**
238
     * Returns the list of columns based on a query.
239
     *
240
     * @param  string $table
241
     * @param  string $query
242
     * @param  array  $columns
243
     * @return \Rougin\Describe\Column[]
244
     */
245 126
    protected function query($table, $query, $columns = array())
246
    {
247 126
        $result = $this->pdo->prepare($query);
248
249 126
        $result->execute();
250
251 120
        $result->setFetchMode(\PDO::FETCH_OBJ);
252
253 120
        while ($row = $result->fetch()) {
254 114
            $column = $this->column(new Column, $table, $row);
255
256 114
            array_push($columns, $column);
257 38
        }
258
259 120
        if (empty($columns) === true) {
260 6
            $message = 'Table "' . $table . '" does not exists!';
261
262 6
            throw new TableNotFoundException($message);
263
        }
264
265 114
        return $columns;
266
    }
267
268
    /**
269
     * Sets the properties of a column.
270
     *
271
     * @param  mixed                   $row
272
     * @param  \Rougin\Describe\Column $column
273
     * @return \Rougin\Describe\Column
274
     */
275 78
    protected function properties($row, Column $column)
276
    {
277 78
        $increment = $row->Extra === 'auto_increment';
278
279 78
        $column->setAutoIncrement($increment);
280
281 78
        $column->setNull($row->{'Null'} === 'YES');
282
283 78
        return $column;
284
    }
285
286
    /**
287
     * Strips the table schema from the table name.
288
     *
289
     * @param  string $table
290
     * @return string
291
     */
292 78
    protected function strip($table)
293
    {
294 78
        $exists = strpos($table, '.') !== false;
295
296 78
        $updated = substr($table, strpos($table, '.') + 1);
297
298 78
        return $exists ? $updated : $table;
299
    }
300
}
301