Completed
Pull Request — master (#4246)
by Axel
04:45
created

CharsetRecodeHelper::getCommands()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 50
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 2
eloc 14
c 2
b 0
f 0
nc 2
nop 0
dl 0
loc 50
rs 9.7998
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Zikula package.
7
 *
8
 * Copyright Zikula - https://ziku.la/
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Zikula\Bundle\CoreBundle\Doctrine\Helper;
15
16
use Doctrine\DBAL\Connection;
17
use Doctrine\DBAL\Driver\AbstractMySQLDriver;
18
use Doctrine\DBAL\ParameterType;
19
20
class CharsetRecodeHelper
21
{
22
    /**
23
     * @var Connection
24
     */
25
    private $conn;
26
27
    public function __construct(
28
        Connection $connection
29
    ) {
30
        $this->conn = $connection;
31
    }
32
33
    private function isRequired(): bool
34
    {
35
        $driver = $this->conn->getDriver();
36
37
        // recoding utf8 to utf8mb4 is only required for mysql
38
        return $driver instanceof AbstractMySQLDriver;
39
    }
40
41
    public function getCommands(): array
42
    {
43
        if (!$this->isRequired()) {
44
            return [];
45
        }
46
47
        // the following is based on
48
        // https://dba.stackexchange.com/questions/8239/how-to-easily-convert-utf8-tables-to-utf8mb4-in-mysql-5-5#answer-104866
49
        $commands = [];
50
51
        $this->conn->executeQuery('use information_schema;');
52
53
        // database level
54
        $rows = $this->retrieveCommands('
0 ignored issues
show
Bug introduced by
The call to Zikula\Bundle\CoreBundle...per::retrieveCommands() has too few arguments starting with dbName. ( Ignorable by Annotation )

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

54
        /** @scrutinizer ignore-call */ 
55
        $rows = $this->retrieveCommands('

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
55
            SELECT CONCAT("ALTER DATABASE `",table_schema,"` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;") AS _sql 
56
            FROM `TABLES`
57
            WHERE table_schema LIKE ?
58
            GROUP BY table_schema;
59
        ');
60
        $commands = array_merge($commands, $rows);
61
62
        // table level
63
        $rows = $this->retrieveCommands('
64
            SELECT CONCAT("ALTER TABLE `",table_schema,"`.`",table_name,"` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;") AS _sql  
65
            FROM `TABLES`
66
            WHERE table_schema LIKE ?
67
            GROUP BY table_schema, table_name;
68
        ');
69
        $commands = array_merge($commands, $rows);
70
71
        // column level
72
        $rows = $this->retrieveCommands('
73
            SELECT CONCAT("ALTER TABLE `",table_schema,"`.`",table_name, "` CHANGE `",column_name,"` `",column_name,"` ",data_type,"(",character_maximum_length,") CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",IF(is_nullable="YES"," NULL"," NOT NULL"),";") AS _sql 
74
            FROM `COLUMNS`
75
            WHERE table_schema LIKE ?
76
            AND data_type IN (\'varchar\', \'char\');
77
        ');
78
        $commands = array_merge($commands, $rows);
79
80
        $rows = $this->retrieveCommands('
81
            SELECT CONCAT("ALTER TABLE `",table_schema,"`.`",table_name, "` CHANGE `",column_name,"` `",column_name,"` ",data_type," CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",IF(is_nullable="YES"," NULL"," NOT NULL"),";") AS _sql 
82
            FROM `COLUMNS`
83
            WHERE table_schema LIKE ?
84
            AND data_type IN (\'text\', \'tinytext\', \'mediumtext\', \'longtext\');
85
        ');
86
        $commands = array_merge($commands, $rows);
87
88
        $this->conn->executeQuery('use ' . $this->conn->getDatabase() . ';');
89
90
        return $commands;
91
    }
92
93
    private function retrieveCommands(string $sql, string $dbName): array
94
    {
95
        $result = [];
96
        $stmt = $this->conn->executeQuery(
97
            $sql,
98
            [
99
                $this->conn->getDatabase()
100
            ],
101
            [
102
                ParameterType::STRING
103
            ]
104
        );
105
        while ($row = $stmt->fetch()) {
106
            $result[] = $row['_sql'];
107
        }
108
109
        return $result;
110
    }
111
}
112