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.
Passed
Pull Request — master (#49)
by Burhan
02:28
created

MysqlDump::skipQuery()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 6
nc 4
nop 1
dl 0
loc 9
ccs 0
cts 9
cp 0
crap 20
rs 10
c 0
b 0
f 0
1
<?php
2
namespace Graze\Morphism\Parse;
3
4
/**
5
 * Represents a dump of one or more databases.
6
 */
7
class MysqlDump
8
{
9
    /**
10
     * @var CreateDatabase[]
11
     *
12
     * indexed by (string) database name; when enumerated, reflects the order
13
     * in which the databases declarations were parsed.
14
     */
15
    public $databases = [];
16
17
    /** @var string */
18
    private $database = null;
19
    /** @var string */
20
    private $defaultDatabaseName = '';
21
    /** @var string */
22
    private $defaultEngine = 'InnoDB';
23
    /** @var CollationInfo|null */
24
    private $defaultCollation = null;
25
26
    /**
27
     * Constructor
28
     */
29
    public function __construct()
30
    {
31
        $this->defaultCollation = new CollationInfo();
32
    }
33
34
    /**
35
     * Parses one or more MySQL dump files from the specified paths.
36
     *
37
     * Each path may refer either to a file, or to a directory from which each
38
     * contained file is parsed. There is no recursion into sub-directories.
39
     *
40
     * @param string[]    $paths            files or directories to parse
41
     * @param string|null $defaultEngine    default database engine to use (e.g. InnoDB)
42
     * @param string|null $defaultCollation default collation to use (e.g. utf8)
43
     * @param string|null $defaultDatabaseName database name to use if unspecified in stream
44
     * @return MysqlDump
45
     */
46
    public static function parseFromPaths(array $paths, $defaultEngine = null, $defaultCollation = null, $defaultDatabaseName = null)
47
    {
48
        $dump = new self;
49
        if (!is_null($defaultEngine)) {
50
            $dump->setDefaultEngine($defaultEngine);
51
        }
52
        if (!is_null($defaultCollation)) {
53
            $dump->setDefaultCollation(new CollationInfo($defaultCollation));
54
        }
55
        if (!is_null($defaultDatabaseName)) {
56
            $dump->setDefaultDatabase($defaultDatabaseName);
57
        }
58
59
        $files = [];
60
        foreach ($paths as $path) {
61
            if (is_dir($path)) {
62
                foreach (new \GlobIterator("$path/*.sql") as $fileInfo) {
63
                    $files[] = $fileInfo->getPathname();
64
                }
65
            } else {
66
                $files[] = $path;
67
            }
68
        }
69
70
        foreach ($files as $file) {
71
            $stream = TokenStream::newFromFile($file);
72
            try {
73
                $dump->parse($stream);
74
            } catch (\RuntimeException $e) {
75
                $message = $stream->contextualise($e->getMessage());
76
                throw new \RuntimeException($message);
77
            }
78
        }
79
80
        return $dump;
81
    }
82
83
    /**
84
     * Sets the name to use for the database if none is specified in the stream.
85
     *
86
     * @param string $databaseName
87
     */
88
    public function setDefaultDatabase($databaseName)
89
    {
90
        $this->defaultDatabaseName = $databaseName;
91
    }
92
93
    /**
94
     * Sets the default storage engine to assume when the ENGINE= option is
95
     * not specified in a CREATE TABLE.
96
     *
97
     * @param string $engine  name of storage engine, e.g. 'InnoDB'
98
     */
99
    public function setDefaultEngine($engine)
100
    {
101
        $this->defaultEngine = $engine;
102
    }
103
104
    /**
105
     * Sets the default collation to assume when no collation or charset
106
     * is specified in CREATE DATABASE or CREATE TABLE.
107
     *
108
     * @param CollationInfo $collation
109
     */
110
    public function setDefaultCollation(CollationInfo $collation)
111
    {
112
        $this->defaultCollation = clone $collation;
113
    }
114
115
    /**
116
     * Parses a sequence of CREATE DATABASE and CREATE TABLE clauses from $stream.
117
     *
118
     * All other SQL statements and comments are skipped. After a CREATE DATABASE,
119
     * any subsequent CREATE TABLEs are assumed to belong to that database. Any
120
     * CREATE TABLEs encountered before the first CREATE DATABASE are assigned to
121
     * an anonymous dummy database named ''.
122
     *
123
     * @param TokenStream $stream
124
     * @param array $flags
125
     */
126
    public function parse(TokenStream $stream, array $flags = [])
127
    {
128
        $flags += [
129
            'matchTables' => [
130
                'include' => '',
131
                'exclude' => '',
132
            ]
133
        ];
134
135
        while (true) {
136
            if ($stream->peek('CREATE DATABASE')) {
137
                $this->database = new CreateDatabase($this->defaultCollation);
0 ignored issues
show
Bug introduced by
It seems like $this->defaultCollation can also be of type null; however, parameter $defaultCollation of Graze\Morphism\Parse\CreateDatabase::__construct() does only seem to accept Graze\Morphism\Parse\CollationInfo, 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

137
                $this->database = new CreateDatabase(/** @scrutinizer ignore-type */ $this->defaultCollation);
Loading history...
Documentation Bug introduced by
It seems like new Graze\Morphism\Parse...this->defaultCollation) of type Graze\Morphism\Parse\CreateDatabase is incompatible with the declared type string of property $database.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
138
                $this->database->parse($stream);
139
                $stream->expect(Token::SYMBOL, ';');
140
141
                $this->databases[$this->database->name] = $this->database;
142
            } elseif ($stream->peek('CREATE TABLE')) {
143
                if (is_null($this->database)) {
144
                    $name = $this->defaultDatabaseName;
145
                    $this->database = new CreateDatabase($this->defaultCollation);
146
                    $this->database->name = $name;
147
                    $this->databases[$name] = $this->database;
148
                }
149
                $table = new CreateTable($this->database->getCollation());
150
                $table->setDefaultEngine($this->defaultEngine);
151
                $table->parse($stream);
152
                $stream->expect(Token::SYMBOL, ';');
153
154
                $includeTablesRegex = $flags['matchTables']['include'];
155
                $excludeTablesRegex = $flags['matchTables']['exclude'];
156
                if (($includeTablesRegex == '' || preg_match($includeTablesRegex, $table->name)) &&
157
                    ($excludeTablesRegex == '' || !preg_match($excludeTablesRegex, $table->name))
158
                ) {
159
                    $this->database->addTable($table);
160
                }
161
            } elseif (!$this->skipQuery($stream)) {
162
                break;
163
            }
164
        }
165
    }
166
167
    /**
168
     * @param TokenStream $stream
169
     * @return bool
170
     */
171
    private function skipQuery(TokenStream $stream)
172
    {
173
        while (true) {
174
            $token = $stream->nextToken();
175
            if ($token->isEof()) {
176
                return false;
177
            }
178
            if ($token->eq(Token::SYMBOL, ';')) {
179
                return true;
180
            }
181
        }
182
    }
183
184
    /**
185
     * Returns an array of SQL DDL statements for creating the database schema.
186
     *
187
     * @return string[]
188
     */
189
    public function getDDL()
190
    {
191
        $ddl = [];
192
193
        foreach ($this->databases as $database) {
194
            if ($database->name !== '') {
195
                $ddl = array_merge($ddl, $database->getDDL());
0 ignored issues
show
Bug introduced by
$database->getDDL() of type string is incompatible with the type null|array expected by parameter $array2 of array_merge(). ( Ignorable by Annotation )

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

195
                $ddl = array_merge($ddl, /** @scrutinizer ignore-type */ $database->getDDL());
Loading history...
196
                $ddl[] = "USE " . Token::escapeIdentifier($database->name);
197
            }
198
            foreach ($database->tables as $table) {
199
                $ddl = array_merge($ddl, $table->getDDL());
200
            }
201
        }
202
203
        return $ddl;
204
    }
205
206
    /**
207
     * Returns an array of SQL DDL statements for transforming the database
208
     * schema into the one represented by $that.
209
     *
210
     * $flags           |
211
     * :----------------|
212
     * 'createDatabase' | (bool) include 'CREATE DATABASE' statements and dependent CREATE TABLEs [default: true]
213
     * 'dropDatabase'   | (bool) include 'DROP DATABASE' statements [default: true]
214
     * 'createTable'    | (bool) include 'CREATE TABLE' statements [default: true]
215
     * 'dropTable'      | (bool) include 'DROP TABLE' statements [default: true]
216
     * 'alterEngine'    | (bool) include 'ALTER TABLE ... ENGINE=' [default: true]
217
     * 'matchTables'    | [$database => ['include' => $regex, 'exclude' => $regex], ...] tables to include / exclude
218
     *
219
     * @param MysqlDump $that
220
     * @param bool[] $flags controls what to include in the generated DDL
221
     * @return \string[]
222
     */
223
    public function diff(MysqlDump $that, array $flags = [])
224
    {
225
        $flags += [
226
            'createDatabase' => true,
227
            'dropDatabase'   => true,
228
            'createTable'    => true,
229
            'dropTable'      => true,
230
            'alterEngine'    => true,
231
            'matchTables'    => [
232
                'include' => '',
233
                'exclude' => '',
234
            ],
235
        ];
236
237
        $thisDatabaseNames = array_keys($this->databases);
238
        $thatDatabaseNames = array_keys($that->databases);
239
240
        $commonDatabaseNames  = array_intersect($thisDatabaseNames, $thatDatabaseNames);
241
        $droppedDatabaseNames = array_diff($thisDatabaseNames, $thatDatabaseNames);
242
        $createdDatabaseNames = array_diff($thatDatabaseNames, $thisDatabaseNames);
243
244
        $diff = [];
245
246
        if ($flags['dropDatabase'] && count($droppedDatabaseNames) > 0) {
247
            foreach ($droppedDatabaseNames as $databaseName) {
248
                $diff[] = "DROP DATABASE IF EXISTS " . Token::escapeIdentifier($databaseName);
249
            }
250
        }
251
252
        if ($flags['createDatabase']) {
253
            foreach ($createdDatabaseNames as $databaseName) {
254
                $matchTables = $flags['matchTables'][$databaseName];
255
                $includeTablesRegex = $matchTables['include'];
256
                $excludeTablesRegex = $matchTables['exclude'];
257
                $thatDatabase = $that->databases[$databaseName];
258
                $diff[] = $thatDatabase->getDDL();
259
                $diff[] = "USE " . Token::escapeIdentifier($databaseName);
260
                foreach ($thatDatabase->tables as $table) {
261
                    if (($includeTablesRegex == '' || preg_match($includeTablesRegex, $table->name)) &&
262
                        ($excludeTablesRegex == '' || !preg_match($excludeTablesRegex, $table->name))
263
                    ) {
264
                        $diff[] = $table->getDDL($thatDatabase->getCollation());
0 ignored issues
show
Unused Code introduced by
The call to Graze\Morphism\Parse\CreateTable::getDDL() has too many arguments starting with $thatDatabase->getCollation(). ( Ignorable by Annotation )

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

264
                        /** @scrutinizer ignore-call */ 
265
                        $diff[] = $table->getDDL($thatDatabase->getCollation());

This check compares calls to functions or methods with their respective definitions. If the call has more 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...
265
                    }
266
                }
267
            }
268
        }
269
270
        foreach ($commonDatabaseNames as $databaseName) {
271
            $matchTables = $flags['matchTables'][$databaseName];
272
            $thisDatabase = $this->databases[$databaseName];
273
            $thatDatabase = $that->databases[$databaseName];
274
            $databaseDiff = $thisDatabase->diff($thatDatabase, [
275
                'createTable' => $flags['createTable'],
276
                'dropTable'   => $flags['dropTable'],
277
                'alterEngine' => $flags['alterEngine'],
278
                'matchTables' => $matchTables,
279
            ]);
280
281
            if ($databaseDiff !== '') {
282
                if ($databaseName !== $this->defaultDatabaseName) {
283
                    $diff[] = "USE " . Token::escapeIdentifier($databaseName);
284
                }
285
                $diff = array_merge($diff, $databaseDiff);
286
            }
287
        }
288
289
        return $diff;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $diff returns an array which contains values of type string which are incompatible with the documented value type string.
Loading history...
290
    }
291
}
292