Test Failed
Push — master ( 8f4370...dd5caa )
by CodexShaper
02:16
created

MysqlDumper::runCommand()   A

Complexity

Conditions 5
Paths 33

Size

Total Lines 32
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 18
c 1
b 0
f 0
nc 33
nop 2
dl 0
loc 32
rs 9.3554
1
<?php
2
3
namespace CodexShaper\Dumper\Drivers;
4
5
use CodexShaper\Dumper\Dumper;
6
use Symfony\Component\Process\Exception\ProcessFailedException;
7
8
class MysqlDumper extends Dumper
9
{
10
    /*@var bool*/
11
    protected $singleTransaction = false;
12
    /*@var bool*/
13
    protected $skipLockTables = false;
14
    /*@var bool*/
15
    protected $quick = false;
16
    /*@var bool*/
17
    protected $skipComments = true;
18
    /*@var string*/
19
    protected $defaultCharacterSet = '';
20
    /*@var bool*/
21
    protected $createTables = true;
22
23
    public function useSingleTransaction()
24
    {
25
        $this->singleTransaction = true;
26
        return $this;
27
    }
28
    public function useSkipLockTables()
29
    {
30
        $this->skipLockTables = true;
31
        return $this;
32
    }
33
    public function useQuick()
34
    {
35
        $this->quick = true;
36
        return $this;
37
    }
38
    public function doNotUseSkipComments()
39
    {
40
        $this->skipComments = false;
41
        return $this;
42
    }
43
    public function doNotUseCreateTables()
44
    {
45
        $this->createTables = false;
46
        return $this;
47
    }
48
    public function setDefaultCharacterSet(string $charecterSet)
49
    {
50
        $this->defaultCharacterSet = $charecterSet;
51
        return $this;
52
    }
53
54
    public function dump(string $destinationPath = "")
55
    {
56
        $destinationPath = !empty($destinationPath) ? $destinationPath : $this->destinationPath;
57
        $this->runCommand($destinationPath, "dump");
58
        return $this;
59
    }
60
61
    public function restore(string $restorePath = "")
62
    {
63
        $restorePath = !empty($restorePath) ? $restorePath : $this->restorePath;
64
        $this->runCommand($restorePath, 'restore');
65
        return $this;
66
    }
67
68
    protected function prepareDumpCommand(string $credentialFile, string $destinationPath): string
69
    {
70
        $options = [];
71
72
        if(count($this->tables) > 0) {
73
            $options['tables'] = '--tables ' . implode(' ', $this->tables);
74
        }
75
        // Ignore Tables
76
        $ignoreTables = [];
77
        foreach ($this->ignoreTables as $tableName) {
78
            $ignoreTables[] = "--ignore-table=" . $databaseArg . "." . $tableName;
79
            $options['ignoreTables'] = implode(' ', $ignoreTables);
80
        }
81
82
        if($this->singleTransaction) {
83
            $options['singleTransaction'] => '--single-transaction';
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected T_DOUBLE_ARROW on line 83 at column 42
Loading history...
84
        }
85
86
        if($this->skipLockTable) {
87
            $options['skipLockTable'] => '--skip-lock-tables';
88
        }
89
90
        if($this->quick) {
91
            $options['quick'] => '--quick';
92
        }
93
94
        if(!$this->createTables) {
95
            $options['createTables'] => '--no-create-info';
96
        }
97
        if($this->skipComments) {
98
            $options['skipComments'] => '--skip-comments';
99
        }
100
        if($this->socket !== '') {
101
            $options['socket'] => "--socket={$this->socket}";
102
        }
103
        if($this->defaultCharacterSet) {
104
            $options['defaultCharacterSet'] => '--default-character-set=' . $this->defaultCharacterSet;
105
        }
106
        if($this->authenticate) {
107
            $options['authenticate'] => "--defaults-extra-file={$credentialFile}";
108
        }
109
        // Dump command
110
        $dumpCommand = sprintf(
111
            '%smysqldump %s %s %s %s %s %s %s %s %s %s %s',
112
            $this->dumpCommandPath,
113
            $authenticate,
114
            $this->dbName,
115
            $options['socket'],
116
            $options['skipComments'],
117
            $options['createTables'],
118
            $options['singleTransaction'],
119
            $options['skipLockTable'],
120
            $options['quick'],
121
            $options['defaultCharacterSet'],
122
            $options['tables'],
123
            $options['ignoreTables']
124
        );
125
        // Add compressor if compress is enable
126
        if ($this->isCompress) {
127
            return "{$dumpCommand} | {$this->compressBinaryPath}{$this->compressCommand} > {$destinationPath}{$this->compressExtension}";
128
        }
129
130
        return "{$dumpCommand} > {$destinationPath}";
131
    }
132
133
    protected function prepareRestoreCommand(string $credentialFile, string $filePath): string
134
    {
135
        // Database
136
        $database = $this->dbName;
137
        // Authentication File
138
        $authenticate = "--defaults-extra-file=" . $credentialFile;
139
        // Restore command
140
        $restoreCommand = sprintf("%smysql %s %s",
141
            $this->dumpCommandPath,
142
            $authenticate,
143
            $database
144
        );
145
        // Add compressor if compress is enable
146
        if ($this->isCompress) {
147
            return "{$this->compressBinaryPath}{$this->compressCommand} < {$filePath} | {$restoreCommand}";
148
        }
149
150
        return "{$restoreCommand} < {$filePath}";
151
    }
152
153
    protected function runCommand($filePath, $action)
154
    {
155
        try {
156
            // Get Credentials
157
            $credentials = $this->getCredentials();
158
            // Create a temporary file
159
            $this->tempFile = tempnam(sys_get_temp_dir(), 'mysqlpass');
160
            // Create file handler
161
            $handler = fopen($this->tempFile, 'r+');
162
            // Write credentials into temporary file
163
            fwrite($handler, $credentials);
164
165
            if ($action == 'dump') {
166
                $this->command = preg_replace('/\s+/', ' ', $this->prepareDumpCommand($this->tempFile, $filePath));
167
            } else if ($action == 'restore') {
168
                $this->command = preg_replace('/\s+/', ' ', $this->prepareRestoreCommand($this->tempFile, $filePath));
169
            }
170
            // Get Symfony process with prepared command
171
            $process = $this->prepareProcessCommand();
172
173
            if ($this->debug) {
174
                $process->mustRun();
175
            } else {
176
                $process->run();
177
            }
178
            // close handler
179
            fclose($handler);
180
            // Remove temporary file
181
            unlink($this->tempFile);
182
183
        } catch (ProcessFailedException $e) {
184
            throw new \Exception($e->getMessage());
185
186
        }
187
    }
188
189
    protected function getCredentials()
190
    {
191
        $contents = [
192
            '[client]',
193
            "user = '{$this->username}'",
194
            "password = '{$this->password}'",
195
            "host = '{$this->host}'",
196
            "port = '{$this->port}'",
197
        ];
198
        return implode(PHP_EOL, $contents);
199
    }
200
}
201