MySql   A
last analyzed

Complexity

Total Complexity 41

Size/Duplication

Total Lines 327
Duplicated Lines 6.42 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 41
lcom 1
cbo 3
dl 21
loc 327
rs 9.1199
c 0
b 0
f 0

20 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A skipComments() 0 6 1
A dontSkipComments() 0 6 1
A useExtendedInserts() 0 6 1
A dontUseExtendedInserts() 0 6 1
A useSingleTransaction() 0 6 1
A dontUseSingleTransaction() 0 6 1
A skipLockTables() 0 6 1
A dontSkipLockTables() 0 6 1
A useQuick() 0 6 1
A dontUseQuick() 0 6 1
A setDefaultCharacterSet() 0 6 1
A setGtidPurged() 0 6 1
A dumpToFile() 16 16 1
A addExtraOption() 0 14 3
A doNotCreateTables() 0 6 1
F getDumpCommand() 0 70 16
A getContentsOfCredentialsFile() 0 12 1
A guardAgainstIncompleteCredentials() 5 12 5
A doNotUseColumnStatistics() 0 6 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like MySql often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use MySql, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Spatie\DbDumper\Databases;
4
5
use Spatie\DbDumper\DbDumper;
6
use Spatie\DbDumper\Exceptions\CannotStartDump;
7
use Symfony\Component\Process\Process;
8
9
class MySql extends DbDumper
10
{
11
    /** @var bool */
12
    protected $skipComments = true;
13
14
    /** @var bool */
15
    protected $useExtendedInserts = true;
16
17
    /** @var bool */
18
    protected $useSingleTransaction = false;
19
20
    /** @var bool */
21
    protected $skipLockTables = false;
22
23
    /** @var bool */
24
    protected $doNotUseColumnStatistics = false;
25
26
    /** @var bool */
27
    protected $useQuick = false;
28
29
    /** @var string */
30
    protected $defaultCharacterSet = '';
31
32
    /** @var bool */
33
    protected $dbNameWasSetAsExtraOption = false;
34
35
    /** @var bool */
36
    protected $allDatabasesWasSetAsExtraOption = false;
37
38
    /** @var string */
39
    protected $setGtidPurged = 'AUTO';
40
41
    /** @var bool */
42
    protected $createTables = true;
43
44
    public function __construct()
45
    {
46
        $this->port = 3306;
47
    }
48
49
    /**
50
     * @return $this
51
     */
52
    public function skipComments()
53
    {
54
        $this->skipComments = true;
55
56
        return $this;
57
    }
58
59
    /**
60
     * @return $this
61
     */
62
    public function dontSkipComments()
63
    {
64
        $this->skipComments = false;
65
66
        return $this;
67
    }
68
69
    /**
70
     * @return $this
71
     */
72
    public function useExtendedInserts()
73
    {
74
        $this->useExtendedInserts = true;
75
76
        return $this;
77
    }
78
79
    /**
80
     * @return $this
81
     */
82
    public function dontUseExtendedInserts()
83
    {
84
        $this->useExtendedInserts = false;
85
86
        return $this;
87
    }
88
89
    /**
90
     * @return $this
91
     */
92
    public function useSingleTransaction()
93
    {
94
        $this->useSingleTransaction = true;
95
96
        return $this;
97
    }
98
99
    /**
100
     * @return $this
101
     */
102
    public function dontUseSingleTransaction()
103
    {
104
        $this->useSingleTransaction = false;
105
106
        return $this;
107
    }
108
109
    /**
110
     * @return $this
111
     */
112
    public function skipLockTables()
113
    {
114
        $this->skipLockTables = true;
115
116
        return $this;
117
    }
118
119
    /**
120
     * @return $this
121
     */
122
    public function doNotUseColumnStatistics()
123
    {
124
        $this->doNotUseColumnStatistics = true;
125
126
        return $this;
127
    }
128
129
    /**
130
     * @return $this
131
     */
132
    public function dontSkipLockTables()
133
    {
134
        $this->skipLockTables = false;
135
136
        return $this;
137
    }
138
139
    /**
140
     * @return $this
141
     */
142
    public function useQuick()
143
    {
144
        $this->useQuick = true;
145
146
        return $this;
147
    }
148
149
    /**
150
     * @return $this
151
     */
152
    public function dontUseQuick()
153
    {
154
        $this->useQuick = false;
155
156
        return $this;
157
    }
158
159
    /**
160
     * @param string $characterSet
161
     *
162
     * @return $this
163
     */
164
    public function setDefaultCharacterSet(string $characterSet)
165
    {
166
        $this->defaultCharacterSet = $characterSet;
167
168
        return $this;
169
    }
170
171
    /**
172
     * @return $this
173
     */
174
    public function setGtidPurged(string $setGtidPurged)
175
    {
176
        $this->setGtidPurged = $setGtidPurged;
177
178
        return $this;
179
    }
180
181
    /**
182
     * Dump the contents of the database to the given file.
183
     *
184
     * @param string $dumpFile
185
     *
186
     * @throws \Spatie\DbDumper\Exceptions\CannotStartDump
187
     * @throws \Spatie\DbDumper\Exceptions\DumpFailed
188
     */
189 View Code Duplication
    public function dumpToFile(string $dumpFile)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
190
    {
191
        $this->guardAgainstIncompleteCredentials();
192
193
        $tempFileHandle = tmpfile();
194
        fwrite($tempFileHandle, $this->getContentsOfCredentialsFile());
195
        $temporaryCredentialsFile = stream_get_meta_data($tempFileHandle)['uri'];
196
197
        $command = $this->getDumpCommand($dumpFile, $temporaryCredentialsFile);
198
199
        $process = Process::fromShellCommandline($command, null, null, null, $this->timeout);
200
201
        $process->run();
202
203
        $this->checkIfDumpWasSuccessFul($process, $dumpFile);
204
    }
205
206
    public function addExtraOption(string $extraOption)
207
    {
208
        if (strpos($extraOption, '--all-databases') !== false) {
209
            $this->dbNameWasSetAsExtraOption = true;
210
            $this->allDatabasesWasSetAsExtraOption = true;
211
        }
212
213
        if (preg_match('/^--databases (\S+)/', $extraOption, $matches) === 1) {
214
            $this->setDbName($matches[1]);
215
            $this->dbNameWasSetAsExtraOption = true;
216
        }
217
218
        return parent::addExtraOption($extraOption);
219
    }
220
221
    /**
222
     * @return $this
223
     */
224
    public function doNotCreateTables()
225
    {
226
        $this->createTables = false;
227
228
        return $this;
229
    }
230
231
    /**
232
     * Get the command that should be performed to dump the database.
233
     *
234
     * @param string $dumpFile
235
     * @param string $temporaryCredentialsFile
236
     *
237
     * @return string
238
     */
239
    public function getDumpCommand(string $dumpFile, string $temporaryCredentialsFile): string
240
    {
241
        $quote = $this->determineQuote();
242
243
        $command = [
244
            "{$quote}{$this->dumpBinaryPath}mysqldump{$quote}",
245
            "--defaults-extra-file=\"{$temporaryCredentialsFile}\"",
246
        ];
247
248
        if (! $this->createTables) {
249
            $command[] = '--no-create-info';
250
        }
251
252
        if ($this->skipComments) {
253
            $command[] = '--skip-comments';
254
        }
255
256
        $command[] = $this->useExtendedInserts ? '--extended-insert' : '--skip-extended-insert';
257
258
        if ($this->useSingleTransaction) {
259
            $command[] = '--single-transaction';
260
        }
261
262
        if ($this->skipLockTables) {
263
            $command[] = '--skip-lock-tables';
264
        }
265
266
        if ($this->doNotUseColumnStatistics) {
267
            $command[] = '--column-statistics=0';
268
        }
269
270
        if ($this->useQuick) {
271
            $command[] = '--quick';
272
        }
273
274
        if ($this->socket !== '') {
275
            $command[] = "--socket={$this->socket}";
276
        }
277
278
        foreach ($this->excludeTables as $tableName) {
279
            $command[] = "--ignore-table={$this->dbName}.{$tableName}";
280
        }
281
282
        if (! empty($this->defaultCharacterSet)) {
283
            $command[] = '--default-character-set='.$this->defaultCharacterSet;
284
        }
285
286
        foreach ($this->extraOptions as $extraOption) {
287
            $command[] = $extraOption;
288
        }
289
290
        if ($this->setGtidPurged !== 'AUTO') {
291
            $command[] = '--set-gtid-purged='.$this->setGtidPurged;
292
        }
293
294
        if (! $this->dbNameWasSetAsExtraOption) {
295
            $command[] = $this->dbName;
296
        }
297
298
        if (! empty($this->includeTables)) {
299
            $includeTables = implode(' ', $this->includeTables);
300
            $command[] = "--tables {$includeTables}";
301
        }
302
303
        foreach ($this->extraOptionsAfterDbName as $extraOptionAfterDbName) {
304
            $command[] = $extraOptionAfterDbName;
305
        }
306
307
        return $this->echoToFile(implode(' ', $command), $dumpFile);
308
    }
309
310
    public function getContentsOfCredentialsFile(): string
311
    {
312
        $contents = [
313
            '[client]',
314
            "user = '{$this->userName}'",
315
            "password = '{$this->password}'",
316
            "host = '{$this->host}'",
317
            "port = '{$this->port}'",
318
        ];
319
320
        return implode(PHP_EOL, $contents);
321
    }
322
323
    protected function guardAgainstIncompleteCredentials()
324
    {
325 View Code Duplication
        foreach (['userName', 'host'] as $requiredProperty) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
326
            if (strlen($this->$requiredProperty) === 0) {
327
                throw CannotStartDump::emptyParameter($requiredProperty);
328
            }
329
        }
330
331
        if (strlen($this->dbName) === 0 && ! $this->allDatabasesWasSetAsExtraOption) {
332
            throw CannotStartDump::emptyParameter('dbName');
333
        }
334
    }
335
}
336