Файловый менеджер - Редактировать - /home/lexlmvtu/public_html/wp-content/plugins/backup-backup/includes/database/better-backup-v3.php
Назад
<?php /** * Author: Mikołaj `iClyde` Chodorowski * Contact: kontakt@iclyde.pl * Package: Backup Migration – WP Plugin */ // Namespace namespace BMI\Plugin\Database; // Use use BMI\Plugin\BMI_Logger AS Logger; use BMI\Plugin\Progress\BMI_ZipProgress AS Progress; use BMI\Plugin\Dashboard AS Dashboard; use BMI\Plugin\Staging\BMI_Staging as Staging; // Exit on direct access if (!defined('ABSPATH')) exit; // echo "Memory usage at the beginning: " . (memory_get_usage() / 1024 / 1024) . " MB \n"; // function bmi_find_wordpress_base_path() { // // $dir = dirname(__FILE__); // $previous = null; // // do { // // if (file_exists($dir . '/wp-config.php')) return $dir; // if ($previous == $dir) break; // $previous = $dir; // // } while ($dir = dirname($dir)); // // return null; // // } // // define('BASE_PATH', bmi_find_wordpress_base_path() . '/'); // define('WP_USE_THEMES', false); // // // Use WP Globals and load WordPress // global $wp, $wp_query, $wp_the_query, $wp_rewrite, $wp_did_header; // require_once BASE_PATH . 'wp-load.php'; // echo "Memory usage after core load: " . (memory_get_usage() / 1024 / 1024) . " MB \n"; // ini_set('memory_limit', '2M'); /** * Database exporting * Main Class, requires $wpdb */ class BMI_Database_Exporter { /** * Private local variables */ private $total_tables = 0; private $recipes = []; private $tables_by_size = []; public $total_queries = 0; public $total_rows = 0; public $total_size = 0; public $files = []; public $wpdb; public $logger; public $storage; public $percentage; public $max_rows; public $max_query_size; public $table_prefix; public $init_start; /** * __construct - Initialization and logger resolver * * @return self */ function __construct($storage, &$logger, $batcher = false, $backupStart = false) { /** * WP Global Database variable */ global $wpdb; $this->wpdb = &$wpdb; /** * Logger of BMI core */ $this->logger = &$logger; /** * Storage directory */ // $this->storage = trailingslashit(__DIR__) . 'data'; $this->storage = $storage; /** * Percentage escape to replace * This way we know what the randomized string is */ $this->percentage = trim($this->wpdb->prepare('%s', '%'), "'"); /** * Max rows to pass each query */ $this->max_rows = BMI_DB_MAX_ROWS_PER_QUERY; /** * Max size in bytes of single query export/import */ $this->max_query_size = 1 * 1024 * 1024; $this->table_prefix = time(); if ($backupStart && $backupStart !== false && is_numeric($backupStart)) { $this->table_prefix = $backupStart; } $this->init_start = microtime(true); if ($batcher === false || $batcher === 0) { $this->logger->log("Memory usage after initialization: " . number_format(memory_get_usage() / 1024 / 1024, 2) . " MB", 'INFO'); } } /** * export - Export initializer * * @return filename/filenames */ public function export($batchingStep = false, $indexEnded = 0) { // Table names $this->get_table_names_and_sizes($batchingStep); if ($batchingStep === false || $batchingStep === 0) { $this->logger->log("Scan found $this->total_tables tables ($this->total_rows rows), estimated total size: $this->total_size MB.", 'INFO'); $this->logger->log("Memory usage after getting table names: " . number_format(memory_get_usage() / 1024 / 1024, 2) . " MB ", 'INFO'); } // Recipes if ($batchingStep === false || $batchingStep === 0) { $this->logger->log("Getting table recipes...", 'INFO'); $this->table_recipes(); $this->logger->log("Table recipes have been exported.", 'INFO'); $this->logger->log("Memory usage after loading recipes: " . number_format(memory_get_usage() / 1024 / 1024, 2) . " MB ", 'INFO'); } // Save Recipes if ($batchingStep === false || $batchingStep === 0) { $this->logger->log("Saving recipes...", 'INFO'); $this->save_recipes(); $this->logger->log("Recipes saved.", 'INFO'); $this->logger->log("Memory usage after recipe off-load: " . number_format(memory_get_usage() / 1024 / 1024, 2) . " MB", 'INFO'); } // Tables data if ($batchingStep === false || $batchingStep === 0) { $this->logger->log("Exporting table data...", 'INFO'); } $finishedAt = $this->get_tables_data($batchingStep, $indexEnded); if ($batchingStep === false || $finishedAt['dumpCompleted'] === true) { $this->logger->log("Table data exported.", 'INFO'); $this->logger->log("Memory usage after data export: " . number_format(memory_get_usage() / 1024 / 1024, 2) . " MB", 'INFO'); } if ($batchingStep === false) { $end = number_format(microtime(true) - $this->init_start, 4); $this->logger->log("Entire process took: $end s", 'INFO'); } return $finishedAt; } /** * getPrefixesOfStagingSitesTables - Gets database prefixes of staging sites * * @return {array} of prefixes (can be empty) */ private function getPrefixesOfStagingSitesTables() { global $table_prefix; require_once BMI_INCLUDES . '/staging/controller.php'; $staging = new Staging('..ajax..'); $stagingSites = $staging->getStagingSites(true); $prefixes = []; foreach ($stagingSites as $name => $data) { if (!isset($data['db_prefix'])) continue; if (!$data['db_prefix']) continue; if (trim(strtolower($data['db_prefix'])) == '') continue; if (trim(strtolower($data['db_prefix'])) == trim(strtolower($table_prefix))) continue; if (isset($data['db_prefix'])) $prefixes[] = $data['db_prefix']; } return $prefixes; } /** * checkIfTableIsPartOfStaging - Compares table prefix with staging site prefixes * * @return {bool} true/false */ private function checkIfTableIsPartOfStaging(&$stagingSitePrefixes, $table) { for ($i = 0; $i < sizeof($stagingSitePrefixes); ++$i) { $prefix = $stagingSitePrefixes[$i]; if (substr($table, 0, strlen($prefix)) == $prefix) return true; } return false; } /** * get_table_names_and_sizes - Gets table names and sizes * * @return {array} associative array table_name => [size => its size in MB, rows => rows count] */ private function get_table_names_and_sizes($batchingStep) { $tables = $this->wpdb->get_results('SHOW TABLES'); $shouldExcludeTables = Dashboard\bmi_get_config('BACKUP:DATABASE:EXCLUDE'); $stagingPrefixes = $this->getPrefixesOfStagingSitesTables(); $excludedTables = []; $excludedTables = Dashboard\bmi_get_config('BACKUP:DATABASE:EXCLUDE:LIST'); if (!is_array($excludedTables) || empty($excludedTables)) $excludedTables = []; foreach ($tables as $table_index => $table_object) { foreach ($table_object as $database_name => $table_name) { if (in_array($table_name, $excludedTables) && $shouldExcludeTables == 'true') { $str = __('Excluding %s table from backup (due to exclusion rules).', 'backup-backup'); $str = str_replace('%s', $table_name, $str); if ($batchingStep === false || intval($batchingStep) === 0) $this->logger->log($str, 'INFO'); continue; } if ($this->checkIfTableIsPartOfStaging($stagingPrefixes, $table_name)) { $str = __('Excluding %s table from backup (as it is part of staging site).', 'backup-backup'); $str = str_replace('%s', $table_name, $str); if ($batchingStep === false || intval($batchingStep) === 0) $this->logger->log($str, 'INFO'); continue; } $query = "SELECT table_name AS `table`, round(((data_length + index_length) / 1024 / 1024), 2) AS `size`, "; $query .= "(SELECT COUNT(*) FROM `$table_name`) AS `rows`"; $query .= "FROM information_schema.TABLES "; $query .= "WHERE table_schema = %s AND table_name = %s"; $results = $this->wpdb->get_results($this->wpdb->prepare($query, DB_NAME, $table_name)); if (!is_object($results[0])) { if ($batchingStep === false || intval($batchingStep) === 0) { $this->logger->log("Could not get info about: $table_name (#01)", 'WARN'); } continue; } $table_name_returned = trim($results[0]->table); if ($table_name != $table_name_returned || strlen(trim($table_name)) <= 0) { if ($batchingStep === false || intval($batchingStep) === 0) { $this->logger->log("Could not get info about: $table_name (#02)", 'WARN'); } continue; } $this->tables_by_size[$table_name_returned] = array( 'size' => floatval($results[0]->size), 'rows' => intval($results[0]->rows) ); $this->total_size += floatval($results[0]->size); $this->total_rows += intval($results[0]->rows); $this->total_tables++; } } return $this->tables_by_size; } /** * table_recipes - Gets CREATION recipe of each table * * @return {array} - Creation recipes for each table_name => recipe */ private function table_recipes() { foreach ($this->tables_by_size as $table_name => $table_object) { $query = "SHOW CREATE TABLE $table_name"; $result = $this->wpdb->get_results($query); foreach ($result as $index => $result_object) { foreach ($result_object as $column_name => $column_value) { if ($column_value == $table_name) continue; else { $column_value = str_replace("`" . $table_name . "`", "`" . $this->table_prefix . '_' . $table_name . "`", $column_value); $recipe = 'CREATE TABLE IF NOT EXISTS '; $recipe .= substr($column_value, 13); $recipe = str_replace("\n ", "", $recipe); $recipe = str_replace("\n", "", $recipe); $this->recipes[$table_name] = $recipe; } } } } return $this->recipes; } /** * save_recipes - Save recipes and off-load the memory * * @return {void} */ private function save_recipes() { $time_prefix = $this->table_prefix; foreach ($this->recipes as $table_name => $table_recipe) { $this->total_queries += 3; $recipe = "/* CUSTOM VARS START */\n"; $recipe .= "/* REAL_TABLE_NAME: `$table_name`; */\n"; $recipe .= "/* PRE_TABLE_NAME: `$time_prefix" . "_" . "$table_name`; */\n"; $recipe .= "/* CUSTOM VARS END */\n\n"; $recipe .= $table_recipe . ";\n"; $this->total_rows++; $location = $this->file_name($table_name); $file = fopen($location, 'w'); fwrite($file, $recipe); fclose($file); unset($file); $this->files[] = $location; unset($location); } unset($this->recipes); } private function getArraySize(&$a, $baseSize = 0) { $maxSize = $this->max_query_size; $totalSize = 0 + $baseSize; $i = 0; $reachedLimit = false; foreach ($a as $k => $v) { if (is_object($v) || is_array($v)) { $subSize = $this->getArraySize($v); $size = $subSize['size']; if (($totalSize + $size) > $maxSize && $totalSize != 0) { $reachedLimit = true; break; } else { $totalSize += $size; $i++; } } else if (strval($v)) { $totalSize += strlen($v); } } return [ 'size' => $totalSize, 'index' => $i, 'limit' => $reachedLimit ]; } /** * get_tables_data - Table data getter * * @return {int} Total rows count */ private function get_tables_data($batchingStep = false, $indexEnded = 0) { $finishedAt = 0; $currentTableIndex = 0; $dumpCompleted = true; foreach ($this->tables_by_size as $table_name => $table_object) { $emptyTable = false; $currentTableIndex = $currentTableIndex + 1; if ($batchingStep !== false) { if (intval($currentTableIndex - 1) !== intval($batchingStep)) { continue; } else { $dumpCompleted = false; } } $start_time = microtime(true); if ($batchingStep === false || intval($indexEnded) === 0) { $this->logger->log("Getting data of table: " . $table_name . " (" . $currentTableIndex . "/" . $this->total_tables . ", " . number_format($table_object['size'], 2) . " MB)", 'STEP'); } $rows = intval($table_object['rows']); $this->wpdb->query("SET foreign_key_checks = 0;"); $currentBufferSize = 0; $bufferResult = []; $i = 0; if ($batchingStep !== false) $i = $indexEnded; if (intval($table_object['rows']) > 0) { for (;$i < $rows;) { $query = $this->wpdb->prepare("SELECT * FROM `$table_name` LIMIT %d, $this->max_rows", $i); $result = $this->wpdb->get_results($query); $valuesSize = $this->getArraySize($result, $currentBufferSize); $rowsAmount = sizeof($result); $valuesBytesSize = $valuesSize['size'] - $currentBufferSize; $valuesMaxRow = $valuesSize['index']; $valuesLimit = $valuesSize['limit']; if ($valuesMaxRow < $rowsAmount && $valuesMaxRow != 0) $result = array_slice($result, 0, $valuesMaxRow); $i += $valuesMaxRow; $currentBufferSize += $valuesBytesSize; $finishedAt = $i; if ($valuesMaxRow != 0) $bufferResult = array_merge($bufferResult, $result); if ($currentBufferSize >= $this->max_query_size || $i >= $rows || $valuesLimit == true) { $currentBufferSize = 0; $this->save_data($bufferResult, $table_name); unset($bufferResult); $bufferResult = []; if ($batchingStep !== false) break; } unset($result); } $percentg = 100; if (intval($table_object['rows']) !== 0 && is_numeric(intval($table_object['rows']))) { $percentg = number_format(($i / intval($table_object['rows']) * 100), 2); } if ($i >= $rows && $batchingStep !== false) { $batchingStep = $batchingStep + 1; $finishedAt = 0; $this->logger->log("Milestone of table " . $table_name . ": " . $i . "/" . $table_object['rows'] . " rows (" . $percentg . "%, " . number_format((microtime(true) - $start_time), 5) . "s)", 'INFO'); $this->logger->log("Table export for: " . $table_name . " finished", 'SUCCESS'); } else if ($batchingStep !== false) { $this->logger->log("Milestone of table " . $table_name . ": " . $i . "/" . $table_object['rows'] . " rows (" . $percentg . "%, " . number_format((microtime(true) - $start_time), 5) . "s)", 'INFO'); } $this->wpdb->query("SET foreign_key_checks = 1;"); if ($batchingStep === false) { $this->logger->log("Table export for: " . $table_name . " finished (" . number_format((microtime(true) - $start_time), 5) . "s)", 'SUCCESS'); } unset($start_time); } else { $this->logger->log("Table " . $table_name . " is empty, saving only recipe.", 'INFO'); $emptyTable = true; if ($batchingStep !== false) { $batchingStep = $batchingStep + 1; $finishedAt = 0; } } if ($batchingStep !== false && $emptyTable === false) break; } return [ 'finishedQuery' => $finishedAt, 'batchingStep' => $batchingStep, 'dumpCompleted' => $dumpCompleted ]; } /** * save_data - Saves table data/row as query * * @param {wpdb object} &$result Database query result * @param {string} &$table_name Table name * @return {void} */ private function save_data(&$result, &$table_name) { $columns_schema_added = false; $file = fopen($this->file_name($table_name), 'a+'); $this->total_queries++; $query = "INSERT INTO `" . $this->table_prefix . "_" . $table_name . "` "; foreach ($result as $index => $result_object) { $data_in_order = array(); $format_in_order = array(); $columns_in_order = array(); foreach ($result_object as $column_name => $value) { $data_in_order[] = $value; $columns_in_order[] = "`$column_name`"; if (is_numeric($value)) { if (is_float($value + 0)) $format_in_order[] = '%f'; else $format_in_order[] = '%d'; } else if (gettype($value) == 'NULL') { $format_in_order[] = '%null'; } else $format_in_order[] = '%s'; } if ($columns_schema_added === false) { $query .= "(" . implode(', ', $columns_in_order) . ") VALUES ("; $columns_schema_added = true; } else { $query = "),("; } $columns = sizeof($columns_in_order); unset($columns_in_order); // $query .= "/* VALUES START */\n"; for ($i = 0; $i < $columns; ++$i) { if ($format_in_order[$i] == '%f') { $floatresult = floatval($data_in_order[$i]); if (!is_infinite($floatresult) && is_numeric($floatresult)) { $query .= $floatresult; } else { if (defined('PHP_FLOAT_MAX')) $query .= PHP_INT_MAX; else $query .= PHP_FLOAT_MAX; } } elseif ($format_in_order[$i] == '%d') { $intresult = intval($data_in_order[$i]); if (!is_infinite($intresult) && is_numeric($intresult)) { $query .= $intresult; } else { $query .= PHP_INT_MAX; } } elseif ($format_in_order[$i] == '%null') { $query .= 'NULL'; } else { $query .= $this->wpdb->prepare("%s", $data_in_order[$i]); $query = str_replace($this->percentage, '%', $query); } if ($i < ($columns - 1)) $query .= ","; } unset($data_in_order); unset($format_in_order); unset($columns_in_order); fwrite($file, $query); } // fwrite($file, ");\n/* QUERY END */\n\n"); fwrite($file, ");\n"); fclose($file); unset($file); } /** * file_name - Replaces table name to file name friendly format * * @param {string} $table_name Table name * @return {string} Friendly format for file */ private function file_name($table_name) { $friendly_name = preg_replace("/[^A-Za-z0-9_-]/", '', $table_name); $friendly_name = trailingslashit($this->storage) . $friendly_name . '.sql'; return $friendly_name; } }
| ver. 1.4 |
Github
|
.
| PHP 7.2.34 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка