forked from oceanbase/ecology-plugins
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoceanbase-compatibility.php
More file actions
134 lines (115 loc) · 5.61 KB
/
oceanbase-compatibility.php
File metadata and controls
134 lines (115 loc) · 5.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<?php
/*
* Plugin Name: OceanBase Compatibility
* Plugin URI: https://github.com/oceanbase/ecology-plugins/tree/main/wordpress-oceanbase-plugin
* Description: Intercepts and modifies specific SQL DELETE queries targeting wp_options and wp_sitemeta.
* Version: 1.0.1
* Requires at least: 6.1
* Requires PHP: 7.2
* Author: sc-source
* Author URI: https://github.com/sc-source
* License: Apache License Version 2.0
* License URI: http://www.apache.org/licenses/LICENSE-2.0
* Text Domain: oceanbase-compatibility
*/
if (!defined('ABSPATH')) {
exit;
}
class OceanBase_Delete_Expired_Transients {
public function __construct() {
add_filter('query', array($this, 'modify_delete_expired_transients'));
}
private function build_delete_query($original_query, $results) {
global $wpdb;
$ids_to_delete = [];
foreach ($results as $row) {
$ids_to_delete[] = intval($row['a_id']);
$ids_to_delete[] = intval($row['b_id']);
}
if (!empty($ids_to_delete)) {
$placeholders = implode(',', array_fill(0, count($ids_to_delete), '%d'));
$table = (strpos($original_query, $wpdb->options) !== false) ? $wpdb->options : $wpdb->sitemeta;
$column = (strpos($original_query, $wpdb->options) !== false) ? "option_id" : "meta_id";
return $wpdb->prepare(
"DELETE FROM $table WHERE $column IN ($placeholders)",
$ids_to_delete
);
}
return '';
}
public function modify_delete_expired_transients($query) {
global $wpdb;
$regex_options = '/^DELETE\s+\w+,\s+\w+\s+FROM\s+' . preg_quote($wpdb->options, '/') . '\s+(\w+),\s+' . preg_quote($wpdb->options, '/') . '\s+(\w+)\s+WHERE\s+' .
'.*?a\.option_name\s+LIKE\s+\'(.+?)\'.*?' .
'.*?AND\s+a\.option_name\s+NOT\s+LIKE\s+\'(.+?)\'.*?' .
'.*?AND\s+b\.option_value\s*<\s*(\d+)\s*$/is';
$regex_sitemeta = '';
if (is_string($wpdb->sitemeta)) {
$regex_sitemeta = '/^DELETE\s+\w+,\s+\w+\s+FROM\s+' . preg_quote($wpdb->sitemeta, '/') . '\s+(\w+),\s+' . preg_quote($wpdb->sitemeta, '/') . '\s+(\w+)\s+WHERE\s+' .
'.*?a\.meta_key\s+LIKE\s+\'(.+?)\'.*?' .
'.*?AND\s+a\.meta_key\s+NOT\s+LIKE\s+\'(.+?)\'.*?' .
'.*?AND\s+b\.meta_value\s*<\s*(\d+)\s*$/is';
}
if ($regex_sitemeta && preg_match($regex_sitemeta, $query, $matches)) {
if (!isset($matches[3], $matches[4], $matches[5])) {
return $query;
}
$like_pattern = stripslashes($matches[3]);
$not_like_pattern = stripslashes($matches[4]);
$timeout_value = intval($matches[5]);
$clean_pattern = str_replace('\\', '', $like_pattern);
if (strpos($clean_pattern, needle: '_site_transient_') !== false) {
$prepared_query = $wpdb->prepare(
"SELECT a.meta_id AS a_id, b.meta_id AS b_id
FROM {$wpdb->sitemeta} a, {$wpdb->sitemeta} b
WHERE a.meta_key LIKE %s
AND a.meta_key NOT LIKE %s
AND b.meta_key = CONCAT('_site_transient_timeout_', SUBSTRING(a.meta_key, 17))
AND b.meta_value < %d",
$like_pattern, $not_like_pattern, $timeout_value
);
}else{
return $query;
}
$results = $wpdb->get_results($prepared_query, ARRAY_A);
return $this->build_delete_query($query, $results);
}
if (preg_match($regex_options, $query, $matches)) {
if (!isset($matches[3], $matches[4], $matches[5])) {
return $query;
}
$like_pattern = stripslashes($matches[3]);
$not_like_pattern = stripslashes($matches[4]);
$timeout_value = intval($matches[5]);
$clean_pattern = str_replace('\\', '', $like_pattern);
if (strpos($clean_pattern, needle: '_site_transient_') !== false) {
$prepared_query = $wpdb->prepare(
"SELECT a.option_id AS a_id, b.option_id AS b_id
FROM {$wpdb->options} a, {$wpdb->options} b
WHERE a.option_name LIKE %s
AND a.option_name NOT LIKE %s
AND b.option_name = CONCAT('_site_transient_timeout_', SUBSTRING(a.option_name, 17))
AND b.option_value < %d",
$like_pattern, $not_like_pattern, $timeout_value
);
}elseif (strpos($clean_pattern, needle: '_transient_') !== false) {
$prepared_query = $wpdb->prepare(
"SELECT a.option_id AS a_id, b.option_id AS b_id
FROM {$wpdb->options} a, {$wpdb->options} b
WHERE a.option_name LIKE %s
AND a.option_name NOT LIKE %s
AND b.option_name = CONCAT('_transient_timeout_', SUBSTRING(a.option_name, 12))
AND b.option_value < %d",
$like_pattern, $not_like_pattern, $timeout_value
);
} else {
return $query;
}
$results = $wpdb->get_results($prepared_query, ARRAY_A);
return $this->build_delete_query($query, $results);
}
return $query;
}
}
// Initialize the plugin
new OceanBase_Delete_Expired_Transients();