PluginProbe
UpdraftCentral Dashboard / 0.8.13
UpdraftCentral Dashboard v0.8.13
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.13, at classes/site-meta.php

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