Completed
Push — master ( 58d02c...4bffa9 )
by CodexShaper
05:11 queued 02:40
created

MysqlDumper   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 208
Duplicated Lines 0 %

Test Coverage

Coverage 82.24%

Importance

Changes 11
Bugs 0 Features 0
Metric Value
eloc 93
c 11
b 0
f 0
dl 0
loc 208
ccs 88
cts 107
cp 0.8224
rs 8.96
wmc 43

23 Methods

Rating   Name   Duplication   Size   Complexity  
A prepareSocket() 0 3 2
A dump() 0 5 2
A useQuick() 0 4 1
A useSkipLockTables() 0 4 1
A useSingleTransaction() 0 4 1
A prepareCreateTables() 0 3 2
A prepareSkipLockTables() 0 3 2
A restore() 0 5 2
A prepareAuthentication() 0 3 1
A prepareQuick() 0 3 2
A prepareDefaultCharSet() 0 3 2
A prepareRestoreCommand() 0 14 2
A doNotUseSkipComments() 0 4 1
A prepareIncludeTables() 0 5 3
A prepareDumpCommand() 0 24 2
A getCredentials() 0 10 1
A prepareIgnoreTables() 0 8 3
A setDefaultCharacterSet() 0 4 1
A prepareSkipComments() 0 3 2
A prepareSingleTransaction() 0 3 2
A doNotUseCreateTables() 0 4 1
A prepareDatabase() 0 3 2
A runCommand() 0 30 5

How to fix   Complexity   

Complex Class

Complex classes like MysqlDumper 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.

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 MysqlDumper, and based on these observations, apply Extract Interface, too.

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 2
    public function doNotUseSkipComments()
39
    {
40 2
        $this->skipComments = false;
41 2
        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 8
    public function dump(string $destinationPath = "")
55
    {
56 8
        $destinationPath = !empty($destinationPath) ? $destinationPath : $this->destinationPath;
57 8
        $this->runCommand($destinationPath, "dump");
58 8
        return $this;
59
    }
60
61 6
    public function restore(string $restorePath = "")
62
    {
63 6
        $restorePath = !empty($restorePath) ? $restorePath : $this->restorePath;
64 6
        $this->runCommand($restorePath, 'restore');
65 6
        return $this;
66
    }
67
68 8
    protected function prepareDumpCommand(string $credentialFile, string $destinationPath): string
69
    {
70 8
        $dumpCommand = sprintf(
71 8
            '%smysqldump %s %s %s %s %s %s %s %s %s %s %s',
72 8
            $this->dumpCommandPath,
73 8
            $this->prepareAuthentication($credentialFile),
74 8
            $this->prepareDatabase(),
75 8
            $this->prepareSocket(),
76 8
            $this->prepareSkipComments(),
77 8
            $this->prepareCreateTables(),
78 8
            $this->prepareSingleTransaction(),
79 8
            $this->prepareSkipLockTables(),
80 8
            $this->prepareQuick(),
81 8
            $this->prepareDefaultCharSet(),
82 8
            $this->prepareIncludeTables(),
83 8
            $this->prepareIgnoreTables()
84
        );
85
86 8
        if ($this->isCompress) {
87
88 2
            return "{$dumpCommand} | {$this->compressBinaryPath}{$this->compressCommand} > {$destinationPath}{$this->compressExtension}";
89
        }
90
91 6
        return "{$dumpCommand} > {$destinationPath}";
92
    }
93
94 6
    protected function prepareRestoreCommand(string $credentialFile, string $filePath): string
95
    {
96 6
        $restoreCommand = sprintf("%smysql %s %s",
97 6
            $this->dumpCommandPath,
98 6
            $this->prepareAuthentication($credentialFile),
99 6
            $this->prepareDatabase()
100
        );
101
102 6
        if ($this->isCompress) {
103
104 2
            return "{$this->compressBinaryPath}{$this->compressCommand} < {$filePath} | {$restoreCommand}";
105
        }
106
107 4
        return "{$restoreCommand} < {$filePath}";
108
    }
109
110 14
    protected function runCommand($filePath, $action)
111
    {
112
        try {
113
114 14
            $credentials    = $this->getCredentials();
115 14
            $this->tempFile = tempnam(sys_get_temp_dir(), 'mysqlpass');
116 14
            $handler        = fopen($this->tempFile, 'r+');
117 14
            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

117
            fwrite(/** @scrutinizer ignore-type */ $handler, $credentials);
Loading history...
118
119 14
            if ($action == 'dump') {
120 8
                $dumpCommand   = $this->prepareDumpCommand($this->tempFile, $filePath);
121 8
                $this->command = $this->removeExtraSpaces($dumpCommand);
122 6
            } else if ($action == 'restore') {
123 6
                $dumpCommand   = $this->prepareRestoreCommand($this->tempFile, $filePath);
124 6
                $this->command = $this->removeExtraSpaces($dumpCommand);
125
            }
126
127 14
            $process = $this->prepareProcessCommand();
128
129 14
            if ($this->debug) {
130
                $process->mustRun();
131
            } else {
132 14
                $process->run();
133
            }
134
135 14
            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

135
            fclose(/** @scrutinizer ignore-type */ $handler);
Loading history...
136 14
            unlink($this->tempFile);
137
138
        } catch (ProcessFailedException $e) {
139
            throw new \Exception($e->getMessage());
140
141
        }
142 14
    }
143
144 14
    protected function getCredentials()
145
    {
146
        $contents = [
147 14
            '[client]',
148 14
            "user = '{$this->username}'",
149 14
            "password = '{$this->password}'",
150 14
            "host = '{$this->host}'",
151 14
            "port = '{$this->port}'",
152
        ];
153 14
        return implode(PHP_EOL, $contents);
154
    }
155
156 14
    public function prepareDatabase()
157
    {
158 14
        return $this->dbName ? $this->dbName : "";
159
    }
160
161 8
    public function prepareIncludeTables()
162
    {
163 8
        $includeTables    = (count($this->tables) > 0) ? implode(' ', $this->tables) : '';
164 8
        $includeTablesArg = !empty($includeTables) ? "--tables {$includeTables}" : '';
165 8
        return $includeTablesArg;
166
    }
167
168 8
    public function prepareIgnoreTables()
169
    {
170 8
        $ignoreTablesArgs = [];
171 8
        foreach ($this->ignoreTables as $tableName) {
172
            $ignoreTablesArgs[] = "--ignore-table={$databaseArg}.{$tableName}";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $databaseArg seems to be never defined.
Loading history...
173
        }
174 8
        $ignoreTablesArg = (count($ignoreTablesArgs) > 0) ? implode(' ', $ignoreTablesArgs) : '';
175 8
        return $ignoreTablesArg;
176
    }
177
178 8
    public function prepareSingleTransaction()
179
    {
180 8
        return $this->singleTransaction ? '--single-transaction' : '';
181
    }
182
183 8
    public function prepareSkipLockTables()
184
    {
185 8
        return $this->skipLockTables ? '--skip-lock-tables' : '';
186
    }
187
188 8
    public function prepareQuick()
189
    {
190 8
        return $this->quick ? '--quick' : '';
191
    }
192
193 8
    public function prepareCreateTables()
194
    {
195 8
        return !$this->createTables ? '--no-create-info' : '';
196
    }
197
198 8
    public function prepareSkipComments()
199
    {
200 8
        return $this->skipComments ? '--skip-comments' : '';
201
    }
202
203 8
    public function prepareSocket()
204
    {
205 8
        return ($this->socket !== '') ? "--socket={$this->socket}" : '';
206
    }
207
208 8
    public function prepareDefaultCharSet()
209
    {
210 8
        return ($this->defaultCharacterSet !== '') ? "--default-character-set={$this->defaultCharacterSet}" : '';
211
    }
212
213 14
    public function prepareAuthentication(string $credentialFile)
214
    {
215 14
        return "--defaults-extra-file={$credentialFile}";
216
    }
217
}
218