PluginProbe
UpdraftCentral Dashboard / 0.8.0
UpdraftCentral Dashboard v0.8.0
0.8.33 0.7.2 0.7.3 0.7.4 0.8.0 0.8.1 0.8.10 0.8.11 0.8.12 0.8.13 0.8.14 0.8.15 0.8.16 0.8.17 0.8.18 0.8.19 0.8.2 0.8.20 0.8.21 0.8.22 0.8.23 0.8.24 0.8.25 0.8.26 0.8.27 All 51 releases
updraftcentral / classes / site-meta.php

site-meta.php in UpdraftCentral Dashboard 0.8.0, at classes/site-meta.php

1,164 lines 36.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // @codingStandardsIgnoreFile
3 if (!defined('UD_CENTRAL_DIR')) die('Security check');
4
5 /**
6 * Largely from wp-includes/meta.php and wp-includes/user.php
7 *
8 * Firstly is our constructor, which accepts + stores the table prefix.
9 * Next come the methods for accessing meta data.
10 * Next comes the WP infrastructure, which only required very minor modifications (mostly, removing the table name check and calling $this->function instead of functions directly
11 */
12 class UpdraftCentral_Site_Meta {
13 private $_uc_table_prefix;
14
15 public function __construct($table_prefix) {
16 $this->_uc_table_prefix = $table_prefix;
17 }
18
19 /**
20 * Retrieve metadata for the specified website.
21 *
22 * @param mixed $data The value on which the filters hooked are applied on.
23 * @param int $site_id Website ID of the object metadata is for
24 * @param string $meta_key Optional. Metadata key. If not specified, retrieve all metadata for the specified website.
25 * @param bool $single Optional, default is false.
26 * If true, return only the first value of the specified meta_key.
27 * This parameter has no effect if meta_key is not specified.
28 * @param bool|int $maximum_age Optional, default is false.
29 * If value is integer, only return data that is equal or less than the maximum age.
30 * Otherwise (if false), it will return all data with any age.
31 * @param bool $with_fields Indicates whether a complete record with field names will be returned
32 *
33 * @return mixed For single the metadata value, or array of values if single = false or the original value of $data
34 */
35 public function updraftcentral_get_site_metadata($data, $site_id, $meta_key = "", $single = false, $maximum_age = false, $with_fields = false) {
36 global $wpdb;
37
38 $table = $this->_get_meta_table('site');
39 if (!$table) {
40 return $data;
41 }
42
43 if (!absint($site_id)) {
44 return $data;
45 }
46
47 $wpdb_api = 'get_col';
48 $wpdb_fields = 'meta_value';
49 if ($with_fields) {
50 $wpdb_api = 'get_results';
51 $wpdb_fields = '*';
52 }
53
54 if (!empty($meta_key)) {
55 $meta_key = wp_unslash($meta_key);
56
57 $meta_values = array();
58 if (false !== $maximum_age) {
59 if (!is_numeric($maximum_age)) {
60 return $data;
61 }
62
63 $meta_values = $wpdb->{$wpdb_api}($wpdb->prepare("SELECT {$wpdb_fields} FROM $table WHERE meta_key = %s AND site_id = %d AND (UNIX_TIMESTAMP()-created) <= %s", $meta_key, $site_id, $maximum_age));
64 } else {
65 $meta_values = $wpdb->{$wpdb_api}($wpdb->prepare("SELECT {$wpdb_fields} FROM $table WHERE meta_key = %s AND site_id = %d", $meta_key, $site_id));
66 }
67 } else {
68 $meta_values = $wpdb->{$wpdb_api}($wpdb->prepare("SELECT {$wpdb_fields} FROM $table WHERE site_id = %d", $site_id));
69 }
70
71 if (empty($meta_values)) {
72 // N.B. Here, we're returning false if $meta_values is empty since we are
73 // shortcircuiting the result from the current query it is best to return
74 // the actual "false" value rather than returning the default $data value
75 // which can be null. A return value of null does not actually return this
76 // result as empty (which is our expected result if the query fails) because it will still check
77 // WordPress's own caching implementation and fill it if this call returns null.
78 return false;
79 } else {
80 return array_map(array(UpdraftCentral(), 'maybe_json_decode'), (array) $meta_values);
81 }
82 }
83
84 /**
85 * Retrieve the value of the "created" column from the sitemeta table
86 *
87 * @param mixed $data The value on which the filters hooked are applied on.
88 * @param int $site_id Website ID of the object metadata is for
89 * @param string $meta_key Metadata key. If not specified, retrieve all metadata for the specified website.
90 *
91 * @return mixed Created column value, or the origin $data value
92 */
93 public function updraftcentral_get_site_metadata_created($data, $site_id, $meta_key) {
94 global $wpdb;
95
96 $table = $this->_get_meta_table('site');
97 if (!$table) {
98 return $data;
99 }
100
101 if (!absint($site_id)) {
102 return $data;
103 }
104
105 if (!isset($meta_key) || empty($meta_key)) {
106 return $data;
107 }
108
109 $meta_key = wp_unslash($meta_key);
110 $result = $wpdb->get_col($wpdb->prepare("SELECT created FROM $table WHERE meta_key = %s AND site_id = %d", $meta_key, $site_id));
111
112 if (empty($result)) {
113 return $data;
114 } else {
115 return $result[0];
116 }
117
118 }
119
120
121
122 /**
123 * Add meta data field to a site.
124 *
125 * @since 3.0.0
126 *
127 * @param int $site_id Site ID.
128 * @param string $meta_key Metadata name.
129 * @param mixed $meta_value Metadata value.
130 * @param bool $unique Optional, default is false. Whether the same key should not be added.
131 *
132 * @return int|false Meta ID on success, false on failure.
133 */
134 public function add_site_meta($site_id, $meta_key, $meta_value, $unique = false) {
135 return $this->add_metadata('site', $site_id, $meta_key, $meta_value, $unique);
136 }
137
138 /**
139 * Remove metadata matching criteria from a site.
140 *
141 * You can match based on the key, or key and value. Removing based on key and
142 * value, will keep from removing duplicate metadata with the same key. It also
143 * allows removing all metadata matching key, if needed.
144 *
145 * @param int $site_id Site ID
146 * @param string $meta_key Metadata name.
147 * @param mixed $meta_value Optional. Metadata value.
148 *
149 * @return bool True on success, false on failure.
150 */
151 public function delete_site_meta($site_id, $meta_key, $meta_value = '') {
152 return $this->delete_metadata('site', $site_id, $meta_key, $meta_value);
153 }
154
155 /**
156 * Retrieve site meta field for a site.
157 *
158 * @param int $site_id Site ID.
159 * @param string $key Optional. The meta key to retrieve. By default, returns data for all keys.
160 * @param bool $single Whether to return a single value.
161 * @param bool|int $maximum_age Optional, default is false.
162 * If value is integer, only return data that is equal or less than the maximum age.
163 * Otherwise (if false), it will return all data with any age.
164 * @param bool $with_fields Indicates whether a complete record with field names will be returned
165 *
166 * @return mixed Will be an array if $single is false. Will be value of meta data field if $single is true.
167 */
168 public function get_site_meta($site_id, $key = '', $single = false, $maximum_age = false, $with_fields = false) {
169 return $this->get_metadata('site', $site_id, $key, $single, $maximum_age, $with_fields);
170 }
171
172 /**
173 * Update site meta field based on site ID.
174 *
175 * Use the $prev_value parameter to differentiate between meta fields with the
176 * same key and site ID.
177 *
178 * If the meta field for the site does not exist, it will be added.
179 *
180 * @param int $site_id Site ID.
181 * @param string $meta_key Metadata key.
182 * @param mixed $meta_value Metadata value.
183 * @param mixed $prev_value Optional. Previous value to check before removing.
184 *
185 * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.
186 */
187 public function update_site_meta($site_id, $meta_key, $meta_value, $prev_value = '') {
188 return $this->update_metadata('site', $site_id, $meta_key, $meta_value, $prev_value);
189 }
190
191 /**
192 * Retrieve the name of the metadata table for the specified object type.
193 *
194 * @since 2.9.0
195 *
196 * @global wpdb $wpdb WordPress database abstraction object.
197 *
198 * @param string $type Type of object to get metadata table for (e.g., comment, post, or user)
199 *
200 * @return string|false Metadata table name, or false if no metadata table exists
201 */
202 private function _get_meta_table($type) {
203
204 global $wpdb;
205
206 $table_name = $type.'meta';
207
208 return $wpdb->base_prefix.$this->_uc_table_prefix.$table_name;
209 }
210
211 /**
212 * Add metadata for the specified object.
213 *
214 * @global wpdb $wpdb WordPress database abstraction object.
215 *
216 * @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
217 * @param int $object_id ID of the object metadata is for
218 * @param string $meta_key Metadata key
219 * @param mixed $meta_value Metadata value. Must be serializable if non-scalar.
220 * @param bool $unique Optional, default is false.
221 * Whether the specified metadata key should be unique for the object.
222 * If true, and the object already has a value for the specified metadata key,
223 * no change will be made.
224 *
225 * @return int|false The meta ID on success, false on failure.
226 */
227 public function add_metadata($meta_type, $object_id, $meta_key, $meta_value, $unique = false) {
228 global $wpdb;
229
230 if (!$meta_type || !$meta_key || !is_numeric($object_id)) {
231 return false;
232 }
233
234 $object_id = absint($object_id);
235 if (!$object_id) {
236 return false;
237 }
238
239 $table = $this->_get_meta_table($meta_type);
240 if (!$table) {
241 return false;
242 }
243
244 $column = sanitize_key($meta_type.'_id');
245
246 // expected_slashed ($meta_key)
247 $meta_key = wp_unslash($meta_key);
248 $meta_value = wp_unslash($meta_value);
249 $meta_value = $this->sanitize_meta($meta_key, $meta_value, $meta_type);
250
251 /**
252 * Filter whether to add metadata of a specific type.
253 *
254 * The dynamic portion of the hook, `$meta_type`, refers to the meta
255 * object type (comment, post, or user). Returning a non-null value
256 * will effectively short-circuit the public function.
257 *
258 * @since 3.1.0
259 *
260 * @param null|bool $check Whether to allow adding metadata for the given type.
261 * @param int $object_id Object ID.
262 * @param string $meta_key Meta key.
263 * @param mixed $meta_value Meta value. Must be serializable if non-scalar.
264 * @param bool $unique Whether the specified meta key should be unique
265 * for the object. Optional. Default false.
266 */
267 $check = apply_filters("add_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, $unique);
268 if (null !== $check)
269 return $check;
270
271 if ($unique && $wpdb->get_var($wpdb->prepare(
272 "SELECT COUNT(*) FROM $table WHERE meta_key = %s AND $column = %d",
273 $meta_key, $object_id)))
274 return false;
275
276 $_meta_value = $meta_value;
277 $meta_value = UpdraftCentral()->maybe_json_encode($meta_value);
278
279 /*
280 * Fires immediately before meta of a specific type is added.
281 *
282 * The dynamic portion of the hook, `$meta_type`, refers to the meta
283 * object type (comment, post, or user).
284 *
285 * @since 3.1.0
286 *
287 * @param int $object_id Object ID.
288 * @param string $meta_key Meta key.
289 * @param mixed $meta_value Meta value.
290 */
291 do_action("add_{$meta_type}_meta", $object_id, $meta_key, $_meta_value);
292
293 $result = $wpdb->insert($table, array(
294 $column => $object_id,
295 'meta_key' => $meta_key,
296 'meta_value' => $meta_value,
297 'created' => time(),
298 ));
299
300 if (!$result)
301 return false;
302
303 $mid = (int) $wpdb->insert_id;
304
305 wp_cache_delete($object_id, $meta_type.'_meta');
306
307 /*
308 * Fires immediately after meta of a specific type is added.
309 *
310 * The dynamic portion of the hook, `$meta_type`, refers to the meta
311 * object type (comment, post, or user).
312 *
313 * @since 2.9.0
314 *
315 * @param int $mid The meta ID after successful update.
316 * @param int $object_id Object ID.
317 * @param string $meta_key Meta key.
318 * @param mixed $meta_value Meta value.
319 */
320 do_action("added_{$meta_type}_meta", $mid, $object_id, $meta_key, $_meta_value);
321
322 return $mid;
323 }
324
325 /**
326 * Update metadata for the specified object. If no value already exists for the specified object
327 * ID and metadata key, the metadata will be added.
328 *
329 * @since 2.9.0
330 *
331 * @global wpdb $wpdb WordPress database abstraction object.
332 *
333 * @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
334 * @param int $object_id ID of the object metadata is for
335 * @param string $meta_key Metadata key
336 * @param mixed $meta_value Metadata value. Must be serializable if non-scalar.
337 * @param mixed $prev_value Optional. If specified, only update existing metadata entries with
338 * the specified value. Otherwise, update all entries.
339 *
340 * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.
341 */
342 public function update_metadata($meta_type, $object_id, $meta_key, $meta_value, $prev_value = '') {
343 global $wpdb;
344
345 if (!$meta_type || !$meta_key || !is_numeric($object_id)) {
346 return false;
347 }
348
349 $object_id = absint($object_id);
350 if (!$object_id) {
351 return false;
352 }
353
354 $table = $this->_get_meta_table($meta_type);
355 if (!$table) {
356 return false;
357 }
358
359 $column = sanitize_key($meta_type.'_id');
360 $id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
361
362 // expected_slashed ($meta_key)
363 $meta_key = wp_unslash($meta_key);
364 $passed_value = $meta_value;
365 $meta_value = wp_unslash($meta_value);
366 $meta_value = $this->sanitize_meta($meta_key, $meta_value, $meta_type);
367
368 /**
369 * Filter whether to update metadata of a specific type.
370 *
371 * The dynamic portion of the hook, `$meta_type`, refers to the meta
372 * object type (comment, post, or user). Returning a non-null value
373 * will effectively short-circuit the public function.
374 *
375 * @since 3.1.0
376 *
377 * @param null|bool $check Whether to allow updating metadata for the given type.
378 * @param int $object_id Object ID.
379 * @param string $meta_key Meta key.
380 * @param mixed $meta_value Meta value. Must be serializable if non-scalar.
381 * @param mixed $prev_value Optional. If specified, only update existing
382 * metadata entries with the specified value.
383 * Otherwise, update all entries.
384 */
385 $check = apply_filters("update_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, $prev_value);
386 if (null !== $check)
387 return (bool) $check;
388
389 // Compare existing value to new value if no prev value given and the key exists only once.
390 if (empty($prev_value)) {
391 $old_value = $this->get_metadata($meta_type, $object_id, $meta_key);
392 if (count($old_value) == 1) {
393 if ($old_value[0] === $meta_value)
394 return false;
395 }
396 }
397
398 $meta_ids = $wpdb->get_col($wpdb->prepare("SELECT $id_column FROM $table WHERE meta_key = %s AND $column = %d", $meta_key, $object_id));
399 if (empty($meta_ids)) {
400 return $this->add_metadata($meta_type, $object_id, $meta_key, $passed_value);
401 }
402
403 $_meta_value = $meta_value;
404 $meta_value = UpdraftCentral()->maybe_json_encode($meta_value);
405 $created = time();
406
407 $data = compact('meta_value', 'created');
408 $where = array($column => $object_id, 'meta_key' => $meta_key);
409
410 if (!empty($prev_value)) {
411 $prev_value = UpdraftCentral()->maybe_json_encode($prev_value);
412 $where['meta_value'] = $prev_value;
413 }
414
415 foreach ($meta_ids as $meta_id) {
416 /*
417 * Fires immediately before updating metadata of a specific type.
418 *
419 * The dynamic portion of the hook, `$meta_type`, refers to the meta
420 * object type (comment, post, or user).
421 *
422 * @since 2.9.0
423 *
424 * @param int $meta_id ID of the metadata entry to update.
425 * @param int $object_id Object ID.
426 * @param string $meta_key Meta key.
427 * @param mixed $meta_value Meta value.
428 */
429 do_action("update_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value);
430 }
431
432 if ('post' == $meta_type) {
433 foreach ($meta_ids as $meta_id) {
434 /*
435 * Fires immediately before updating a post's metadata.
436 *
437 * @since 2.9.0
438 *
439 * @param int $meta_id ID of metadata entry to update.
440 * @param int $object_id Object ID.
441 * @param string $meta_key Meta key.
442 * @param mixed $meta_value Meta value.
443 */
444 do_action('update_postmeta', $meta_id, $object_id, $meta_key, $meta_value);
445 }
446 }
447
448 $result = $wpdb->update($table, $data, $where);
449 if (!$result)
450 return false;
451
452 wp_cache_delete($object_id, $meta_type.'_meta');
453
454 foreach ($meta_ids as $meta_id) {
455 /*
456 * Fires immediately after updating metadata of a specific type.
457 *
458 * The dynamic portion of the hook, `$meta_type`, refers to the meta
459 * object type (comment, post, or user).
460 *
461 * @since 2.9.0
462 *
463 * @param int $meta_id ID of updated metadata entry.
464 * @param int $object_id Object ID.
465 * @param string $meta_key Meta key.
466 * @param mixed $meta_value Meta value.
467 */
468 do_action("updated_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value);
469 }
470
471 if ('post' == $meta_type) {
472 foreach ($meta_ids as $meta_id) {
473 /*
474 * Fires immediately after updating a post's metadata.
475 *
476 * @since 2.9.0
477 *
478 * @param int $meta_id ID of updated metadata entry.
479 * @param int $object_id Object ID.
480 * @param string $meta_key Meta key.
481 * @param mixed $meta_value Meta value.
482 */
483 do_action('updated_postmeta', $meta_id, $object_id, $meta_key, $meta_value);
484 }
485 }
486
487 return true;
488 }
489
490 /**
491 * Delete metadata for the specified object.
492 *
493 * @since 2.9.0
494 *
495 * @global wpdb $wpdb WordPress database abstraction object.
496 *
497 * @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
498 * @param int $object_id ID of the object metadata is for
499 * @param string $meta_key Metadata key
500 * @param mixed $meta_value Optional. Metadata value. Must be serializable if non-scalar. If specified, only delete
501 * metadata entries with this value. Otherwise, delete all entries with the specified meta_key.
502 * Pass `null, `false`, or an empty string to skip this check. (For backward compatibility,
503 * it is not possible to pass an empty string to delete those entries with an empty string
504 * for a value.)
505 * @param bool $delete_all Optional, default is false. If true, delete matching metadata entries for all objects,
506 * ignoring the specified object_id. Otherwise, only delete matching metadata entries for
507 * the specified object_id.
508 *
509 * @return bool True on successful delete, false on failure.
510 */
511 public function delete_metadata($meta_type, $object_id, $meta_key, $meta_value = '', $delete_all = false) {
512 global $wpdb;
513
514 if (!$meta_type || !$meta_key || !is_numeric($object_id) && !$delete_all) {
515 return false;
516 }
517
518 $object_id = absint($object_id);
519 if (!$object_id && !$delete_all) {
520 return false;
521 }
522
523 $table = $this->_get_meta_table($meta_type);
524 if (!$table) {
525 return false;
526 }
527
528 $type_column = sanitize_key($meta_type.'_id');
529 $id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
530 // expected_slashed ($meta_key)
531 $meta_key = wp_unslash($meta_key);
532 $meta_value = wp_unslash($meta_value);
533
534 /*
535 * Filter whether to delete metadata of a specific type.
536 *
537 * The dynamic portion of the hook, `$meta_type`, refers to the meta
538 * object type (comment, post, or user). Returning a non-null value
539 * will effectively short-circuit the public function.
540 *
541 * @since 3.1.0
542 *
543 * @param null|bool $delete Whether to allow metadata deletion of the given type.
544 * @param int $object_id Object ID.
545 * @param string $meta_key Meta key.
546 * @param mixed $meta_value Meta value. Must be serializable if non-scalar.
547 * @param bool $delete_all Whether to delete the matching metadata entries
548 * for all objects, ignoring the specified $object_id.
549 * Default false.
550 */
551 $check = apply_filters("delete_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, $delete_all);
552 if (null !== $check)
553 return (bool) $check;
554
555 $_meta_value = $meta_value;
556 $meta_value = UpdraftCentral()->maybe_json_encode($meta_value);
557
558 $query = $wpdb->prepare("SELECT $id_column FROM $table WHERE meta_key = %s", $meta_key);
559
560 if (!$delete_all)
561 $query .= $wpdb->prepare(" AND $type_column = %d", $object_id);
562
563 if ('' !== $meta_value && null !== $meta_value && false !== $meta_value)
564 $query .= $wpdb->prepare(' AND meta_value = %s', $meta_value);
565
566 $meta_ids = $wpdb->get_col($query);
567 if (!count($meta_ids))
568 return false;
569
570 if ($delete_all)
571 $object_ids = $wpdb->get_col($wpdb->prepare("SELECT $type_column FROM $table WHERE meta_key = %s", $meta_key));
572
573 /*
574 * Fires immediately before deleting metadata of a specific type.
575 *
576 * The dynamic portion of the hook, `$meta_type`, refers to the meta
577 * object type (comment, post, or user).
578 *
579 * @since 3.1.0
580 *
581 * @param array $meta_ids An array of metadata entry IDs to delete.
582 * @param int $object_id Object ID.
583 * @param string $meta_key Meta key.
584 * @param mixed $meta_value Meta value.
585 */
586 do_action("delete_{$meta_type}_meta", $meta_ids, $object_id, $meta_key, $_meta_value);
587
588 // Old-style action.
589 if ('post' == $meta_type) {
590 /*
591 * Fires immediately before deleting metadata for a post.
592 *
593 * @since 2.9.0
594 *
595 * @param array $meta_ids An array of post metadata entry IDs to delete.
596 */
597 do_action('delete_postmeta', $meta_ids);
598 }
599
600 $query = "DELETE FROM $table WHERE $id_column IN( ".implode(',', $meta_ids).' )';
601
602 $count = $wpdb->query($query);
603
604 if (!$count)
605 return false;
606
607 if ($delete_all) {
608 foreach ((array) $object_ids as $o_id) {
609 wp_cache_delete($o_id, $meta_type.'_meta');
610 }
611 } else {
612 wp_cache_delete($object_id, $meta_type.'_meta');
613 }
614
615 /*
616 * Fires immediately after deleting metadata of a specific type.
617 *
618 * The dynamic portion of the hook name, `$meta_type`, refers to the meta
619 * object type (comment, post, or user).
620 *
621 * @since 2.9.0
622 *
623 * @param array $meta_ids An array of deleted metadata entry IDs.
624 * @param int $object_id Object ID.
625 * @param string $meta_key Meta key.
626 * @param mixed $meta_value Meta value.
627 */
628 do_action("deleted_{$meta_type}_meta", $meta_ids, $object_id, $meta_key, $_meta_value);
629
630 // Old-style action.
631 if ('post' == $meta_type) {
632 /*
633 * Fires immediately after deleting metadata for a post.
634 *
635 * @since 2.9.0
636 *
637 * @param array $meta_ids An array of deleted post metadata entry IDs.
638 */
639 do_action('deleted_postmeta', $meta_ids);
640 }
641
642 return true;
643 }
644
645 /**
646 * Retrieve metadata for the specified object.
647 *
648 * @since 2.9.0
649 *
650 * @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
651 * @param int $object_id ID of the object metadata is for
652 * @param string $meta_key Optional. Metadata key. If not specified, retrieve all metadata for
653 * the specified object.
654 * @param bool $single Optional, default is false.
655 * If true, return only the first value of the specified meta_key.
656 * This parameter has no effect if meta_key is not specified.
657 * @param bool|int $maximum_age Optional, default is false.
658 * If value is integer, only return data that is equal or less than the maximum age.
659 * Otherwise (if false), it will return all data with any age.
660 * @param bool $with_fields Indicates whether a complete record with field names will be returned
661 *
662 * @return mixed Single metadata value, or array of values
663 */
664 public function get_metadata($meta_type, $object_id, $meta_key = '', $single = false, $maximum_age = false, $with_fields = false) {
665 if (!$meta_type || !is_numeric($object_id)) {
666 return false;
667 }
668
669 $object_id = absint($object_id);
670 if (!$object_id) {
671 return false;
672 }
673
674 /*
675 * Filter whether to retrieve metadata of a specific type.
676 *
677 * The dynamic portion of the hook, `$meta_type`, refers to the meta
678 * object type (comment, post, or user). Returning a non-null value
679 * will effectively short-circuit the public function.
680 *
681 * @since 3.1.0
682 *
683 * @param null|array|string $value The value get_metadata() should return - a single metadata value,
684 * or an array of values.
685 * @param int $object_id Object ID.
686 * @param string $meta_key Meta key.
687 * @param bool $single Whether to return only the first value of the specified $meta_key.
688 * @param int $maximum_age Determines how fresh the data that needs to be pulled.
689 * @param bool $with_fields Indicates whether a complete record with field names will be returned
690 */
691 $check = apply_filters("get_{$meta_type}_metadata", null, $object_id, $meta_key, $single, $maximum_age, $with_fields);
692 if (null !== $check) {
693 if ($single && is_array($check))
694 return $check[0];
695 else
696 return $check;
697 }
698
699 $meta_cache = wp_cache_get($object_id, $meta_type.'_meta');
700
701 if (!$meta_cache) {
702 $meta_cache = $this->update_meta_cache($meta_type, array($object_id));
703 $meta_cache = $meta_cache[$object_id];
704 }
705
706 if (!$meta_key) {
707 return $meta_cache;
708 }
709
710 if (isset($meta_cache[$meta_key])) {
711 if ($single)
712 return UpdraftCentral()->maybe_json_decode($meta_cache[$meta_key][0]);
713 else
714 return array_map(array(UpdraftCentral(), 'maybe_json_decode'), $meta_cache[$meta_key]);
715 }
716
717 if ($single)
718 return '';
719 else
720 return array();
721 }
722
723 /**
724 * Determine if a meta key is set for a given object.
725 *
726 * @since 3.3.0
727 *
728 * @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
729 * @param int $object_id ID of the object metadata is for
730 * @param string $meta_key Metadata key.
731 *
732 * @return bool True of the key is set, false if not.
733 */
734 public function metadata_exists($meta_type, $object_id, $meta_key) {
735 if (!$meta_type || !is_numeric($object_id)) {
736 return false;
737 }
738
739 $object_id = absint($object_id);
740 if (!$object_id) {
741 return false;
742 }
743
744 /* This filter is documented in wp-includes/meta.php */
745 $check = apply_filters("get_{$meta_type}_metadata", null, $object_id, $meta_key, true);
746 if (null !== $check)
747 return (bool) $check;
748
749 $meta_cache = wp_cache_get($object_id, $meta_type.'_meta');
750
751 if (!$meta_cache) {
752 $meta_cache = $this->update_meta_cache($meta_type, array($object_id));
753 $meta_cache = $meta_cache[$object_id];
754 }
755
756 if (isset($meta_cache[ $meta_key ]))
757 return true;
758
759 return false;
760 }
761
762 /**
763 * Get meta data by meta ID.
764 *
765 * @since 3.3.0
766 *
767 * @global wpdb $wpdb WordPress database abstraction object.
768 *
769 * @param string $meta_type Type of object metadata is for (e.g., comment, post, term, or user).
770 * @param int $meta_id ID for a specific meta row
771 *
772 * @return object|false Meta object or false.
773 */
774 public function get_metadata_by_mid($meta_type, $meta_id) {
775 global $wpdb;
776
777 if (!$meta_type || !is_numeric($meta_id)) {
778 return false;
779 }
780
781 $meta_id = absint($meta_id);
782 if (!$meta_id) {
783 return false;
784 }
785
786 $table = $this->_get_meta_table($meta_type);
787 if (!$table) {
788 return false;
789 }
790
791 $id_column = ('user' == $meta_type) ? 'umeta_id' : 'meta_id';
792
793 $meta = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table WHERE $id_column = %d", $meta_id));
794
795 if (empty($meta))
796 return false;
797
798 if (isset($meta->meta_value))
799 $meta->meta_value = UpdraftCentral()->maybe_json_decode($meta->meta_value);
800
801 return $meta;
802 }
803
804 /**
805 * Update meta data by meta ID.
806 *
807 * @since 3.3.0
808 *
809 * @global wpdb $wpdb WordPress database abstraction object.
810 *
811 * @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
812 * @param int $meta_id ID for a specific meta row
813 * @param string $meta_value Metadata value
814 * @param string $meta_key Optional, you can provide a meta key to update it
815 *
816 * @return bool True on successful update, false on failure.
817 */
818 public function update_metadata_by_mid($meta_type, $meta_id, $meta_value, $meta_key = false) {
819 global $wpdb;
820
821 // Make sure everything is valid.
822 if (!$meta_type || !is_numeric($meta_id)) {
823 return false;
824 }
825
826 $meta_id = absint($meta_id);
827 if (!$meta_id) {
828 return false;
829 }
830
831 $table = $this->_get_meta_table($meta_type);
832 if (!$table) {
833 return false;
834 }
835
836 $column = sanitize_key($meta_type.'_id');
837 $id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
838
839 // Fetch the meta and go on if it's found.
840 if ($meta = $this->get_metadata_by_mid($meta_type, $meta_id)) {
841 $original_key = $meta->meta_key;
842 $object_id = $meta->{$column};
843
844 // If a new meta_key (last parameter) was specified, change the meta key,
845 // otherwise use the original key in the update statement.
846 if (false === $meta_key) {
847 $meta_key = $original_key;
848 } elseif (!is_string($meta_key)) {
849 return false;
850 }
851
852 // Sanitize the meta
853 $_meta_value = $meta_value;
854 $meta_value = $this->sanitize_meta($meta_key, $meta_value, $meta_type);
855 $meta_value = UpdraftCentral()->maybe_json_encode($meta_value);
856
857 // Format the data query arguments.
858 $data = array(
859 'meta_key' => $meta_key,
860 'meta_value' => $meta_value,
861 );
862
863 // Format the where query arguments.
864 $where = array();
865 $where[$id_column] = $meta_id;
866
867 /* This action is documented in wp-includes/meta.php */
868 do_action("update_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value);
869
870 if ('post' == $meta_type) {
871 /* This action is documented in wp-includes/meta.php */
872 do_action('update_postmeta', $meta_id, $object_id, $meta_key, $meta_value);
873 }
874
875 // Run the update query, all fields in $data are %s, $where is a %d.
876 $result = $wpdb->update($table, $data, $where, '%s', '%d');
877 if (!$result)
878 return false;
879
880 // Clear the caches.
881 wp_cache_delete($object_id, $meta_type.'_meta');
882
883 /* This action is documented in wp-includes/meta.php */
884 do_action("updated_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value);
885
886 if ('post' == $meta_type) {
887 /* This action is documented in wp-includes/meta.php */
888 do_action('updated_postmeta', $meta_id, $object_id, $meta_key, $meta_value);
889 }
890
891 return true;
892 }
893
894 // And if the meta was not found.
895 return false;
896 }
897
898 /**
899 * Delete meta data by meta ID.
900 *
901 * @since 3.3.0
902 *
903 * @global wpdb $wpdb WordPress database abstraction object.
904 *
905 * @param string $meta_type Type of object metadata is for (e.g., comment, post, term, or user).
906 * @param int $meta_id ID for a specific meta row
907 *
908 * @return bool True on successful delete, false on failure.
909 */
910 public function delete_metadata_by_mid($meta_type, $meta_id) {
911 global $wpdb;
912
913 // Make sure everything is valid.
914 if (!$meta_type || !is_numeric($meta_id)) {
915 return false;
916 }
917
918 $meta_id = absint($meta_id);
919 if (!$meta_id) {
920 return false;
921 }
922
923 $table = $this->_get_meta_table($meta_type);
924 if (!$table) {
925 return false;
926 }
927
928 // object and id columns
929 $column = sanitize_key($meta_type.'_id');
930 $id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
931
932 // Fetch the meta and go on if it's found.
933 if ($meta = $this->get_metadata_by_mid($meta_type, $meta_id)) {
934 $object_id = $meta->{$column};
935
936 /* This action is documented in wp-includes/meta.php */
937 do_action("delete_{$meta_type}_meta", (array) $meta_id, $object_id, $meta->meta_key, $meta->meta_value);
938
939 // Old-style action.
940 if ('post' == $meta_type || 'comment' == $meta_type) {
941 /*
942 * Fires immediately before deleting post or comment metadata of a specific type.
943 *
944 * The dynamic portion of the hook, `$meta_type`, refers to the meta
945 * object type (post or comment).
946 *
947 * @since 3.4.0
948 *
949 * @param int $meta_id ID of the metadata entry to delete.
950 */
951 do_action("delete_{$meta_type}meta", $meta_id);
952 }
953
954 // Run the query, will return true if deleted, false otherwise
955 $result = (bool) $wpdb->delete($table, array($id_column => $meta_id));
956
957 // Clear the caches.
958 wp_cache_delete($object_id, $meta_type.'_meta');
959
960 /* This action is documented in wp-includes/meta.php */
961 do_action("deleted_{$meta_type}_meta", (array) $meta_id, $object_id, $meta->meta_key, $meta->meta_value);
962
963 // Old-style action.
964 if ('post' == $meta_type || 'comment' == $meta_type) {
965 /*
966 * Fires immediately after deleting post or comment metadata of a specific type.
967 *
968 * The dynamic portion of the hook, `$meta_type`, refers to the meta
969 * object type (post or comment).
970 *
971 * @since 3.4.0
972 *
973 * @param int $meta_ids Deleted metadata entry ID.
974 */
975 do_action("deleted_{$meta_type}meta", $meta_id);
976 }
977
978 return $result;
979
980 }
981
982 // Meta id was not found.
983 return false;
984 }
985
986 /**
987 * Update the metadata cache for the specified objects.
988 *
989 * @since 2.9.0
990 *
991 * @global wpdb $wpdb WordPress database abstraction object.
992 *
993 * @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
994 * @param int|array $object_ids Array or comma delimited list of object IDs to update cache for
995 *
996 * @return array|false Metadata cache for the specified objects, or false on failure.
997 */
998 public function update_meta_cache($meta_type, $object_ids) {
999 global $wpdb;
1000
1001 if (!$meta_type || !$object_ids) {
1002 return false;
1003 }
1004
1005 $table = $this->_get_meta_table($meta_type);
1006 if (!$table) {
1007 return false;
1008 }
1009
1010 $column = sanitize_key($meta_type.'_id');
1011
1012 if (!is_array($object_ids)) {
1013 $object_ids = preg_replace('|[^0-9,]|', '', $object_ids);
1014 $object_ids = explode(',', $object_ids);
1015 }
1016
1017 $object_ids = array_map('intval', $object_ids);
1018
1019 $cache_key = $meta_type.'_meta';
1020 $ids = array();
1021 $cache = array();
1022 foreach ($object_ids as $id) {
1023 $cached_object = wp_cache_get($id, $cache_key);
1024 if (false === $cached_object)
1025 $ids[] = $id;
1026 else
1027 $cache[$id] = $cached_object;
1028 }
1029
1030 if (empty($ids))
1031 return $cache;
1032
1033 // Get meta info
1034 $id_list = implode(',', $ids);
1035 $id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
1036 $meta_list = $wpdb->get_results("SELECT $column, meta_key, meta_value FROM $table WHERE $column IN ($id_list) ORDER BY $id_column ASC", ARRAY_A);
1037
1038 if (!empty($meta_list)) {
1039 foreach ($meta_list as $metarow) {
1040 $mpid = intval($metarow[$column]);
1041 $mkey = $metarow['meta_key'];
1042 $mval = $metarow['meta_value'];
1043
1044 // Force subkeys to be array type:
1045 if (!isset($cache[$mpid]) || !is_array($cache[$mpid]))
1046 $cache[$mpid] = array();
1047 if (!isset($cache[$mpid][$mkey]) || !is_array($cache[$mpid][$mkey]))
1048 $cache[$mpid][$mkey] = array();
1049
1050 // Add a value to the current pid/key:
1051 $cache[$mpid][$mkey][] = $mval;
1052 }
1053 }
1054
1055 foreach ($ids as $id) {
1056 if (!isset($cache[$id]))
1057 $cache[$id] = array();
1058 wp_cache_add($id, $cache[$id], $cache_key);
1059 }
1060
1061 return $cache;
1062 }
1063
1064 /**
1065 * Given a meta query, generates SQL clauses to be appended to a main query.
1066 *
1067 * @since 3.2.0
1068 * @see WP_Meta_Query
1069 *
1070 * @param array $meta_query A meta query.
1071 * @param string $type Type of meta.
1072 * @param string $primary_table Primary database table name.
1073 * @param string $primary_id_column Primary ID column name.
1074 * @param object $context Optional. The main query object
1075 *
1076 * @return array Associative array of `JOIN` and `WHERE` SQL.
1077 */
1078 public function get_meta_sql($meta_query, $type, $primary_table, $primary_id_column, $context = null) {
1079 $meta_query_obj = new WP_Meta_Query($meta_query);
1080
1081 return $meta_query_obj->get_sql($type, $primary_table, $primary_id_column, $context);
1082 }
1083
1084 /**
1085 * Determine whether a meta key is protected.
1086 *
1087 * @since 3.1.3
1088 *
1089 * @param string $meta_key Meta key
1090 * @param string|null $meta_type
1091 *
1092 * @return bool True if the key is protected, false otherwise.
1093 */
1094 public function is_protected_meta($meta_key, $meta_type = null) {
1095 $protected = ('_' == $meta_key[0]);
1096
1097 /*
1098 * Filter whether a meta key is protected.
1099 *
1100 * @since 3.2.0
1101 *
1102 * @param bool $protected Whether the key is protected. Default false.
1103 * @param string $meta_key Meta key.
1104 * @param string $meta_type Meta type.
1105 */
1106 return apply_filters('is_protected_meta', $protected, $meta_key, $meta_type);
1107 }
1108
1109 /**
1110 * Sanitize meta value.
1111 *
1112 * @since 3.1.3
1113 *
1114 * @param string $meta_key Meta key
1115 * @param mixed $meta_value Meta value to sanitize
1116 * @param string $meta_type Type of meta
1117 *
1118 * @return mixed Sanitized $meta_value
1119 */
1120 public function sanitize_meta($meta_key, $meta_value, $meta_type) {
1121
1122 /*
1123 * Filter the sanitization of a specific meta key of a specific meta type.
1124 *
1125 * The dynamic portions of the hook name, `$meta_type`, and `$meta_key`,
1126 * refer to the metadata object type (comment, post, or user) and the meta
1127 * key value,
1128 * respectively.
1129 *
1130 * @since 3.3.0
1131 *
1132 * @param mixed $meta_value Meta value to sanitize.
1133 * @param string $meta_key Meta key.
1134 * @param string $meta_type Meta type.
1135 */
1136 return apply_filters("sanitize_{$meta_type}_meta_{$meta_key}", $meta_value, $meta_key, $meta_type);
1137 }
1138
1139 /**
1140 * Register meta key.
1141 *
1142 * @since 3.3.0
1143 *
1144 * @param string $meta_type Type of meta
1145 * @param string $meta_key Meta key
1146 * @param string|array $sanitize_callback A public function or method to call when sanitizing the value of $meta_key.
1147 * @param string|array $auth_callback Optional. A public function or method to call when performing edit_post_meta, add_post_meta, and delete_post_meta capability checks.
1148 */
1149 public function register_meta($meta_type, $meta_key, $sanitize_callback, $auth_callback = null) {
1150 if (is_callable($sanitize_callback))
1151 add_filter("sanitize_{$meta_type}_meta_{$meta_key}", $sanitize_callback, 10, 3);
1152
1153 if (empty($auth_callback)) {
1154 if ($this->is_protected_meta($meta_key, $meta_type))
1155 $auth_callback = '__return_false';
1156 else
1157 $auth_callback = '__return_true';
1158 }
1159
1160 if (is_callable($auth_callback))
1161 add_filter("auth_{$meta_type}_meta_{$meta_key}", $auth_callback, 10, 6);
1162 }
1163 }
1164