PluginProbe ʕ •ᴥ•ʔ
Backup Migration / 1.4.3
Backup Migration v1.4.3
2.1.6 2.1.5.2 trunk 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.6.1 1.4.7 1.4.8 1.4.9 1.4.9.1 2.0.0 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.5.1
backup-backup / includes / database / manager.php
backup-backup / includes / database Last commit date
better-backup-v3.php 2 years ago better-backup.php 2 years ago better-restore.php 2 years ago even-better-restore-v3.php 2 years ago even-better-restore-v4.php 2 years ago manager.php 2 years ago search-replace.php 2 years ago smart-sort.php 2 years ago
manager.php
291 lines
1 <?php
2
3 // Namespace
4 namespace BMI\Plugin\Database;
5
6 // Use
7 use BMI\Plugin\BMI_Logger AS Logger;
8 use BMI\Plugin\Progress\BMI_ZipProgress AS Progress;
9 use BMI\Plugin\Backup_Migration_Plugin as BMP;
10
11 // Exit on direct access
12 if (!defined('ABSPATH')) exit;
13
14 /**
15 * BMI_Database
16 */
17 class BMI_Database {
18
19 function __construct($host, $user, $pass, $name) {
20
21 $this->host = $host;
22 $this->user = $user;
23 $this->pass = $pass;
24 $this->name = $name;
25
26 }
27
28 public function exportDatabase($backup_name = false) {
29
30 $mysqli = new \mysqli($this->host, $this->user, $this->pass, $this->name);
31 $mysqli->select_db($this->name);
32 $mysqli->query("SET NAMES 'utf8'");
33
34 $file = fopen(BMI_TMP . DIRECTORY_SEPARATOR . $backup_name, 'w');
35 $queryTables = $mysqli->query('SHOW TABLES');
36 while ($row = $queryTables->fetch_row()) $target_tables[] = $row[0];
37
38 fwrite($file, "SET SQL_MODE = \"\";\r\n");
39 fwrite($file, "SET time_zone = \"+00:00\";\r\n\r\n\r\n");
40 fwrite($file, "/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\r\n");
41 fwrite($file, "/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\r\n");
42 fwrite($file, "/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\r\n");
43 fwrite($file, "SET SQL_MODE = \"\";\r\n");
44 fwrite($file, "/*!40101 SET NAMES utf8 */;\r\n");
45 fwrite($file, "--\r\n-- Database: `" . $this->name . "`\r\n");
46 fwrite($file, "--\r\n\r\n\r\n");
47
48 foreach ($target_tables as $table) {
49
50 if (empty($table)) { continue; }
51
52 $chunks_req = $mysqli->query('SELECT count(1) FROM `'.$table.'`');
53 $chunks_res = mysqli_fetch_array($chunks_req);
54 $chunks = intval($chunks_res[0]);
55
56 $res = $mysqli->query('SHOW CREATE TABLE `' . $table . '`');
57 $TableMLine = $res->fetch_row();
58 fwrite($file, "\n\n".$TableMLine[1].";\n\n");
59 $TableMLine[1] = str_ireplace('CREATE TABLE `','CREATE TABLE IF NOT EXISTS `', $TableMLine[1]);
60
61 if ($chunks > 0) {
62 $g = 0;
63 while($g < $chunks) {
64 if (($g + 100) > $chunks) $limit_str = 'LIMIT '. $g . ',1000';
65 else $limit_str = 'LIMIT '. $g . ',100';
66 $this->saveDatabaseFields($mysqli, $table, $file, $limit_str);
67 $g += 100;
68 }
69 } else $this->saveDatabaseFields($mysqli, $table, $file);
70
71 fwrite($file, "\n\n\n");
72
73 }
74
75 fwrite($file, "\r\n\r\n/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\r\n");
76 fwrite($file, "/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\r\n");
77 fwrite($file, "/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;");
78
79 $mysqli->close();
80 $backup_name = $backup_name ? $backup_name : $this->name.'___('.date('H-i-s').'_'.date('d-m-Y').').sql';
81 fclose($file);
82
83 }
84
85 public function saveDatabaseFields(&$mysqli, $table, &$file, $limit = '') {
86
87 $result = $mysqli->query('SELECT * FROM `'.$table.'` ' . $limit);
88 $fields_amount = $result->field_count;
89 $rows_num = $mysqli->affected_rows;
90 for ($i = 0, $st_counter = 0; $i < $fields_amount; $i++, $st_counter = 0) {
91 while ($row = $result->fetch_row()) {
92
93 if ($st_counter % 100 == 0 || $st_counter == 0) {
94 fwrite($file, "\nINSERT INTO `" . $table . "` VALUES");
95 }
96
97 fwrite($file, "\n(");
98 for ($j = 0; $j < $fields_amount; $j++) {
99 $row[$j] = str_replace("\n","\\n", addslashes($row[$j]));
100
101 if (isset($row[$j])) fwrite($file, '"'.$row[$j].'"');
102 else fwrite($file, '""');
103
104 if ($j<($fields_amount-1)) fwrite($file, ',');
105 }
106
107 fwrite($file, ")");
108 if ((($st_counter+1)%100==0 && $st_counter!=0) || $st_counter+1==$rows_num) {
109
110 fwrite($file, ";");
111
112 } else fwrite($file, ",");
113
114 $st_counter = $st_counter + 1;
115
116 }
117 }
118
119 }
120
121 public function recursiveReplace(&$line, &$at, &$from, &$to) {
122
123 $end = -1;
124 for ($i = $at; $i > 3; --$i) {
125 $str = $line[$i-2] . $line[$i-1] . $line[$i];
126 if ($str === ':\"') {
127 $end = $i;
128 break;
129 }
130 unset($str);
131 }
132
133 $start = -1; $semi = false;
134 for ($i = $end; $i > 0; --$i) {
135 $str = $line[$i] . $line[$i+1] . $line[$i+2];
136 if ($str === ';s:') {
137 $semi = true;
138 $start = $i + 3;
139 break;
140 }
141 if ($str === '{s:') {
142 $start = $i + 3;
143 break;
144 }
145 unset($str);
146 }
147
148 if ($start == -1 || $end == -1) return $line;
149 $diff = $end - $start; $eof = -1;
150 $len = intval(substr($line, $start, $diff));
151 $maxend = strlen($line);
152 if ($maxend > ($end + 3 + $len + 6)) {
153 $maxend = ($end + 3 + $len + 6);
154 }
155
156 for ($j = ($end + 3); $j < $maxend; ++$j) {
157 $str = $line[$j] . $line[$j+1] . $line[$j+2];
158 if ($str === '\";') {
159 $eof = $j;
160 break;
161 }
162 unset($str);
163 }
164
165 if ($eof == -1) {
166 for ($i = $maxend; $i > ($end + 3); --$i) {
167 $str = $line[$i] . $line[$i+1] . $line[$i+2];;
168 if ($str === '\";') {
169 $eof = $i;
170 break;
171 }
172 unset($str);
173 }
174 }
175
176 if ($eof == -1 || $eof < $end || $eof < $start) return $line;
177 $should = abs(strlen($from) - strlen($to));
178 $toreplace = substr($line, $start - 3, (($eof + 6) - $start));
179 $content = str_replace($from, $to, substr($toreplace, $diff + 6, -3));
180 if ($semi) $newreplace = ';s:' . strlen($content) . ':\"' . $content . '\";';
181 else $newreplace = '{s:' . strlen($content) . ':\"' . $content . '\";';
182 $line = str_replace($toreplace, $newreplace, $line);
183 // if (strlen($len >= $content)) {
184
185 // error_log($start . ' - ' . $end . ' - ' . $eof . ' - ' . $len . '['.strlen($toreplace).']' . ' - ' . '['.strlen($newreplace).']');
186 // error_log(strlen($toreplace) . ' -> ' . strlen($newreplace));
187 // error_log($toreplace);
188 // error_log($newreplace);
189 // error_log('');
190 // }
191
192 // Do the same for every occurence
193 $d = strpos($line, $from);
194 if ($d !== false) $line = $this->recursiveReplace($line, $d, $from, $to);
195
196 return $line;
197 }
198
199 public function replaceInLine(&$line) {
200
201 if (strpos($line, ':\"') !== false) {
202
203 $d = strpos($line, $this->old_domain);
204 if ($d !== false) $this->recursiveReplace($line, $d, $this->old_domain, $this->new_domain);
205
206 $b = strpos($line, $this->abs);
207 if ($b !== false) $this->recursiveReplace($line, $b, $this->abs, $this->newabs);
208
209 } else {
210
211 // Replace in case user had this wrongly defined in wp-config.
212 // Of course, those two ifs will take a lot of memory...
213 if (substr($line, 0, 16) === '("1","siteurl","') $line = '("1","siteurl","' . $this->new_domain . '","yes"),';
214 if (substr($line, 0, 13) === '("2","home","') $line = '("2","home","' . $this->new_domain . '","yes"),';
215
216 $line = str_replace($this->old_domain, $this->new_domain, $line);
217 $line = str_replace($this->abs, $this->newabs, $line);
218
219 }
220
221 return $line;
222 }
223
224 public function importDatabase($file, $old_domain, $new_domain, $abs, $newabs, $newprefix, $siteurl, $home) {
225
226 if (BMP::isFunctionEnabled('ignore_user_abort')) @ignore_user_abort(true);
227 if (BMP::isFunctionEnabled('set_time_limit')) @set_time_limit(16000);
228 if (BMP::isFunctionEnabled('ini_set')) {
229 @ini_set('max_execution_time', '259200');
230 @ini_set('max_input_time', '259200');
231 @ini_set('session.gc_maxlifetime', '1200');
232 }
233
234 $SQL_CONTENT = $file;
235 $mysqli = new \mysqli($this->host, $this->user, $this->pass, $this->name);
236
237 if (mysqli_connect_errno()) {
238 Logger::error(__("Failed to connect to MySQL: ", 'backup-backup') . mysqli_connect_error());
239 return __("Importing failed - cannot connect to the database.", 'backup-backup');
240 }
241
242 $this->old_domain = $old_domain;
243 $this->new_domain = $new_domain;
244 $this->escaped_old = str_replace('/', '\\\/', $old_domain);
245 $this->escaped_new = str_replace('/', '\\\/', $new_domain);
246
247 $this->abs = $abs;
248 $this->newabs = $newabs;
249 $this->e_abs_old = str_replace('/', '\\\/', $abs);
250 $this->e_abs_new = str_replace('/', '\\\/', $newabs);
251
252 $handle = fopen($file, 'r');
253 if ($handle) {
254 $templine = '';
255 $qyr = $mysqli->query('SET foreign_key_checks = 0');
256
257 while (($line = fgets($handle)) !== false) {
258 preg_match_all("/\nCREATE TABLE(.*?)\`(.*?)\`/si", "\n" . $line, $target_tables);
259 foreach ($target_tables[2] as $table) $mysqli->query('DROP TABLE IF EXISTS `' . $table . '`');
260 if (substr($line, 0, 2) != '--' && $line != '') {
261 $this->replaceInLine($line);
262 $templine .= $line;
263 if (substr(trim($line), -1, 1) == ';') {
264 if (!$mysqli->query($templine)) {
265 Logger::error('Error performing query ' . $templine . ': ' . $mysqli->error);
266 }
267 $templine = '';
268 $line = '';
269 }
270 }
271 }
272
273 fclose($handle);
274 } else {
275 Logger::error(__("Cannot open SQL file...", 'backup-backup'));
276 return __("Importing failed - Cannot open SQL file...", 'backup-backup');
277 }
278
279 $qyr = $mysqli->query('SET foreign_key_checks = 1');
280 $mysqli->query("SET NAMES 'utf8'");
281
282 // $mysqli->query("UPDATE `".$new_prefix."options` SET option_value = '" . $siteurl. "' WHERE option_name = 'siteurl'");
283 // $mysqli->query("UPDATE `".$new_prefix."options` SET option_value = '" . $home. "' WHERE option_name = 'home'");
284
285 $mysqli->close();
286 return __("Importing finished. Now, Delete the import file.", 'backup-backup');
287
288 }
289
290 }
291