Completed
Push — master ( c3eaef...22082b )
by Freek
01:17
created

MySql::addExtraOption()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 1
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 string */
21
    protected $defaultCharacterSet = '';
22
23
    /** @var bool */
24
    protected $dbNameWasSetAsExtraOption = false;
25
26
    public function __construct()
27
    {
28
        $this->port = 3306;
29
    }
30
31
    /**
32
     * @return $this
33
     */
34
    public function skipComments()
35
    {
36
        $this->skipComments = true;
37
38
        return $this;
39
    }
40
41
    /**
42
     * @return $this
43
     */
44
    public function dontSkipComments()
45
    {
46
        $this->skipComments = false;
47
48
        return $this;
49
    }
50
51
    /**
52
     * @return $this
53
     */
54
    public function useExtendedInserts()
55
    {
56
        $this->useExtendedInserts = true;
57
58
        return $this;
59
    }
60
61
    /**
62
     * @return $this
63
     */
64
    public function dontUseExtendedInserts()
65
    {
66
        $this->useExtendedInserts = false;
67
68
        return $this;
69
    }
70
71
    /**
72
     * @return $this
73
     */
74
    public function useSingleTransaction()
75
    {
76
        $this->useSingleTransaction = true;
77
78
        return $this;
79
    }
80
81
    /**
82
     * @return $this
83
     */
84
    public function dontUseSingleTransaction()
85
    {
86
        $this->useSingleTransaction = false;
87
88
        return $this;
89
    }
90
91
    /**
92
     * @param string $characterSet
93
     *
94
     * @return $this
95
     */
96
    public function setDefaultCharacterSet(string $characterSet)
97
    {
98
        $this->defaultCharacterSet = $characterSet;
99
100
        return $this;
101
    }
102
103
    /**
104
     * Dump the contents of the database to the given file.
105
     *
106
     * @param string $dumpFile
107
     *
108
     * @throws \Spatie\DbDumper\Exceptions\CannotStartDump
109
     * @throws \Spatie\DbDumper\Exceptions\DumpFailed
110
     */
111
    public function dumpToFile(string $dumpFile)
112
    {
113
        $this->guardAgainstIncompleteCredentials();
114
115
        $tempFileHandle = tmpfile();
116
        fwrite($tempFileHandle, $this->getContentsOfCredentialsFile());
117
        $temporaryCredentialsFile = stream_get_meta_data($tempFileHandle)['uri'];
118
119
        $command = $this->getDumpCommand($dumpFile, $temporaryCredentialsFile);
120
121
        $process = new Process($command);
122
123
        if (! is_null($this->timeout)) {
124
            $process->setTimeout($this->timeout);
125
        }
126
127
        $process->run();
128
129
        $this->checkIfDumpWasSuccessFul($process, $dumpFile);
130
    }
131
132
    public function addExtraOption(string $extraOption)
133
    {
134
        if (preg_match('/^--databases (\S+)/', $extraOption, $matches) === 1) {
135
            $this->setDbName($matches[1]);
136
            $this->dbNameWasSetAsExtraOption = true;
137
        }
138
139
        return parent::addExtraOption($extraOption);
140
    }
141
142
    /**
143
     * Get the command that should be performed to dump the database.
144
     *
145
     * @param string $dumpFile
146
     * @param string $temporaryCredentialsFile
147
     *
148
     * @return string
149
     */
150
    public function getDumpCommand(string $dumpFile, string $temporaryCredentialsFile): string
151
    {
152
        $quote = $this->determineQuote();
153
154
        $command = [
155
            "{$quote}{$this->dumpBinaryPath}mysqldump{$quote}",
156
            "--defaults-extra-file=\"{$temporaryCredentialsFile}\"",
157
        ];
158
159
        if ($this->skipComments) {
160
            $command[] = '--skip-comments';
161
        }
162
163
        $command[] = $this->useExtendedInserts ? '--extended-insert' : '--skip-extended-insert';
164
165
        if ($this->useSingleTransaction) {
166
            $command[] = '--single-transaction';
167
        }
168
169
        if ($this->socket !== '') {
170
            $command[] = "--socket={$this->socket}";
171
        }
172
173
        foreach ($this->excludeTables as $tableName) {
174
            $command[] = "--ignore-table={$this->dbName}.{$tableName}";
175
        }
176
177
        if (! empty($this->defaultCharacterSet)) {
178
            $command[] = '--default-character-set='.$this->defaultCharacterSet;
179
        }
180
181
        foreach ($this->extraOptions as $extraOption) {
182
            $command[] = $extraOption;
183
        }
184
185
        $command[] = "--result-file=\"{$dumpFile}\"";
186
187
        if (! $this->dbNameWasSetAsExtraOption) {
188
            $command[] = $this->dbName;
189
        }
190
191
        if (! empty($this->includeTables)) {
192
            $includeTables = implode(' ', $this->includeTables);
193
            $command[] = "--tables {$includeTables}";
194
        }
195
196
        return implode(' ', $command);
197
    }
198
199
    public function getContentsOfCredentialsFile(): string
200
    {
201
        $contents = [
202
            '[client]',
203
            "user = '{$this->userName}'",
204
            "password = '{$this->password}'",
205
            "host = '{$this->host}'",
206
            "port = '{$this->port}'",
207
        ];
208
209
        return implode(PHP_EOL, $contents);
210
    }
211
212 View Code Duplication
    protected function guardAgainstIncompleteCredentials()
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...
213
    {
214
        foreach (['userName', 'dbName', 'host'] as $requiredProperty) {
215
            if (strlen($this->$requiredProperty) === 0) {
216
                throw CannotStartDump::emptyParameter($requiredProperty);
217
            }
218
        }
219
    }
220
221
    protected function determineQuote(): string
222
    {
223
        return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? '"' : "'";
224
    }
225
}
226