FileMaster
Search
Toggle Dark Mode
Home
/
.
/
wp-content
/
plugins
/
backup-backup
/
includes
/
database
Edit File: search-replace.php
<?php /** * Modifications by: MikoĊaj `iClyde` Chodorowski * Modified by e-mail contact: kontakt@iclyde.pl * Package: Safe Search and Replace on Database with Serialized Data v2.0.1 * * Please contact above e-mail if you see any credits problem. */ // Namespace namespace BMI\Plugin\Database; // Use use BMI\Plugin\BMI_Logger AS Logger; use BMI\Plugin\Backup_Migration_Plugin as BMP; use BMI\Plugin\Progress\BMI_ZipProgress AS Progress; // Exit on direct access if (!defined('ABSPATH')) exit; /** * Database Search and Replace for Enginge v3 */ class BMI_Search_Replace_Engine { function __construct($tables, $currentPage = 0, $totalPages = 0, $isStaging = false) { $this->totalPages = $totalPages; $this->currentPage = $currentPage; $this->all_tables = $tables; $this->isStaging = $isStaging; } public function perform($search, $replace, $limitColumns = false) { return $this->search_replace($search, $replace, $this->all_tables, $limitColumns); } private function recursive_unserialize_replace($from = '', $to = '', $data = '', $serialised = false, $visited = []) { if (is_array($data) || is_object($data)) { if (in_array($data, $visited, true)) { return $data; } $visited[] = $data; } try { if (is_string($data) && is_serialized($data) && ($unserialized = @unserialize($data, ['allowed_classes' => ['stdClass']])) !== false) { $data = $this->recursive_unserialize_replace($from, $to, $unserialized, true); } else if (is_array($data)) { $_tmp = []; foreach ($data as $key => $value) { $_tmp[$key] = $this->recursive_unserialize_replace($from, $to, $value, false, $visited); } $data = $_tmp; unset($_tmp); } else if (is_object($data) && !is_a($data, '__PHP_Incomplete_Class')) { $tmp = $data; $props = get_object_vars($data); foreach ($props as $key => $value) { $tmp->$key = $this->recursive_unserialize_replace($from, $to, $value, false, $visited); } $data = $tmp; unset($tmp); } else if (is_string($data) && (null !== ($_tmp = json_decode($data, true))) && is_array($_tmp)) { foreach ($_tmp as $key => $value) { $_tmp[$key] = $this->recursive_unserialize_replace($from, $to, $value, false, $visited); } $data = json_encode($_tmp); unset($_tmp); } else if (is_string($data)) { $data = str_replace($from, $to, $data); } if ($serialised) return serialize($data); } catch (\Exception $error) {} catch (\Throwable $error) {} return $data; } private function search_replace($search = '', $replace = '', $tables = [], $limitColumns = false) { global $wpdb; $excluded_columns = ['id', 'ID']; $report = ['tables' => 0, 'rows' => 0, 'change' => 0, 'updates' => 0, 'currentPage' => 0, 'totalPages' => 0]; if ($this->currentPage !== 0 && is_numeric($this->currentPage)) { $report['currentPage'] = $this->currentPage; } if ($this->totalPages !== 0 && is_numeric($this->totalPages)) { $report['totalPages'] = $this->totalPages; } if (is_array($tables) && !empty($tables)) { $wpdb->show_errors(); foreach($tables as $table) { $report['tables']++; $columns = []; // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Identifier is safely escaped via escapeSQLIDentifier() $fields = $wpdb->get_results('DESCRIBE ' . BMP::escapeSQLIDentifier($table) . ';'); foreach ($fields as $index => $object) { $columns[$object->Field] = $object->Key == 'PRI' ? true : false; } $fieldsForWhereStmt = []; foreach ($fields as $index => $columnInfo) { $type = strtolower($columnInfo->Type); if (strpos($type, 'char') !== false || strpos($type, 'text') !== false) { $column = mysqli_real_escape_string($wpdb->dbh, $columnInfo->Field); if (!in_array($column, $fieldsForWhereStmt)) { $fieldsForWhereStmt[] = $column; } } } $whereStmt = ''; $totalColumns = sizeof($fieldsForWhereStmt); for ($i = 0; $i < $totalColumns; ++$i) { $column = $fieldsForWhereStmt[$i]; if ($i == 0) $whereStmt .= ' WHERE '; // if ($this->isStaging) { $whereStmt .= '(' . BMP::escapeSQLIDentifier($column) . ' LIKE ' . '"%' . esc_sql($search) . '%"'; $whereStmt .= ' AND ' . BMP::escapeSQLIDentifier($column) . ' NOT LIKE ' . '"%' . esc_sql($replace) . '%")'; // } else { // $whereStmt .= '`' . $column . '`' . ' LIKE ' . '"%' . mysqli_real_escape_string($wpdb->dbh, $search) . '%"'; // } if ($i != $totalColumns - 1) $whereStmt .= ' OR '; } if ($whereStmt === '') continue; $sql = 'SELECT COUNT(*) AS num FROM ' . BMP::escapeSQLIDentifier($table) . $whereStmt . ';'; // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Identifier and where clause are safely escaped $row_count = $wpdb->get_results($sql); $row_count = $row_count[0]->num; if ($row_count == 0) { $report['currentPage'] = $report['currentPage'] + 1; continue; } $page_size = BMI_MAX_SEARCH_REPLACE_PAGE; $pages = ceil($row_count / $page_size); $page = 0; if ($report['totalPages'] === 0) { $report['totalPages'] = $pages; } for ($page; $page < $pages; $page++) { $report['currentPage'] = $report['currentPage'] + 1; $current_row = 0; $start = $page * $page_size; $end = $start + $page_size; // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Identifier and where clause are safely escaped $data = $wpdb->get_results($wpdb->prepare('SELECT * FROM ' . BMP::escapeSQLIDentifier($table) . $whereStmt . ' LIMIT %d, %d;', $start, $page_size)); for ($i = 0; $i < sizeof($data); ++$i) { $row = $data[$i]; $report['rows']++; $current_row++; $update_sql = []; $where_sql = []; $upd = false; foreach ($columns as $column => $primary_key) { if ($limitColumns != false) { if (!in_array($column, $limitColumns)) continue; } if (in_array($column, $excluded_columns)) continue; if (!in_array($column, $fieldsForWhereStmt)) continue; $edited_data = $data_to_fix = $row->$column; $edited_data = $this->recursive_unserialize_replace($search, $replace, $data_to_fix); if ($edited_data != $data_to_fix) { $report['change']++; $update_sql[] = '' . BMP::escapeSQLIDentifier($column) . ' = "' . esc_sql($edited_data) . '"'; $upd = true; $where_sql[] = '' . BMP::escapeSQLIDentifier($column) . ' = "' . esc_sql($data_to_fix) . '"'; } } if ($upd && !empty($where_sql)) { // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Identifiers and values are safely escaped via escapeSQLIDentifier() and esc_sql() $wpdb->get_results($wpdb->prepare("UPDATE " . BMP::escapeSQLIDentifier($table) . " SET " . implode(', ', $update_sql) . " WHERE " . implode(' AND ', array_filter($where_sql)) . ";")); unset($sql); $report['updates']++; if ($wpdb->last_error !== '') { // error_log(strval($wpdb->last_query)); // error_log(strval($wpdb->last_result)); // error_log(strval($wpdb->last_error)); } } unset($row); } unset($data); return $report; } } } return $report; } }
Save
Back