Passed
Push — master ( 536d38...8f4370 )
by CodexShaper
02:06
created

MysqlDumper::useSingleTransaction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 4
rs 10
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
        // Database
71
        $databaseArg = $this->dbName;
72
        // Include tables
73
        $includeTables    = (count($this->tables) > 0) ? implode(' ', $this->tables) : "";
74
        $includeTablesArg = !empty($includeTables) ? '--tables ' . $includeTables : '';
75
        // Ignore Tables
76
        $ignoreTablesArgs = [];
77
        foreach ($this->ignoreTables as $tableName) {
78
            $ignoreTablesArgs[] = "--ignore-table=" . $databaseArg . "." . $tableName;
79
        }
80
        $ignoreTablesArg = (count($ignoreTablesArgs) > 0) ? implode(' ', $ignoreTablesArgs) : '';
81
        // Single Transaction
82
        $singleTransaction = ($this->singleTransaction) ? "--single-transaction" : "";
83
        // Skip Lock Table
84
        $skipLockTable = ($this->skipLockTables) ? "--skip-lock-tables" : "";
85
        // Quick
86
        $quick = ($this->quick) ? "--quick" : "";
87
        // Create Tables
88
        $createTables = (!$this->createTables) ? '--no-create-info' : '';
89
        // Skip Comments
90
        $skipComments = ($this->skipComments) ? '--skip-comments' : '';
91
        // Socket
92
        $socket = ($this->socket !== '') ? "--socket={$this->socket}" : '';
93
        // Default charecter set
94
        $defaultCharacterSet = ($this->defaultCharacterSet !== '') ? '--default-character-set=' . $this->defaultCharacterSet : '';
95
        // Authentication File
96
        $authenticate = "--defaults-extra-file=" . $credentialFile;
97
        // Dump command
98
        $dumpCommand = sprintf(
99
            '%smysqldump %s %s %s %s %s %s %s %s %s %s %s',
100
            $this->dumpCommandPath,
101
            $authenticate,
102
            $databaseArg,
103
            $socket,
104
            $skipComments,
105
            $createTables,
106
            $singleTransaction,
107
            $skipLockTable,
108
            $quick,
109
            $defaultCharacterSet,
110
            $includeTablesArg,
111
            $ignoreTablesArg
112
        );
113
        // Add compressor if compress is enable
114
        if ($this->isCompress) {
115
            return "{$dumpCommand} | {$this->compressBinaryPath}{$this->compressCommand} > {$destinationPath}{$this->compressExtension}";
116
        }
117
118
        return "{$dumpCommand} > {$destinationPath}";
119
    }
120
121
    protected function prepareRestoreCommand(string $credentialFile, string $filePath): string
122
    {
123
        // Database
124
        $database = $this->dbName;
125
        // Authentication File
126
        $authenticate = "--defaults-extra-file=" . $credentialFile;
127
        // Restore command
128
        $restoreCommand = sprintf("%smysql %s %s",
129
            $this->dumpCommandPath,
130
            $authenticate,
131
            $database
132
        );
133
        // Add compressor if compress is enable
134
        if ($this->isCompress) {
135
            return "{$this->compressBinaryPath}{$this->compressCommand} < {$filePath} | {$restoreCommand}";
136
        }
137
138
        return "{$restoreCommand} < {$filePath}";
139
    }
140
141
    protected function runCommand($filePath, $action)
142
    {
143
        try {
144
            // Get Credentials
145
            $credentials = $this->getCredentials();
146
            // Create a temporary file
147
            $this->tempFile = tempnam(sys_get_temp_dir(), 'mysqlpass');
148
            // Create file handler
149
            $handler = fopen($this->tempFile, 'r+');
150
            // Write credentials into temporary file
151
            fwrite($handler, $credentials);
0 ignored issues
show
Bug introduced by
It seems like $handler can also be of type false; however, parameter $handle of fwrite() does only seem to accept resource, 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

151
            fwrite(/** @scrutinizer ignore-type */ $handler, $credentials);
Loading history...
152
153
            if ($action == 'dump') {
154
                $this->command = preg_replace('/\s+/', ' ', $this->prepareDumpCommand($this->tempFile, $filePath));
155
            } else if ($action == 'restore') {
156
                $this->command = preg_replace('/\s+/', ' ', $this->prepareRestoreCommand($this->tempFile, $filePath));
157
            }
158
            // Get Symfony process with prepared command
159
            $process = $this->prepareProcessCommand();
160
161
            if ($this->debug) {
162
                $process->mustRun();
163
            } else {
164
                $process->run();
165
            }
166
            // close handler
167
            fclose($handler);
0 ignored issues
show
Bug introduced by
It seems like $handler can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, 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

167
            fclose(/** @scrutinizer ignore-type */ $handler);
Loading history...
168
            // Remove temporary file
169
            unlink($this->tempFile);
170
171
        } catch (ProcessFailedException $e) {
172
            throw new \Exception($e->getMessage());
173
174
        }
175
    }
176
177
    protected function getCredentials()
178
    {
179
        $contents = [
180
            '[client]',
181
            "user = '{$this->username}'",
182
            "password = '{$this->password}'",
183
            "host = '{$this->host}'",
184
            "port = '{$this->port}'",
185
        ];
186
        return implode(PHP_EOL, $contents);
187
    }
188
}
189