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 / search-replace.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
search-replace.php
214 lines
1 <?php
2
3 /**
4 * Modifications by: Mikołaj `iClyde` Chodorowski
5 * Modified by e-mail contact: kontakt@iclyde.pl
6 * Package: Safe Search and Replace on Database with Serialized Data v2.0.1
7 *
8 * Please contact above e-mail if you see any credits problem.
9 */
10
11 // Namespace
12 namespace BMI\Plugin\Database;
13
14 // Use
15 use BMI\Plugin\BMI_Logger AS Logger;
16 use BMI\Plugin\Backup_Migration_Plugin as BMP;
17 use BMI\Plugin\Progress\BMI_ZipProgress AS Progress;
18
19 // Exit on direct access
20 if (!defined('ABSPATH')) exit;
21
22 /**
23 * Database Search and Replace for Enginge v3
24 */
25 class BMI_Search_Replace_Engine {
26
27 function __construct($tables, $currentPage = 0, $totalPages = 0, $isStaging = false) {
28
29 $this->totalPages = $totalPages;
30 $this->currentPage = $currentPage;
31 $this->all_tables = $tables;
32 $this->isStaging = $isStaging;
33
34 }
35
36 public function perform($search, $replace, $limitColumns = false) {
37
38 return $this->search_replace($search, $replace, $this->all_tables, $limitColumns);
39
40 }
41
42 private function recursive_unserialize_replace($from = '', $to = '', $data = '', $serialised = false) {
43
44 try {
45
46 if (is_string($data) && is_serialized($data) && ($unserialized = @maybe_unserialize($data)) !== false) {
47
48 $data = $this->recursive_unserialize_replace($from, $to, $unserialized, true);
49
50 } else if (is_array($data)) {
51
52 $_tmp = [];
53 foreach ($data as $key => $value) {
54 $_tmp[$key] = $this->recursive_unserialize_replace($from, $to, $value, false);
55 }
56
57 $data = $_tmp;
58 unset($_tmp);
59
60 } else if (is_string($data)) $data = str_replace($from, $to, $data);
61
62 if ($serialised) return serialize($data);
63
64 }
65 catch (\Exception $error) {}
66 catch (\Throwable $error) {}
67
68 return $data;
69
70 }
71
72 private function search_replace($search = '', $replace = '', $tables = [], $limitColumns = false) {
73
74 global $wpdb;
75
76 $excluded_columns = ['id', 'ID'];
77 $report = ['tables' => 0, 'rows' => 0, 'change' => 0, 'updates' => 0, 'currentPage' => 0, 'totalPages' => 0];
78
79 if ($this->currentPage !== 0 && is_numeric($this->currentPage)) {
80 $report['currentPage'] = $this->currentPage;
81 }
82
83 if ($this->totalPages !== 0 && is_numeric($this->totalPages)) {
84 $report['totalPages'] = $this->totalPages;
85 }
86
87 if (is_array($tables) && !empty($tables)) {
88
89 $wpdb->show_errors();
90
91 foreach($tables as $table) {
92
93 $report['tables']++;
94 $columns = [];
95
96 $fields = $wpdb->get_results('DESCRIBE ' . $table);
97 foreach ($fields as $index => $object) {
98 $columns[$object->Field] = $object->Key == 'PRI' ? true : false;
99 }
100
101 $fieldsForWhereStmt = [];
102
103 foreach ($fields as $index => $columnInfo) {
104 $type = strtolower($columnInfo->Type);
105 if (strpos($type, 'char') !== false || strpos($type, 'text') !== false) {
106 $column = mysqli_real_escape_string($wpdb->dbh, $columnInfo->Field);
107 if (!in_array($column, $fieldsForWhereStmt)) {
108 $fieldsForWhereStmt[] = $column;
109 }
110 }
111 }
112
113 $whereStmt = '';
114 $totalColumns = sizeof($fieldsForWhereStmt);
115 for ($i = 0; $i < $totalColumns; ++$i) {
116 $column = $fieldsForWhereStmt[$i];
117 if ($i == 0) $whereStmt .= ' WHERE ';
118 // if ($this->isStaging) {
119 $whereStmt .= '(`' . $column . '`' . ' LIKE ' . '"%' . mysqli_real_escape_string($wpdb->dbh, $search) . '%"';
120 $whereStmt .= ' AND `' . $column . '`' . ' NOT LIKE ' . '"%' . mysqli_real_escape_string($wpdb->dbh, $replace) . '%")';
121 // } else {
122 // $whereStmt .= '`' . $column . '`' . ' LIKE ' . '"%' . mysqli_real_escape_string($wpdb->dbh, $search) . '%"';
123 // }
124 if ($i != $totalColumns - 1) $whereStmt .= ' OR ';
125 }
126
127 if ($whereStmt === '') continue;
128 $row_count = $wpdb->get_results('SELECT COUNT(*) AS num FROM `' . $table . '`' . $whereStmt);
129 $row_count = $row_count[0]->num;
130 if ($row_count == 0) {
131 $report['currentPage'] = $report['currentPage'] + 1;
132 continue;
133 }
134
135 $page_size = BMI_MAX_SEARCH_REPLACE_PAGE;
136 $pages = ceil($row_count / $page_size);
137 $page = 0;
138
139 if ($report['totalPages'] === 0) {
140 $report['totalPages'] = $pages;
141 }
142
143 for ($page; $page < $pages; $page++) {
144
145 $report['currentPage'] = $report['currentPage'] + 1;
146
147 $current_row = 0;
148 $start = $page * $page_size;
149 $end = $start + $page_size;
150
151 $data = $wpdb->get_results(sprintf('SELECT * FROM %s%s LIMIT %d, %d', $table, $whereStmt, $start, $end));
152 for ($i = 0; $i < sizeof($data); ++$i) {
153
154 $row = $data[$i];
155 $report['rows']++;
156 $current_row++;
157
158 $update_sql = [];
159 $where_sql = [];
160 $upd = false;
161
162 foreach ($columns as $column => $primary_key) {
163
164 if ($limitColumns != false) {
165 if (!in_array($column, $limitColumns)) continue;
166 }
167 if (in_array($column, $excluded_columns)) continue;
168 if (!in_array($column, $fieldsForWhereStmt)) continue;
169
170 $edited_data = $data_to_fix = $row->$column;
171 $edited_data = $this->recursive_unserialize_replace($search, $replace, $data_to_fix);
172
173 if ($edited_data != $data_to_fix) {
174 $report['change']++;
175 $update_sql[] = '`' . $column . '`' . ' = "' . mysqli_real_escape_string($wpdb->dbh, $edited_data) . '"';
176 $upd = true;
177 $where_sql[] = '`' . $column . '`' . ' = "' . mysqli_real_escape_string($wpdb->dbh, $data_to_fix) . '"';
178 }
179
180 }
181
182 if ($upd && !empty($where_sql)) {
183 $sql = 'UPDATE ' . $table . ' SET ' . implode(', ', $update_sql) . ' WHERE ' . implode(' AND ', array_filter($where_sql));
184 $results = $wpdb->get_results($sql);
185
186 unset($sql);
187
188 $report['updates']++;
189
190 if ($wpdb->last_error !== '') {
191 // error_log(strval($wpdb->last_query));
192 // error_log(strval($wpdb->last_result));
193 // error_log(strval($wpdb->last_error));
194 }
195 }
196
197 unset($row);
198
199 }
200
201 unset($data);
202 return $report;
203
204 }
205
206 }
207
208 }
209
210 return $report;
211 }
212
213 }
214