PluginProbe ʕ •ᴥ•ʔ
Backup Migration / 2.0.0
Backup Migration v2.0.0
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 / even-better-restore-v4.php
backup-backup / includes / database Last commit date
better-backup-v3.php 8 months ago better-backup.php 8 months ago better-restore.php 8 months ago even-better-restore-v3.php 8 months ago even-better-restore-v4.php 8 months ago manager.php 8 months ago search-replace.php 8 months ago smart-sort.php 8 months ago
even-better-restore-v4.php
945 lines
1 <?php
2
3 /**
4 * Author: Mikołaj `iClyde` Chodorowski
5 * Contact: kontakt@iclyde.pl
6 * Package: Backup Migration – WP Plugin
7 */
8
9 // Namespace
10 namespace BMI\Plugin\Database;
11
12 // Use
13 use BMI\Plugin\BMI_Logger AS Logger;
14 use BMI\Plugin\Backup_Migration_Plugin as BMP;
15 use BMI\Plugin\Progress\BMI_ZipProgress AS Progress;
16 use BMI\Plugin\Database\BMI_Search_Replace_Engine as BMISearchReplace;
17
18 // Exit on direct access
19 if (!defined('ABSPATH')) exit;
20
21 /**
22 * Database Restore Enginge v4
23 */
24 class BMI_Even_Better_Database_Restore {
25
26 // Unwanted tables
27 private $unwantedTables = [
28 'wfblockediplog',
29 'wfblocks7',
30 'wfcrawlers',
31 'wffilechanges',
32 'wffilemods',
33 'wfhits',
34 'wfhoover',
35 'wfissues',
36 'wfknownfilelist',
37 'wflivetraffichuman',
38 'wflocs',
39 'wflogins',
40 'wfnotifications',
41 'wfpendingissues',
42 'wfreversecache',
43 'wfsnipcache',
44 'wfstatus',
45 'wftrafficrate',
46 'actionscheduler_logs',
47 'slim_stats',
48 'woocommerce_sessions',
49 'yoast_indexable',
50 'slim_events',
51 'cerber_files',
52 'cerber_traffic',
53 'cerber_log',
54 'cerber_countries',
55 'cerber_blocks',
56 'cerber_acl',
57 'statistics_views',
58 'pcachewpr',
59 'statistics_visitor_relationships',
60 'statistics_visitor',
61 'statistics_visit',
62 'statistics_search',
63 'statistics_pages',
64 'icl_languages_translations',
65 'icl_string_pages',
66 'icl_string_translations',
67 'itsec_log',
68 'actionscheduler_actions',
69 'aepc_logs',
70 'WP_SEO_404_links',
71 'wp_seo_404_links',
72 'WP_SEO_Redirection_LOG'
73 ];
74
75 private $excludeSearchReplaceTables = [
76 'itsec_log'
77 ];
78
79 /**
80 * __construct - Make connection
81 *
82 * @return @self
83 */
84 function __construct($storage, $firstDB, &$manifest, &$logger, $splitting, $isCLI) {
85
86 $this->isCLI = $isCLI;
87 $this->splitting = $splitting;
88 $this->storage = $storage;
89 $this->logger = &$logger;
90 $this->manifest = &$manifest;
91 $this->tablemap = BMI_TMP . DIRECTORY_SEPARATOR . '.table_map';
92
93 if ($firstDB) $this->initMessage();
94
95 $this->map = $this->getTableMap();
96 $this->seek = &$this->map['seek'];
97
98 }
99
100 public function start() {
101
102 if ($this->isCLI) {
103
104 while ($nextFile = $this->getNextFile()) {
105 $this->processFile($nextFile);
106 }
107
108 return true;
109
110 } else {
111
112 $nextFile = $this->getNextFile();
113 if ($nextFile === false) return true;
114 else {
115
116 $this->processFile($nextFile);
117
118 return false;
119
120 }
121
122 }
123
124 }
125
126 private function getTableMap() {
127
128 if (file_exists($this->tablemap)) {
129
130 $data = json_decode(file_get_contents($this->tablemap), true);
131 $this->map = $data;
132
133 } else {
134
135 $data = [
136 'tables' => [],
137 'seek' => [
138 'last_seek' => 0,
139 'last_file' => '...',
140 'last_start' => 0,
141 'total_tables' => sizeof(array_diff(scandir($this->storage), ['..', '.'])),
142 'active_plugins' => 'a:1:{i:0;s:31:"backup-backup/backup-backup.php";}'
143 ]
144 ];
145
146 file_put_contents($this->tablemap, json_encode($data));
147
148 }
149
150 return $data;
151
152 }
153
154 private function getTableProgress() {
155
156 $total_tables = $this->seek['total_tables'];
157 $tables_left = sizeof(array_diff(scandir($this->storage), ['..', '.']));
158
159 $finished_tables = ($total_tables - $tables_left) + 1;
160 $percentage = number_format(($finished_tables / $total_tables) * 100, 2);
161
162 $this->logger->progress(50 + ((number_format($percentage, 0) / 2) - 10));
163
164 return $finished_tables . '/' . $total_tables . ' (' . $percentage . '%)';
165
166 }
167
168 private function queryFile(&$objFile, $filePath, $tableName, $realTableName) {
169
170 global $wpdb;
171
172 $seek = &$this->seek['last_seek'];
173 if ($seek == 0) {
174 $seek = 5;
175 $wpdb->query("DROP TABLE IF EXISTS `" . $tableName . "`;");
176
177 $str = __("Started restoration of %table_name% %total_tables% table", 'backup-backup');
178 $str = str_replace('%table_name%', $realTableName, $str);
179 $str = str_replace('%total_tables%', $this->getTableProgress(), $str);
180 $this->logger->log($str, 'STEP');
181
182 // Check if file can be cleaned
183 $this->filterFile($filePath, basename($filePath));
184 }
185
186 $wpdb->suppress_errors();
187
188 $wpdb->query('SET autocommit = 0;');
189 $wpdb->query('SET foreign_key_checks = 0;');
190 $wpdb->query("SET SQL_MODE = '';");
191 $wpdb->query('START TRANSACTION;');
192
193 $sql = '';
194 while (!$objFile->eof()) {
195 $objFile->seek($seek); $seek++;
196 $line = rtrim($objFile->current(), "\n");
197 if (strlen($line) !== 0) {
198 $sql = $line;
199 unset($line);
200 break;
201 }
202 }
203
204 $wpdb->query($sql);
205 unset($sql);
206 $wpdb->query('COMMIT;');
207 $wpdb->query('SET autocommit = 1;');
208 $wpdb->query('SET foreign_key_checks = 1;');
209
210 $str = __("Progress of %table_name%: %progress%", 'backup-backup');
211 $str = str_replace('%table_name%', $realTableName, $str);
212
213 $objFile->seek($objFile->getSize());
214 $total_size = $objFile->key() - 5;
215 $objFile->seek($seek);
216
217 if ($total_size <= 0) $total_size = 1;
218 if (($seek - 5) <= 0) $seek = 6;
219 if ($total_size > 0) $total_size += 1;
220
221 $progress = ($seek - 5) . '/' . $total_size . " (" . number_format(($seek - 5) / $total_size * 100, 2) . "%)";
222 $str = str_replace('%progress%', $progress, $str);
223 $this->logger->log($str, 'INFO');
224
225 $wpdb->show_errors();
226
227 if ($objFile->eof()) {
228 return true;
229 } else {
230 return false;
231 }
232
233 }
234
235 private function addNewTableToMap($from, $to, $file) {
236
237 if (!array_key_exists($from, $this->map['tables'])) {
238 $this->map['tables'][$from] = $to;
239 }
240
241 file_put_contents($this->tablemap, json_encode($this->map));
242
243 }
244
245 private function processFile($file) {
246
247 if ($this->seek['last_seek'] == 0) {
248 $this->seek['last_start'] = microtime(true);
249 }
250
251 $objFile = new \SplFileObject($file);
252
253 $objFile->seek(1);
254 $realTableName = explode('`', $objFile->current())[1];
255
256 $objFile->seek(2);
257 $tmpTableName = explode('`', $objFile->current())[1];
258
259 $finished = $this->queryFile($objFile, $file, $tmpTableName, $realTableName);
260
261 if ($finished && file_exists($file)) {
262 $this->seek['last_seek'] = 0;
263 $this->seek['last_file'] = '...';
264 @unlink($file);
265
266 $totalTime = microtime(true) - intval($this->seek['last_start']);
267 $totalTime = number_format($totalTime, 5);
268
269 $str = __("Table %table_name% restoration took %time% seconds", 'backup-backup');
270 $str = str_replace('%table_name%', $realTableName, $str);
271 $str = str_replace('%time%', $totalTime, $str);
272
273 $this->logger->log($str, 'SUCCESS');
274 $this->seek['last_start'] = 0;
275 }
276
277 $this->addNewTableToMap($tmpTableName, $realTableName, $file);
278
279 return true;
280
281 }
282
283 private function parseDomain($domain, $removeWWW = true) {
284
285 if (substr($domain, 0, 8) == 'https://') $domain = substr($domain, 8);
286 if (substr($domain, 0, 7) == 'http://') $domain = substr($domain, 7);
287 if ($removeWWW === true) {
288 if (substr($domain, 0, 4) == 'www.') $domain = substr($domain, 4);
289 }
290 $domain = untrailingslashit($domain);
291
292 return $domain;
293
294 }
295
296 private function replaceTableNames($tables) {
297
298 global $wpdb;
299
300 $this->logger->log(__('Performing table replacement', 'backup-backup'), 'STEP');
301
302 $wpdb->suppress_errors();
303 foreach ($tables as $oldTable => $newTable) {
304
305 $sql = "DROP TABLE IF EXISTS `" . $newTable . "`;";
306 $wpdb->query($sql);
307
308 $sql = "ALTER TABLE `" . $oldTable . "` RENAME TO `" . $newTable . "`;";
309 $wpdb->query($sql);
310
311 $str = __('Table %old% renamed to %new%', 'backup-backup');
312 $str = str_replace('%old%', $oldTable, $str);
313 $str = str_replace('%new%', $newTable, $str);
314 $this->logger->log($str, 'INFO');
315
316 }
317
318 $wpdb->show_errors();
319 $this->logger->log(__('All tables replaced', 'backup-backup'), 'SUCCESS');
320
321 }
322
323 private function performReplace($step = 0, $tableIndex = 0, $currentPage = 0, $totalPages = 0, $fieldAdjustments = 0, $newPrefix = "wp_") {
324
325 $status = [
326 'step' => $step,
327 'tableIndex' => $tableIndex,
328 'finished' => false,
329 'currentPage' => $currentPage,
330 'totalPages' => $totalPages,
331 'fieldAdjustments' => $fieldAdjustments
332 ];
333
334 require_once BMI_INCLUDES . DIRECTORY_SEPARATOR . 'database' . DIRECTORY_SEPARATOR . 'search-replace.php';
335
336 $backupRootDir = $this->manifest->config->ABSPATH;
337 $currentRootDir = ABSPATH;
338
339 $homeURL = site_url();
340 if (strlen($homeURL) <= 8) $homeURL = home_url();
341 if (defined('WP_SITEURL') && strlen(WP_SITEURL) > 8) $homeURL = WP_SITEURL;
342
343 $backupDomain = $this->parseDomain($this->manifest->dbdomain);
344 $currentDomain = $this->parseDomain($homeURL, false);
345
346 $currentTable = false;
347 $allTables = array_keys($this->map['tables']);
348
349 if ($tableIndex < sizeof($allTables) && array_key_exists($tableIndex, $allTables)) {
350 $currentTable = $allTables[$tableIndex];
351 }
352
353 if ($currentTable == false && !$currentTable) {
354 if ($backupRootDir != $currentRootDir || $currentDomain != $this->parseDomain($backupDomain, false)) {
355 $this->logger->log(__('Search & Replace finished successfully.', 'backup-backup'), 'SUCCESS');
356 }
357
358 $status['finished'] = true;
359 return $status;
360 }
361
362 if (strpos($currentTable, $newPrefix) === false) {
363 $this->logger->log(__('Adjustments are not required for this table.', 'backup-backup') . "(" . sanitize_text_field(strval($currentTable)) . ")", 'INFO');
364
365 $status['step'] = 1;
366 $status['fieldAdjustments'] = 0;
367 $status['tableIndex'] = $tableIndex + 1;
368 return $status;
369 }
370
371 if ($this->searchForIncludesInList($this->excludeSearchReplaceTables, $currentTable)) {
372 $this->logger->log(__('Adjustments are not required for this table.', 'backup-backup') . "(" . sanitize_text_field(strval($currentTable)) . ")", 'INFO');
373
374 $status['step'] = 1;
375 $status['fieldAdjustments'] = 0;
376 $status['tableIndex'] = $tableIndex + 1;
377 return $status;
378 }
379
380 $replaceEngine = new BMISearchReplace([$currentTable], $currentPage, $totalPages);
381
382 if ($step == 0) {
383 $ssl = is_ssl() == true ? 'https://' : 'http://';
384 $this->logger->log('Previous detected domain: ' . $backupDomain, 'VERBOSE');
385 $this->logger->log('Previous detected domain parsed: ' . $this->parseDomain($backupDomain, false), 'VERBOSE');
386 $this->logger->log('New detected domain: ' . $currentDomain, 'VERBOSE');
387 $this->logger->log('SSL: ' . $ssl, 'VERBOSE');
388
389 $this->logger->log('Previous ABSPATH: ' . $backupRootDir, 'VERBOSE');
390 $this->logger->log('New detected ABSPATH: ' . $currentRootDir, 'VERBOSE');
391
392 if ($backupRootDir != $currentRootDir || $currentDomain != $this->parseDomain($backupDomain, false)) {
393 $this->logger->log(__('Performing Search & Replace', 'backup-backup'), 'STEP');
394 $pagesize = '?';
395 if (defined('BMI_MAX_SEARCH_REPLACE_PAGE')) $pagesize = BMI_MAX_SEARCH_REPLACE_PAGE;
396 $this->logger->log(__('Page size for that restoration: ', 'backup-backup') . $pagesize, 'INFO');
397 $status['step'] = $step + 1; $step++;
398 } else {
399 $this->logger->log(__('This backup was made on the same site, ommiting search & replace.', 'backup-backup'), 'INFO');
400 $status['finished'] = true;
401 return $status;
402 }
403 }
404
405 if ($step == 1) {
406 $replaceProgress = ($tableIndex + 1) . "/" . sizeof($allTables);
407 $replaceProgressPercentage = number_format((($tableIndex + 1) / sizeof($allTables) * 100), 2);
408 $progressLogT = __('Performing database adjustments for table %progress%: %table_name% (%progress_percentage%)', 'backup-backup');
409 $progressLogT = str_replace('%progress%', $replaceProgress, $progressLogT);
410 $progressLogT = str_replace('%table_name%', $currentTable, $progressLogT);
411 $progressLogT = str_replace('%progress_percentage%', $replaceProgressPercentage . '%', $progressLogT);
412 $this->logger->log($progressLogT, 'STEP');
413
414 $percentageProgress = number_format($replaceProgressPercentage, 0);
415 $this->logger->progress(number_format(90 + ($percentageProgress / 100) * 8, 0));
416
417 if ($backupRootDir != $currentRootDir) {
418
419 $dtables = 0; $drows = 0; $dchange = 0; $dupdates = 0;
420
421 $r = $replaceEngine->perform($backupRootDir, $currentRootDir);
422 $dtables += $r['tables']; $drows += $r['rows']; $dchange += $r['change']; $dupdates += $r['updates'];
423
424 $status['currentPage'] = $r['currentPage'];
425 $status['totalPages'] = $r['totalPages'];
426
427 if ($status['totalPages'] > 0) {
428
429 $info = __("Batch for path adjustment (%page%/%allPages%) updated: %updates% fields.", 'backup-backup');
430 $updates = $dupdates;
431 if ($updates == 0) $updates = 1;
432 $info = str_replace('%page%', $status['currentPage'], $info);
433 $info = str_replace('%allPages%', $status['totalPages'], $info);
434 $info = str_replace('%updates%', $updates, $info);
435 $this->logger->log($info, 'INFO');
436 $status['fieldAdjustments']++;
437
438 }
439
440 if ($status['currentPage'] >= $status['totalPages']) {
441 $status['currentPage'] = 0;
442 $status['totalPages'] = 0;
443 $status['step'] = $step + 1;
444 }
445 return $status;
446
447 } else {
448
449 $status['step'] = $step + 1;
450 $step++;
451
452 }
453 }
454
455 if ($step == 2 || $step == 3 || $step == 4 || $step == 5 || $step == 6 || $step == 7) {
456 if ($currentDomain != $this->parseDomain($backupDomain, false)) {
457 $ssl = is_ssl() == true ? 'https://' : 'http://';
458
459 $dtables = 0; $drows = 0; $dchange = 0; $dupdates = 0;
460
461 $possibleDomainsBackup = [
462 "https://www." . $backupDomain,
463 "http://www." . $backupDomain,
464 "https://" . $backupDomain,
465 "http://" . $backupDomain,
466 'www.' . $backupDomain,
467 $backupDomain
468 ];
469
470 $possibleDomainsCurrent = [
471 $ssl . $currentDomain,
472 $ssl . $currentDomain,
473 $ssl . $currentDomain,
474 $ssl . $currentDomain,
475 $currentDomain,
476 $currentDomain
477 ];
478
479 if ($step == 2) {
480 $r = $replaceEngine->perform($possibleDomainsBackup[0], $possibleDomainsCurrent[0]);
481 $dtables += $r['tables']; $drows += $r['rows']; $dchange += $r['change']; $dupdates += $r['updates'];
482 }
483
484 if ($step == 3) {
485 $r = $replaceEngine->perform($possibleDomainsBackup[1], $possibleDomainsCurrent[1]);
486 $dtables += $r['tables']; $drows += $r['rows']; $dchange += $r['change']; $dupdates += $r['updates'];
487 }
488
489 if ($step == 4) {
490 $r = $replaceEngine->perform($possibleDomainsBackup[2], $possibleDomainsCurrent[2]);
491 $dtables += $r['tables']; $drows += $r['rows']; $dchange += $r['change']; $dupdates += $r['updates'];
492 }
493
494 if ($step == 5) {
495 $r = $replaceEngine->perform($possibleDomainsBackup[3], $possibleDomainsCurrent[3]);
496 $dtables += $r['tables']; $drows += $r['rows']; $dchange += $r['change']; $dupdates += $r['updates'];
497 }
498
499 if ($step == 6) {
500 $r = $replaceEngine->perform($possibleDomainsBackup[4], $possibleDomainsCurrent[4]);
501 $dchange += $r['change']; $dupdates += $r['updates'];
502 }
503
504 if ($step == 7) {
505 if (!(substr($currentDomain, -strlen($backupDomain)) === $backupDomain)) {
506 $r = $replaceEngine->perform($possibleDomainsBackup[5], $possibleDomainsCurrent[5]);
507 $dchange += $r['change']; $dupdates += $r['updates'];
508 }
509 }
510
511 $status['currentPage'] = $r['currentPage'];
512 $status['totalPages'] = $r['totalPages'];
513
514 $variants = [
515 __('variant A', 'backup-backup'),
516 __('variant B', 'backup-backup'),
517 __('variant C', 'backup-backup'),
518 __('variant D', 'backup-backup'),
519 __('variant E', 'backup-backup'),
520 __('variant F', 'backup-backup'),
521 ];
522
523 if ($status['totalPages'] > 0) {
524
525 $info = __("Batch for domain (%variant%) adjustments (%page%/%allPages%) updated: %updates% fields.", 'backup-backup');
526 $updates = $dupdates;
527 if ($updates == 0) $updates = 1;
528 $info = str_replace('%variant%', $variants[$step - 2], $info);
529 $info = str_replace('%page%', $status['currentPage'], $info);
530 $info = str_replace('%allPages%', $status['totalPages'], $info);
531 $info = str_replace('%updates%', $updates, $info);
532 $this->logger->log($info, 'INFO');
533 $status['fieldAdjustments']++;
534
535 } else {
536
537 // $info = __('Domain (%variant%) adjustments are not required for this table.', 'backup-backup');
538 // $info = str_replace('%variant%', $variants[$step - 2], $info);
539 // $this->logger->log($info, 'INFO');
540
541 }
542
543 if ($status['currentPage'] >= $status['totalPages']) {
544 $status['currentPage'] = 0;
545 $status['totalPages'] = 0;
546 $status['step'] = $step + 1;
547 }
548
549 return $status;
550
551 } else {
552
553 $status['currentPage'] = 0;
554 $status['totalPages'] = 0;
555 $status['step'] = 8;
556 $step = 8;
557
558 }
559 }
560
561 if ($step == 8) {
562 if ($fieldAdjustments === 0) {
563 $this->logger->log(__('Adjustments are not required for this table.', 'backup-backup'), 'INFO');
564 }
565
566 $status['step'] = 1;
567 $status['fieldAdjustments'] = 0;
568 $status['tableIndex'] = $tableIndex + 1;
569 return $status;
570 }
571
572 return $status;
573
574 }
575
576 public function searchForIncludesInList($items, $search) {
577 $search = strtolower($search);
578 foreach ($items as $index => $item) {
579 if (strpos($search, strtolower($item)) !== false) return true;
580 }
581
582 return false;
583 }
584
585 public function is_valid_plugin($plugin) {
586
587 global $wp_version;
588
589 $default_headers = array( 'wp' => 'Requires at least', 'php' => 'Requires PHP' );
590
591 $wp = false;
592 $php = false;
593
594 $detectedwp = '0.0.0';
595 $detectedphp = '0.0.0';
596
597 try {
598
599 $plugin_file = BMP::fixSlashes(WP_PLUGIN_DIR . '/' . $plugin);
600 $plugin_readme = BMP::fixSlashes(WP_PLUGIN_DIR . '/' . dirname($plugin) . '/readme.txt');
601 if (!file_exists($plugin_readme)) $plugin_readme = BMP::fixSlashes(WP_PLUGIN_DIR . '/' . dirname($plugin) . '/README.txt');
602
603 if (file_exists($plugin_file)) {
604 $plugin_data = get_file_data($plugin_file, $default_headers, 'plugin');
605 if (!empty($plugin_data['wp']) && version_compare($plugin_data['wp'], $wp_version, '<=')) {
606 $detectedwp = $plugin_data['wp'];
607 $wp = true;
608 }
609 if (!empty($plugin_data['php']) && version_compare($plugin_data['php'], PHP_VERSION, '<=')) {
610 $detectedphp = $plugin_data['php'];
611 $php = true;
612 }
613 }
614
615 if (file_exists($plugin_readme)) {
616 $readme_data = get_file_data($plugin_readme, $default_headers, 'plugin');
617 if (!empty($readme_data['wp']) && version_compare($readme_data['wp'], $wp_version, '<=')) {
618 $detectedwp = $readme_data['wp'];
619 $wp = true;
620 }
621
622 if (!empty($readme_data['php']) && version_compare($readme_data['php'], PHP_VERSION, '<=')) {
623 $detectedphp = $readme_data['php'];
624 $php = true;
625 }
626 }
627
628 $this->logger->log(sprintf('Detected version WP/PHP for plugin: %s, is (%s/%s)', $plugin, $detectedwp, $detectedphp), 'VERBOSE');
629
630 if ($plugin == 'hello.php') return true;
631 if ($php && $wp) return true;
632 else return false;
633
634 } catch (Error $e) {
635 return false;
636 }
637
638 return false;
639
640 }
641
642 private function try_activate_plugins($plugins, $sucstr_source, $failstr_source, $failed_plugins = []) {
643
644 $plugins_copy = array_values($plugins);
645 $should_continue = false;
646 $activated_plugins = [];
647 $failed_plugins = $failed_plugins;
648 $disallowed_plugins = [
649 'bluehost-wordpress-plugin/bluehost-wordpress-plugin.php',
650 'sg-cachepress/sg-cachepress.php',
651 'wordpress-starter/siteground-wizard.php',
652 'revslider/revslider.php',
653 'easy-soundcloud-shortcode/easy-soundcloud-shortcode.php',
654 'easy-soundcloud-shortcode/EasySoundcloudShortcode.php',
655 'mainwp-child/mainwp-child.php',
656 'wp-google-maps/wp-google-maps.php',
657 'wp-google-maps/wpGoogleMaps.php'
658 ];
659
660 for ($i = 0; $i < sizeof($plugins_copy); ++$i) {
661
662 $plugin_name = $plugins_copy[$i];
663 $plugin_display = $plugin_name;
664
665 $shouldActivate = true;
666
667 if (empty($plugin_name)) {
668 $shouldActivate = false;
669 $plugin_display = '(---)';
670 } else if ($plugin_name == 'hello.php') {
671 $shouldActivate = true;
672 } else if (strpos($plugin_name, '/') === false) {
673 $shouldActivate = false;
674 }
675
676 $sucstr = str_replace('%plugin_name%', $plugin_display, $sucstr_source);
677 $failstr = str_replace('%plugin_name%', $plugin_display, $failstr_source);
678
679 if ($shouldActivate) {
680 try {
681
682 if ($this->is_valid_plugin($plugin_name) && !in_array($plugin_name, $disallowed_plugins)) {
683
684 $resultWP = activate_plugin($plugin_name, '', true, true);
685
686 $this->logger->log($sucstr, 'INFO');
687 $activated_plugins[] = $plugin_name;
688
689 $should_continue = true;
690 break;
691
692 } else {
693
694 if (!in_array($plugin_name, $failed_plugins)) {
695 $failed_plugins[] = $plugin_name;
696 }
697
698 }
699
700 } catch (\Exception $e) {
701
702 if (!in_array($plugin_name, $failed_plugins)) {
703
704 $failed_plugins[] = $plugin_name;
705 error_log(strval($e));
706
707 }
708
709 } catch (\Throwable $e) {
710
711 if (!in_array($plugin_name, $failed_plugins)) {
712
713 $msg = $e->getMessage();
714 if (strpos($msg, 'add_rule()') != false || strpos($msg, 'rewrite.php:143') != false) {
715
716 $activated_plugins[] = $plugin_name;
717 error_log(strval($e));
718
719 } else {
720
721 $failed_plugins[] = $plugin_name;
722 error_log(strval($e));
723
724 }
725
726 }
727
728 }
729
730 } else {
731
732 $this->logger->log($failstr, 'WARN');
733
734 }
735
736 }
737
738 return [ 'failed' => $failed_plugins, 'active' => $activated_plugins, 'should_continue' => $should_continue ];
739
740 }
741
742 public function enablePlugins() {
743
744 global $wpdb;
745
746 $this->logger->log(__('Enabling plugins included in the backup', 'backup-backup'), 'STEP');
747
748 if (is_serialized($this->seek['active_plugins'])) {
749
750 $plugins = unserialize($this->seek['active_plugins']);
751 usort($plugins, function ($a, $b) { return strlen($a) - strlen($b); });
752 $plugins = array_values($plugins);
753
754 $sucstr_source = __('Plugin %plugin_name% enabled successfully.', 'backup-backup');
755 $failstr_source = __('Failed to enable plugin %plugin_name%, trying to not end at fatal error...', 'backup-backup');
756
757 $fullyActive = [];
758 $failed_plugins = [];
759
760 if (!function_exists('activate_plugin')) {
761 require_once(ABSPATH .'/wp-admin/includes/plugin.php');
762 }
763
764 $one_more_time = true;
765 $try_again = true;
766 while ($try_again) {
767
768 $res = $this->try_activate_plugins($plugins, $sucstr_source, $failstr_source, $failed_plugins);
769
770 $fullyActive = array_unique(array_merge($fullyActive, $res['active']));
771 $plugins = array_diff($plugins, $res['active']);
772 $failed_plugins = array_unique(array_diff(array_merge($failed_plugins, $res['failed']), $fullyActive));
773
774 $try_again = $res['should_continue'];
775 if ($try_again == false && $one_more_time == true) {
776 $one_more_time = false;
777 $try_again = true;
778 }
779
780 }
781
782 for ($i = 0; $i < sizeof($failed_plugins); ++$i) {
783
784 $failstr = str_replace('%plugin_name%', $failed_plugins[$i], $failstr_source);
785 $this->logger->log($failstr, 'WARN');
786
787 }
788
789 if (!in_array('backup-backup/backup-backup.php', $fullyActive)) {
790 $fullyActive[] = 'backup-backup/backup-backup.php';
791 }
792
793 update_option('active_plugins', $fullyActive);
794
795 }
796
797 $this->logger->progress(100);
798 $this->logger->log(__('All plugins enabled, you are ready to go :)', 'backup-backup'), 'SUCCESS');
799
800 }
801
802 public function searchReplace($step = 0, $tableIndex = 0, $currentPage = 0, $totalPages = 0, $fieldAdjustments = 0, $newPrefix = 'wp_') {
803
804 $this->logger->progress(90);
805 return $this->performReplace($step, $tableIndex, $currentPage, $totalPages, $fieldAdjustments, $newPrefix);
806
807 }
808
809 public function alter_tables() {
810
811 $this->logger->progress(98);
812 $this->prepareFinalDatabase();
813 $this->replaceTableNames($this->map['tables']);
814
815 }
816
817 private function prepareFinalDatabase() {
818
819 global $wpdb;
820
821 $tables = array_keys($this->map['tables']);
822 $unique_prefix = explode('_', $tables[0])[0];
823 $backupPrefix = $this->manifest->config->table_prefix;
824
825 $options_table = $unique_prefix . '_' . $backupPrefix . 'options';
826 if (!in_array($options_table, $tables)) {
827 $tablename = false;
828 for ($i = 0; $i < sizeof($tables); ++$i) {
829 $table = $tables[$i];
830 if (substr($table, -7) == 'options') {
831 $tablename = $table;
832 break;
833 }
834 }
835
836 $options_table = $tablename;
837 }
838
839 if ($options_table != false && in_array($options_table, $tables)) {
840
841 $sql = "DELETE FROM " . $options_table . " WHERE option_name LIKE ('%\_transient\_%')";
842 $wpdb->query($sql);
843
844 $active_plugins = $wpdb->get_results('SELECT option_value FROM `' . $options_table . '` WHERE option_name = "active_plugins"');
845 $active_plugins = $active_plugins[0]->option_value;
846
847 $this->seek['active_plugins'] = $active_plugins;
848
849 update_option('active_plugins', ['backup-backup/backup-backup.php']);
850
851 $homeURL = site_url();
852 if (strlen($homeURL) <= 8) $homeURL = home_url();
853 if (defined('WP_SITEURL') && strlen(WP_SITEURL) > 8) $homeURL = WP_SITEURL;
854
855 $ssl = is_ssl() == true ? 'https://' : 'http://';
856 $currentDomain = $ssl . $this->parseDomain($homeURL, false);
857
858 $sql = 'UPDATE ' . $options_table . ' SET option_value = %s WHERE option_name = "siteurl"';
859 $wpdb->query($wpdb->prepare($sql, $currentDomain));
860
861 $sql = 'UPDATE ' . $options_table . ' SET option_value = %s WHERE option_name = "home"';
862 $wpdb->query($wpdb->prepare($sql, $currentDomain));
863
864 }
865
866 }
867
868 private function filterFile($path, $name) {
869
870 $blacklist = $this->unwantedTables;
871 $tablename = strtolower(substr($name, 0, -4));
872
873 $shouldBeExcluded = false;
874 for ($i = 0; $i < sizeof($blacklist); ++$i) {
875
876 $rule = strtolower($blacklist[$i]);
877 if (substr($tablename, -(strlen($rule))) == $rule) {
878 $shouldBeExcluded = true;
879 break;
880 }
881
882 }
883
884 if ($shouldBeExcluded == true) {
885
886 $file = new \SplFileObject($path);
887 $file->seek($file->getSize());
888 $total_lines = $file->key() + 1;
889
890 if ($total_lines >= 6) {
891
892 $str = "\n\n\n\n\n";
893
894 $file->seek(5);
895 $str .= trim($file->current());
896
897 $this->logger->log(str_replace('%s', substr($name, 0, -4), __('Cleaning up contents of %s table.', 'backup-backup')), 'INFO');
898 file_put_contents($path, $str);
899
900 $file = null;
901
902 }
903
904 }
905
906 }
907
908 private function getNextFile() {
909
910 if ($this->seek['last_file'] == '...') {
911
912 $nextFile = false;
913
914 $sqlFiles = array_diff(scandir($this->storage), ['..', '.']);
915 $sqlFiles = array_values($sqlFiles);
916
917 if (sizeof($sqlFiles) > 0) {
918 $nextFilePath = $this->storage . DIRECTORY_SEPARATOR . $sqlFiles[0];
919 return $nextFilePath;
920 }
921
922 $this->seek['last_file'] = $nextFile;
923 return $nextFile;
924
925 } else {
926
927 return $this->seek['last_file'];
928
929 }
930
931 }
932
933 private function initMessage() {
934
935 $this->logger->log(__('Successfully detected backup created with v3 engine, importing...', 'backup-backup'), 'INFO');
936 $this->logger->log(__('Restoring database (using v4 engine)...', 'backup-backup'), 'STEP');
937
938 if (file_exists($this->tablemap)) {
939 @unlink($this->tablemap);
940 }
941
942 }
943
944 }
945