Completed
Push — master ( 7b7ebd...db1323 )
by Sébastien
02:06
created

MysqlDriver51   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 271
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 98.57%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 31
c 1
b 0
f 0
lcom 1
cbo 3
dl 0
loc 271
ccs 138
cts 140
cp 0.9857
rs 9.8

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
F getSchemaConfig() 0 237 30
1
<?php
2
3
namespace Soluble\Schema\Source\Mysql;
4
5
use Soluble\Schema\Db\Wrapper\MysqlConnectionAdapter;
6
use ArrayObject;
7
use Zend\Config\Config;
8
9
class MysqlDriver51 extends AbstractMysqlDriver
10
{
11
12
    /**
13
     * @var MysqlConnectionAdapter
14
     */
15
    protected $adapter;
16
17
    /**
18
     * Schema name
19
     * @var string
20
     */
21
    protected $schema;
22
23
    /**
24
     *
25
     * @param MysqlConnectionAdapter $adapter
26
     * @param string $schema Schema name
27
     */
28 23
    public function __construct(MysqlConnectionAdapter $adapter, $schema)
29
    {
30 23
        parent::__construct($adapter, $schema);
0 ignored issues
show
Documentation introduced by
$schema is of type string, but the function expects a object<Soluble\Schema\Source\Mysql\strinbg>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
31 23
    }
32
33
    /**
34
     * Return object (table/schema) configuration
35
     *
36
     * @throws Exception\ErrorException
37
     *
38
     * @param string $table
39
     * @param boolean|null $include_options
40
     * @return ArrayObject
41
     */
42 6
    public function getSchemaConfig($table = null, $include_options = null)
43
    {
44 6
        if ($include_options === null) {
45
            $include_options = $this->include_options;
0 ignored issues
show
Bug introduced by
The property include_options does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
46
        }
47
48 6
        $schema = $this->schema;
49 6
        $qSchema = $this->adapter->quoteValue($schema);
50
51 6
        if ($table !== null) {
52 4
            $qTable = $this->adapter->quoteValue($table);
53 4
            $table_clause = "and (t.TABLE_NAME = $qTable or (kcu.referenced_table_name = $qTable and kcu.constraint_name = 'FOREIGN KEY'))";
54 4
            $table_join_condition = "(t.table_name = kcu.table_name or  kcu.referenced_table_name = t.table_name)";
55 4
        } else {
56 2
            $table_join_condition = "t.table_name = kcu.table_name";
57 2
            $table_clause = '';
58
        }
59
60
        $query = "
61
62
            SELECT
63
                    t.table_name,
64
                    c.column_name,
65
                    c.data_type,
66
                    c.column_type,
67
68
                    c.extra,
69
70
                    tc.constraint_type,
71
                    kcu.constraint_name,
72
                    kcu.referenced_table_name,
73
                    kcu.referenced_column_name,
74
75
                    c.column_default,
76
                    c.is_nullable,
77
                    c.numeric_precision,
78
                    c.numeric_scale,
79
                    c.character_octet_length,
80
                    c.character_maximum_length,
81
                    c.ordinal_position,
82
83
                    c.column_key, -- UNI/MUL/PRI
84
                    c.character_set_name,
85
86
87
                    c.collation_name,
88
89
                    c.column_comment,
90
91
                    t.table_type,
92
                    t.engine,
93
                    t.table_comment,
94
                    t.table_collation
95
96
            FROM `INFORMATION_SCHEMA`.`COLUMNS` c
97
            INNER JOIN `INFORMATION_SCHEMA`.`TABLES` t on c.TABLE_NAME = t.TABLE_NAME
98
            LEFT JOIN `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` kcu
99
               on (
100
                    $table_join_condition
101
                     and kcu.table_schema = t.table_schema
102
                     and kcu.column_name = c.column_name
103
                 )
104
              LEFT JOIN
105
                `INFORMATION_SCHEMA`.`TABLE_CONSTRAINTS` tc
106
               on (
107
                     t.table_name = tc.table_name
108
                      and tc.table_schema = t.table_schema
109
                      and tc.constraint_name = kcu.constraint_name
110
                  )
111
112
113 6
            where c.TABLE_SCHEMA = $qSchema
114 6
            and t.TABLE_SCHEMA = $qSchema
115 6
            $table_clause
116 6
            and (kcu.table_schema = $qSchema  or kcu.table_schema is null)
117
118
            and (kcu.column_name = c.column_name or kcu.column_name is null)
119
            order by t.table_name, c.ordinal_position
120 6
        ";
121
122 6
        $this->disableInnoDbStats();
123
        try {
124 6
            $results = $this->adapter->query($query);
125 6
        } catch (\Exception $e) {
126
            //@codeCoverageIgnoreStart
127
            $this->restoreInnoDbStats();
128
            throw new Exception\ErrorException(__METHOD__ . ": " . $e->getMessage());
129
            //@codeCoverageIgnoreEnd
130
        }
131 6
        $this->restoreInnoDbStats();
132
133 6
        $references = array();
134 6
        $config = new Config(array('tables' => array()), true);
135 6
        $tables = $config->offsetGet('tables');
136
137
138 6
        foreach ($results as $r) {
139
            // Setting table information
140 3
            $table_name = $r['table_name'];
141 3
            if (!$tables->offsetExists($table_name)) {
142
                $table_def = array(
143 3
                    'name'          => $table_name,
144 3
                    'columns'       => array(),
145 3
                    'primary_keys'  => array(),
146 3
                    'unique_keys'   => array(),
147 3
                    'foreign_keys'  => array(),
148 3
                    'references'    => array(),
149 3
                    'indexes'       => array(),
150 3
                );
151 3
                if ($include_options) {
152 3
                    $table_def['options'] = array(
153 3
                       'comment'   => $r['table_comment'],
154 3
                       'collation' => $r['table_collation'],
155 3
                       'type'      => $r['table_type'],
156 3
                       'engine'    => $r['engine']
157 3
                    );
158 3
                }
159 3
                $tables->offsetSet($table_name, $table_def);
160 3
            }
161 3
            $table   = $tables->offsetGet($table_name);
162 3
            $columns = $table->columns;
163 3
            $column_name = $r['column_name'];
164
165 3
            $data_type = strtolower($r['data_type']);
166
167
            $col_def = array(
168 3
                'type'          => $data_type,
169 3
                'primary'       => ($r['constraint_type'] == 'PRIMARY KEY'),
170 3
                'nullable'      => ($r['is_nullable'] == 'YES'),
171 3
                'default'       => $r['column_default']
172 3
            );
173 3
            if (($r['constraint_type'] == 'PRIMARY KEY')) {
174 2
                $col_def['primary'] = true;
175 2
                $col_def['autoincrement'] = ($r['extra'] == 'auto_increment');
176 2
            }
177
178 3
            $has_charset = false;
179 3
            if (in_array($data_type, array('int', 'tinyint', 'mediumint', 'bigint', 'int', 'smallint', 'year'))) {
180 3
                $col_def['unsigned']  = (bool) preg_match('/unsigned/', strtolower($r['column_type']));
181 3
                $col_def['precision'] = is_numeric($r['numeric_precision']) ? (int) $r['numeric_precision'] : null;
182 3
            } elseif (in_array($data_type, array('real', 'double precision', 'decimal', 'numeric', 'float', 'dec', 'fixed'))) {
183 1
                $col_def['precision'] = is_numeric($r['numeric_precision']) ? (int) $r['numeric_precision'] : null;
184 1
                $col_def['scale']     = is_numeric($r['numeric_scale']) ? (int) $r['numeric_scale'] : null;
185 2
            } elseif (in_array($data_type, array('timestamp', 'date', 'time', 'datetime'))) {
186
                // nothing yet
187 2
            } elseif (in_array($data_type, array('char', 'varchar', 'binary', 'varbinary', 'text', 'tinytext', 'mediumtext', 'longtext'))) {
188 2
                $col_def['octet_length'] = is_numeric($r['character_octet_length']) ? (int) $r['character_octet_length'] : null;
189 2
                $col_def['length'] = is_numeric($r['character_maximum_length']) ? (int) $r['character_maximum_length'] : null;
190 2
                $has_charset = true;
191 2
            } elseif (in_array($data_type, array('blob', 'tinyblob', 'mediumblob', 'longblob'))) {
192 1
                $col_def['octet_length'] = (int) $r['character_octet_length'];
193 1
                $col_def['length'] = (int) $r['character_maximum_length'];
194 1
            } elseif (in_array($data_type, array('enum', 'set'))) {
195 1
                $col_def['octet_length'] = (int) $r['character_octet_length'];
196 1
                $col_def['length'] = (int) $r['character_maximum_length'];
197 1
                $def = $r['column_type'];
198
199 1
                preg_match_all("/'([^']+)'/", $def, $matches);
200 1
                if (is_array($matches[1]) && count($matches) > 0) {
201 1
                    $col_def['values'] = $matches[1];
202 1
                }
203 1
            }
204
205 3
            if ($include_options) {
206 3
                $col_def['options'] = array(
207 3
                        'comment'           => $r['column_comment'],
208 3
                        'definition'        => $r['column_type'],
209 3
                        'column_key'        => $r['column_key'],
210 3
                        'ordinal_position'  => $r['ordinal_position'],
211 3
                        'constraint_type'   => $r['constraint_type'], // 'PRIMARY KEY', 'FOREIGN_KEY', 'UNIQUE'
212
                    );
213 3
                if ($has_charset) {
214 2
                    $col_def['options']['charset']     = $r['character_set_name'];
215 2
                    $col_def['options']['collation']   = $r['collation_name'];
216 2
                }
217 3
            }
218
219 3
            $columns[$column_name] = $col_def;
220
221 3
            $foreign_keys = $table->foreign_keys;
222 3
            $unique_keys  = $table->unique_keys;
223
224 3
            $constraint_name = $r['constraint_name'];
225 3
            $referenced_table_name = $r['referenced_table_name'];
226 3
            $referenced_column_name = $r['referenced_column_name'];
227 3
            switch ($r['constraint_type']) {
228 3
                case 'PRIMARY KEY':
229 2
                    $table->primary_keys = array_merge($table->primary_keys->toArray(), (array) $column_name);
230 2
                    break;
231 3
                case 'UNIQUE':
232 2
                    if (!$unique_keys->offsetExists($constraint_name)) {
233 2
                        $unique_keys[$constraint_name] = array();
234 2
                    }
235 2
                    $unique_keys[$constraint_name] = array_merge($unique_keys[$constraint_name]->toArray(), (array) $column_name);
236 2
                    break;
237 3
                case 'FOREIGN KEY':
238
                    /*
239
                    if (!$foreign_keys->offsetExists($constraint_name)) {
240
                        $foreign_keys[$constraint_name] = array();
241
                    }
242
                     *
243
                     */
244
                    $fk = array(
245 1
                       'referenced_table'  => $referenced_table_name,
246 1
                       'referenced_column' => $referenced_column_name,
247
                       'constraint_name' => $constraint_name
248 1
                    );
249 1
                    $foreign_keys[$column_name] = $fk;
250
                    //$table->references[$referenced_table_name] = array($column_name => $r['referenced_column_name']);
251
252 1
                    if (!array_key_exists($referenced_table_name, $references)) {
253 1
                        $references[$referenced_table_name] = array();
254 1
                    }
255
256 1
                    $k = "$table_name:$referenced_column_name->$column_name";
257 1
                    $references[$referenced_table_name][$k] = array(
258 1
                        'column' => $column_name,
259 1
                        'referencing_table' => $table_name,
260 1
                        'referencing_column' => $referenced_column_name,
261
                        'constraint_name' => $constraint_name
262 1
                    );
263 1
                    break;
264 3
            }
265 6
        }
266
267 6
        foreach ($references as $referenced_table_name => $refs) {
268 1
            if ($tables->offsetExists($referenced_table_name)) {
269 1
                $table = $tables[$referenced_table_name];
270 1
                $table->references = $refs;
271 1
            }
272 6
        }
273
274 6
        $array = new ArrayObject($config->toArray());
275 6
        unset($config);
276 6
        return $array;
277
278
    }
279
}
280