Completed
Pull Request — develop (#716)
by Agel_Nash
06:39
created

MysqlDumper   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 231
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
dl 0
loc 231
rs 9.8
c 0
b 0
f 0
wmc 31
lcom 1
cbo 2

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A setDroptables() 0 4 1
A setDBtables() 0 4 1
F createDump() 0 111 18
A result2Array() 0 11 2
A isDroptables() 0 4 1
A loadObjectList() 0 15 3
A object2Array() 0 16 4
1
<?php namespace EvolutionCMS\Support;
2
3
use EvolutionCMS\Interfaces\MysqlDumperInterface;
4
5
/**
6
 * @package  MySQLdumper
7
 * @version  1.0
8
 * @author   Dennis Mozes <[email protected]>
9
 * @url        http://www.mosix.nl/mysqldumper
10
 * @since    PHP 4.0
11
 * @copyright Dennis Mozes
12
 * @license GNU/LGPL License: http://www.gnu.org/copyleft/lgpl.html
13
 *
14
 * Modified by Raymond for use with this module
15
 *
16
 **/
17
class MysqlDumper implements MysqlDumperInterface
0 ignored issues
show
Coding Style introduced by
The property $_dbtables is not named in camelCase.

This check marks property names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style introduced by
The property $_isDroptables is not named in camelCase.

This check marks property names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style introduced by
The property $database_server is not named in camelCase.

This check marks property names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
18
{
19
    /**
20
     * @var array
21
     */
22
    public $_dbtables;
23
    /**
24
     * @var bool
25
     */
26
    public $_isDroptables;
27
    /**
28
     * @var string
29
     */
30
    public $dbname;
31
    /**
32
     * @var string
33
     */
34
    public $database_server;
35
36
    /**
37
     * Mysqldumper constructor.
38
     * @param string $dbname
39
     */
40
    public function __construct($dbname)
41
    {
42
        // Don't drop tables by default.
43
        $this->dbname = $dbname;
44
        $this->setDroptables(false);
45
    }
46
47
    /**
48
     * If set to true, it will generate 'DROP TABLE IF EXISTS'-statements for each table.
49
     *
50
     * @param bool $state
51
     */
52
    public function setDroptables($state)
53
    {
54
        $this->_isDroptables = $state;
55
    }
56
57
    /**
58
     * @param array $dbtables
59
     */
60
    public function setDBtables($dbtables)
61
    {
62
        $this->_dbtables = $dbtables;
63
    }
64
65
    /**
66
     * @param string $callBack
67
     * @return bool
68
     */
69
    public function createDump($callBack)
0 ignored issues
show
Coding Style introduced by
createDump uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
70
    {
71
        $modx = evolutionCMS();
72
        $createtable = array();
73
74
        // Set line feed
75
        $lf = "\n";
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $lf. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
76
        $tempfile_path = $modx->config['base_path'] . 'assets/backup/temp.php';
77
78
        $result = $modx->db->query('SHOW TABLES');
79
        $tables = $this->result2Array(0, $result);
80
        foreach ($tables as $tblval) {
81
            $result = $modx->db->query("SHOW CREATE TABLE `{$tblval}`");
82
            $createtable[$tblval] = $this->result2Array(1, $result);
83
        }
84
85
        $version = $modx->getVersionData();
86
87
        // Set header
88
        $output = "#{$lf}";
89
        $output .= "# " . addslashes($modx->config['site_name']) . " Database Dump{$lf}";
90
        $output .= "# MODX Version:{$version['version']}{$lf}";
91
        $output .= "# {$lf}";
92
        $output .= "# Host: {$this->database_server}{$lf}";
93
        $output .= "# Generation Time: " . $modx->toDateFormat(time()) . $lf;
94
        $output .= "# Server version: " . $modx->db->getVersion() . $lf;
95
        $output .= "# PHP Version: " . phpversion() . $lf;
96
        $output .= "# Database: `{$this->dbname}`{$lf}";
97
        $output .= "# Description: " . trim($_REQUEST['backup_title']) . "{$lf}";
98
        $output .= "#";
99
        file_put_contents($tempfile_path, $output, FILE_APPEND | LOCK_EX);
100
        $output = '';
101
102
        // Generate dumptext for the tables.
103
        if (isset($this->_dbtables) && count($this->_dbtables)) {
104
            $this->_dbtables = implode(',', $this->_dbtables);
0 ignored issues
show
Documentation Bug introduced by
It seems like implode(',', $this->_dbtables) of type string is incompatible with the declared type array of property $_dbtables.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
105
        } else {
106
            unset($this->_dbtables);
107
        }
108
        foreach ($tables as $tblval) {
109
            // check for selected table
110
            if (isset($this->_dbtables)) {
111
                if (strstr(",{$this->_dbtables},", ",{$tblval},") === false) {
112
                    continue;
113
                }
114
            }
115
            if ($callBack === 'snapshot') {
116
                if (!preg_match('@^' . $modx->db->config['table_prefix'] . '@', $tblval)) {
117
                    continue;
118
                }
119
            }
120
            $output .= "{$lf}{$lf}# --------------------------------------------------------{$lf}{$lf}";
121
            $output .= "#{$lf}# Table structure for table `{$tblval}`{$lf}";
122
            $output .= "#{$lf}{$lf}";
123
            // Generate DROP TABLE statement when client wants it to.
124
            if ($this->isDroptables()) {
125
                $output .= "SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;{$lf}";
126
                $output .= "DROP TABLE IF EXISTS `{$tblval}`;{$lf}";
127
                $output .= "SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;{$lf}{$lf}";
128
            }
129
            $output .= "{$createtable[$tblval][0]};{$lf}";
130
            $output .= $lf;
131
            $output .= "#{$lf}# Dumping data for table `{$tblval}`{$lf}#{$lf}";
132
            $result = $modx->db->select('*', $tblval);
133
            $rows = $this->loadObjectList('', $result);
134
            foreach ($rows as $row) {
135
                $insertdump = $lf;
136
                $insertdump .= "INSERT INTO `{$tblval}` VALUES (";
137
                $arr = $this->object2Array($row);
138
                if (!is_array($arr)) {
139
                    $arr = array();
140
                }
141
                foreach ($arr as $key => $value) {
142
                    if (is_null($value)) {
143
                        $value = 'NULL';
144
                    } else {
145
                        $value = addslashes($value);
146
                        $value = str_replace(array(
147
                            "\r\n",
148
                            "\r",
149
                            "\n"
150
                        ), '\\n', $value);
151
                        $value = "'{$value}'";
152
                    }
153
                    $insertdump .= $value . ',';
154
                }
155
                $output .= rtrim($insertdump, ',') . ");\n";
156
                if (1048576 < strlen($output)) {
157
                    file_put_contents($tempfile_path, $output, FILE_APPEND | LOCK_EX);
158
                    $output = '';
159
                }
160
            }
161
            file_put_contents($tempfile_path, $output, FILE_APPEND | LOCK_EX);
162
            $output = '';
163
        }
164
        $output = file_get_contents($tempfile_path);
165
        if (!empty($output)) {
166
            unlink($tempfile_path);
167
        }
168
169
        switch ($callBack) {
170
            case 'dumpSql':
171
                dumpSql($output);
172
                break;
173
            case 'snapshot':
174
                snapshot($output);
175
                break;
176
        }
177
178
        return true;
179
    }
180
181
    /**
182
     * @param int $numinarray
183
     * @param \mysqli_result $resource
184
     * @return array
185
     */
186
    public function result2Array($numinarray = 0, $resource)
0 ignored issues
show
Coding Style introduced by
Parameters which have default values should be placed at the end.

If you place a parameter with a default value before a parameter with a default value, the default value of the first parameter will never be used as it will always need to be passed anyway:

// $a must always be passed; it's default value is never used.
function someFunction($a = 5, $b) { }
Loading history...
187
    {
188
        $modx = evolutionCMS();
189
        $array = array();
190
        while ($row = $modx->db->getRow($resource, 'num')) {
191
            $array[] = $row[$numinarray];
192
        }
193
        $modx->db->freeResult($resource);
194
195
        return $array;
196
    }
197
198
    /**
199
     * @return bool
200
     */
201
    public function isDroptables()
202
    {
203
        return $this->_isDroptables;
204
    }
205
206
    /**
207
     * @param string $key
208
     * @param \mysqli_result $resource
209
     * @return array
210
     */
211
    public function loadObjectList($key = '', $resource)
0 ignored issues
show
Coding Style introduced by
Parameters which have default values should be placed at the end.

If you place a parameter with a default value before a parameter with a default value, the default value of the first parameter will never be used as it will always need to be passed anyway:

// $a must always be passed; it's default value is never used.
function someFunction($a = 5, $b) { }
Loading history...
212
    {
213
        $modx = evolutionCMS();
214
        $array = array();
215
        while ($row = $modx->db->getRow($resource, 'object')) {
216
            if ($key) {
217
                $array[$row->$key] = $row;
218
            } else {
219
                $array[] = $row;
220
            }
221
        }
222
        $modx->db->freeResult($resource);
223
224
        return $array;
225
    }
226
227
    /**
228
     * @param \stdClass $obj
229
     * @return array|null
230
     */
231
    public function object2Array($obj)
232
    {
233
        $array = null;
234
        if (is_object($obj)) {
235
            $array = array();
236
            foreach (get_object_vars($obj) as $key => $value) {
237
                if (is_object($value)) {
238
                    $array[$key] = $this->object2Array($value);
239
                } else {
240
                    $array[$key] = $value;
241
                }
242
            }
243
        }
244
245
        return $array;
246
    }
247
}
248