MysqlDumper::runCommand()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
ccs 4
cts 4
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * Yii2 Dumpling.
4
 *
5
 * This file contains MySQL dumper class.
6
 *
7
 * @author  Alexei Korotin <[email protected]>
8
 */
9
10
namespace herroffizier\yii2dumpling\dumpers;
11
12
use Yii;
13
use yii\base\Exception;
14
use yii\base\InvalidConfigException;
15
use Symfony\Component\Process\Process;
16
use Symfony\Component\Process\Exception\ProcessFailedException;
17
18
/**
19
 * MySQL dumper.
20
 *
21
 * Utilizes mysql and mysqldump commands so they should be available on host.
22
 */
23
class MysqlDumper extends BaseDumper implements DumperInterface
24
{
25
    /**
26
     * Path to mysqldump binary file.
27
     *
28
     * @var string
29
     */
30
    public $mysqldumpPath = 'mysqldump';
31
32
    /**
33
     * Path to mysql binary file.
34
     *
35
     * @var string
36
     */
37
    public $mysqlPath = 'mysql';
38
39
    /**
40
     * Path to store temporary defaults file.
41
     *
42
     * @var string
43
     */
44
    public $defaultsFilePath = '@app/runtime';
45
46 18
    public function __construct(array $dsn, $username, $password)
47
    {
48 18
        parent::__construct($dsn, $username, $password);
49
50 18
        if (!isset($this->dsn['dbname'])) {
51 3
            throw new InvalidConfigException('DSN string does not contain dbname param');
52
        }
53 18
    }
54
55
    /**
56
     * Create defaults file with auth and some other params for MySQL client.
57
     *
58
     * Auth params plus all supported options from DSN will be stored this file.
59
     * File name is randomized.
60
     *
61
     * Returns absolute path to file.
62
     *
63
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|boolean?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
64
     */
65 15
    protected function createMysqlDefaultsFile()
66
    {
67 15
        $fileName = Yii::getAlias($this->defaultsFilePath.'/mysql_defaults_'.md5(rand()).'.cnf');
68
69
        // @see http://php.net/manual/ru/ref.pdo-mysql.connection.php
70
        $optionsMap = [
71 15
            'user' => 'user',
72 10
            'password' => 'password',
73 10
            'host' => 'host',
74 10
            'port' => 'port',
75 10
            'unix_socket' => 'socket',
76 10
            'charset' => 'default-character-set',
77 10
        ];
78
79 15
        $rawOptions = array_merge($this->dsn, [
80 15
            'user' => $this->username,
81 15
            'password' => $this->password,
82 10
        ]);
83
84 15
        $content = ['[client]'];
85 15
        foreach ($rawOptions as $option => $value) {
86
            // If option from DSN has no mapping name, ignore it
87 15
            if (!isset($optionsMap[$option])) {
88 15
                continue;
89
            }
90
            // If option came with empty value, ignore it
91 15
            if (!$value) {
92 15
                continue;
93
            }
94
95 15
            $content[] = $optionsMap[$option].' = '.$value;
96 10
        }
97 15
        $content = implode("\n", $content);
98
99 15
        file_put_contents($fileName, $content);
100
101 15
        return $fileName;
102
    }
103
104 15
    protected function runCommand($cmd)
105
    {
106 15
        $process = new Process($cmd);
107
108 15
        $process->mustRun();
109 12
    }
110
111 9 View Code Duplication
    public function dump($file)
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...
112
    {
113 9
        $defaultsFileName = $this->createMysqlDefaultsFile();
114
115
        try {
116 9
            $this->runCommand(
117 9
                escapeshellcmd($this->mysqldumpPath)
118 9
                .' --defaults-extra-file='.escapeshellarg($defaultsFileName)
119 9
                .' '.escapeshellarg($this->dsn['dbname'])
120 9
                .' > '.escapeshellarg($file)
121 6
            );
122 7
        } catch (ProcessFailedException $e) {
123 3
            unlink($defaultsFileName);
124
125 3
            throw new Exception('mysqldump failed: '.$e->getProcess()->getErrorOutput());
126
        }
127 6
    }
128
129 9 View Code Duplication
    public function restore($file)
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...
130
    {
131 9
        $defaultsFileName = $this->createMysqlDefaultsFile();
132
133
        try {
134 9
            $this->runCommand(
135 9
                escapeshellcmd($this->mysqlPath)
136 9
                .' --defaults-extra-file='.escapeshellarg($defaultsFileName)
137 9
                .' '.escapeshellarg($this->dsn['dbname'])
138 9
                .' < '.escapeshellarg($file)
139 6
            );
140 7
        } catch (ProcessFailedException $e) {
141 3
            unlink($defaultsFileName);
142
143 3
            throw new Exception('mysql failed: '.$e->getProcess()->getErrorOutput());
144
        }
145 6
    }
146
}
147