Completed
Push — develop ( fa6865...01fb76 )
by Freddie
10:19
created

Builder   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 155
Duplicated Lines 0 %

Test Coverage

Coverage 98.39%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 17
eloc 62
c 1
b 0
f 0
dl 0
loc 155
rs 10
ccs 61
cts 62
cp 0.9839

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 2
A createUser() 0 6 1
A createDatabase() 0 5 1
A getCollateDatabase() 0 9 2
A isSQLSrvPlatform() 0 3 1
A getPrettyTable() 0 16 2
A createTable() 0 26 4
A toSql() 0 18 4
1
<?php declare(strict_types=1);
2
/*
3
 * This file is part of FlexPHP.
4
 *
5
 * (c) Freddie Gar <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace FlexPHP\Database;
11
12
use Doctrine\DBAL\Platforms\AbstractPlatform;
13
use Doctrine\DBAL\Schema\Schema as DBALSchema;
14
use Doctrine\DBAL\Schema\SchemaConfig as DBALSchemaConfig;
15
use FlexPHP\Schema\SchemaInterface;
16
17
final class Builder
18
{
19
    public const PLATFORM_MYSQL = 'MySQL';
20
21
    public const PLATFORM_SQLSRV = 'SQLSrv';
22
23
    /**
24
     * @var string
25
     */
26
    private $platform;
27
28
    /**
29
     * @var AbstractPlatform
30
     */
31
    private $DBALPlatform;
32
33
    /**
34
     * @var DBALSchema
35
     */
36
    private $DBALSchema;
37
38
    /**
39
     * @var array<int, string>
40
     */
41
    private $databases = [];
42
43
    /**
44
     * @var array<int, string>
45
     */
46
    private $users = [];
47
48
    /**
49
     * @var array<int, string>
50
     */
51
    private $tables = [];
52
53
    /**
54
     * @var array<string, string>
55
     */
56
    private $platformSupport = [
57
        self::PLATFORM_MYSQL => 'MySQL57',
58
        self::PLATFORM_SQLSRV => 'SQLServer2012',
59
    ];
60
61 8
    public function __construct(string $platform)
62
    {
63 8
        if (empty($this->platformSupport[$platform])) {
64 1
            throw new \InvalidArgumentException(\sprintf(
65 1
                'Platform %s not supported, try: %s',
66 1
                $platform,
67 1
                \implode(', ', \array_keys($this->platformSupport))
68
            ));
69
        }
70
71 7
        $fqdnPlatform = \sprintf('\Doctrine\DBAL\Platforms\%sPlatform', $this->platformSupport[$platform]);
72
73 7
        $this->platform = $platform;
74 7
        $this->DBALPlatform = new $fqdnPlatform();
75 7
    }
76
77 3
    public function createDatabase(string $name): void
78
    {
79 3
        $this->databases[] = $this->DBALPlatform->getCreateDatabaseSQL($name)
80 3
            . ' ' . $this->getCollateDatabase()
81 3
            . ';';
82 3
    }
83
84 3
    public function createUser(string $name, string $password, string $host = ''): void
85
    {
86 3
        $user = new User($name, $password, $host);
87 3
        $user->setPlatform($this->platform);
88
89 3
        $this->users[] = $user->toSqlCreate();
90 3
    }
91
92 3
    public function createTable(SchemaInterface $schema): void
93
    {
94 3
        $table = new Table($schema);
95
96 3
        $DBALSchemaConfig = new DBALSchemaConfig();
97 3
        $DBALSchemaConfig->setDefaultTableOptions($table->getOptions());
98
99 3
        $this->DBALSchema = new DBALSchema([], [], $DBALSchemaConfig);
100
101 3
        $DBALTable = $this->DBALSchema->createTable($table->getName());
102
103 3
        foreach ($table->getColumns() as $column) {
104 3
            $DBALTable->addColumn($column->getName(), $column->getType(), $column->getOptions());
105
106 3
            if ($column->isPrimaryKey()) {
107
                $DBALTable->setPrimaryKey([$column->getName()]);
108
            }
109
110 3
            if ($column->isForeingKey()) {
111 1
                $fkRel = $schema->fkRelations()[$column->getName()];
112
113 1
                $DBALTable->addForeignKeyConstraint($fkRel['pkTable'], [$fkRel['pkId']], [$fkRel['fkId']]);
114
            }
115
        }
116
117 3
        $this->tables[] = $this->getPrettyTable(\implode(";\n\n", $this->DBALSchema->toSql($this->DBALPlatform))) . ';';
118 3
    }
119
120 7
    public function toSql(): string
121
    {
122 7
        $sql = [];
123 7
        $glue = \str_repeat("\n", 2);
124
125 7
        if (\count($this->databases)) {
126 3
            $sql[] = \implode($glue, $this->databases);
127
        }
128
129 7
        if (\count($this->users)) {
130 3
            $sql[] = \implode($glue, $this->users);
131
        }
132
133 7
        if (\count($this->tables)) {
134 3
            $sql[] = \implode($glue, $this->tables);
135
        }
136
137 7
        return \implode($glue, $sql);
138
    }
139
140 3
    private function getCollateDatabase(): string
141
    {
142 3
        $collate = 'CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci';
143
144 3
        if ($this->isSQLSrvPlatform()) {
145 1
            $collate = 'COLLATE latin1_general_100_ci_ai_sc';
146
        }
147
148 3
        return $collate;
149
    }
150
151 3
    private function isSQLSrvPlatform(): bool
152
    {
153 3
        return $this->platform === self::PLATFORM_SQLSRV;
154
    }
155
156 3
    private function getPrettyTable(string $sql): string
157
    {
158 3
        $tag = '<columns>';
159 3
        $regExpColumns = "/\((?$tag.*)\)/";
160 3
        $prettySql = $sql;
161
162 3
        \preg_match($regExpColumns, $sql, $matches);
163
164 3
        if (!empty($matches['columns'])) {
165 3
            $columns = $matches['columns'];
166 3
            $table = \str_replace($columns, "\n    $tag\n", $sql);
167
168 3
            $prettySql = \str_replace($tag, \str_replace(', ', ",\n    ", $columns), $table);
169
        }
170
171 3
        return $prettySql;
172
    }
173
}
174