PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.6.5
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.6.5
2.7.1 2.7.2 2.7.0 2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.12 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 All 141 releases
metasync / redirections / class-metasync-redirection-database.php

class-metasync-redirection-database.php in Search Atlas SEO – OTTO AI SEO Automation for WordPress 2.6.5, at redirections/class-metasync-redirection-database.php

370 lines 10.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * The database operations for the redirections.
5 *
6 * @since 1.0.0
7 * @package Metasync
8 * @subpackage Metasync/redirections
9 * @author Engineering Team <[email protected]>
10 */
11 if (!class_exists('Metasync_Redirection_Database')) {
12 class Metasync_Redirection_Database
13 {
14 public static $table_name = "metasync_redirections";
15
16 private function get_table_name()
17 {
18 global $wpdb;
19 return $wpdb->prefix . self::$table_name;
20 }
21
22 /**
23 * Ensure table structure is up to date
24 */
25 private function ensure_table_structure()
26 {
27 global $wpdb;
28 $table_name = $this->get_table_name();
29
30 // Check if table exists
31 if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_name)) != $table_name) {
32 // Table doesn't exist, run full migration
33 require_once dirname(__FILE__, 2) . '/database/class-db-migrations.php';
34 MetaSync_DBMigration::activation();
35 return;
36 }
37
38 // Check if required columns exist
39 $columns = $wpdb->get_col("DESCRIBE {$table_name}");
40
41 $required_columns = [
42 'pattern_type' => "ALTER TABLE {$table_name} ADD COLUMN pattern_type ENUM('exact', 'contain', 'start', 'end', 'regex') NOT NULL DEFAULT 'exact' AFTER status",
43 'regex_pattern' => "ALTER TABLE {$table_name} ADD COLUMN regex_pattern TEXT NULL AFTER pattern_type",
44 'description' => "ALTER TABLE {$table_name} ADD COLUMN description TEXT NULL AFTER regex_pattern",
45 'created_at' => "ALTER TABLE {$table_name} ADD COLUMN created_at DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER description",
46 'updated_at' => "ALTER TABLE {$table_name} ADD COLUMN updated_at DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER created_at",
47 'last_accessed_at' => "ALTER TABLE {$table_name} ADD COLUMN last_accessed_at DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER updated_at"
48 ];
49
50 foreach ($required_columns as $column => $sql) {
51 if (!in_array($column, $columns)) {
52 $wpdb->query($sql);
53 }
54 }
55
56 // Check and add indexes
57 $indexes = $wpdb->get_results("SHOW INDEX FROM {$table_name}");
58 $index_names = array_column($indexes, 'Key_name');
59
60 $required_indexes = [
61 'pattern_type' => "ALTER TABLE {$table_name} ADD KEY pattern_type (pattern_type)",
62 'created_at' => "ALTER TABLE {$table_name} ADD KEY created_at (created_at)",
63 'status_created' => "ALTER TABLE {$table_name} ADD KEY status_created (status, created_at)"
64 ];
65
66 foreach ($required_indexes as $index => $sql) {
67 if (!in_array($index, $index_names)) {
68 $wpdb->query($sql);
69 }
70 }
71
72 // Set default pattern_type for existing records
73 $wpdb->query("UPDATE {$table_name} SET pattern_type = 'exact' WHERE pattern_type IS NULL OR pattern_type = ''");
74 }
75
76 /**
77 * Manually trigger table structure update
78 * Can be called from admin or via AJAX if needed
79 */
80 public function force_table_update()
81 {
82 $this->ensure_table_structure();
83 return true;
84 }
85
86 public function getAllRecords()
87 {
88 global $wpdb;
89 $tableName = $this->get_table_name();
90 return $wpdb->get_results(" SELECT * FROM `$tableName` ");
91 }
92
93 public function getAllActiveRecords()
94 {
95 global $wpdb;
96 $tableName = $this->get_table_name();
97
98 // Check cache first
99 $cache_key = 'metasync_active_redirections';
100 $cached_redirections = wp_cache_get($cache_key, 'metasync');
101
102 if ($cached_redirections !== false) {
103 return $cached_redirections;
104 }
105
106 $redirections = $wpdb->get_results($wpdb->prepare("SELECT * FROM `$tableName` WHERE status = %s ORDER BY created_at DESC", 'active'));
107
108 // Cache for 1 hour
109 wp_cache_set($cache_key, $redirections, 'metasync', HOUR_IN_SECONDS);
110
111 return $redirections;
112 }
113
114 /**
115 * Find a single redirection by ID
116 * @param int $id The redirection ID
117 * @return object|null The redirection record or null if not found
118 */
119 public function find($id)
120 {
121 global $wpdb;
122 $tableName = $this->get_table_name();
123 return $wpdb->get_row($wpdb->prepare("SELECT * FROM `$tableName` WHERE id = %d", intval($id)));
124 }
125
126 /**
127 * Add a record.
128 * @param array $args Values to insert.
129 */
130 public function add($args)
131 {
132 global $wpdb;
133
134 // Ensure table structure is up to date
135 $this->ensure_table_structure();
136
137 $args = wp_parse_args(
138 $args,
139 [
140 'sources_from' => [],
141 'url_redirect_to' => site_url(),
142 'http_code' => 301,
143 'hits_count' => 0,
144 'status' => 'active',
145 'pattern_type' => 'exact',
146 'regex_pattern' => null,
147 'description' => '',
148 'created_at' => current_time('mysql'),
149 'updated_at' => current_time('mysql'),
150 ]
151 );
152
153 // Serialize sources_from if array (rest of codebase uses serialized format)
154 if ( is_array( $args['sources_from'] ) ) {
155 $sources = $args['sources_from'];
156 $args['sources_from'] = serialize( array_combine( array_values( $sources ), array_fill( 0, count( $sources ), 'exact' ) ) ?: [] );
157 }
158
159 $result = $wpdb->insert( $this->get_table_name(), $args );
160
161 // Clear cache after adding
162 $this->clear_cache();
163
164 return $result !== false ? (int) $wpdb->insert_id : false;
165 }
166
167 /**
168 * Update a record.
169 * @param array $args Values to update.
170 * @param string $id
171 */
172 public function update($args, $id)
173 {
174 global $wpdb;
175
176 // Ensure table structure is up to date
177 $this->ensure_table_structure();
178
179 $tableName = $this->get_table_name();
180 $row = $wpdb->get_row($wpdb->prepare("SELECT * FROM `$tableName` WHERE `id` = %s ", $id));
181 if (!$row) return;
182
183 $args['updated_at'] = current_time('mysql');
184 $wpdb->update($tableName, $args, ['id' => $id]);
185
186 // Clear cache after updating
187 $this->clear_cache();
188 }
189
190 /**
191 * Get total number of rows in the DB table).
192 */
193 public function get_count()
194 {
195 return count($this->getAllRecords());
196 }
197
198 /**
199 * Delete a redirection record.
200 */
201 public function delete($items)
202 {
203 global $wpdb;
204 $tableName = $this->get_table_name();
205 if (!is_array($items) || empty($items)) return;
206 $ids = implode(',', array_fill(0, count($items), '%d'));
207 $wpdb->query($wpdb->prepare(
208 "
209 DELETE FROM `$tableName`
210 WHERE `id` IN ($ids) ",
211 $items
212 ));
213
214 // Clear cache after deleting
215 $this->clear_cache();
216 }
217
218 /**
219 * activate a redirection record.
220 */
221 public function update_status($items, $status)
222 {
223 global $wpdb;
224 $tableName = $this->get_table_name();
225 if (!is_array($items) || empty($items)) return;
226 $ids = implode(', ', array_fill(0, count($items), '%d'));
227 $set_status = $wpdb->prepare(
228 "
229 UPDATE `$tableName`
230 SET `status` = %s, `updated_at` = %s",
231 $status,
232 current_time('mysql')
233 );
234 $where = $wpdb->prepare(
235 "
236 WHERE `id` IN ( $ids )",
237 $items
238 );
239 $query = "{$set_status}{$where}";
240 $wpdb->query($query);
241
242 // Clear cache after updating status
243 $this->clear_cache();
244 }
245
246 /**
247 * Update if URL is matched and hit.
248 * @param object $row Record to update.
249 */
250 public function update_counter($row)
251 {
252 global $wpdb;
253 $update_data = [
254 'last_accessed_at' => current_time('mysql'),
255 'hits_count' => absint($row->hits_count) + 1,
256 ];
257 $wpdb->update($this->get_table_name(), $update_data, ['id' => $row->id]);
258 }
259
260 /**
261 * Clear redirection cache
262 */
263 public function clear_cache()
264 {
265 wp_cache_delete('metasync_active_redirections', 'metasync');
266 }
267
268 /**
269 * Search redirections with filters
270 * @param array $filters Search filters
271 */
272 public function search_redirections($filters = [])
273 {
274 global $wpdb;
275 $tableName = $this->get_table_name();
276
277 $where_conditions = ['1=1'];
278 $where_values = [];
279
280 if (!empty($filters['search'])) {
281 $where_conditions[] = "(sources_from LIKE %s OR url_redirect_to LIKE %s OR description LIKE %s)";
282 $search_term = '%' . $wpdb->esc_like($filters['search']) . '%';
283 $where_values[] = $search_term;
284 $where_values[] = $search_term;
285 $where_values[] = $search_term;
286 }
287
288 if (!empty($filters['status'])) {
289 $where_conditions[] = "status = %s";
290 $where_values[] = $filters['status'];
291 }
292
293 if (!empty($filters['pattern_type'])) {
294 $where_conditions[] = "pattern_type = %s";
295 $where_values[] = $filters['pattern_type'];
296 }
297
298 if (!empty($filters['http_code'])) {
299 $where_conditions[] = "http_code = %d";
300 $where_values[] = intval($filters['http_code']);
301 }
302
303 $where_clause = implode(' AND ', $where_conditions);
304 $order_by = !empty($filters['order_by']) ? sanitize_sql_orderby($filters['order_by']) : 'created_at';
305 $order = !empty($filters['order']) && strtoupper($filters['order']) === 'ASC' ? 'ASC' : 'DESC';
306
307 // Add pagination support
308 $limit_clause = '';
309 if (isset($filters['per_page']) && isset($filters['offset'])) {
310 $limit_clause = " LIMIT %d OFFSET %d";
311 $where_values[] = intval($filters['per_page']);
312 $where_values[] = intval($filters['offset']);
313 }
314
315 $query = "SELECT * FROM `$tableName` WHERE $where_clause ORDER BY $order_by $order" . $limit_clause;
316
317 if (!empty($where_values)) {
318 return $wpdb->get_results($wpdb->prepare($query, $where_values));
319 } else {
320 return $wpdb->get_results($query);
321 }
322 }
323
324 /**
325 * Count total redirections with filters (for pagination)
326 * @param array $filters Search filters
327 */
328 public function count_redirections($filters = [])
329 {
330 global $wpdb;
331 $tableName = $this->get_table_name();
332
333 $where_conditions = ['1=1'];
334 $where_values = [];
335
336 if (!empty($filters['search'])) {
337 $where_conditions[] = "(sources_from LIKE %s OR url_redirect_to LIKE %s OR description LIKE %s)";
338 $search_term = '%' . $wpdb->esc_like($filters['search']) . '%';
339 $where_values[] = $search_term;
340 $where_values[] = $search_term;
341 $where_values[] = $search_term;
342 }
343
344 if (!empty($filters['status'])) {
345 $where_conditions[] = "status = %s";
346 $where_values[] = $filters['status'];
347 }
348
349 if (!empty($filters['pattern_type'])) {
350 $where_conditions[] = "pattern_type = %s";
351 $where_values[] = $filters['pattern_type'];
352 }
353
354 if (!empty($filters['http_code'])) {
355 $where_conditions[] = "http_code = %d";
356 $where_values[] = intval($filters['http_code']);
357 }
358
359 $where_clause = implode(' AND ', $where_conditions);
360 $query = "SELECT COUNT(*) FROM `$tableName` WHERE $where_clause";
361
362 if (!empty($where_values)) {
363 return $wpdb->get_var($wpdb->prepare($query, $where_values));
364 } else {
365 return $wpdb->get_var($query);
366 }
367 }
368 }
369 }
370