PluginProbe
Media Cloud Sync / 1.4.1
Media Cloud Sync v1.4.1
1.4.1 1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 All 35 releases
← All changes | includes/base/cache.php +126 -52 1.4.01.4.1 View file →
@@ -78,10 +78,14 @@
78 78
79 79 /**
80 80 * Build a consistent object cache key for get/set/delete.
81 81 */
82 - private static function build_cache_key($key, $post_id, $meta_name, $is_user_meta = false) {
83 - return ($is_user_meta ? 'user_' : '')
82 + private static function build_cache_key($key, $post_id, $meta_name, $meta_type = 'post') {
83 + $prefix = is_array($meta_type)
84 + ? (isset($meta_type['prefix']) ? $meta_type['prefix'] : 'custom')
85 + : $meta_type;
86 +
87 + return ('post' === $prefix ? '' : $prefix . '_')
84 88 . ($post_id == false ? '' : $post_id . '_')
85 89 . $meta_name
86 90 . (!Utils::is_empty($key) ? '_' . $key : '');
87 91 }
@@ -86,8 +90,89 @@
86 90 . (!Utils::is_empty($key) ? '_' . $key : '');
87 91 }
88 92
89 93 /**
94 + * Read the raw meta array for a given storage backend.
95 + *
96 + * $meta_type is 'post' (default) or 'user' for WP's own dedicated helpers
97 + * (options table when $post_id is false); a plain string is passed straight
98 + * to WP's generic get_metadata() — correct for any standard WP object type
99 + * whose meta table uses WP's usual 'meta_id' primary key (post/user/comment/
100 + * term). Third-party meta tables that don't follow that convention (e.g.
101 + * BuddyBoss's groupmeta, which uses 'id') aren't safe to read/write via
102 + * get_metadata() directly — pass an array of ['get'=>, 'update'=>, 'delete'=>]
103 + * callables (each shaped like get_post_meta($id,$key,true)/update_post_meta(
104 + * $id,$key,$value)/delete_post_meta($id,$key)) so the caller's own,
105 + * already-correct meta functions are used instead.
106 + */
107 + private static function read_meta($post_id, $meta_name, $meta_type) {
108 + if (is_array($meta_type)) {
109 + // Callability is already verified by is_backend_available() before
110 + // any of get/set/delete_object_cache() reach this point.
111 + return call_user_func($meta_type['get'], $post_id, $meta_name, true);
112 + }
113 + if ('post' === $meta_type) {
114 + return $post_id == false ? get_option($meta_name, []) : get_post_meta($post_id, $meta_name, true);
115 + }
116 + if ('user' === $meta_type) {
117 + return get_user_meta($post_id, $meta_name, true);
118 + }
119 + return get_metadata($meta_type, $post_id, $meta_name, true);
120 + }
121 +
122 + /**
123 + * Write the raw meta array for a given storage backend. See read_meta().
124 + */
125 + private static function write_meta($post_id, $meta_name, $meta_data, $meta_type) {
126 + if (is_array($meta_type)) {
127 + return call_user_func($meta_type['update'], $post_id, $meta_name, $meta_data);
128 + }
129 + if ('post' === $meta_type) {
130 + return $post_id == false ? update_option($meta_name, $meta_data) : update_post_meta($post_id, $meta_name, $meta_data);
131 + }
132 + if ('user' === $meta_type) {
133 + return update_user_meta($post_id, $meta_name, $meta_data);
134 + }
135 + return update_metadata($meta_type, $post_id, $meta_name, $meta_data);
136 + }
137 +
138 + /**
139 + * Whether $meta_type can actually be used right now. A custom backend's
140 + * callables may not be defined yet (e.g. the plugin/component that owns
141 + * them is currently inactive) — in that case the whole Cache layer must
142 + * be skipped entirely (no wp_cache_* writes either), so the caller falls
143 + * through to its own non-cached path exactly as it would for 'table' =>
144 + * false. Partially engaging the cache here (writing the intended value to
145 + * wp_cache_* while the real read/update/delete silently no-ops) would
146 + * leave a phantom entry that get/delete can never find to invalidate.
147 + */
148 + private static function is_backend_available($meta_type) {
149 + if (!is_array($meta_type)) {
150 + return true;
151 + }
152 + return isset($meta_type['get'], $meta_type['update'], $meta_type['delete'])
153 + && is_callable($meta_type['get'])
154 + && is_callable($meta_type['update'])
155 + && is_callable($meta_type['delete']);
156 + }
157 +
158 + /**
159 + * Delete the entire meta entry for a given storage backend. See read_meta().
160 + */
161 + private static function delete_meta_entirely($post_id, $meta_name, $meta_type) {
162 + if (is_array($meta_type)) {
163 + return call_user_func($meta_type['delete'], $post_id, $meta_name);
164 + }
165 + if ('post' === $meta_type) {
166 + return $post_id == false ? delete_option($meta_name) : delete_post_meta($post_id, $meta_name);
167 + }
168 + if ('user' === $meta_type) {
169 + return delete_user_meta($post_id, $meta_name);
170 + }
171 + return delete_metadata($meta_type, $post_id, $meta_name);
172 + }
173 +
174 + /**
90 175 * Whether the active object cache supports a feature (WP 6.1+ or drop-in).
91 176 */
92 177 private static function cache_supports($feature) {
93 178 return function_exists('wp_cache_supports') && wp_cache_supports($feature);
@@ -110,15 +195,15 @@
110 195
111 196 /**
112 197 * Write a value to the plugin object cache group.
113 198 */
114 - private static function sync_object_cache($key, $data, $post_id, $meta_name, $cache_expire, $is_user_meta = false) {
199 + private static function sync_object_cache($key, $data, $post_id, $meta_name, $cache_expire, $meta_type = 'post') {
115 200 if (!function_exists('wp_cache_set') || !function_exists('wp_cache_delete')) {
116 201 return;
117 202 }
118 203
119 204 $group = Schema::getConstant('CACHE_GROUP');
120 - $cache_key = self::build_cache_key($key, $post_id, $meta_name, $is_user_meta);
205 + $cache_key = self::build_cache_key($key, $post_id, $meta_name, $meta_type);
121 206
122 207 wp_cache_delete($cache_key, $group);
123 208 wp_cache_set($cache_key, $data, $group, $cache_expire);
124 209 }
@@ -124,13 +209,21 @@
124 209 }
125 210
126 211 /**
127 212 * Get Object Cache
213 + *
214 + * @param string $meta_type 'post' (default; uses options table when $post_id is false),
215 + * 'user', or any object type WP's generic get_metadata() recognizes
216 + * (e.g. 'group', registered by BuddyBoss).
128 217 */
129 - public static function get_object_cache($key = '', $post_id = false, $meta_name = false, $cache_expire = false, $is_user_meta = false) {
218 + public static function get_object_cache($key = '', $post_id = false, $meta_name = false, $cache_expire = false, $meta_type = 'post') {
219 + if (!self::is_backend_available($meta_type)) {
220 + return false;
221 + }
222 +
130 223 $meta_name = $meta_name == false ? Schema::getConstant('META_KEY') : $meta_name;
131 224 $cache_expire = $cache_expire == false ? Schema::getConstant('CACHE_EXPIRE') : $cache_expire;
132 - $cache_key = self::build_cache_key($key, $post_id, $meta_name, $is_user_meta);
225 + $cache_key = self::build_cache_key($key, $post_id, $meta_name, $meta_type);
133 226 $found = false;
134 227
135 228 $data = self::get_cached_value($cache_key, $found);
136 229 if ($found) {
@@ -136,14 +229,10 @@
136 229 if ($found) {
137 230 return $data;
138 231 }
139 232
140 - if ($is_user_meta) {
141 - $meta_data = get_user_meta($post_id, $meta_name, true);
142 - } else {
143 - $meta_data = $post_id == false ? get_option($meta_name, []) : get_post_meta($post_id, $meta_name, true);
144 - }
145 -
233 + $meta_data = self::read_meta($post_id, $meta_name, $meta_type);
234 +
146 235 if( !Utils::is_empty($key) && is_array($meta_data) && array_key_exists($key, $meta_data) ) {
147 236 // If key exists in meta data, return it
148 237 $data = $meta_data[$key];
149 238 } elseif (is_array($meta_data) && Utils::is_empty($key)) {
@@ -153,9 +242,9 @@
153 242 // If key does not exist, return false
154 243 $data = false;
155 244 }
156 245
157 - self::sync_object_cache($key, $data, $post_id, $meta_name, $cache_expire, $is_user_meta);
246 + self::sync_object_cache($key, $data, $post_id, $meta_name, $cache_expire, $meta_type);
158 247
159 248 return $data;
160 249 }
161 250
@@ -161,17 +250,17 @@
161 250
162 251 /**
163 252 * Set Object Cache
164 253 */
165 - public static function set_object_cache($key, $data, $post_id = false, $meta_name = false, $cache_expire = false, $is_user_meta = false) {
254 + public static function set_object_cache($key, $data, $post_id = false, $meta_name = false, $cache_expire = false, $meta_type = 'post') {
255 + if (!self::is_backend_available($meta_type)) {
256 + return false;
257 + }
258 +
166 259 $meta_name = $meta_name == false ? Schema::getConstant('META_KEY') : $meta_name;
167 260 $cache_expire = $cache_expire == false ? Schema::getConstant('CACHE_EXPIRE') : $cache_expire;
168 261
169 - if( $is_user_meta) {
170 - $meta_data = get_user_meta($post_id, $meta_name, true);
171 - } else {
172 - $meta_data = $post_id == false ? get_option($meta_name, []) : get_post_meta($post_id, $meta_name, true);
173 - }
262 + $meta_data = self::read_meta($post_id, $meta_name, $meta_type);
174 263
175 264 // If data is not an array, convert it to an array
176 265 if (!is_array($meta_data)) {
177 266 $meta_data = [];
@@ -186,16 +275,12 @@
186 275 $cache_value = $data;
187 276 }
188 277
189 278 // Update the meta data
190 - if ($is_user_meta) {
191 - $update_result = update_user_meta($post_id, $meta_name, $meta_data);
192 - } else {
193 - $update_result = $post_id == false ? update_option($meta_name, $meta_data) : update_post_meta($post_id, $meta_name, $meta_data);
194 - }
279 + $update_result = self::write_meta($post_id, $meta_name, $meta_data, $meta_type);
195 280
196 281 // Always sync object cache so Redis and default WP cache stay current.
197 - self::sync_object_cache($key, $cache_value, $post_id, $meta_name, $cache_expire, $is_user_meta);
282 + self::sync_object_cache($key, $cache_value, $post_id, $meta_name, $cache_expire, $meta_type);
198 283
199 284 if ($update_result) {
200 285 return true;
201 286 }
@@ -200,49 +285,38 @@
200 285 return true;
201 286 }
202 287
203 288 // update_option/update_meta return false when the value is unchanged — treat as success once cache is synced.
204 - if ($is_user_meta) {
205 - $stored = get_user_meta($post_id, $meta_name, true);
206 - } else {
207 - $stored = $post_id == false ? get_option($meta_name, []) : get_post_meta($post_id, $meta_name, true);
208 - }
289 + $stored = self::read_meta($post_id, $meta_name, $meta_type);
209 290
210 291 return maybe_serialize($stored) === maybe_serialize($meta_data);
211 292 }
212 293
213 -
214 294
295 +
215 296 /**
216 297 * Delete object cache
217 298 */
218 - public static function delete_object_cache($key = false, $post_id = false, $meta_name = false, $is_user_meta = false) {
299 + public static function delete_object_cache($key = false, $post_id = false, $meta_name = false, $meta_type = 'post') {
300 + if (!self::is_backend_available($meta_type)) {
301 + return false;
302 + }
303 +
219 304 $meta_name = $meta_name == false ? Schema::getConstant('META_KEY') : $meta_name;
220 305 $update_result = false;
221 - if ($is_user_meta) {
222 - $meta_data = get_user_meta($post_id, $meta_name, true);
223 - if (is_array($meta_data) && array_key_exists($key, $meta_data)) {
224 - unset($meta_data[$key]);
225 - if (empty($meta_data)) {
226 - $update_result = delete_user_meta($post_id, $meta_name);
227 - } else {
228 - $update_result = update_user_meta($post_id, $meta_name, $meta_data);
229 - }
306 +
307 + $meta_data = self::read_meta($post_id, $meta_name, $meta_type);
308 + if (is_array($meta_data) && array_key_exists($key, $meta_data)) {
309 + unset($meta_data[$key]);
310 + if (empty($meta_data)) {
311 + $update_result = self::delete_meta_entirely($post_id, $meta_name, $meta_type);
312 + } else {
313 + $update_result = self::write_meta($post_id, $meta_name, $meta_data, $meta_type);
230 314 }
231 - } else {
232 - $meta_data = $post_id == false ? get_option($meta_name, []) : get_post_meta($post_id, $meta_name, true);
233 - if (is_array($meta_data) && array_key_exists($key, $meta_data)) {
234 - unset($meta_data[$key]);
235 - if (empty($meta_data)) {
236 - $update_result = $post_id == false ? delete_option($meta_name) : delete_post_meta($post_id, $meta_name);
237 - } else {
238 - $update_result = $post_id == false ? update_option($meta_name, $meta_data) : update_post_meta($post_id, $meta_name, $meta_data);
239 - }
240 - }
241 315 }
242 316
243 317 if ($update_result && !Utils::is_empty($key) && function_exists('wp_cache_delete')) {
244 - $cache_key = self::build_cache_key($key, $post_id, $meta_name, $is_user_meta);
318 + $cache_key = self::build_cache_key($key, $post_id, $meta_name, $meta_type);
245 319 wp_cache_delete($cache_key, Schema::getConstant('CACHE_GROUP'));
246 320 }
247 321
248 322 return $update_result;