Completed
Pull Request — master (#95)
by
unknown
02:32
created

MySql::setDefaultCharacterSet()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Spatie\DbDumper\Databases;
4
5
use Spatie\DbDumper\DbDumper;
6
use Symfony\Component\Process\Process;
7
use Spatie\DbDumper\Exceptions\CannotStartDump;
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 string */
24
    protected $defaultCharacterSet = '';
25
26
    /** @var bool */
27
    protected $dbNameWasSetAsExtraOption = false;
28
29
    /** @var bool */
30
    protected $allDatabasesWasSetAsExtraOption = false;
31
32
    /** @var string */
33
    protected $setGtidPurged = 'AUTO';
34
35
    /** @var bool */
36
    protected $createTables = true;
37
38
    public function __construct()
39
    {
40
        $this->port = 3306;
41
    }
42
43
    /**
44
     * @return $this
45
     */
46
    public function skipComments()
47
    {
48
        $this->skipComments = true;
49
50
        return $this;
51
    }
52
53
    /**
54
     * @return $this
55
     */
56
    public function dontSkipComments()
57
    {
58
        $this->skipComments = false;
59
60
        return $this;
61
    }
62
63
    /**
64
     * @return $this
65
     */
66
    public function useExtendedInserts()
67
    {
68
        $this->useExtendedInserts = true;
69
70
        return $this;
71
    }
72
73
    /**
74
     * @return $this
75
     */
76
    public function dontUseExtendedInserts()
77
    {
78
        $this->useExtendedInserts = false;
79
80
        return $this;
81
    }
82
83
    /**
84
     * @return $this
85
     */
86
    public function useSingleTransaction()
87
    {
88
        $this->useSingleTransaction = true;
89
90
        return $this;
91
    }
92
93
    /**
94
     * @return $this
95
     */
96
    public function dontUseSingleTransaction()
97
    {
98
        $this->useSingleTransaction = false;
99
100
        return $this;
101
    }
102
103
    /**
104
     * @return $this
105
     */
106
    public function skipLockTables()
107
    {
108
        $this->skipLockTables = true;
109
110
        return $this;
111
    }
112
113
    /**
114
     * @return $this
115
     */
116
    public function dontSkipLockTables()
117
    {
118
        $this->skipLockTables = false;
119
120
        return $this;
121
    }
122
123
    /**
124
     * @param string $characterSet
125
     *
126
     * @return $this
127
     */
128
    public function setDefaultCharacterSet(string $characterSet)
129
    {
130
        $this->defaultCharacterSet = $characterSet;
131
132
        return $this;
133
    }
134
135
    /**
136
     * @return $this
137
     */
138
    public function setGtidPurged(string $setGtidPurged)
139
    {
140
        $this->setGtidPurged = $setGtidPurged;
141
142
        return $this;
143
    }
144
145
    /**
146
     * Dump the contents of the database to the given file.
147
     *
148
     * @param string $dumpFile
149
     *
150
     * @throws \Spatie\DbDumper\Exceptions\CannotStartDump
151
     * @throws \Spatie\DbDumper\Exceptions\DumpFailed
152
     */
153 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...
154
    {
155
        $this->guardAgainstIncompleteCredentials();
156
157
        $tempFileHandle = tmpfile();
158
        fwrite($tempFileHandle, $this->getContentsOfCredentialsFile());
159
        $temporaryCredentialsFile = stream_get_meta_data($tempFileHandle)['uri'];
160
161
        $command = $this->getDumpCommand($dumpFile, $temporaryCredentialsFile);
162
163
        $process = Process::fromShellCommandline($command, null, null, null, $this->timeout);
164
165
        $process->run();
166
167
        $this->checkIfDumpWasSuccessFul($process, $dumpFile);
168
    }
169
170
    public function addExtraOption(string $extraOption)
171
    {
172
        if (strpos($extraOption, '--all-databases') !== false) {
173
            $this->dbNameWasSetAsExtraOption = true;
174
            $this->allDatabasesWasSetAsExtraOption = true;
175
        }
176
177
        if (preg_match('/^--databases (\S+)/', $extraOption, $matches) === 1) {
178
            $this->setDbName($matches[1]);
179
            $this->dbNameWasSetAsExtraOption = true;
180
        }
181
182
        return parent::addExtraOption($extraOption);
183
    }
184
185
    /**
186
     * @return $this
187
     */
188
    public function doNotCreateTables()
189
    {
190
        $this->createTables = false;
191
192
        return $this;
193
    }
194
195
    /**
196
     * Get the command that should be performed to dump the database.
197
     *
198
     * @param string $dumpFile
199
     * @param string $temporaryCredentialsFile
200
     *
201
     * @return string
202
     */
203
    public function getDumpCommand(string $dumpFile, string $temporaryCredentialsFile): string
204
    {
205
        $quote = $this->determineQuote();
206
207
        $command = [
208
            "{$quote}{$this->dumpBinaryPath}mysqldump{$quote}",
209
            "--defaults-extra-file=\"{$temporaryCredentialsFile}\"",
210
        ];
211
212
        if (! $this->createTables) {
213
            $command[] = '--no-create-info';
214
        }
215
216
        if ($this->skipComments) {
217
            $command[] = '--skip-comments';
218
        }
219
220
        $command[] = $this->useExtendedInserts ? '--extended-insert' : '--skip-extended-insert';
221
222
        if ($this->useSingleTransaction) {
223
            $command[] = '--single-transaction';
224
        }
225
226
        if ($this->skipLockTables) {
227
            $command[] = '--skip-lock-tables';
228
        }
229
230
        if ($this->socket !== '') {
231
            $command[] = "--socket={$this->socket}";
232
        }
233
234
        foreach ($this->excludeTables as $tableName) {
235
            $command[] = "--ignore-table={$this->dbName}.{$tableName}";
236
        }
237
238
        if (! empty($this->defaultCharacterSet)) {
239
            $command[] = '--default-character-set='.$this->defaultCharacterSet;
240
        }
241
242
        foreach ($this->extraOptions as $extraOption) {
243
            $command[] = $extraOption;
244
        }
245
246
        if ($this->setGtidPurged !== 'AUTO') {
247
            $command[] = '--set-gtid-purged='.$this->setGtidPurged;
248
        }
249
250
        if (! $this->dbNameWasSetAsExtraOption) {
251
            $command[] = $this->dbName;
252
        }
253
254
        if (! empty($this->includeTables)) {
255
            $includeTables = implode(' ', $this->includeTables);
256
            $command[] = "--tables {$includeTables}";
257
        }
258
259
        return $this->echoToFile(implode(' ', $command), $dumpFile);
260
    }
261
262
    public function getContentsOfCredentialsFile(): string
263
    {
264
        $contents = [
265
            '[client]',
266
            "user = '{$this->userName}'",
267
            "password = '{$this->password}'",
268
            "host = '{$this->host}'",
269
            "port = '{$this->port}'",
270
        ];
271
272
        return implode(PHP_EOL, $contents);
273
    }
274
275
    protected function guardAgainstIncompleteCredentials()
276
    {
277 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...
278
            if (strlen($this->$requiredProperty) === 0) {
279
                throw CannotStartDump::emptyParameter($requiredProperty);
280
            }
281
        }
282
283
        if (strlen('dbName') === 0 && ! $this->allDatabasesWasSetAsExtraOption) {
284
            throw CannotStartDump::emptyParameter($requiredProperty);
285
        }
286
    }
287
288
    protected function determineQuote(): string
289
    {
290
        return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? '"' : "'";
291
    }
292
}
293