Completed
Push — master ( 7a85fc...ea7b16 )
by Axel
05:45 queued 41s
created

CharsetRecodeHelper::getCommands()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 50
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 14
c 1
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('
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): 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