GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

CreateDatabase   A
last analyzed

Complexity

Total Complexity 38

Size/Duplication

Total Lines 202
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 82
dl 0
loc 202
rs 9.36
c 1
b 0
f 0
ccs 75
cts 75
cp 1
wmc 38

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
B parse() 0 31 8
A addTable() 0 6 2
D diff() 0 60 21
A getDDL() 0 17 4
A getCollation() 0 5 2
1
<?php
2
namespace Graze\Morphism\Parse;
3
4
use RuntimeException;
5
6
/**
7
 * Represents the definition of a database.
8
 */
9
class CreateDatabase
10
{
11
    /** @var string */
12
    public $name = '';
13
14
    /**
15
     * @var CreateTable[]
16
     *
17
     * indexed by (string) table name; when enumerated, reflects the order
18
     * in which the table definitions were parsed.
19
     */
20
    public $tables = [];
21
22
    /** @var CollationInfo */
23
    private $collation = null;
24
    /** @var CollationInfo */
25
    private $defaultCollation = null;
26
27
    /**
28
     * Constructor.
29
     *
30
     * @param CollationInfo $defaultCollation
31
     */
32 12
    public function __construct(CollationInfo $defaultCollation)
33
    {
34 12
        $this->collation = new CollationInfo();
35 12
        $this->defaultCollation = clone $defaultCollation;
36 12
    }
37
38
    /**
39
     * Parses a database declaration from $stream.
40
     *
41
     * Declarations must be of the form 'CREATE DATABASE ...' or
42
     * 'CREATE DATABASE IF NOT EXISTS ...'. Anything else will cause
43
     * an exception to be thrown.
44
     *
45
     * @param TokenStream $stream
46
     */
47 8
    public function parse(TokenStream $stream)
48
    {
49 8
        if ($stream->consume('CREATE DATABASE')) {
50 7
            $stream->consume('IF NOT EXISTS');
51
        } else {
52 1
            throw new RuntimeException("Expected CREATE DATABASE");
53
        }
54
55 7
        $this->name = $stream->expectName();
56 7
        while (true) {
57 7
            $stream->consume('DEFAULT');
58 7
            if ($stream->consume('CHARSET') ||
59 7
                $stream->consume('CHARACTER SET')
60
            ) {
61 3
                $stream->consume([[Token::SYMBOL, '=']]);
62 3
                $charset = $stream->expectName();
63 3
                if (strtoupper($charset) === 'DEFAULT') {
64 2
                    $this->collation = new CollationInfo();
65
                } else {
66 3
                    $this->collation->setCharset($charset);
67
                }
68 7
            } elseif ($stream->consume('COLLATE')) {
69 2
                $stream->consume([[Token::SYMBOL, '=']]);
70 2
                $collation = $stream->expectName();
71 2
                if (strtoupper($collation) === 'DEFAULT') {
72 1
                    $this->collation = new CollationInfo();
73
                } else {
74 2
                    $this->collation->setCollation($collation);
75
                }
76
            } else {
77 7
                break;
78
            }
79
        }
80 7
    }
81
82
    /**
83
     * Returns the default collation associated with the database.
84
     *
85
     * @return CollationInfo
86
     */
87 8
    public function getCollation()
88
    {
89 8
        return $this->collation->isSpecified()
90 2
            ? $this->collation
91 8
            : $this->defaultCollation;
92
    }
93
94
    /**
95
     * @param CreateTable $table
96
     * @throws RuntimeException
97
     */
98 2
    public function addTable(CreateTable $table)
99
    {
100 2
        if ($table->getName()) {
101 1
            $this->tables[$table->getName()] = $table;
102
        } else {
103 1
            throw new RuntimeException("No table name in Create Table object");
104
        }
105 1
    }
106
107
    /**
108
     * Returns an array of SQL DDL statements to create the database.
109
     *
110
     * The returned DDL only refers to the database itself, it does not include
111
     * the necessary DDL to create any contained tables. For that you will need
112
     * to iterate over the $tables property, calling getDDL() on each element.
113
     *
114
     * @return array
115
     * @throws RuntimeException
116
     */
117 4
    public function getDDL()
118
    {
119 4
        if (!$this->name) {
120 1
            throw new RuntimeException('No database name specified');
121
        }
122
123 3
        $text = "CREATE DATABASE IF NOT EXISTS " . Token::escapeIdentifier($this->name);
124
125 3
        $collation = $this->getCollation();
126 3
        if ($collation->isSpecified()) {
127 2
            $text .= " DEFAULT CHARACTER SET " . $collation->getCharset();
128 2
            if (!$collation->isDefaultCollation()) {
129 1
                $text .= " COLLATE " . $collation->getCollation();
130
            }
131
        }
132
133 3
        return [$text];
134
    }
135
136
    /**
137
     * Returns an array of SQL DDL statements to transform this database and
138
     * all contained tables into the database specified by $that.
139
     *
140
     * $flags        |
141
     * :-------------|----
142
     * 'createTable' | (bool) include 'CREATE TABLE' statements [default: true]
143
     * 'dropTable'   | (bool) include 'DROP TABLE' statements [default: true]
144
     * 'alterEngine' | (bool) include ALTER TABLE ... ENGINE= [default: true]
145
     * 'matchTables' | ['include' => $regex, 'exclude' => $regex] regex of tables to include/exclude
146
     *
147
     * @param CreateDatabase $that
148
     * @param array $flags
149
     * @return string[]
150
     */
151 9
    public function diff(CreateDatabase $that, array $flags = [])
152
    {
153
        $flags += [
154 9
            'createTable' => true,
155
            'dropTable'   => true,
156
            'alterEngine' => true,
157
            'matchTables' => [
158
                'include' => '',
159
                'exclude' => '',
160
            ],
161
        ];
162
163 9
        $thisTableNames = array_keys($this->tables);
164 9
        $thatTableNames = array_keys($that->tables);
165
166 9
        $commonTableNames  = array_intersect($thisTableNames, $thatTableNames);
167 9
        $droppedTableNames = array_diff($thisTableNames, $thatTableNames);
168 9
        $createdTableNames = array_diff($thatTableNames, $thisTableNames);
169
170 9
        $diff = [];
171
172 9
        $includeTablesRegex = $flags['matchTables']['include'];
173 9
        $excludeTablesRegex = $flags['matchTables']['exclude'];
174
175 9
        if ($flags['dropTable'] && count($droppedTableNames) > 0) {
176 1
            foreach ($droppedTableNames as $tableName) {
177 1
                if (($includeTablesRegex == '' || preg_match($includeTablesRegex, $tableName)) &&
178 1
                    ($excludeTablesRegex == '' || !preg_match($excludeTablesRegex, $tableName))
179
                ) {
180 1
                    $diff[] = "DROP TABLE IF EXISTS " . Token::escapeIdentifier($tableName);
181
                }
182
            }
183
        }
184
185 9
        if ($flags['createTable'] && count($createdTableNames) > 0) {
186 2
            foreach ($createdTableNames as $tableName) {
187 2
                if (($includeTablesRegex == '' || preg_match($includeTablesRegex, $tableName)) &&
188 2
                    ($excludeTablesRegex == '' || !preg_match($excludeTablesRegex, $tableName))
189
                ) {
190 2
                    $diff = array_merge($diff, $that->tables[$tableName]->getDDL());
191
                }
192
            }
193
        }
194
195 9
        foreach ($commonTableNames as $tableName) {
196 2
            if (($includeTablesRegex == '' || preg_match($includeTablesRegex, $tableName)) &&
197 2
                ($excludeTablesRegex == '' || !preg_match($excludeTablesRegex, $tableName))
198
            ) {
199 2
                $thisTable = $this->tables[$tableName];
200 2
                $thatTable = $that->tables[$tableName];
201 2
                $tableDiff = $thisTable->diff($thatTable, [
202 2
                    'alterEngine' => $flags['alterEngine'],
203
                ]);
204 2
                if (!empty($tableDiff)) {
205 1
                    $diff = array_merge($diff, $tableDiff);
206
                }
207
            }
208
        }
209
210 9
        return $diff;
211
    }
212
}
213