Diff: STRATO-apps/wordpress_03/app/wp-includes/meta.php

Keine Baseline-Datei – Diff nur gegen leer.
Zur Liste
1 -
1 + <?php
2 + /**
3 + * Core Metadata API
4 + *
5 + * Functions for retrieving and manipulating metadata of various WordPress object types. Metadata
6 + * for an object is a represented by a simple key-value pair. Objects may contain multiple
7 + * metadata entries that share the same key and differ only in their value.
8 + *
9 + * @package WordPress
10 + * @subpackage Meta
11 + */
12 +
13 + require ABSPATH . WPINC . '/class-wp-metadata-lazyloader.php';
14 +
15 + /**
16 + * Adds metadata for the specified object.
17 + *
18 + * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
19 + *
20 + * @since 2.9.0
21 + *
22 + * @global wpdb $wpdb WordPress database abstraction object.
23 + *
24 + * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
25 + * 'user', or any other object type with an associated meta table.
26 + * @param int $object_id ID of the object metadata is for.
27 + * @param string $meta_key Metadata key.
28 + * @param mixed $meta_value Metadata value. Arrays and objects are stored as serialized data and
29 + * will be returned as the same type when retrieved. Other data types will
30 + * be stored as strings in the database:
31 + * - false is stored and retrieved as an empty string ('')
32 + * - true is stored and retrieved as '1'
33 + * - numbers (both integer and float) are stored and retrieved as strings
34 + * Must be serializable if non-scalar.
35 + * @param bool $unique Optional. Whether the specified metadata key should be unique for the object.
36 + * If true, and the object already has a value for the specified metadata key,
37 + * no change will be made. Default false.
38 + * @return int|false The meta ID on success, false on failure.
39 + */
40 + function add_metadata( $meta_type, $object_id, $meta_key, $meta_value, $unique = false ) {
41 + global $wpdb;
42 +
43 + if ( ! $meta_type || ! $meta_key || ! is_numeric( $object_id ) ) {
44 + return false;
45 + }
46 +
47 + $object_id = absint( $object_id );
48 + if ( ! $object_id ) {
49 + return false;
50 + }
51 +
52 + $table = _get_meta_table( $meta_type );
53 + if ( ! $table ) {
54 + return false;
55 + }
56 +
57 + $meta_subtype = get_object_subtype( $meta_type, $object_id );
58 +
59 + $column = sanitize_key( $meta_type . '_id' );
60 +
61 + // expected_slashed ($meta_key)
62 + $meta_key = wp_unslash( $meta_key );
63 + $meta_value = wp_unslash( $meta_value );
64 + $meta_value = sanitize_meta( $meta_key, $meta_value, $meta_type, $meta_subtype );
65 +
66 + /**
67 + * Short-circuits adding metadata of a specific type.
68 + *
69 + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
70 + * (blog, post, comment, term, user, or any other type with an associated meta table).
71 + * Returning a non-null value will effectively short-circuit the function.
72 + *
73 + * Possible hook names include:
74 + *
75 + * - `add_blog_metadata`
76 + * - `add_post_metadata`
77 + * - `add_comment_metadata`
78 + * - `add_term_metadata`
79 + * - `add_user_metadata`
80 + *
81 + * @since 3.1.0
82 + *
83 + * @param null|int|false $check Whether to allow adding metadata for the given type. Return false or a meta ID
84 + * to short-circuit the function. Return null to continue with the default behavior.
85 + * @param int $object_id ID of the object metadata is for.
86 + * @param string $meta_key Metadata key.
87 + * @param mixed $meta_value Metadata value. Must be serializable if non-scalar.
88 + * @param bool $unique Whether the specified meta key should be unique for the object.
89 + */
90 + $check = apply_filters( "add_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, $unique );
91 + if ( null !== $check ) {
92 + return $check;
93 + }
94 +
95 + if ( $unique && $wpdb->get_var(
96 + $wpdb->prepare(
97 + "SELECT COUNT(*) FROM $table WHERE meta_key = %s AND $column = %d",
98 + $meta_key,
99 + $object_id
100 + )
101 + ) ) {
102 + return false;
103 + }
104 +
105 + $_meta_value = $meta_value;
106 + $meta_value = maybe_serialize( $meta_value );
107 +
108 + /**
109 + * Fires immediately before meta of a specific type is added.
110 + *
111 + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
112 + * (blog, post, comment, term, user, or any other type with an associated meta table).
113 + *
114 + * Possible hook names include:
115 + *
116 + * - `add_blog_meta`
117 + * - `add_post_meta`
118 + * - `add_comment_meta`
119 + * - `add_term_meta`
120 + * - `add_user_meta`
121 + *
122 + * @since 3.1.0
123 + *
124 + * @param int $object_id ID of the object metadata is for.
125 + * @param string $meta_key Metadata key.
126 + * @param mixed $_meta_value Metadata value.
127 + */
128 + do_action( "add_{$meta_type}_meta", $object_id, $meta_key, $_meta_value );
129 +
130 + $result = $wpdb->insert(
131 + $table,
132 + array(
133 + $column => $object_id,
134 + 'meta_key' => $meta_key,
135 + 'meta_value' => $meta_value,
136 + )
137 + );
138 +
139 + if ( ! $result ) {
140 + return false;
141 + }
142 +
143 + $mid = (int) $wpdb->insert_id;
144 +
145 + wp_cache_delete( $object_id, $meta_type . '_meta' );
146 +
147 + /**
148 + * Fires immediately after meta of a specific type is added.
149 + *
150 + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
151 + * (blog, post, comment, term, user, or any other type with an associated meta table).
152 + *
153 + * Possible hook names include:
154 + *
155 + * - `added_blog_meta`
156 + * - `added_post_meta`
157 + * - `added_comment_meta`
158 + * - `added_term_meta`
159 + * - `added_user_meta`
160 + *
161 + * @since 2.9.0
162 + *
163 + * @param int $mid The meta ID after successful update.
164 + * @param int $object_id ID of the object metadata is for.
165 + * @param string $meta_key Metadata key.
166 + * @param mixed $_meta_value Metadata value.
167 + */
168 + do_action( "added_{$meta_type}_meta", $mid, $object_id, $meta_key, $_meta_value );
169 +
170 + return $mid;
171 + }
172 +
173 + /**
174 + * Updates metadata for the specified object. If no value already exists for the specified object
175 + * ID and metadata key, the metadata will be added.
176 + *
177 + * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
178 + *
179 + * @since 2.9.0
180 + *
181 + * @global wpdb $wpdb WordPress database abstraction object.
182 + *
183 + * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
184 + * 'user', or any other object type with an associated meta table.
185 + * @param int $object_id ID of the object metadata is for.
186 + * @param string $meta_key Metadata key.
187 + * @param mixed $meta_value Metadata value. Must be serializable if non-scalar.
188 + * @param mixed $prev_value Optional. Previous value to check before updating.
189 + * If specified, only update existing metadata entries with
190 + * this value. Otherwise, update all entries. Default empty string.
191 + * @return int|bool The new meta field ID if a field with the given key didn't exist
192 + * and was therefore added, true on successful update,
193 + * false on failure or if the value passed to the function
194 + * is the same as the one that is already in the database.
195 + */
196 + function update_metadata( $meta_type, $object_id, $meta_key, $meta_value, $prev_value = '' ) {
197 + global $wpdb;
198 +
199 + if ( ! $meta_type || ! $meta_key || ! is_numeric( $object_id ) ) {
200 + return false;
201 + }
202 +
203 + $object_id = absint( $object_id );
204 + if ( ! $object_id ) {
205 + return false;
206 + }
207 +
208 + $table = _get_meta_table( $meta_type );
209 + if ( ! $table ) {
210 + return false;
211 + }
212 +
213 + $meta_subtype = get_object_subtype( $meta_type, $object_id );
214 +
215 + $column = sanitize_key( $meta_type . '_id' );
216 + $id_column = ( 'user' === $meta_type ) ? 'umeta_id' : 'meta_id';
217 +
218 + // expected_slashed ($meta_key)
219 + $raw_meta_key = $meta_key;
220 + $meta_key = wp_unslash( $meta_key );
221 + $passed_value = $meta_value;
222 + $meta_value = wp_unslash( $meta_value );
223 + $meta_value = sanitize_meta( $meta_key, $meta_value, $meta_type, $meta_subtype );
224 +
225 + /**
226 + * Short-circuits updating metadata of a specific type.
227 + *
228 + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
229 + * (blog, post, comment, term, user, or any other type with an associated meta table).
230 + * Returning a non-null value will effectively short-circuit the function.
231 + *
232 + * Possible hook names include:
233 + *
234 + * - `update_blog_metadata`
235 + * - `update_post_metadata`
236 + * - `update_comment_metadata`
237 + * - `update_term_metadata`
238 + * - `update_user_metadata`
239 + *
240 + * @since 3.1.0
241 + *
242 + * @param null|bool $check Whether to allow updating metadata for the given type.
243 + * @param int $object_id ID of the object metadata is for.
244 + * @param string $meta_key Metadata key.
245 + * @param mixed $meta_value Metadata value. Must be serializable if non-scalar.
246 + * @param mixed $prev_value Optional. Previous value to check before updating.
247 + * If specified, only update existing metadata entries with
248 + * this value. Otherwise, update all entries.
249 + */
250 + $check = apply_filters( "update_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, $prev_value );
251 + if ( null !== $check ) {
252 + return (bool) $check;
253 + }
254 +
255 + // Compare existing value to new value if no prev value given and the key exists only once.
256 + if ( empty( $prev_value ) ) {
257 + $old_value = get_metadata_raw( $meta_type, $object_id, $meta_key );
258 + if ( is_countable( $old_value ) && count( $old_value ) === 1 ) {
259 + if ( $old_value[0] === $meta_value ) {
260 + return false;
261 + }
262 + }
263 + }
264 +
265 + $meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT $id_column FROM $table WHERE meta_key = %s AND $column = %d", $meta_key, $object_id ) );
266 + if ( empty( $meta_ids ) ) {
267 + return add_metadata( $meta_type, $object_id, $raw_meta_key, $passed_value );
268 + }
269 +
270 + $_meta_value = $meta_value;
271 + $meta_value = maybe_serialize( $meta_value );
272 +
273 + $data = compact( 'meta_value' );
274 + $where = array(
275 + $column => $object_id,
276 + 'meta_key' => $meta_key,
277 + );
278 +
279 + if ( ! empty( $prev_value ) ) {
280 + $prev_value = maybe_serialize( $prev_value );
281 + $where['meta_value'] = $prev_value;
282 + }
283 +
284 + foreach ( $meta_ids as $meta_id ) {
285 + /**
286 + * Fires immediately before updating metadata of a specific type.
287 + *
288 + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
289 + * (blog, post, comment, term, user, or any other type with an associated meta table).
290 + *
291 + * Possible hook names include:
292 + *
293 + * - `update_blog_meta`
294 + * - `update_post_meta`
295 + * - `update_comment_meta`
296 + * - `update_term_meta`
297 + * - `update_user_meta`
298 + *
299 + * @since 2.9.0
300 + *
301 + * @param int $meta_id ID of the metadata entry to update.
302 + * @param int $object_id ID of the object metadata is for.
303 + * @param string $meta_key Metadata key.
304 + * @param mixed $_meta_value Metadata value.
305 + */
306 + do_action( "update_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value );
307 +
308 + if ( 'post' === $meta_type ) {
309 + /**
310 + * Fires immediately before updating a post's metadata.
311 + *
312 + * @since 2.9.0
313 + *
314 + * @param int $meta_id ID of metadata entry to update.
315 + * @param int $object_id Post ID.
316 + * @param string $meta_key Metadata key.
317 + * @param mixed $meta_value Metadata value. This will be a PHP-serialized string representation of the value
318 + * if the value is an array, an object, or itself a PHP-serialized string.
319 + */
320 + do_action( 'update_postmeta', $meta_id, $object_id, $meta_key, $meta_value );
321 + }
322 + }
323 +
324 + $result = $wpdb->update( $table, $data, $where );
325 + if ( ! $result ) {
326 + return false;
327 + }
328 +
329 + wp_cache_delete( $object_id, $meta_type . '_meta' );
330 +
331 + foreach ( $meta_ids as $meta_id ) {
332 + /**
333 + * Fires immediately after updating metadata of a specific type.
334 + *
335 + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
336 + * (blog, post, comment, term, user, or any other type with an associated meta table).
337 + *
338 + * Possible hook names include:
339 + *
340 + * - `updated_blog_meta`
341 + * - `updated_post_meta`
342 + * - `updated_comment_meta`
343 + * - `updated_term_meta`
344 + * - `updated_user_meta`
345 + *
346 + * @since 2.9.0
347 + *
348 + * @param int $meta_id ID of updated metadata entry.
349 + * @param int $object_id ID of the object metadata is for.
350 + * @param string $meta_key Metadata key.
351 + * @param mixed $_meta_value Metadata value.
352 + */
353 + do_action( "updated_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value );
354 +
355 + if ( 'post' === $meta_type ) {
356 + /**
357 + * Fires immediately after updating a post's metadata.
358 + *
359 + * @since 2.9.0
360 + *
361 + * @param int $meta_id ID of updated metadata entry.
362 + * @param int $object_id Post ID.
363 + * @param string $meta_key Metadata key.
364 + * @param mixed $meta_value Metadata value. This will be a PHP-serialized string representation of the value
365 + * if the value is an array, an object, or itself a PHP-serialized string.
366 + */
367 + do_action( 'updated_postmeta', $meta_id, $object_id, $meta_key, $meta_value );
368 + }
369 + }
370 +
371 + return true;
372 + }
373 +
374 + /**
375 + * Deletes metadata for the specified object.
376 + *
377 + * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input.
378 + *
379 + * @since 2.9.0
380 + *
381 + * @global wpdb $wpdb WordPress database abstraction object.
382 + *
383 + * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
384 + * 'user', or any other object type with an associated meta table.
385 + * @param int $object_id ID of the object metadata is for.
386 + * @param string $meta_key Metadata key.
387 + * @param mixed $meta_value Optional. Metadata value. Must be serializable if non-scalar.
388 + * If specified, only delete metadata entries with this value.
389 + * Otherwise, delete all entries with the specified meta_key.
390 + * Pass `null`, `false`, or an empty string to skip this check.
391 + * (For backward compatibility, it is not possible to pass an empty string
392 + * to delete those entries with an empty string for a value.)
393 + * Default empty string.
394 + * @param bool $delete_all Optional. If true, delete matching metadata entries for all objects,
395 + * ignoring the specified object_id. Otherwise, only delete
396 + * matching metadata entries for the specified object_id. Default false.
397 + * @return bool True on successful delete, false on failure.
398 + */
399 + function delete_metadata( $meta_type, $object_id, $meta_key, $meta_value = '', $delete_all = false ) {
400 + global $wpdb;
401 +
402 + if ( ! $meta_type || ! $meta_key || ! is_numeric( $object_id ) && ! $delete_all ) {
403 + return false;
404 + }
405 +
406 + $object_id = absint( $object_id );
407 + if ( ! $object_id && ! $delete_all ) {
408 + return false;
409 + }
410 +
411 + $table = _get_meta_table( $meta_type );
412 + if ( ! $table ) {
413 + return false;
414 + }
415 +
416 + $type_column = sanitize_key( $meta_type . '_id' );
417 + $id_column = ( 'user' === $meta_type ) ? 'umeta_id' : 'meta_id';
418 +
419 + // expected_slashed ($meta_key)
420 + $meta_key = wp_unslash( $meta_key );
421 + $meta_value = wp_unslash( $meta_value );
422 +
423 + /**
424 + * Short-circuits deleting metadata of a specific type.
425 + *
426 + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
427 + * (blog, post, comment, term, user, or any other type with an associated meta table).
428 + * Returning a non-null value will effectively short-circuit the function.
429 + *
430 + * Possible hook names include:
431 + *
432 + * - `delete_blog_metadata`
433 + * - `delete_post_metadata`
434 + * - `delete_comment_metadata`
435 + * - `delete_term_metadata`
436 + * - `delete_user_metadata`
437 + *
438 + * @since 3.1.0
439 + *
440 + * @param null|bool $delete Whether to allow metadata deletion of the given type.
441 + * @param int $object_id ID of the object metadata is for.
442 + * @param string $meta_key Metadata key.
443 + * @param mixed $meta_value Metadata value. Must be serializable if non-scalar.
444 + * @param bool $delete_all Whether to delete the matching metadata entries
445 + * for all objects, ignoring the specified $object_id.
446 + * Default false.
447 + */
448 + $check = apply_filters( "delete_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, $delete_all );
449 + if ( null !== $check ) {
450 + return (bool) $check;
451 + }
452 +
453 + $_meta_value = $meta_value;
454 + $meta_value = maybe_serialize( $meta_value );
455 +
456 + $query = $wpdb->prepare( "SELECT $id_column FROM $table WHERE meta_key = %s", $meta_key );
457 +
458 + if ( ! $delete_all ) {
459 + $query .= $wpdb->prepare( " AND $type_column = %d", $object_id );
460 + }
461 +
462 + if ( '' !== $meta_value && null !== $meta_value && false !== $meta_value ) {
463 + $query .= $wpdb->prepare( ' AND meta_value = %s', $meta_value );
464 + }
465 +
466 + $meta_ids = $wpdb->get_col( $query );
467 + if ( ! count( $meta_ids ) ) {
468 + return false;
469 + }
470 +
471 + if ( $delete_all ) {
472 + if ( '' !== $meta_value && null !== $meta_value && false !== $meta_value ) {
473 + $object_ids = $wpdb->get_col( $wpdb->prepare( "SELECT $type_column FROM $table WHERE meta_key = %s AND meta_value = %s", $meta_key, $meta_value ) );
474 + } else {
475 + $object_ids = $wpdb->get_col( $wpdb->prepare( "SELECT $type_column FROM $table WHERE meta_key = %s", $meta_key ) );
476 + }
477 + }
478 +
479 + /**
480 + * Fires immediately before deleting metadata of a specific type.
481 + *
482 + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
483 + * (blog, post, comment, term, user, or any other type with an associated meta table).
484 + *
485 + * Possible hook names include:
486 + *
487 + * - `delete_blog_meta`
488 + * - `delete_post_meta`
489 + * - `delete_comment_meta`
490 + * - `delete_term_meta`
491 + * - `delete_user_meta`
492 + *
493 + * @since 3.1.0
494 + *
495 + * @param string[] $meta_ids An array of metadata entry IDs to delete.
496 + * @param int $object_id ID of the object metadata is for.
497 + * @param string $meta_key Metadata key.
498 + * @param mixed $_meta_value Metadata value.
499 + */
500 + do_action( "delete_{$meta_type}_meta", $meta_ids, $object_id, $meta_key, $_meta_value );
501 +
502 + // Old-style action.
503 + if ( 'post' === $meta_type ) {
504 + /**
505 + * Fires immediately before deleting metadata for a post.
506 + *
507 + * @since 2.9.0
508 + *
509 + * @param string[] $meta_ids An array of metadata entry IDs to delete.
510 + */
511 + do_action( 'delete_postmeta', $meta_ids );
512 + }
513 +
514 + $query = "DELETE FROM $table WHERE $id_column IN( " . implode( ',', $meta_ids ) . ' )';
515 +
516 + $count = $wpdb->query( $query );
517 +
518 + if ( ! $count ) {
519 + return false;
520 + }
521 +
522 + if ( $delete_all ) {
523 + $data = (array) $object_ids;
524 + } else {
525 + $data = array( $object_id );
526 + }
527 + wp_cache_delete_multiple( $data, $meta_type . '_meta' );
528 +
529 + /**
530 + * Fires immediately after deleting metadata of a specific type.
531 + *
532 + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
533 + * (blog, post, comment, term, user, or any other type with an associated meta table).
534 + *
535 + * Possible hook names include:
536 + *
537 + * - `deleted_blog_meta`
538 + * - `deleted_post_meta`
539 + * - `deleted_comment_meta`
540 + * - `deleted_term_meta`
541 + * - `deleted_user_meta`
542 + *
543 + * @since 2.9.0
544 + *
545 + * @param string[] $meta_ids An array of metadata entry IDs to delete.
546 + * @param int $object_id ID of the object metadata is for.
547 + * @param string $meta_key Metadata key.
548 + * @param mixed $_meta_value Metadata value.
549 + */
550 + do_action( "deleted_{$meta_type}_meta", $meta_ids, $object_id, $meta_key, $_meta_value );
551 +
552 + // Old-style action.
553 + if ( 'post' === $meta_type ) {
554 + /**
555 + * Fires immediately after deleting metadata for a post.
556 + *
557 + * @since 2.9.0
558 + *
559 + * @param string[] $meta_ids An array of metadata entry IDs to delete.
560 + */
561 + do_action( 'deleted_postmeta', $meta_ids );
562 + }
563 +
564 + return true;
565 + }
566 +
567 + /**
568 + * Retrieves the value of a metadata field for the specified object type and ID.
569 + *
570 + * If the meta field exists, a single value is returned if `$single` is true,
571 + * or an array of values if it's false.
572 + *
573 + * If the meta field does not exist, the result depends on get_metadata_default().
574 + * By default, an empty string is returned if `$single` is true, or an empty array
575 + * if it's false.
576 + *
577 + * @since 2.9.0
578 + *
579 + * @see get_metadata_raw()
580 + * @see get_metadata_default()
581 + *
582 + * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
583 + * 'user', or any other object type with an associated meta table.
584 + * @param int $object_id ID of the object metadata is for.
585 + * @param string $meta_key Optional. Metadata key. If not specified, retrieve all metadata for
586 + * the specified object. Default empty string.
587 + * @param bool $single Optional. If true, return only the first value of the specified `$meta_key`.
588 + * This parameter has no effect if `$meta_key` is not specified. Default false.
589 + * @return mixed An array of values if `$single` is false.
590 + * The value of the meta field if `$single` is true.
591 + * False for an invalid `$object_id` (non-numeric, zero, or negative value),
592 + * or if `$meta_type` is not specified.
593 + * An empty array if a valid but non-existing object ID is passed and `$single` is false.
594 + * An empty string if a valid but non-existing object ID is passed and `$single` is true.
595 + * Note: Non-serialized values are returned as strings:
596 + * - false values are returned as empty strings ('')
597 + * - true values are returned as '1'
598 + * - numbers (both integer and float) are returned as strings
599 + * Arrays and objects retain their original type.
600 + */
601 + function get_metadata( $meta_type, $object_id, $meta_key = '', $single = false ) {
602 + $value = get_metadata_raw( $meta_type, $object_id, $meta_key, $single );
603 + if ( ! is_null( $value ) ) {
604 + return $value;
605 + }
606 +
607 + return get_metadata_default( $meta_type, $object_id, $meta_key, $single );
608 + }
609 +
610 + /**
611 + * Retrieves raw metadata value for the specified object.
612 + *
613 + * @since 5.5.0
614 + *
615 + * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
616 + * 'user', or any other object type with an associated meta table.
617 + * @param int $object_id ID of the object metadata is for.
618 + * @param string $meta_key Optional. Metadata key. If not specified, retrieve all metadata for
619 + * the specified object. Default empty string.
620 + * @param bool $single Optional. If true, return only the first value of the specified `$meta_key`.
621 + * This parameter has no effect if `$meta_key` is not specified. Default false.
622 + * @return mixed An array of values if `$single` is false.
623 + * The value of the meta field if `$single` is true.
624 + * False for an invalid `$object_id` (non-numeric, zero, or negative value),
625 + * or if `$meta_type` is not specified.
626 + * Null if the value does not exist.
627 + */
628 + function get_metadata_raw( $meta_type, $object_id, $meta_key = '', $single = false ) {
629 + if ( ! $meta_type || ! is_numeric( $object_id ) ) {
630 + return false;
631 + }
632 +
633 + $object_id = absint( $object_id );
634 + if ( ! $object_id ) {
635 + return false;
636 + }
637 +
638 + /**
639 + * Short-circuits the return value of a meta field.
640 + *
641 + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
642 + * (blog, post, comment, term, user, or any other type with an associated meta table).
643 + * Returning a non-null value will effectively short-circuit the function.
644 + *
645 + * Possible filter names include:
646 + *
647 + * - `get_blog_metadata`
648 + * - `get_post_metadata`
649 + * - `get_comment_metadata`
650 + * - `get_term_metadata`
651 + * - `get_user_metadata`
652 + *
653 + * @since 3.1.0
654 + * @since 5.5.0 Added the `$meta_type` parameter.
655 + *
656 + * @param mixed $value The value to return, either a single metadata value or an array
657 + * of values depending on the value of `$single`. Default null.
658 + * @param int $object_id ID of the object metadata is for.
659 + * @param string $meta_key Metadata key.
660 + * @param bool $single Whether to return only the first value of the specified `$meta_key`.
661 + * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
662 + * 'user', or any other object type with an associated meta table.
663 + */
664 + $check = apply_filters( "get_{$meta_type}_metadata", null, $object_id, $meta_key, $single, $meta_type );
665 + if ( null !== $check ) {
666 + if ( $single && is_array( $check ) ) {
667 + return $check[0];
668 + } else {
669 + return $check;
670 + }
671 + }
672 +
673 + $meta_cache = wp_cache_get( $object_id, $meta_type . '_meta' );
674 +
675 + if ( ! $meta_cache ) {
676 + $meta_cache = update_meta_cache( $meta_type, array( $object_id ) );
677 + if ( isset( $meta_cache[ $object_id ] ) ) {
678 + $meta_cache = $meta_cache[ $object_id ];
679 + } else {
680 + $meta_cache = null;
681 + }
682 + }
683 +
684 + if ( ! $meta_key ) {
685 + return $meta_cache;
686 + }
687 +
688 + if ( isset( $meta_cache[ $meta_key ] ) ) {
689 + if ( $single ) {
690 + return maybe_unserialize( $meta_cache[ $meta_key ][0] );
691 + } else {
692 + return array_map( 'maybe_unserialize', $meta_cache[ $meta_key ] );
693 + }
694 + }
695 +
696 + return null;
697 + }
698 +
699 + /**
700 + * Retrieves default metadata value for the specified meta key and object.
701 + *
702 + * By default, an empty string is returned if `$single` is true, or an empty array
703 + * if it's false.
704 + *
705 + * @since 5.5.0
706 + *
707 + * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
708 + * 'user', or any other object type with an associated meta table.
709 + * @param int $object_id ID of the object metadata is for.
710 + * @param string $meta_key Metadata key.
711 + * @param bool $single Optional. If true, return only the first value of the specified `$meta_key`.
712 + * This parameter has no effect if `$meta_key` is not specified. Default false.
713 + * @return mixed An array of default values if `$single` is false.
714 + * The default value of the meta field if `$single` is true.
715 + */
716 + function get_metadata_default( $meta_type, $object_id, $meta_key, $single = false ) {
717 + if ( $single ) {
718 + $value = '';
719 + } else {
720 + $value = array();
721 + }
722 +
723 + /**
724 + * Filters the default metadata value for a specified meta key and object.
725 + *
726 + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
727 + * (blog, post, comment, term, user, or any other type with an associated meta table).
728 + *
729 + * Possible filter names include:
730 + *
731 + * - `default_blog_metadata`
732 + * - `default_post_metadata`
733 + * - `default_comment_metadata`
734 + * - `default_term_metadata`
735 + * - `default_user_metadata`
736 + *
737 + * @since 5.5.0
738 + *
739 + * @param mixed $value The value to return, either a single metadata value or an array
740 + * of values depending on the value of `$single`.
741 + * @param int $object_id ID of the object metadata is for.
742 + * @param string $meta_key Metadata key.
743 + * @param bool $single Whether to return only the first value of the specified `$meta_key`.
744 + * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
745 + * 'user', or any other object type with an associated meta table.
746 + */
747 + $value = apply_filters( "default_{$meta_type}_metadata", $value, $object_id, $meta_key, $single, $meta_type );
748 +
749 + if ( ! $single && ! wp_is_numeric_array( $value ) ) {
750 + $value = array( $value );
751 + }
752 +
753 + return $value;
754 + }
755 +
756 + /**
757 + * Determines if a meta field with the given key exists for the given object ID.
758 + *
759 + * @since 3.3.0
760 + *
761 + * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
762 + * 'user', or any other object type with an associated meta table.
763 + * @param int $object_id ID of the object metadata is for.
764 + * @param string $meta_key Metadata key.
765 + * @return bool Whether a meta field with the given key exists.
766 + */
767 + function metadata_exists( $meta_type, $object_id, $meta_key ) {
768 + if ( ! $meta_type || ! is_numeric( $object_id ) ) {
769 + return false;
770 + }
771 +
772 + $object_id = absint( $object_id );
773 + if ( ! $object_id ) {
774 + return false;
775 + }
776 +
777 + /** This filter is documented in wp-includes/meta.php */
778 + $check = apply_filters( "get_{$meta_type}_metadata", null, $object_id, $meta_key, true, $meta_type );
779 + if ( null !== $check ) {
780 + return (bool) $check;
781 + }
782 +
783 + $meta_cache = wp_cache_get( $object_id, $meta_type . '_meta' );
784 +
785 + if ( ! $meta_cache ) {
786 + $meta_cache = update_meta_cache( $meta_type, array( $object_id ) );
787 + $meta_cache = $meta_cache[ $object_id ];
788 + }
789 +
790 + if ( isset( $meta_cache[ $meta_key ] ) ) {
791 + return true;
792 + }
793 +
794 + return false;
795 + }
796 +
797 + /**
798 + * Retrieves metadata by meta ID.
799 + *
800 + * @since 3.3.0
801 + *
802 + * @global wpdb $wpdb WordPress database abstraction object.
803 + *
804 + * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
805 + * 'user', or any other object type with an associated meta table.
806 + * @param int $meta_id ID for a specific meta row.
807 + * @return stdClass|false {
808 + * Metadata object, or boolean `false` if the metadata doesn't exist.
809 + *
810 + * @type string $meta_key The meta key.
811 + * @type mixed $meta_value The unserialized meta value.
812 + * @type string $meta_id Optional. The meta ID when the meta type is any value except 'user'.
813 + * @type string $umeta_id Optional. The meta ID when the meta type is 'user'.
814 + * @type string $blog_id Optional. The object ID when the meta type is 'blog'.
815 + * @type string $post_id Optional. The object ID when the meta type is 'post'.
816 + * @type string $comment_id Optional. The object ID when the meta type is 'comment'.
817 + * @type string $term_id Optional. The object ID when the meta type is 'term'.
818 + * @type string $user_id Optional. The object ID when the meta type is 'user'.
819 + * }
820 + */
821 + function get_metadata_by_mid( $meta_type, $meta_id ) {
822 + global $wpdb;
823 +
824 + if ( ! $meta_type || ! is_numeric( $meta_id ) || floor( $meta_id ) != $meta_id ) {
825 + return false;
826 + }
827 +
828 + $meta_id = (int) $meta_id;
829 + if ( $meta_id <= 0 ) {
830 + return false;
831 + }
832 +
833 + $table = _get_meta_table( $meta_type );
834 + if ( ! $table ) {
835 + return false;
836 + }
837 +
838 + /**
839 + * Short-circuits the return value when fetching a meta field by meta ID.
840 + *
841 + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
842 + * (blog, post, comment, term, user, or any other type with an associated meta table).
843 + * Returning a non-null value will effectively short-circuit the function.
844 + *
845 + * Possible hook names include:
846 + *
847 + * - `get_blog_metadata_by_mid`
848 + * - `get_post_metadata_by_mid`
849 + * - `get_comment_metadata_by_mid`
850 + * - `get_term_metadata_by_mid`
851 + * - `get_user_metadata_by_mid`
852 + *
853 + * @since 5.0.0
854 + *
855 + * @param stdClass|null $value The value to return.
856 + * @param int $meta_id Meta ID.
857 + */
858 + $check = apply_filters( "get_{$meta_type}_metadata_by_mid", null, $meta_id );
859 + if ( null !== $check ) {
860 + return $check;
861 + }
862 +
863 + $id_column = ( 'user' === $meta_type ) ? 'umeta_id' : 'meta_id';
864 +
865 + $meta = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table WHERE $id_column = %d", $meta_id ) );
866 +
867 + if ( empty( $meta ) ) {
868 + return false;
869 + }
870 +
871 + if ( isset( $meta->meta_value ) ) {
872 + $meta->meta_value = maybe_unserialize( $meta->meta_value );
873 + }
874 +
875 + return $meta;
876 + }
877 +
878 + /**
879 + * Updates metadata by meta ID.
880 + *
881 + * @since 3.3.0
882 + *
883 + * @global wpdb $wpdb WordPress database abstraction object.
884 + *
885 + * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
886 + * 'user', or any other object type with an associated meta table.
887 + * @param int $meta_id ID for a specific meta row.
888 + * @param string $meta_value Metadata value. Must be serializable if non-scalar.
889 + * @param string|false $meta_key Optional. You can provide a meta key to update it. Default false.
890 + * @return bool True on successful update, false on failure.
891 + */
892 + function update_metadata_by_mid( $meta_type, $meta_id, $meta_value, $meta_key = false ) {
893 + global $wpdb;
894 +
895 + // Make sure everything is valid.
896 + if ( ! $meta_type || ! is_numeric( $meta_id ) || floor( $meta_id ) != $meta_id ) {
897 + return false;
898 + }
899 +
900 + $meta_id = (int) $meta_id;
901 + if ( $meta_id <= 0 ) {
902 + return false;
903 + }
904 +
905 + $table = _get_meta_table( $meta_type );
906 + if ( ! $table ) {
907 + return false;
908 + }
909 +
910 + $column = sanitize_key( $meta_type . '_id' );
911 + $id_column = ( 'user' === $meta_type ) ? 'umeta_id' : 'meta_id';
912 +
913 + /**
914 + * Short-circuits updating metadata of a specific type by meta ID.
915 + *
916 + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
917 + * (blog, post, comment, term, user, or any other type with an associated meta table).
918 + * Returning a non-null value will effectively short-circuit the function.
919 + *
920 + * Possible hook names include:
921 + *
922 + * - `update_blog_metadata_by_mid`
923 + * - `update_post_metadata_by_mid`
924 + * - `update_comment_metadata_by_mid`
925 + * - `update_term_metadata_by_mid`
926 + * - `update_user_metadata_by_mid`
927 + *
928 + * @since 5.0.0
929 + *
930 + * @param null|bool $check Whether to allow updating metadata for the given type.
931 + * @param int $meta_id Meta ID.
932 + * @param mixed $meta_value Meta value. Must be serializable if non-scalar.
933 + * @param string|false $meta_key Meta key, if provided.
934 + */
935 + $check = apply_filters( "update_{$meta_type}_metadata_by_mid", null, $meta_id, $meta_value, $meta_key );
936 + if ( null !== $check ) {
937 + return (bool) $check;
938 + }
939 +
940 + // Fetch the meta and go on if it's found.
941 + $meta = get_metadata_by_mid( $meta_type, $meta_id );
942 + if ( $meta ) {
943 + $original_key = $meta->meta_key;
944 + $object_id = $meta->{$column};
945 +
946 + /*
947 + * If a new meta_key (last parameter) was specified, change the meta key,
948 + * otherwise use the original key in the update statement.
949 + */
950 + if ( false === $meta_key ) {
951 + $meta_key = $original_key;
952 + } elseif ( ! is_string( $meta_key ) ) {
953 + return false;
954 + }
955 +
956 + $meta_subtype = get_object_subtype( $meta_type, $object_id );
957 +
958 + // Sanitize the meta.
959 + $_meta_value = $meta_value;
960 + $meta_value = sanitize_meta( $meta_key, $meta_value, $meta_type, $meta_subtype );
961 + $meta_value = maybe_serialize( $meta_value );
962 +
963 + // Format the data query arguments.
964 + $data = array(
965 + 'meta_key' => $meta_key,
966 + 'meta_value' => $meta_value,
967 + );
968 +
969 + // Format the where query arguments.
970 + $where = array();
971 + $where[ $id_column ] = $meta_id;
972 +
973 + /** This action is documented in wp-includes/meta.php */
974 + do_action( "update_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value );
975 +
976 + if ( 'post' === $meta_type ) {
977 + /** This action is documented in wp-includes/meta.php */
978 + do_action( 'update_postmeta', $meta_id, $object_id, $meta_key, $meta_value );
979 + }
980 +
981 + // Run the update query, all fields in $data are %s, $where is a %d.
982 + $result = $wpdb->update( $table, $data, $where, '%s', '%d' );
983 + if ( ! $result ) {
984 + return false;
985 + }
986 +
987 + // Clear the caches.
988 + wp_cache_delete( $object_id, $meta_type . '_meta' );
989 +
990 + /** This action is documented in wp-includes/meta.php */
991 + do_action( "updated_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value );
992 +
993 + if ( 'post' === $meta_type ) {
994 + /** This action is documented in wp-includes/meta.php */
995 + do_action( 'updated_postmeta', $meta_id, $object_id, $meta_key, $meta_value );
996 + }
997 +
998 + return true;
999 + }
1000 +
1001 + // And if the meta was not found.
1002 + return false;
1003 + }
1004 +
1005 + /**
1006 + * Deletes metadata by meta ID.
1007 + *
1008 + * @since 3.3.0
1009 + *
1010 + * @global wpdb $wpdb WordPress database abstraction object.
1011 + *
1012 + * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
1013 + * 'user', or any other object type with an associated meta table.
1014 + * @param int $meta_id ID for a specific meta row.
1015 + * @return bool True on successful delete, false on failure.
1016 + */
1017 + function delete_metadata_by_mid( $meta_type, $meta_id ) {
1018 + global $wpdb;
1019 +
1020 + // Make sure everything is valid.
1021 + if ( ! $meta_type || ! is_numeric( $meta_id ) || floor( $meta_id ) != $meta_id ) {
1022 + return false;
1023 + }
1024 +
1025 + $meta_id = (int) $meta_id;
1026 + if ( $meta_id <= 0 ) {
1027 + return false;
1028 + }
1029 +
1030 + $table = _get_meta_table( $meta_type );
1031 + if ( ! $table ) {
1032 + return false;
1033 + }
1034 +
1035 + // Object and ID columns.
1036 + $column = sanitize_key( $meta_type . '_id' );
1037 + $id_column = ( 'user' === $meta_type ) ? 'umeta_id' : 'meta_id';
1038 +
1039 + /**
1040 + * Short-circuits deleting metadata of a specific type by meta ID.
1041 + *
1042 + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
1043 + * (blog, post, comment, term, user, or any other type with an associated meta table).
1044 + * Returning a non-null value will effectively short-circuit the function.
1045 + *
1046 + * Possible hook names include:
1047 + *
1048 + * - `delete_blog_metadata_by_mid`
1049 + * - `delete_post_metadata_by_mid`
1050 + * - `delete_comment_metadata_by_mid`
1051 + * - `delete_term_metadata_by_mid`
1052 + * - `delete_user_metadata_by_mid`
1053 + *
1054 + * @since 5.0.0
1055 + *
1056 + * @param null|bool $delete Whether to allow metadata deletion of the given type.
1057 + * @param int $meta_id Meta ID.
1058 + */
1059 + $check = apply_filters( "delete_{$meta_type}_metadata_by_mid", null, $meta_id );
1060 + if ( null !== $check ) {
1061 + return (bool) $check;
1062 + }
1063 +
1064 + // Fetch the meta and go on if it's found.
1065 + $meta = get_metadata_by_mid( $meta_type, $meta_id );
1066 + if ( $meta ) {
1067 + $object_id = (int) $meta->{$column};
1068 +
1069 + /** This action is documented in wp-includes/meta.php */
1070 + do_action( "delete_{$meta_type}_meta", (array) $meta_id, $object_id, $meta->meta_key, $meta->meta_value );
1071 +
1072 + // Old-style action.
1073 + if ( 'post' === $meta_type || 'comment' === $meta_type ) {
1074 + /**
1075 + * Fires immediately before deleting post or comment metadata of a specific type.
1076 + *
1077 + * The dynamic portion of the hook name, `$meta_type`, refers to the meta
1078 + * object type (post or comment).
1079 + *
1080 + * Possible hook names include:
1081 + *
1082 + * - `delete_postmeta`
1083 + * - `delete_commentmeta`
1084 + *
1085 + * @since 3.4.0
1086 + *
1087 + * @param int $meta_id ID of the metadata entry to delete.
1088 + */
1089 + do_action( "delete_{$meta_type}meta", $meta_id );
1090 + }
1091 +
1092 + // Run the query, will return true if deleted, false otherwise.
1093 + $result = (bool) $wpdb->delete( $table, array( $id_column => $meta_id ) );
1094 +
1095 + // Clear the caches.
1096 + wp_cache_delete( $object_id, $meta_type . '_meta' );
1097 +
1098 + /** This action is documented in wp-includes/meta.php */
1099 + do_action( "deleted_{$meta_type}_meta", (array) $meta_id, $object_id, $meta->meta_key, $meta->meta_value );
1100 +
1101 + // Old-style action.
1102 + if ( 'post' === $meta_type || 'comment' === $meta_type ) {
1103 + /**
1104 + * Fires immediately after deleting post or comment metadata of a specific type.
1105 + *
1106 + * The dynamic portion of the hook name, `$meta_type`, refers to the meta
1107 + * object type (post or comment).
1108 + *
1109 + * Possible hook names include:
1110 + *
1111 + * - `deleted_postmeta`
1112 + * - `deleted_commentmeta`
1113 + *
1114 + * @since 3.4.0
1115 + *
1116 + * @param int $meta_id Deleted metadata entry ID.
1117 + */
1118 + do_action( "deleted_{$meta_type}meta", $meta_id );
1119 + }
1120 +
1121 + return $result;
1122 +
1123 + }
1124 +
1125 + // Meta ID was not found.
1126 + return false;
1127 + }
1128 +
1129 + /**
1130 + * Updates the metadata cache for the specified objects.
1131 + *
1132 + * @since 2.9.0
1133 + *
1134 + * @global wpdb $wpdb WordPress database abstraction object.
1135 + *
1136 + * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
1137 + * 'user', or any other object type with an associated meta table.
1138 + * @param string|int[] $object_ids Array or comma delimited list of object IDs to update cache for.
1139 + * @return array|false Metadata cache for the specified objects, or false on failure.
1140 + */
1141 + function update_meta_cache( $meta_type, $object_ids ) {
1142 + global $wpdb;
1143 +
1144 + if ( ! $meta_type || ! $object_ids ) {
1145 + return false;
1146 + }
1147 +
1148 + $table = _get_meta_table( $meta_type );
1149 + if ( ! $table ) {
1150 + return false;
1151 + }
1152 +
1153 + $column = sanitize_key( $meta_type . '_id' );
1154 +
1155 + if ( ! is_array( $object_ids ) ) {
1156 + $object_ids = preg_replace( '|[^0-9,]|', '', $object_ids );
1157 + $object_ids = explode( ',', $object_ids );
1158 + }
1159 +
1160 + $object_ids = array_map( 'intval', $object_ids );
1161 +
1162 + /**
1163 + * Short-circuits updating the metadata cache of a specific type.
1164 + *
1165 + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
1166 + * (blog, post, comment, term, user, or any other type with an associated meta table).
1167 + * Returning a non-null value will effectively short-circuit the function.
1168 + *
1169 + * Possible hook names include:
1170 + *
1171 + * - `update_blog_metadata_cache`
1172 + * - `update_post_metadata_cache`
1173 + * - `update_comment_metadata_cache`
1174 + * - `update_term_metadata_cache`
1175 + * - `update_user_metadata_cache`
1176 + *
1177 + * @since 5.0.0
1178 + *
1179 + * @param mixed $check Whether to allow updating the meta cache of the given type.
1180 + * @param int[] $object_ids Array of object IDs to update the meta cache for.
1181 + */
1182 + $check = apply_filters( "update_{$meta_type}_metadata_cache", null, $object_ids );
1183 + if ( null !== $check ) {
1184 + return (bool) $check;
1185 + }
1186 +
1187 + $cache_group = $meta_type . '_meta';
1188 + $non_cached_ids = array();
1189 + $cache = array();
1190 + $cache_values = wp_cache_get_multiple( $object_ids, $cache_group );
1191 +
1192 + foreach ( $cache_values as $id => $cached_object ) {
1193 + if ( false === $cached_object ) {
1194 + $non_cached_ids[] = $id;
1195 + } else {
1196 + $cache[ $id ] = $cached_object;
1197 + }
1198 + }
1199 +
1200 + if ( empty( $non_cached_ids ) ) {
1201 + return $cache;
1202 + }
1203 +
1204 + // Get meta info.
1205 + $id_list = implode( ',', $non_cached_ids );
1206 + $id_column = ( 'user' === $meta_type ) ? 'umeta_id' : 'meta_id';
1207 +
1208 + $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 );
1209 +
1210 + if ( ! empty( $meta_list ) ) {
1211 + foreach ( $meta_list as $metarow ) {
1212 + $mpid = (int) $metarow[ $column ];
1213 + $mkey = $metarow['meta_key'];
1214 + $mval = $metarow['meta_value'];
1215 +
1216 + // Force subkeys to be array type.
1217 + if ( ! isset( $cache[ $mpid ] ) || ! is_array( $cache[ $mpid ] ) ) {
1218 + $cache[ $mpid ] = array();
1219 + }
1220 + if ( ! isset( $cache[ $mpid ][ $mkey ] ) || ! is_array( $cache[ $mpid ][ $mkey ] ) ) {
1221 + $cache[ $mpid ][ $mkey ] = array();
1222 + }
1223 +
1224 + // Add a value to the current pid/key.
1225 + $cache[ $mpid ][ $mkey ][] = $mval;
1226 + }
1227 + }
1228 +
1229 + $data = array();
1230 + foreach ( $non_cached_ids as $id ) {
1231 + if ( ! isset( $cache[ $id ] ) ) {
1232 + $cache[ $id ] = array();
1233 + }
1234 + $data[ $id ] = $cache[ $id ];
1235 + }
1236 + wp_cache_add_multiple( $data, $cache_group );
1237 +
1238 + return $cache;
1239 + }
1240 +
1241 + /**
1242 + * Retrieves the queue for lazy-loading metadata.
1243 + *
1244 + * @since 4.5.0
1245 + *
1246 + * @return WP_Metadata_Lazyloader Metadata lazyloader queue.
1247 + */
1248 + function wp_metadata_lazyloader() {
1249 + static $wp_metadata_lazyloader;
1250 +
1251 + if ( null === $wp_metadata_lazyloader ) {
1252 + $wp_metadata_lazyloader = new WP_Metadata_Lazyloader();
1253 + }
1254 +
1255 + return $wp_metadata_lazyloader;
1256 + }
1257 +
1258 + /**
1259 + * Given a meta query, generates SQL clauses to be appended to a main query.
1260 + *
1261 + * @since 3.2.0
1262 + *
1263 + * @see WP_Meta_Query
1264 + *
1265 + * @param array $meta_query A meta query.
1266 + * @param string $type Type of meta.
1267 + * @param string $primary_table Primary database table name.
1268 + * @param string $primary_id_column Primary ID column name.
1269 + * @param object $context Optional. The main query object. Default null.
1270 + * @return string[]|false {
1271 + * Array containing JOIN and WHERE SQL clauses to append to the main query,
1272 + * or false if no table exists for the requested meta type.
1273 + *
1274 + * @type string $join SQL fragment to append to the main JOIN clause.
1275 + * @type string $where SQL fragment to append to the main WHERE clause.
1276 + * }
1277 + */
1278 + function get_meta_sql( $meta_query, $type, $primary_table, $primary_id_column, $context = null ) {
1279 + $meta_query_obj = new WP_Meta_Query( $meta_query );
1280 + return $meta_query_obj->get_sql( $type, $primary_table, $primary_id_column, $context );
1281 + }
1282 +
1283 + /**
1284 + * Retrieves the name of the metadata table for the specified object type.
1285 + *
1286 + * @since 2.9.0
1287 + *
1288 + * @global wpdb $wpdb WordPress database abstraction object.
1289 + *
1290 + * @param string $type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
1291 + * 'user', or any other object type with an associated meta table.
1292 + * @return string|false Metadata table name, or false if no metadata table exists
1293 + */
1294 + function _get_meta_table( $type ) {
1295 + global $wpdb;
1296 +
1297 + $table_name = $type . 'meta';
1298 +
1299 + if ( empty( $wpdb->$table_name ) ) {
1300 + return false;
1301 + }
1302 +
1303 + return $wpdb->$table_name;
1304 + }
1305 +
1306 + /**
1307 + * Determines whether a meta key is considered protected.
1308 + *
1309 + * @since 3.1.3
1310 + *
1311 + * @param string $meta_key Metadata key.
1312 + * @param string $meta_type Optional. Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
1313 + * 'user', or any other object type with an associated meta table. Default empty string.
1314 + * @return bool Whether the meta key is considered protected.
1315 + */
1316 + function is_protected_meta( $meta_key, $meta_type = '' ) {
1317 + $sanitized_key = preg_replace( "/[^\x20-\x7E\p{L}]/", '', $meta_key );
1318 + $protected = strlen( $sanitized_key ) > 0 && ( '_' === $sanitized_key[0] );
1319 +
1320 + /**
1321 + * Filters whether a meta key is considered protected.
1322 + *
1323 + * @since 3.2.0
1324 + *
1325 + * @param bool $protected Whether the key is considered protected.
1326 + * @param string $meta_key Metadata key.
1327 + * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
1328 + * 'user', or any other object type with an associated meta table.
1329 + */
1330 + return apply_filters( 'is_protected_meta', $protected, $meta_key, $meta_type );
1331 + }
1332 +
1333 + /**
1334 + * Sanitizes meta value.
1335 + *
1336 + * @since 3.1.3
1337 + * @since 4.9.8 The `$object_subtype` parameter was added.
1338 + *
1339 + * @param string $meta_key Metadata key.
1340 + * @param mixed $meta_value Metadata value to sanitize.
1341 + * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
1342 + * 'user', or any other object type with an associated meta table.
1343 + * @param string $object_subtype Optional. The subtype of the object type. Default empty string.
1344 + * @return mixed Sanitized $meta_value.
1345 + */
1346 + function sanitize_meta( $meta_key, $meta_value, $object_type, $object_subtype = '' ) {
1347 + if ( ! empty( $object_subtype ) && has_filter( "sanitize_{$object_type}_meta_{$meta_key}_for_{$object_subtype}" ) ) {
1348 +
1349 + /**
1350 + * Filters the sanitization of a specific meta key of a specific meta type and subtype.
1351 + *
1352 + * The dynamic portions of the hook name, `$object_type`, `$meta_key`,
1353 + * and `$object_subtype`, refer to the metadata object type (blog, comment, post, term, or user),
1354 + * the meta key value, and the object subtype respectively.
1355 + *
1356 + * @since 4.9.8
1357 + *
1358 + * @param mixed $meta_value Metadata value to sanitize.
1359 + * @param string $meta_key Metadata key.
1360 + * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
1361 + * 'user', or any other object type with an associated meta table.
1362 + * @param string $object_subtype Object subtype.
1363 + */
1364 + return apply_filters( "sanitize_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $meta_value, $meta_key, $object_type, $object_subtype );
1365 + }
1366 +
1367 + /**
1368 + * Filters the sanitization of a specific meta key of a specific meta type.
1369 + *
1370 + * The dynamic portions of the hook name, `$meta_type`, and `$meta_key`,
1371 + * refer to the metadata object type (blog, comment, post, term, or user) and the meta
1372 + * key value, respectively.
1373 + *
1374 + * @since 3.3.0
1375 + *
1376 + * @param mixed $meta_value Metadata value to sanitize.
1377 + * @param string $meta_key Metadata key.
1378 + * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
1379 + * 'user', or any other object type with an associated meta table.
1380 + */
1381 + return apply_filters( "sanitize_{$object_type}_meta_{$meta_key}", $meta_value, $meta_key, $object_type );
1382 + }
1383 +
1384 + /**
1385 + * Registers a meta key.
1386 + *
1387 + * It is recommended to register meta keys for a specific combination of object type and object subtype. If passing
1388 + * an object subtype is omitted, the meta key will be registered for the entire object type, however it can be partly
1389 + * overridden in case a more specific meta key of the same name exists for the same object type and a subtype.
1390 + *
1391 + * If an object type does not support any subtypes, such as blogs, users, or comments, you should commonly call this function
1392 + * without passing a subtype.
1393 + *
1394 + * @since 3.3.0
1395 + * @since 4.6.0 {@link https://core.trac.wordpress.org/ticket/35658 Modified
1396 + * to support an array of data to attach to registered meta keys}. Previous arguments for
1397 + * `$sanitize_callback` and `$auth_callback` have been folded into this array.
1398 + * @since 4.9.8 The `$object_subtype` argument was added to the arguments array.
1399 + * @since 5.3.0 Valid meta types expanded to include "array" and "object".
1400 + * @since 5.5.0 The `$default` argument was added to the arguments array.
1401 + * @since 6.4.0 The `$revisions_enabled` argument was added to the arguments array.
1402 + * @since 6.7.0 The `label` argument was added to the arguments array.
1403 + *
1404 + * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
1405 + * 'user', or any other object type with an associated meta table.
1406 + * @param string $meta_key Meta key to register.
1407 + * @param array $args {
1408 + * Data used to describe the meta key when registered.
1409 + *
1410 + * @type string $object_subtype A subtype; e.g. if the object type is "post", the post type. If left empty,
1411 + * the meta key will be registered on the entire object type. Default empty.
1412 + * @type string $type The type of data associated with this meta key.
1413 + * Valid values are 'string', 'boolean', 'integer', 'number', 'array', and 'object'.
1414 + * @type string $label A human-readable label of the data attached to this meta key.
1415 + * @type string $description A description of the data attached to this meta key.
1416 + * @type bool $single Whether the meta key has one value per object, or an array of values per object.
1417 + * @type mixed $default The default value returned from get_metadata() if no value has been set yet.
1418 + * When using a non-single meta key, the default value is for the first entry.
1419 + * In other words, when calling get_metadata() with `$single` set to `false`,
1420 + * the default value given here will be wrapped in an array.
1421 + * @type callable $sanitize_callback A function or method to call when sanitizing `$meta_key` data.
1422 + * @type callable $auth_callback Optional. A function or method to call when performing edit_post_meta,
1423 + * add_post_meta, and delete_post_meta capability checks.
1424 + * @type bool|array $show_in_rest Whether data associated with this meta key can be considered public and
1425 + * should be accessible via the REST API. A custom post type must also declare
1426 + * support for custom fields for registered meta to be accessible via REST.
1427 + * When registering complex meta values this argument may optionally be an
1428 + * array with 'schema' or 'prepare_callback' keys instead of a boolean.
1429 + * @type bool $revisions_enabled Whether to enable revisions support for this meta_key. Can only be used when the
1430 + * object type is 'post'.
1431 + * }
1432 + * @param string|array $deprecated Deprecated. Use `$args` instead.
1433 + * @return bool True if the meta key was successfully registered in the global array, false if not.
1434 + * Registering a meta key with distinct sanitize and auth callbacks will fire those callbacks,
1435 + * but will not add to the global registry.
1436 + */
1437 + function register_meta( $object_type, $meta_key, $args, $deprecated = null ) {
1438 + global $wp_meta_keys;
1439 +
1440 + if ( ! is_array( $wp_meta_keys ) ) {
1441 + $wp_meta_keys = array();
1442 + }
1443 +
1444 + $defaults = array(
1445 + 'object_subtype' => '',
1446 + 'type' => 'string',
1447 + 'label' => '',
1448 + 'description' => '',
1449 + 'default' => '',
1450 + 'single' => false,
1451 + 'sanitize_callback' => null,
1452 + 'auth_callback' => null,
1453 + 'show_in_rest' => false,
1454 + 'revisions_enabled' => false,
1455 + );
1456 +
1457 + // There used to be individual args for sanitize and auth callbacks.
1458 + $has_old_sanitize_cb = false;
1459 + $has_old_auth_cb = false;
1460 +
1461 + if ( is_callable( $args ) ) {
1462 + $args = array(
1463 + 'sanitize_callback' => $args,
1464 + );
1465 +
1466 + $has_old_sanitize_cb = true;
1467 + } else {
1468 + $args = (array) $args;
1469 + }
1470 +
1471 + if ( is_callable( $deprecated ) ) {
1472 + $args['auth_callback'] = $deprecated;
1473 + $has_old_auth_cb = true;
1474 + }
1475 +
1476 + /**
1477 + * Filters the registration arguments when registering meta.
1478 + *
1479 + * @since 4.6.0
1480 + *
1481 + * @param array $args Array of meta registration arguments.
1482 + * @param array $defaults Array of default arguments.
1483 + * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
1484 + * 'user', or any other object type with an associated meta table.
1485 + * @param string $meta_key Meta key.
1486 + */
1487 + $args = apply_filters( 'register_meta_args', $args, $defaults, $object_type, $meta_key );
1488 + unset( $defaults['default'] );
1489 + $args = wp_parse_args( $args, $defaults );
1490 +
1491 + // Require an item schema when registering array meta.
1492 + if ( false !== $args['show_in_rest'] && 'array' === $args['type'] ) {
1493 + if ( ! is_array( $args['show_in_rest'] ) || ! isset( $args['show_in_rest']['schema']['items'] ) ) {
1494 + _doing_it_wrong( __FUNCTION__, __( 'When registering an "array" meta type to show in the REST API, you must specify the schema for each array item in "show_in_rest.schema.items".' ), '5.3.0' );
1495 +
1496 + return false;
1497 + }
1498 + }
1499 +
1500 + $object_subtype = ! empty( $args['object_subtype'] ) ? $args['object_subtype'] : '';
1501 + if ( $args['revisions_enabled'] ) {
1502 + if ( 'post' !== $object_type ) {
1503 + _doing_it_wrong( __FUNCTION__, __( 'Meta keys cannot enable revisions support unless the object type supports revisions.' ), '6.4.0' );
1504 +
1505 + return false;
1506 + } elseif ( ! empty( $object_subtype ) && ! post_type_supports( $object_subtype, 'revisions' ) ) {
1507 + _doing_it_wrong( __FUNCTION__, __( 'Meta keys cannot enable revisions support unless the object subtype supports revisions.' ), '6.4.0' );
1508 +
1509 + return false;
1510 + }
1511 + }
1512 +
1513 + // If `auth_callback` is not provided, fall back to `is_protected_meta()`.
1514 + if ( empty( $args['auth_callback'] ) ) {
1515 + if ( is_protected_meta( $meta_key, $object_type ) ) {
1516 + $args['auth_callback'] = '__return_false';
1517 + } else {
1518 + $args['auth_callback'] = '__return_true';
1519 + }
1520 + }
1521 +
1522 + // Back-compat: old sanitize and auth callbacks are applied to all of an object type.
1523 + if ( is_callable( $args['sanitize_callback'] ) ) {
1524 + if ( ! empty( $object_subtype ) ) {
1525 + add_filter( "sanitize_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $args['sanitize_callback'], 10, 4 );
1526 + } else {
1527 + add_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'], 10, 3 );
1528 + }
1529 + }
1530 +
1531 + if ( is_callable( $args['auth_callback'] ) ) {
1532 + if ( ! empty( $object_subtype ) ) {
1533 + add_filter( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $args['auth_callback'], 10, 6 );
1534 + } else {
1535 + add_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'], 10, 6 );
1536 + }
1537 + }
1538 +
1539 + if ( array_key_exists( 'default', $args ) ) {
1540 + $schema = $args;
1541 + if ( is_array( $args['show_in_rest'] ) && isset( $args['show_in_rest']['schema'] ) ) {
1542 + $schema = array_merge( $schema, $args['show_in_rest']['schema'] );
1543 + }
1544 +
1545 + $check = rest_validate_value_from_schema( $args['default'], $schema );
1546 + if ( is_wp_error( $check ) ) {
1547 + _doing_it_wrong( __FUNCTION__, __( 'When registering a default meta value the data must match the type provided.' ), '5.5.0' );
1548 +
1549 + return false;
1550 + }
1551 +
1552 + if ( ! has_filter( "default_{$object_type}_metadata", 'filter_default_metadata' ) ) {
1553 + add_filter( "default_{$object_type}_metadata", 'filter_default_metadata', 10, 5 );
1554 + }
1555 + }
1556 +
1557 + // Global registry only contains meta keys registered with the array of arguments added in 4.6.0.
1558 + if ( ! $has_old_auth_cb && ! $has_old_sanitize_cb ) {
1559 + unset( $args['object_subtype'] );
1560 +
1561 + $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ] = $args;
1562 +
1563 + return true;
1564 + }
1565 +
1566 + return false;
1567 + }
1568 +
1569 + /**
1570 + * Filters into default_{$object_type}_metadata and adds in default value.
1571 + *
1572 + * @since 5.5.0
1573 + *
1574 + * @param mixed $value Current value passed to filter.
1575 + * @param int $object_id ID of the object metadata is for.
1576 + * @param string $meta_key Metadata key.
1577 + * @param bool $single If true, return only the first value of the specified `$meta_key`.
1578 + * This parameter has no effect if `$meta_key` is not specified.
1579 + * @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
1580 + * 'user', or any other object type with an associated meta table.
1581 + * @return mixed An array of default values if `$single` is false.
1582 + * The default value of the meta field if `$single` is true.
1583 + */
1584 + function filter_default_metadata( $value, $object_id, $meta_key, $single, $meta_type ) {
1585 + global $wp_meta_keys;
1586 +
1587 + if ( wp_installing() ) {
1588 + return $value;
1589 + }
1590 +
1591 + if ( ! is_array( $wp_meta_keys ) || ! isset( $wp_meta_keys[ $meta_type ] ) ) {
1592 + return $value;
1593 + }
1594 +
1595 + $defaults = array();
1596 + foreach ( $wp_meta_keys[ $meta_type ] as $sub_type => $meta_data ) {
1597 + foreach ( $meta_data as $_meta_key => $args ) {
1598 + if ( $_meta_key === $meta_key && array_key_exists( 'default', $args ) ) {
1599 + $defaults[ $sub_type ] = $args;
1600 + }
1601 + }
1602 + }
1603 +
1604 + if ( ! $defaults ) {
1605 + return $value;
1606 + }
1607 +
1608 + // If this meta type does not have subtypes, then the default is keyed as an empty string.
1609 + if ( isset( $defaults[''] ) ) {
1610 + $metadata = $defaults[''];
1611 + } else {
1612 + $sub_type = get_object_subtype( $meta_type, $object_id );
1613 + if ( ! isset( $defaults[ $sub_type ] ) ) {
1614 + return $value;
1615 + }
1616 + $metadata = $defaults[ $sub_type ];
1617 + }
1618 +
1619 + if ( $single ) {
1620 + $value = $metadata['default'];
1621 + } else {
1622 + $value = array( $metadata['default'] );
1623 + }
1624 +
1625 + return $value;
1626 + }
1627 +
1628 + /**
1629 + * Checks if a meta key is registered.
1630 + *
1631 + * @since 4.6.0
1632 + * @since 4.9.8 The `$object_subtype` parameter was added.
1633 + *
1634 + * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
1635 + * 'user', or any other object type with an associated meta table.
1636 + * @param string $meta_key Metadata key.
1637 + * @param string $object_subtype Optional. The subtype of the object type. Default empty string.
1638 + * @return bool True if the meta key is registered to the object type and, if provided,
1639 + * the object subtype. False if not.
1640 + */
1641 + function registered_meta_key_exists( $object_type, $meta_key, $object_subtype = '' ) {
1642 + $meta_keys = get_registered_meta_keys( $object_type, $object_subtype );
1643 +
1644 + return isset( $meta_keys[ $meta_key ] );
1645 + }
1646 +
1647 + /**
1648 + * Unregisters a meta key from the list of registered keys.
1649 + *
1650 + * @since 4.6.0
1651 + * @since 4.9.8 The `$object_subtype` parameter was added.
1652 + *
1653 + * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
1654 + * 'user', or any other object type with an associated meta table.
1655 + * @param string $meta_key Metadata key.
1656 + * @param string $object_subtype Optional. The subtype of the object type. Default empty string.
1657 + * @return bool True if successful. False if the meta key was not registered.
1658 + */
1659 + function unregister_meta_key( $object_type, $meta_key, $object_subtype = '' ) {
1660 + global $wp_meta_keys;
1661 +
1662 + if ( ! registered_meta_key_exists( $object_type, $meta_key, $object_subtype ) ) {
1663 + return false;
1664 + }
1665 +
1666 + $args = $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ];
1667 +
1668 + if ( isset( $args['sanitize_callback'] ) && is_callable( $args['sanitize_callback'] ) ) {
1669 + if ( ! empty( $object_subtype ) ) {
1670 + remove_filter( "sanitize_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $args['sanitize_callback'] );
1671 + } else {
1672 + remove_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'] );
1673 + }
1674 + }
1675 +
1676 + if ( isset( $args['auth_callback'] ) && is_callable( $args['auth_callback'] ) ) {
1677 + if ( ! empty( $object_subtype ) ) {
1678 + remove_filter( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $args['auth_callback'] );
1679 + } else {
1680 + remove_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'] );
1681 + }
1682 + }
1683 +
1684 + unset( $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ] );
1685 +
1686 + // Do some clean up.
1687 + if ( empty( $wp_meta_keys[ $object_type ][ $object_subtype ] ) ) {
1688 + unset( $wp_meta_keys[ $object_type ][ $object_subtype ] );
1689 + }
1690 + if ( empty( $wp_meta_keys[ $object_type ] ) ) {
1691 + unset( $wp_meta_keys[ $object_type ] );
1692 + }
1693 +
1694 + return true;
1695 + }
1696 +
1697 + /**
1698 + * Retrieves a list of registered metadata args for an object type, keyed by their meta keys.
1699 + *
1700 + * @since 4.6.0
1701 + * @since 4.9.8 The `$object_subtype` parameter was added.
1702 + *
1703 + * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
1704 + * 'user', or any other object type with an associated meta table.
1705 + * @param string $object_subtype Optional. The subtype of the object type. Default empty string.
1706 + * @return array[] List of registered metadata args, keyed by their meta keys.
1707 + */
1708 + function get_registered_meta_keys( $object_type, $object_subtype = '' ) {
1709 + global $wp_meta_keys;
1710 +
1711 + if ( ! is_array( $wp_meta_keys ) || ! isset( $wp_meta_keys[ $object_type ] ) || ! isset( $wp_meta_keys[ $object_type ][ $object_subtype ] ) ) {
1712 + return array();
1713 + }
1714 +
1715 + return $wp_meta_keys[ $object_type ][ $object_subtype ];
1716 + }
1717 +
1718 + /**
1719 + * Retrieves registered metadata for a specified object.
1720 + *
1721 + * The results include both meta that is registered specifically for the
1722 + * object's subtype and meta that is registered for the entire object type.
1723 + *
1724 + * @since 4.6.0
1725 + *
1726 + * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
1727 + * 'user', or any other object type with an associated meta table.
1728 + * @param int $object_id ID of the object the metadata is for.
1729 + * @param string $meta_key Optional. Registered metadata key. If not specified, retrieve all registered
1730 + * metadata for the specified object.
1731 + * @return mixed A single value or array of values for a key if specified. An array of all registered keys
1732 + * and values for an object ID if not. False if a given $meta_key is not registered.
1733 + */
1734 + function get_registered_metadata( $object_type, $object_id, $meta_key = '' ) {
1735 + $object_subtype = get_object_subtype( $object_type, $object_id );
1736 +
1737 + if ( ! empty( $meta_key ) ) {
1738 + if ( ! empty( $object_subtype ) && ! registered_meta_key_exists( $object_type, $meta_key, $object_subtype ) ) {
1739 + $object_subtype = '';
1740 + }
1741 +
1742 + if ( ! registered_meta_key_exists( $object_type, $meta_key, $object_subtype ) ) {
1743 + return false;
1744 + }
1745 +
1746 + $meta_keys = get_registered_meta_keys( $object_type, $object_subtype );
1747 + $meta_key_data = $meta_keys[ $meta_key ];
1748 +
1749 + $data = get_metadata( $object_type, $object_id, $meta_key, $meta_key_data['single'] );
1750 +
1751 + return $data;
1752 + }
1753 +
1754 + $data = get_metadata( $object_type, $object_id );
1755 + if ( ! $data ) {
1756 + return array();
1757 + }
1758 +
1759 + $meta_keys = get_registered_meta_keys( $object_type );
1760 + if ( ! empty( $object_subtype ) ) {
1761 + $meta_keys = array_merge( $meta_keys, get_registered_meta_keys( $object_type, $object_subtype ) );
1762 + }
1763 +
1764 + return array_intersect_key( $data, $meta_keys );
1765 + }
1766 +
1767 + /**
1768 + * Filters out `register_meta()` args based on an allowed list.
1769 + *
1770 + * `register_meta()` args may change over time, so requiring the allowed list
1771 + * to be explicitly turned off is a warranty seal of sorts.
1772 + *
1773 + * @access private
1774 + * @since 5.5.0
1775 + *
1776 + * @param array $args Arguments from `register_meta()`.
1777 + * @param array $default_args Default arguments for `register_meta()`.
1778 + * @return array Filtered arguments.
1779 + */
1780 + function _wp_register_meta_args_allowed_list( $args, $default_args ) {
1781 + return array_intersect_key( $args, $default_args );
1782 + }
1783 +
1784 + /**
1785 + * Returns the object subtype for a given object ID of a specific type.
1786 + *
1787 + * @since 4.9.8
1788 + *
1789 + * @param string $object_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
1790 + * 'user', or any other object type with an associated meta table.
1791 + * @param int $object_id ID of the object to retrieve its subtype.
1792 + * @return string The object subtype or an empty string if unspecified subtype.
1793 + */
1794 + function get_object_subtype( $object_type, $object_id ) {
1795 + $object_id = (int) $object_id;
1796 + $object_subtype = '';
1797 +
1798 + switch ( $object_type ) {
1799 + case 'post':
1800 + $post_type = get_post_type( $object_id );
1801 +
1802 + if ( ! empty( $post_type ) ) {
1803 + $object_subtype = $post_type;
1804 + }
1805 + break;
1806 +
1807 + case 'term':
1808 + $term = get_term( $object_id );
1809 + if ( ! $term instanceof WP_Term ) {
1810 + break;
1811 + }
1812 +
1813 + $object_subtype = $term->taxonomy;
1814 + break;
1815 +
1816 + case 'comment':
1817 + $comment = get_comment( $object_id );
1818 + if ( ! $comment ) {
1819 + break;
1820 + }
1821 +
1822 + $object_subtype = 'comment';
1823 + break;
1824 +
1825 + case 'user':
1826 + $user = get_user_by( 'id', $object_id );
1827 + if ( ! $user ) {
1828 + break;
1829 + }
1830 +
1831 + $object_subtype = 'user';
1832 + break;
1833 + }
1834 +
1835 + /**
1836 + * Filters the object subtype identifier.
1837 + *
1838 + * The dynamic portion of the hook name, `$object_type`, refers to the meta object type
1839 + * (blog, post, comment, term, user, or any other type with an associated meta table).
1840 + *
1841 + * Possible hook names include:
1842 + *
1843 + * - `get_object_subtype_blog`
1844 + * - `get_object_subtype_post`
1845 + * - `get_object_subtype_comment`
1846 + * - `get_object_subtype_term`
1847 + * - `get_object_subtype_user`
1848 + *
1849 + * @since 4.9.8
1850 + *
1851 + * @param string $object_subtype Object subtype or empty string to override.
1852 + * @param int $object_id ID of the object to get the subtype for.
1853 + */
1854 + return apply_filters( "get_object_subtype_{$object_type}", $object_subtype, $object_id );
1855 + }
1856 +