PluginProbe ʕ •ᴥ•ʔ
Backup Migration / 2.1.6
Backup Migration v2.1.6
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
export 3 weeks ago better-backup-v3.php 3 weeks ago better-backup.php 3 weeks ago better-restore.php 3 weeks ago even-better-restore-v3.php 3 weeks ago even-better-restore-v4.php 3 weeks ago interface-search-replace-repository.php 3 weeks ago manager.php 3 weeks ago search-replace-processor.php 3 weeks ago search-replace-repository.php 3 weeks ago search-replace-stack-based.php 3 weeks ago search-replace-v2.php 3 weeks ago search-replace.php 3 weeks ago smart-sort.php 3 weeks ago
manager.php
290 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 ' . BMP::escapeSQLIDentifier($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 " . BMP::escapeSQLIDentifier($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 }
232
233 $SQL_CONTENT = $file;
234 $mysqli = new \mysqli($this->host, $this->user, $this->pass, $this->name);
235
236 if (mysqli_connect_errno()) {
237 Logger::error(__("Failed to connect to MySQL: ", 'backup-backup') . mysqli_connect_error());
238 return __("Importing failed - cannot connect to the database.", 'backup-backup');
239 }
240
241 $this->old_domain = $old_domain;
242 $this->new_domain = $new_domain;
243 $this->escaped_old = str_replace('/', '\\\/', $old_domain);
244 $this->escaped_new = str_replace('/', '\\\/', $new_domain);
245
246 $this->abs = $abs;
247 $this->newabs = $newabs;
248 $this->e_abs_old = str_replace('/', '\\\/', $abs);
249 $this->e_abs_new = str_replace('/', '\\\/', $newabs);
250
251 $handle = fopen($file, 'r');
252 if ($handle) {
253 $templine = '';
254 $qyr = $mysqli->query('SET foreign_key_checks = 0');
255
256 while (($line = fgets($handle)) !== false) {
257 preg_match_all("/\nCREATE TABLE(.*?)\`(.*?)\`/si", "\n" . $line, $target_tables);
258 foreach ($target_tables[2] as $table) $mysqli->query('DROP TABLE IF EXISTS `' . $table . '`');
259 if (substr($line, 0, 2) != '--' && $line != '') {
260 $this->replaceInLine($line);
261 $templine .= $line;
262 if (substr(trim($line), -1, 1) == ';') {
263 if (!$mysqli->query($templine)) {
264 Logger::error('Error performing query ' . $templine . ': ' . $mysqli->error);
265 }
266 $templine = '';
267 $line = '';
268 }
269 }
270 }
271
272 fclose($handle);
273 } else {
274 Logger::error(__("Cannot open SQL file...", 'backup-backup'));
275 return __("Importing failed - Cannot open SQL file...", 'backup-backup');
276 }
277
278 $qyr = $mysqli->query('SET foreign_key_checks = 1');
279 $mysqli->query("SET NAMES 'utf8'");
280
281 // $mysqli->query("UPDATE `".$new_prefix."options` SET option_value = '" . $siteurl. "' WHERE option_name = 'siteurl'");
282 // $mysqli->query("UPDATE `".$new_prefix."options` SET option_value = '" . $home. "' WHERE option_name = 'home'");
283
284 $mysqli->close();
285 return __("Importing finished. Now, Delete the import file.", 'backup-backup');
286
287 }
288
289 }
290