Completed
Push — master ( c17796...052b15 )
by Damian
01:29
created

MySQLSchemaManager   F

Complexity

Total Complexity 93

Size/Duplication

Total Lines 633
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 633
rs 1.4746
c 0
b 0
f 0
wmc 93

38 Methods

Rating   Name   Duplication   Size   Complexity  
B checkAndRepairTable() 0 24 5
C alterTable() 0 70 15
A enum() 0 11 1
A alterIndex() 0 9 1
A indexKey() 0 4 1
A text() 0 8 1
A IdColumn() 0 3 1
A databaseList() 0 3 1
A time() 0 6 1
A boolean() 0 8 1
A createIndex() 0 3 1
A float() 0 6 1
A int() 0 6 1
A isView() 0 4 2
A databaseExists() 0 5 1
A year() 0 3 1
A defaultClause() 0 6 2
A enumValuesForField() 0 11 2
A createDatabase() 0 5 1
A getIndexSqlDefinition() 0 6 2
A createField() 0 3 1
A alterField() 0 3 1
A renameTable() 0 3 1
D createTable() 0 40 9
A hasTable() 0 6 1
A tableList() 0 8 2
A set() 0 11 1
D fieldList() 0 30 10
B decimal() 0 23 5
A renameField() 0 5 2
A dbDataType() 0 10 2
A runTableCheckCommand() 0 9 3
C indexList() 0 34 8
A varchar() 0 11 1
A dropDatabase() 0 3 1
A date() 0 6 1
A bigint() 0 9 1
A datetime() 0 6 1

How to fix   Complexity   

Complex Class

Complex classes like MySQLSchemaManager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use MySQLSchemaManager, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace SilverStripe\ORM\Connect;
4
5
use SilverStripe\Core\Config\Config;
6
use SilverStripe\Core\Convert;
7
8
/**
9
 * Represents schema management object for MySQL
10
 */
11
class MySQLSchemaManager extends DBSchemaManager
12
{
13
14
    /**
15
     * Identifier for this schema, used for configuring schema-specific table
16
     * creation options
17
     *
18
     * @skipUpgrade
19
     */
20
    const ID = 'MySQLDatabase';
21
22
    public function createTable($table, $fields = null, $indexes = null, $options = null, $advancedOptions = null)
23
    {
24
        $fieldSchemas = $indexSchemas = "";
25
26
        if (!empty($options[self::ID])) {
27
            $addOptions = $options[self::ID];
28
        } else {
29
            $addOptions = "ENGINE=InnoDB";
30
        }
31
32
        if (!isset($fields['ID'])) {
33
            $fields['ID'] = "int(11) not null auto_increment";
34
        }
35
        if ($fields) {
36
            foreach ($fields as $k => $v) {
37
                $fieldSchemas .= "\"$k\" $v,\n";
38
            }
39
        }
40
        if ($indexes) {
41
            foreach ($indexes as $k => $v) {
42
                // force MyISAM if we have a fulltext index
43
                if ($v['type'] === 'fulltext') {
44
                    $addOptions = 'ENGINE=MyISAM';
45
                }
46
                $indexSchemas .= $this->getIndexSqlDefinition($k, $v) . ",\n";
47
            }
48
        }
49
50
        // Switch to "CREATE TEMPORARY TABLE" for temporary tables
51
        $temporary = empty($options['temporary'])
52
                ? ""
53
                : "TEMPORARY";
54
55
        $this->query("CREATE $temporary TABLE \"$table\" (
56
				$fieldSchemas
57
				$indexSchemas
58
				primary key (ID)
59
			) {$addOptions}");
60
61
        return $table;
62
    }
63
64
    public function alterTable(
65
        $tableName,
66
        $newFields = null,
67
        $newIndexes = null,
68
        $alteredFields = null,
69
        $alteredIndexes = null,
70
        $alteredOptions = null,
71
        $advancedOptions = null
72
    ) {
73
        if ($this->isView($tableName)) {
74
            $this->alterationMessage(
75
                sprintf("Table %s not changed as it is a view", $tableName),
76
                "changed"
77
            );
78
            return;
79
        }
80
        $alterList = array();
81
82
        if ($newFields) {
83
            foreach ($newFields as $k => $v) {
84
                $alterList[] .= "ADD \"$k\" $v";
85
            }
86
        }
87
        if ($newIndexes) {
88
            foreach ($newIndexes as $k => $v) {
89
                $alterList[] .= "ADD " . $this->getIndexSqlDefinition($k, $v);
90
            }
91
        }
92
        if ($alteredFields) {
93
            foreach ($alteredFields as $k => $v) {
94
                $alterList[] .= "CHANGE \"$k\" \"$k\" $v";
95
            }
96
        }
97
        if ($alteredIndexes) {
98
            foreach ($alteredIndexes as $k => $v) {
99
                $alterList[] .= "DROP INDEX \"$k\"";
100
                $alterList[] .= "ADD " . $this->getIndexSqlDefinition($k, $v);
101
            }
102
        }
103
104
        $dbID = self::ID;
105
        if ($alteredOptions && isset($alteredOptions[$dbID])) {
106
            $indexList = $this->indexList($tableName);
107
            $skip = false;
108
            foreach ($indexList as $index) {
109
                if ($index['type'] === 'fulltext') {
110
                    $skip = true;
111
                    break;
112
                }
113
            }
114
            if ($skip) {
115
                $this->alterationMessage(
116
                    sprintf(
117
                        "Table %s options not changed to %s due to fulltextsearch index",
118
                        $tableName,
119
                        $alteredOptions[$dbID]
120
                    ),
121
                    "changed"
122
                );
123
            } else {
124
                $this->query(sprintf("ALTER TABLE \"%s\" %s", $tableName, $alteredOptions[$dbID]));
125
                $this->alterationMessage(
126
                    sprintf("Table %s options changed: %s", $tableName, $alteredOptions[$dbID]),
127
                    "changed"
128
                );
129
            }
130
        }
131
132
        $alterations = implode(",\n", $alterList);
133
        $this->query("ALTER TABLE \"$tableName\" $alterations");
134
    }
135
136
    public function isView($tableName)
137
    {
138
        $info = $this->query("SHOW /*!50002 FULL*/ TABLES LIKE '$tableName'")->record();
139
        return $info && strtoupper($info['Table_type']) == 'VIEW';
0 ignored issues
show
Bug Best Practice introduced by
The expression $info of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
140
    }
141
142
    public function renameTable($oldTableName, $newTableName)
143
    {
144
        $this->query("ALTER TABLE \"$oldTableName\" RENAME \"$newTableName\"");
145
    }
146
147
    public function checkAndRepairTable($tableName)
148
    {
149
        // Flag to ensure we only send the warning about PDO + native mode once
150
        static $pdo_warning_sent = false;
151
152
        // If running PDO and not in emulated mode, check table will fail
153
        if ($this->database->getConnector() instanceof PDOConnector && !PDOConnector::is_emulate_prepare()) {
154
            if (!$pdo_warning_sent) {
155
                $this->alterationMessage('CHECK TABLE command disabled for PDO in native mode', 'notice');
156
                $pdo_warning_sent = true;
157
            }
158
159
            return true;
160
        }
161
162
        // Perform check
163
        if ($this->runTableCheckCommand("CHECK TABLE \"$tableName\"")) {
164
            return true;
165
        }
166
        $this->alterationMessage(
167
            "Table $tableName: repaired",
168
            "repaired"
169
        );
170
        return $this->runTableCheckCommand("REPAIR TABLE \"$tableName\" USE_FRM");
171
    }
172
173
    /**
174
     * Helper function used by checkAndRepairTable.
175
     * @param string $sql Query to run.
176
     * @return boolean Returns if the query returns a successful result.
177
     */
178
    protected function runTableCheckCommand($sql)
179
    {
180
        $testResults = $this->query($sql);
181
        foreach ($testResults as $testRecord) {
182
            if (strtolower($testRecord['Msg_text']) != 'ok') {
183
                return false;
184
            }
185
        }
186
        return true;
187
    }
188
189
    public function hasTable($table)
190
    {
191
        // MySQLi doesn't like parameterised queries for some queries
192
        // underscores need to be escaped in a SHOW TABLES LIKE query
193
        $sqlTable = str_replace('_', '\\_', $this->database->quoteString($table));
194
        return (bool) ($this->query("SHOW TABLES LIKE $sqlTable")->value());
195
    }
196
197
    public function createField($tableName, $fieldName, $fieldSpec)
198
    {
199
        $this->query("ALTER TABLE \"$tableName\" ADD \"$fieldName\" $fieldSpec");
200
    }
201
202
    public function databaseList()
203
    {
204
        return $this->query("SHOW DATABASES")->column();
205
    }
206
207
    public function databaseExists($name)
208
    {
209
        // MySQLi doesn't like parameterised queries for some queries
210
        $sqlName = $this->database->quoteString($name);
211
        return !!($this->query("SHOW DATABASES LIKE $sqlName")->value());
212
    }
213
214
    public function createDatabase($name)
215
    {
216
        $charset = Config::inst()->get('SilverStripe\ORM\Connect\MySQLDatabase', 'charset');
217
        $collation = Config::inst()->get('SilverStripe\ORM\Connect\MySQLDatabase', 'collation');
218
        $this->query("CREATE DATABASE \"$name\" DEFAULT CHARACTER SET {$charset} DEFAULT COLLATE {$collation}");
219
    }
220
221
    public function dropDatabase($name)
222
    {
223
        $this->query("DROP DATABASE \"$name\"");
224
    }
225
226
    /**
227
     * Change the database type of the given field.
228
     * @param string $tableName The name of the tbale the field is in.
229
     * @param string $fieldName The name of the field to change.
230
     * @param string $fieldSpec The new field specification
231
     */
232
    public function alterField($tableName, $fieldName, $fieldSpec)
233
    {
234
        $this->query("ALTER TABLE \"$tableName\" CHANGE \"$fieldName\" \"$fieldName\" $fieldSpec");
235
    }
236
237
    /**
238
     * Change the database column name of the given field.
239
     *
240
     * @param string $tableName The name of the tbale the field is in.
241
     * @param string $oldName The name of the field to change.
242
     * @param string $newName The new name of the field
243
     */
244
    public function renameField($tableName, $oldName, $newName)
245
    {
246
        $fieldList = $this->fieldList($tableName);
247
        if (array_key_exists($oldName, $fieldList)) {
248
            $this->query("ALTER TABLE \"$tableName\" CHANGE \"$oldName\" \"$newName\" " . $fieldList[$oldName]);
249
        }
250
    }
251
252
    protected static $_cache_collation_info = array();
253
254
    public function fieldList($table)
255
    {
256
        $fields = $this->query("SHOW FULL FIELDS IN \"$table\"");
257
        $fieldList = array();
258
        foreach ($fields as $field) {
259
            $fieldSpec = $field['Type'];
260
            if (!$field['Null'] || $field['Null'] == 'NO') {
261
                $fieldSpec .= ' not null';
262
            }
263
264
            if ($field['Collation'] && $field['Collation'] != 'NULL') {
265
                // Cache collation info to cut down on database traffic
266
                if (!isset(self::$_cache_collation_info[$field['Collation']])) {
267
                    self::$_cache_collation_info[$field['Collation']]
268
                        = $this->query("SHOW COLLATION LIKE '{$field['Collation']}'")->record();
269
                }
270
                $collInfo = self::$_cache_collation_info[$field['Collation']];
271
                $fieldSpec .= " character set $collInfo[Charset] collate $field[Collation]";
272
            }
273
274
            if ($field['Default'] || $field['Default'] === "0") {
275
                $fieldSpec .= " default " . $this->database->quoteString($field['Default']);
276
            }
277
            if ($field['Extra']) {
278
                $fieldSpec .= " " . $field['Extra'];
279
            }
280
281
            $fieldList[$field['Field']] = $fieldSpec;
282
        }
283
        return $fieldList;
284
    }
285
286
    /**
287
     * Create an index on a table.
288
     *
289
     * @param string $tableName The name of the table.
290
     * @param string $indexName The name of the index.
291
     * @param string $indexSpec The specification of the index, see {@link SS_Database::requireIndex()} for more
292
     *                          details.
293
     */
294
    public function createIndex($tableName, $indexName, $indexSpec)
295
    {
296
        $this->query("ALTER TABLE \"$tableName\" ADD " . $this->getIndexSqlDefinition($indexName, $indexSpec));
297
    }
298
299
    /**
300
     * Generate SQL suitable for creating this index
301
     *
302
     * @param string $indexName
303
     * @param string|array $indexSpec See {@link requireTable()} for details
304
     * @return string MySQL compatible ALTER TABLE syntax
305
     */
306
    protected function getIndexSqlDefinition($indexName, $indexSpec)
307
    {
308
        if ($indexSpec['type'] == 'using') {
309
            return sprintf('index "%s" using (%s)', $indexName, $this->implodeColumnList($indexSpec['columns']));
310
        } else {
311
            return sprintf('%s "%s" (%s)', $indexSpec['type'], $indexName, $this->implodeColumnList($indexSpec['columns']));
312
        }
313
    }
314
315
    public function alterIndex($tableName, $indexName, $indexSpec)
316
    {
317
        $this->query(sprintf('ALTER TABLE "%s" DROP INDEX "%s"', $tableName, $indexName));
318
        $this->query(sprintf(
319
            'ALTER TABLE "%s" ADD %s "%s" %s',
320
            $tableName,
321
            $indexSpec['type'],
322
            $indexName,
323
            $this->implodeColumnList($indexSpec['columns'])
324
        ));
325
    }
326
327
    protected function indexKey($table, $index, $spec)
328
    {
329
        // MySQL simply uses the same index name as SilverStripe does internally
330
        return $index;
331
    }
332
333
    public function indexList($table)
334
    {
335
        $indexes = $this->query("SHOW INDEXES IN \"$table\"");
336
        $groupedIndexes = array();
337
        $indexList = array();
338
339
        foreach ($indexes as $index) {
340
            $groupedIndexes[$index['Key_name']]['fields'][$index['Seq_in_index']] = $index['Column_name'];
341
342
            if ($index['Index_type'] == 'FULLTEXT') {
343
                $groupedIndexes[$index['Key_name']]['type'] = 'fulltext';
344
            } elseif (!$index['Non_unique']) {
345
                $groupedIndexes[$index['Key_name']]['type'] = 'unique';
346
            } elseif ($index['Index_type'] == 'HASH') {
347
                $groupedIndexes[$index['Key_name']]['type'] = 'hash';
348
            } elseif ($index['Index_type'] == 'RTREE') {
349
                $groupedIndexes[$index['Key_name']]['type'] = 'rtree';
350
            } else {
351
                $groupedIndexes[$index['Key_name']]['type'] = 'index';
352
            }
353
        }
354
355
        if ($groupedIndexes) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $groupedIndexes of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
356
            foreach ($groupedIndexes as $index => $details) {
357
                ksort($details['fields']);
358
                $indexList[$index] = array(
359
                    'name' => $index,
360
                    'columns' => $details['fields'],
361
                    'type' => $details['type'],
362
                );
363
            }
364
        }
365
366
        return $indexList;
367
    }
368
369
    public function tableList()
370
    {
371
        $tables = array();
372
        foreach ($this->query("SHOW FULL TABLES WHERE Table_Type != 'VIEW'") as $record) {
373
            $table = reset($record);
374
            $tables[strtolower($table)] = $table;
375
        }
376
        return $tables;
377
    }
378
379
    public function enumValuesForField($tableName, $fieldName)
380
    {
381
        // Get the enum of all page types from the SiteTree table
382
        $classnameinfo = $this->query("DESCRIBE \"$tableName\" \"$fieldName\"")->first();
383
        preg_match_all("/'[^,]+'/", $classnameinfo["Type"], $matches);
384
385
        $classes = array();
386
        foreach ($matches[0] as $value) {
387
            $classes[] = stripslashes(trim($value, "'"));
388
        }
389
        return $classes;
390
    }
391
392
    public function dbDataType($type)
393
    {
394
        $values = array(
395
            'unsigned integer' => 'UNSIGNED'
396
        );
397
398
        if (isset($values[$type])) {
399
            return $values[$type];
400
        } else {
401
            return '';
402
        }
403
    }
404
405
    /**
406
     * Return a boolean type-formatted string
407
     *
408
     * @param array $values Contains a tokenised list of info about this data type
409
     * @return string
410
     */
411
    public function boolean($values)
412
    {
413
        //For reference, this is what typically gets passed to this function:
414
        //$parts=Array('datatype'=>'tinyint', 'precision'=>1, 'sign'=>'unsigned', 'null'=>'not null',
0 ignored issues
show
Unused Code Comprehensibility introduced by
83% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
415
        //'default'=>$this->default);
0 ignored issues
show
Unused Code Comprehensibility introduced by
86% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
416
        //DB::requireField($this->tableName, $this->name, "tinyint(1) unsigned not null default
417
        //'{$this->defaultVal}'");
418
        return 'tinyint(1) unsigned not null' . $this->defaultClause($values);
419
    }
420
421
    /**
422
     * Return a date type-formatted string
423
     * For MySQL, we simply return the word 'date', no other parameters are necessary
424
     *
425
     * @param array $values Contains a tokenised list of info about this data type
426
     * @return string
427
     */
428
    public function date($values)
429
    {
430
        //For reference, this is what typically gets passed to this function:
431
        //$parts=Array('datatype'=>'date');
0 ignored issues
show
Unused Code Comprehensibility introduced by
89% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
432
        //DB::requireField($this->tableName, $this->name, "date");
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
433
        return 'date';
434
    }
435
436
    /**
437
     * Return a decimal type-formatted string
438
     *
439
     * @param array $values Contains a tokenised list of info about this data type
440
     * @return string
441
     */
442
    public function decimal($values)
443
    {
444
        //For reference, this is what typically gets passed to this function:
445
        //$parts=Array('datatype'=>'decimal', 'precision'=>"$this->wholeSize,$this->decimalSize");
0 ignored issues
show
Unused Code Comprehensibility introduced by
86% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
446
        //DB::requireField($this->tableName, $this->name, "decimal($this->wholeSize,$this->decimalSize)");
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
447
        // Avoid empty strings being put in the db
448
        if ($values['precision'] == '') {
449
            $precision = 1;
450
        } else {
451
            $precision = $values['precision'];
452
        }
453
454
        // Fix format of default value to match precision
455
        if (isset($values['default']) && is_numeric($values['default'])) {
456
            $decs = strpos($precision, ',') !== false
457
                    ? (int) substr($precision, strpos($precision, ',') + 1)
458
                    : 0;
459
            $values['default'] = number_format($values['default'], $decs, '.', '');
460
        } else {
461
            unset($values['default']);
462
        }
463
464
        return "decimal($precision) not null" . $this->defaultClause($values);
465
    }
466
467
    /**
468
     * Return a enum type-formatted string
469
     *
470
     * @param array $values Contains a tokenised list of info about this data type
471
     * @return string
472
     */
473
    public function enum($values)
474
    {
475
        //For reference, this is what typically gets passed to this function:
476
        //$parts=Array('datatype'=>'enum', 'enums'=>$this->enum, 'character set'=>'utf8', 'collate'=>
0 ignored issues
show
Unused Code Comprehensibility introduced by
79% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
477
        // 'utf8_general_ci', 'default'=>$this->default);
0 ignored issues
show
Unused Code Comprehensibility introduced by
73% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
478
        //DB::requireField($this->tableName, $this->name, "enum('" . implode("','", $this->enum) . "') character set
479
        // utf8 collate utf8_general_ci default '{$this->default}'");
480
        $valuesString = implode(",", Convert::raw2sql($values['enums'], true));
0 ignored issues
show
Bug introduced by
It seems like SilverStripe\Core\Conver...$values['enums'], true) can also be of type string; however, parameter $pieces of implode() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

480
        $valuesString = implode(",", /** @scrutinizer ignore-type */ Convert::raw2sql($values['enums'], true));
Loading history...
481
        $charset = Config::inst()->get('SilverStripe\ORM\Connect\MySQLDatabase', 'charset');
482
        $collation = Config::inst()->get('SilverStripe\ORM\Connect\MySQLDatabase', 'collation');
483
        return "enum($valuesString) character set {$charset} collate {$collation}" . $this->defaultClause($values);
484
    }
485
486
    /**
487
     * Return a set type-formatted string
488
     *
489
     * @param array $values Contains a tokenised list of info about this data type
490
     * @return string
491
     */
492
    public function set($values)
493
    {
494
        //For reference, this is what typically gets passed to this function:
495
        //$parts=Array('datatype'=>'enum', 'enums'=>$this->enum, 'character set'=>'utf8', 'collate'=>
0 ignored issues
show
Unused Code Comprehensibility introduced by
79% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
496
        // 'utf8_general_ci', 'default'=>$this->default);
0 ignored issues
show
Unused Code Comprehensibility introduced by
73% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
497
        //DB::requireField($this->tableName, $this->name, "enum('" . implode("','", $this->enum) . "') character set
498
        //utf8 collate utf8_general_ci default '{$this->default}'");
499
        $valuesString = implode(",", Convert::raw2sql($values['enums'], true));
0 ignored issues
show
Bug introduced by
It seems like SilverStripe\Core\Conver...$values['enums'], true) can also be of type string; however, parameter $pieces of implode() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

499
        $valuesString = implode(",", /** @scrutinizer ignore-type */ Convert::raw2sql($values['enums'], true));
Loading history...
500
        $charset = Config::inst()->get('SilverStripe\ORM\Connect\MySQLDatabase', 'charset');
501
        $collation = Config::inst()->get('SilverStripe\ORM\Connect\MySQLDatabase', 'collation');
502
        return "set($valuesString) character set {$charset} collate {$collation}" . $this->defaultClause($values);
503
    }
504
505
    /**
506
     * Return a float type-formatted string
507
     * For MySQL, we simply return the word 'date', no other parameters are necessary
508
     *
509
     * @param array $values Contains a tokenised list of info about this data type
510
     * @return string
511
     */
512
    public function float($values)
513
    {
514
        //For reference, this is what typically gets passed to this function:
515
        //$parts=Array('datatype'=>'float');
0 ignored issues
show
Unused Code Comprehensibility introduced by
89% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
516
        //DB::requireField($this->tableName, $this->name, "float");
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
517
        return "float not null" . $this->defaultClause($values);
518
    }
519
520
    /**
521
     * Return a int type-formatted string
522
     *
523
     * @param array $values Contains a tokenised list of info about this data type
524
     * @return string
525
     */
526
    public function int($values)
527
    {
528
        //For reference, this is what typically gets passed to this function:
529
        //$parts=Array('datatype'=>'int', 'precision'=>11, 'null'=>'not null', 'default'=>(int)$this->default);
0 ignored issues
show
Unused Code Comprehensibility introduced by
82% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
530
        //DB::requireField($this->tableName, $this->name, "int(11) not null default '{$this->defaultVal}'");
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
531
        return "int(11) not null" . $this->defaultClause($values);
532
    }
533
534
    /**
535
     * Return a bigint type-formatted string
536
     *
537
     * @param array $values Contains a tokenised list of info about this data type
538
     * @return string
539
     */
540
    public function bigint($values)
541
    {
542
        //For reference, this is what typically gets passed to this function:
543
        //$parts=Array('datatype'=>'bigint', 'precision'=>20, 'null'=>'not null', 'default'=>$this->defaultVal,
0 ignored issues
show
Unused Code Comprehensibility introduced by
80% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
544
        //             'arrayValue'=>$this->arrayValue);
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
545
        //$values=Array('type'=>'bigint', 'parts'=>$parts);
0 ignored issues
show
Unused Code Comprehensibility introduced by
86% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
546
        //DB::requireField($this->tableName, $this->name, $values);
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
547
548
        return 'bigint(20) not null' . $this->defaultClause($values);
549
    }
550
551
    /**
552
     * Return a datetime type-formatted string
553
     * For MySQL, we simply return the word 'datetime', no other parameters are necessary
554
     *
555
     * @param array $values Contains a tokenised list of info about this data type
556
     * @return string
557
     */
558
    public function datetime($values)
559
    {
560
        //For reference, this is what typically gets passed to this function:
561
        //$parts=Array('datatype'=>'datetime');
0 ignored issues
show
Unused Code Comprehensibility introduced by
89% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
562
        //DB::requireField($this->tableName, $this->name, $values);
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
563
        return 'datetime';
564
    }
565
566
    /**
567
     * Return a text type-formatted string
568
     *
569
     * @param array $values Contains a tokenised list of info about this data type
570
     * @return string
571
     */
572
    public function text($values)
573
    {
574
        //For reference, this is what typically gets passed to this function:
575
        //$parts=Array('datatype'=>'mediumtext', 'character set'=>'utf8', 'collate'=>'utf8_general_ci');
0 ignored issues
show
Unused Code Comprehensibility introduced by
85% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
576
        //DB::requireField($this->tableName, $this->name, "mediumtext character set utf8 collate utf8_general_ci");
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
577
        $charset = Config::inst()->get('SilverStripe\ORM\Connect\MySQLDatabase', 'charset');
578
        $collation = Config::inst()->get('SilverStripe\ORM\Connect\MySQLDatabase', 'collation');
579
        return 'mediumtext character set ' . $charset . ' collate ' . $collation . $this->defaultClause($values);
580
    }
581
582
    /**
583
     * Return a time type-formatted string
584
     * For MySQL, we simply return the word 'time', no other parameters are necessary
585
     *
586
     * @param array $values Contains a tokenised list of info about this data type
587
     * @return string
588
     */
589
    public function time($values)
590
    {
591
        //For reference, this is what typically gets passed to this function:
592
        //$parts=Array('datatype'=>'time');
0 ignored issues
show
Unused Code Comprehensibility introduced by
89% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
593
        //DB::requireField($this->tableName, $this->name, "time");
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
594
        return 'time';
595
    }
596
597
    /**
598
     * Return a varchar type-formatted string
599
     *
600
     * @param array $values Contains a tokenised list of info about this data type
601
     * @return string
602
     */
603
    public function varchar($values)
604
    {
605
        //For reference, this is what typically gets passed to this function:
606
        //$parts=Array('datatype'=>'varchar', 'precision'=>$this->size, 'character set'=>'utf8', 'collate'=>
0 ignored issues
show
Unused Code Comprehensibility introduced by
79% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
607
        //'utf8_general_ci');
608
        //DB::requireField($this->tableName, $this->name, "varchar($this->size) character set utf8 collate
609
        // utf8_general_ci");
610
        $default = $this->defaultClause($values);
611
        $charset = Config::inst()->get('SilverStripe\ORM\Connect\MySQLDatabase', 'charset');
612
        $collation = Config::inst()->get('SilverStripe\ORM\Connect\MySQLDatabase', 'collation');
613
        return "varchar({$values['precision']}) character set {$charset} collate {$collation}{$default}";
614
    }
615
616
    /*
617
     * Return the MySQL-proprietary 'Year' datatype
618
     *
619
     * @param array $values Contains a tokenised list of info about this data type
620
     * @return string
621
     */
622
    public function year($values)
623
    {
624
        return 'year(4)';
625
    }
626
627
    public function IdColumn($asDbValue = false, $hasAutoIncPK = true)
628
    {
629
        return 'int(11) not null auto_increment';
630
    }
631
632
    /**
633
     * Parses and escapes the default values for a specification
634
     *
635
     * @param array $values Contains a tokenised list of info about this data type
636
     * @return string Default clause
637
     */
638
    protected function defaultClause($values)
639
    {
640
        if (isset($values['default'])) {
641
            return ' default ' . $this->database->quoteString($values['default']);
642
        }
643
        return '';
644
    }
645
}
646