Passed
Pull Request — master (#3092)
by Michael
13:56
created

_getPortableTableColumnDefinition()   F

Complexity

Conditions 31
Paths 6656

Size

Total Lines 102
Code Lines 78

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 71
CRAP Score 31.0197

Importance

Changes 0
Metric Value
dl 0
loc 102
ccs 71
cts 73
cp 0.9726
rs 2
c 0
b 0
f 0
cc 31
eloc 78
nc 6656
nop 1
crap 31.0197

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\DBAL\Schema;
21
22
use Doctrine\DBAL\Platforms\MariaDb1027Platform;
23
use Doctrine\DBAL\Platforms\MySqlPlatform;
24
use Doctrine\DBAL\Types\Type;
25
use const CASE_LOWER;
26
use function array_change_key_case;
27
use function array_shift;
28
use function array_values;
29
use function end;
30
use function preg_match;
31
use function preg_replace;
32
use function str_replace;
33
use function stripslashes;
34
use function strpos;
35
use function strtok;
36
use function strtolower;
37
38
/**
39
 * Schema manager for the MySql RDBMS.
40
 *
41
 * @author Konsta Vesterinen <[email protected]>
42
 * @author Lukas Smith <[email protected]> (PEAR MDB2 library)
43
 * @author Roman Borschel <[email protected]>
44
 * @author Benjamin Eberlei <[email protected]>
45
 * @since  2.0
46
 */
47
class MySqlSchemaManager extends AbstractSchemaManager
48
{
49
    /**
50
     * {@inheritdoc}
51
     */
52 8
    protected function _getPortableViewDefinition($view)
53
    {
54 8
        return new View($view['TABLE_NAME'], $view['VIEW_DEFINITION']);
55
    }
56
57
    /**
58
     * {@inheritdoc}
59
     */
60 574
    protected function _getPortableTableDefinition($table)
61
    {
62 574
        return array_shift($table);
63
    }
64
65
    /**
66
     * {@inheritdoc}
67
     */
68
    protected function _getPortableUserDefinition($user)
69
    {
70
        return [
71
            'user' => $user['User'],
72
            'password' => $user['Password'],
73
        ];
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79 294
    protected function _getPortableTableIndexesList($tableIndexes, $tableName = null)
80
    {
81 294
        foreach ($tableIndexes as $k => $v) {
82 160
            $v = array_change_key_case($v, CASE_LOWER);
83 160
            if ($v['key_name'] === 'PRIMARY') {
84 128
                $v['primary'] = true;
85
            } else {
86 104
                $v['primary'] = false;
87
            }
88 160
            if (strpos($v['index_type'], 'FULLTEXT') !== false) {
89 24
                $v['flags'] = ['FULLTEXT'];
90 152
            } elseif (strpos($v['index_type'], 'SPATIAL') !== false) {
91 24
                $v['flags'] = ['SPATIAL'];
92
            }
93 160
            $tableIndexes[$k] = $v;
94
        }
95
96 294
        return parent::_getPortableTableIndexesList($tableIndexes, $tableName);
97
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102
    protected function _getPortableSequenceDefinition($sequence)
103
    {
104
        return end($sequence);
105
    }
106
107
    /**
108
     * {@inheritdoc}
109
     */
110 16
    protected function _getPortableDatabaseDefinition($database)
111
    {
112 16
        return $database['Database'];
113
    }
114
115
    /**
116
     * {@inheritdoc}
117
     */
118 358
    protected function _getPortableTableColumnDefinition($tableColumn)
119
    {
120 358
        $tableColumn = array_change_key_case($tableColumn, CASE_LOWER);
121
122 358
        $dbType = strtolower($tableColumn['type']);
123 358
        $dbType = strtok($dbType, '(), ');
124 358
        $length = $tableColumn['length'] ?? strtok('(), ');
125
126 358
        $fixed = null;
127
128 358
        if ( ! isset($tableColumn['name'])) {
129 358
            $tableColumn['name'] = '';
130
        }
131
132 358
        $scale     = null;
133 358
        $precision = null;
134
135 358
        $type = $this->_platform->getDoctrineTypeMapping($dbType);
136
137
        // In cases where not connected to a database DESCRIBE $table does not return 'Comment'
138 358
        if (isset($tableColumn['comment'])) {
139 358
            $type                   = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type);
140 358
            $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type);
141
        }
142
143
        switch ($dbType) {
144 358
            case 'char':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
145 342
            case 'binary':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
146 56
                $fixed = true;
147 56
                break;
148 342
            case 'float':
149 342
            case 'double':
150 334
            case 'real':
151 334
            case 'numeric':
152 334
            case 'decimal':
153 56
                if (preg_match('([A-Za-z]+\(([0-9]+)\,([0-9]+)\))', $tableColumn['type'], $match)) {
154 48
                    $precision = $match[1];
155 48
                    $scale     = $match[2];
156 48
                    $length    = null;
157
                }
158 56
                break;
159 326
            case 'tinytext':
160 24
                $length = MySqlPlatform::LENGTH_LIMIT_TINYTEXT;
161 24
                break;
162 326
            case 'text':
163 24
                $length = MySqlPlatform::LENGTH_LIMIT_TEXT;
164 24
                break;
165 326
            case 'mediumtext':
166 24
                $length = MySqlPlatform::LENGTH_LIMIT_MEDIUMTEXT;
167 24
                break;
168 326
            case 'tinyblob':
169
                $length = MySqlPlatform::LENGTH_LIMIT_TINYBLOB;
170
                break;
171 326
            case 'blob':
172 24
                $length = MySqlPlatform::LENGTH_LIMIT_BLOB;
173 24
                break;
174 326
            case 'mediumblob':
175 24
                $length = MySqlPlatform::LENGTH_LIMIT_MEDIUMBLOB;
176 24
                break;
177 326
            case 'tinyint':
178 326
            case 'smallint':
179 326
            case 'mediumint':
180 326
            case 'int':
181 166
            case 'integer':
182 166
            case 'bigint':
183 166
            case 'year':
184 264
                $length = null;
185 264
                break;
186
        }
187
188 358
        if ($this->_platform instanceof MariaDb1027Platform) {
189 88
            $columnDefault = $this->getMariaDb1027ColumnDefault($this->_platform, $tableColumn['default']);
190
        } else {
191 270
            $columnDefault = $tableColumn['default'];
192
        }
193
194
        $options = [
195 358
            'length'        => $length !== null ? (int) $length : null,
196 358
            'unsigned'      => strpos($tableColumn['type'], 'unsigned') !== false,
197 358
            'fixed'         => (bool) $fixed,
198 358
            'default'       => $columnDefault,
199 358
            'notnull'       => $tableColumn['null'] !== 'YES',
200
            'scale'         => null,
201
            'precision'     => null,
202 358
            'autoincrement' => strpos($tableColumn['extra'], 'auto_increment') !== false,
203 358
            'comment'       => isset($tableColumn['comment']) && $tableColumn['comment'] !== ''
204 112
                ? $tableColumn['comment']
205
                : null,
206
        ];
207
208 358
        if ($scale !== null && $precision !== null) {
209 48
            $options['scale']     = (int) $scale;
210 48
            $options['precision'] = (int) $precision;
211
        }
212
213 358
        $column = new Column($tableColumn['field'], Type::getType($type), $options);
214
215 358
        if (isset($tableColumn['collation'])) {
216 160
            $column->setPlatformOption('collation', $tableColumn['collation']);
217
        }
218
219 358
        return $column;
220
    }
221
222
    /**
223
     * Return Doctrine/Mysql-compatible column default values for MariaDB 10.2.7+ servers.
224
     *
225
     * - Since MariaDb 10.2.7 column defaults stored in information_schema are now quoted
226
     *   to distinguish them from expressions (see MDEV-10134).
227
     * - CURRENT_TIMESTAMP, CURRENT_TIME, CURRENT_DATE are stored in information_schema
228
     *   as current_timestamp(), currdate(), currtime()
229
     * - Quoted 'NULL' is not enforced by Maria, it is technically possible to have
230
     *   null in some circumstances (see https://jira.mariadb.org/browse/MDEV-14053)
231
     * - \' is always stored as '' in information_schema (normalized)
232
     *
233
     * @link https://mariadb.com/kb/en/library/information-schema-columns-table/
234
     * @link https://jira.mariadb.org/browse/MDEV-13132
235
     *
236
     * @param null|string $columnDefault default value as stored in information_schema for MariaDB >= 10.2.7
237
     */
238 88
    private function getMariaDb1027ColumnDefault(MariaDb1027Platform $platform, ?string $columnDefault) : ?string
239
    {
240 88
        if ($columnDefault === 'NULL' || $columnDefault === null) {
241 80
            return null;
242
        }
243 20
        if ($columnDefault[0] === "'") {
244 16
            return stripslashes(
245 16
                str_replace("''", "'",
246 16
                    preg_replace('/^\'(.*)\'$/', '$1', $columnDefault)
247
                )
248
            );
249
        }
250
        switch ($columnDefault) {
251 12
            case 'current_timestamp()':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
252 8
                return $platform->getCurrentTimestampSQL();
253 10
            case 'curdate()':
254 6
                return $platform->getCurrentDateSQL();
255 10
            case 'curtime()':
256 6
                return $platform->getCurrentTimeSQL();
257
        }
258 8
        return $columnDefault;
259
    }
260
261
    /**
262
     * {@inheritdoc}
263
     */
264 279
    protected function _getPortableTableForeignKeysList($tableForeignKeys)
265
    {
266 279
        $list = [];
267 279
        foreach ($tableForeignKeys as $value) {
268 73
            $value = array_change_key_case($value, CASE_LOWER);
269 73
            if ( ! isset($list[$value['constraint_name']])) {
270 73
                if ( ! isset($value['delete_rule']) || $value['delete_rule'] === "RESTRICT") {
271 65
                    $value['delete_rule'] = null;
272
                }
273 73
                if ( ! isset($value['update_rule']) || $value['update_rule'] === "RESTRICT") {
274 73
                    $value['update_rule'] = null;
275
                }
276
277 73
                $list[$value['constraint_name']] = [
278 73
                    'name' => $value['constraint_name'],
279
                    'local' => [],
280
                    'foreign' => [],
281 73
                    'foreignTable' => $value['referenced_table_name'],
282 73
                    'onDelete' => $value['delete_rule'],
283 73
                    'onUpdate' => $value['update_rule'],
284
                ];
285
            }
286 73
            $list[$value['constraint_name']]['local'][]   = $value['column_name'];
287 73
            $list[$value['constraint_name']]['foreign'][] = $value['referenced_column_name'];
288
        }
289
290 279
        $result = [];
291 279
        foreach ($list as $constraint) {
292 73
            $result[] = new ForeignKeyConstraint(
293 73
                array_values($constraint['local']),
294 73
                $constraint['foreignTable'],
295 73
                array_values($constraint['foreign']),
296 73
                $constraint['name'],
297
                [
298 73
                    'onDelete' => $constraint['onDelete'],
299 73
                    'onUpdate' => $constraint['onUpdate'],
300
                ]
301
            );
302
        }
303
304 279
        return $result;
305
    }
306
}
307