Diff: STRATO-apps/wordpress_03/app/wp-includes/meta.php
Keine Baseline-Datei – Diff nur gegen leer.
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
+