Issues (2010)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

wp-includes/meta.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
/**
14
 * Add metadata for the specified object.
15
 *
16
 * @since 2.9.0
17
 *
18
 * @global wpdb $wpdb WordPress database abstraction object.
19
 *
20
 * @param string $meta_type  Type of object metadata is for (e.g., comment, post, or user)
21
 * @param int    $object_id  ID of the object metadata is for
22
 * @param string $meta_key   Metadata key
23
 * @param mixed  $meta_value Metadata value. Must be serializable if non-scalar.
24
 * @param bool   $unique     Optional, default is false.
25
 *                           Whether the specified metadata key should be unique for the object.
26
 *                           If true, and the object already has a value for the specified metadata key,
27
 *                           no change will be made.
28
 * @return int|false The meta ID on success, false on failure.
29
 */
30
function add_metadata($meta_type, $object_id, $meta_key, $meta_value, $unique = false) {
31
	global $wpdb;
32
33
	if ( ! $meta_type || ! $meta_key || ! is_numeric( $object_id ) ) {
34
		return false;
35
	}
36
37
	$object_id = absint( $object_id );
38
	if ( ! $object_id ) {
39
		return false;
40
	}
41
42
	$table = _get_meta_table( $meta_type );
43
	if ( ! $table ) {
44
		return false;
45
	}
46
47
	$column = sanitize_key($meta_type . '_id');
48
49
	// expected_slashed ($meta_key)
50
	$meta_key = wp_unslash($meta_key);
51
	$meta_value = wp_unslash($meta_value);
52
	$meta_value = sanitize_meta( $meta_key, $meta_value, $meta_type );
0 ignored issues
show
It seems like $meta_key defined by wp_unslash($meta_key) on line 50 can also be of type array; however, sanitize_meta() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
53
54
	/**
55
	 * Filters whether to add metadata of a specific type.
56
	 *
57
	 * The dynamic portion of the hook, `$meta_type`, refers to the meta
58
	 * object type (comment, post, or user). Returning a non-null value
59
	 * will effectively short-circuit the function.
60
	 *
61
	 * @since 3.1.0
62
	 *
63
	 * @param null|bool $check      Whether to allow adding metadata for the given type.
64
	 * @param int       $object_id  Object ID.
65
	 * @param string    $meta_key   Meta key.
66
	 * @param mixed     $meta_value Meta value. Must be serializable if non-scalar.
67
	 * @param bool      $unique     Whether the specified meta key should be unique
68
	 *                              for the object. Optional. Default false.
69
	 */
70
	$check = apply_filters( "add_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, $unique );
71
	if ( null !== $check )
72
		return $check;
73
74
	if ( $unique && $wpdb->get_var( $wpdb->prepare(
75
		"SELECT COUNT(*) FROM $table WHERE meta_key = %s AND $column = %d",
76
		$meta_key, $object_id ) ) )
77
		return false;
78
79
	$_meta_value = $meta_value;
80
	$meta_value = maybe_serialize( $meta_value );
81
82
	/**
83
	 * Fires immediately before meta of a specific type is added.
84
	 *
85
	 * The dynamic portion of the hook, `$meta_type`, refers to the meta
86
	 * object type (comment, post, or user).
87
	 *
88
	 * @since 3.1.0
89
	 *
90
	 * @param int    $object_id  Object ID.
91
	 * @param string $meta_key   Meta key.
92
	 * @param mixed  $meta_value Meta value.
93
	 */
94
	do_action( "add_{$meta_type}_meta", $object_id, $meta_key, $_meta_value );
95
96
	$result = $wpdb->insert( $table, array(
97
		$column => $object_id,
98
		'meta_key' => $meta_key,
99
		'meta_value' => $meta_value
100
	) );
101
102
	if ( ! $result )
103
		return false;
104
105
	$mid = (int) $wpdb->insert_id;
106
107
	wp_cache_delete($object_id, $meta_type . '_meta');
108
109
	/**
110
	 * Fires immediately after meta of a specific type is added.
111
	 *
112
	 * The dynamic portion of the hook, `$meta_type`, refers to the meta
113
	 * object type (comment, post, or user).
114
	 *
115
	 * @since 2.9.0
116
	 *
117
	 * @param int    $mid        The meta ID after successful update.
118
	 * @param int    $object_id  Object ID.
119
	 * @param string $meta_key   Meta key.
120
	 * @param mixed  $meta_value Meta value.
121
	 */
122
	do_action( "added_{$meta_type}_meta", $mid, $object_id, $meta_key, $_meta_value );
123
124
	return $mid;
125
}
126
127
/**
128
 * Update metadata for the specified object. If no value already exists for the specified object
129
 * ID and metadata key, the metadata will be added.
130
 *
131
 * @since 2.9.0
132
 *
133
 * @global wpdb $wpdb WordPress database abstraction object.
134
 *
135
 * @param string $meta_type  Type of object metadata is for (e.g., comment, post, or user)
136
 * @param int    $object_id  ID of the object metadata is for
137
 * @param string $meta_key   Metadata key
138
 * @param mixed  $meta_value Metadata value. Must be serializable if non-scalar.
139
 * @param mixed  $prev_value Optional. If specified, only update existing metadata entries with
140
 * 		                     the specified value. Otherwise, update all entries.
141
 * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.
142
 */
143
function update_metadata($meta_type, $object_id, $meta_key, $meta_value, $prev_value = '') {
144
	global $wpdb;
145
146
	if ( ! $meta_type || ! $meta_key || ! is_numeric( $object_id ) ) {
147
		return false;
148
	}
149
150
	$object_id = absint( $object_id );
151
	if ( ! $object_id ) {
152
		return false;
153
	}
154
155
	$table = _get_meta_table( $meta_type );
156
	if ( ! $table ) {
157
		return false;
158
	}
159
160
	$column = sanitize_key($meta_type . '_id');
161
	$id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
162
163
	// expected_slashed ($meta_key)
164
	$raw_meta_key = $meta_key;
165
	$meta_key = wp_unslash($meta_key);
166
	$passed_value = $meta_value;
167
	$meta_value = wp_unslash($meta_value);
168
	$meta_value = sanitize_meta( $meta_key, $meta_value, $meta_type );
0 ignored issues
show
It seems like $meta_key defined by wp_unslash($meta_key) on line 165 can also be of type array; however, sanitize_meta() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
169
170
	/**
171
	 * Filters whether to update metadata of a specific type.
172
	 *
173
	 * The dynamic portion of the hook, `$meta_type`, refers to the meta
174
	 * object type (comment, post, or user). Returning a non-null value
175
	 * will effectively short-circuit the function.
176
	 *
177
	 * @since 3.1.0
178
	 *
179
	 * @param null|bool $check      Whether to allow updating metadata for the given type.
180
	 * @param int       $object_id  Object ID.
181
	 * @param string    $meta_key   Meta key.
182
	 * @param mixed     $meta_value Meta value. Must be serializable if non-scalar.
183
	 * @param mixed     $prev_value Optional. If specified, only update existing
184
	 *                              metadata entries with the specified value.
185
	 *                              Otherwise, update all entries.
186
	 */
187
	$check = apply_filters( "update_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, $prev_value );
188
	if ( null !== $check )
189
		return (bool) $check;
190
191
	// Compare existing value to new value if no prev value given and the key exists only once.
192
	if ( empty($prev_value) ) {
193
		$old_value = get_metadata($meta_type, $object_id, $meta_key);
0 ignored issues
show
It seems like $meta_key defined by wp_unslash($meta_key) on line 165 can also be of type array; however, get_metadata() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
194
		if ( count($old_value) == 1 ) {
195
			if ( $old_value[0] === $meta_value )
196
				return false;
197
		}
198
	}
199
200
	$meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT $id_column FROM $table WHERE meta_key = %s AND $column = %d", $meta_key, $object_id ) );
201
	if ( empty( $meta_ids ) ) {
202
		return add_metadata( $meta_type, $object_id, $raw_meta_key, $passed_value );
203
	}
204
205
	$_meta_value = $meta_value;
206
	$meta_value = maybe_serialize( $meta_value );
207
208
	$data  = compact( 'meta_value' );
209
	$where = array( $column => $object_id, 'meta_key' => $meta_key );
210
211
	if ( !empty( $prev_value ) ) {
212
		$prev_value = maybe_serialize($prev_value);
213
		$where['meta_value'] = $prev_value;
214
	}
215
216 View Code Duplication
	foreach ( $meta_ids as $meta_id ) {
217
		/**
218
		 * Fires immediately before updating metadata of a specific type.
219
		 *
220
		 * The dynamic portion of the hook, `$meta_type`, refers to the meta
221
		 * object type (comment, post, or user).
222
		 *
223
		 * @since 2.9.0
224
		 *
225
		 * @param int    $meta_id    ID of the metadata entry to update.
226
		 * @param int    $object_id  Object ID.
227
		 * @param string $meta_key   Meta key.
228
		 * @param mixed  $meta_value Meta value.
229
		 */
230
		do_action( "update_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value );
231
232
		if ( 'post' == $meta_type ) {
233
			/**
234
			 * Fires immediately before updating a post's metadata.
235
			 *
236
			 * @since 2.9.0
237
			 *
238
			 * @param int    $meta_id    ID of metadata entry to update.
239
			 * @param int    $object_id  Object ID.
240
			 * @param string $meta_key   Meta key.
241
			 * @param mixed  $meta_value Meta value.
242
			 */
243
			do_action( 'update_postmeta', $meta_id, $object_id, $meta_key, $meta_value );
244
		}
245
	}
246
247
	$result = $wpdb->update( $table, $data, $where );
248
	if ( ! $result )
249
		return false;
250
251
	wp_cache_delete($object_id, $meta_type . '_meta');
252
253 View Code Duplication
	foreach ( $meta_ids as $meta_id ) {
254
		/**
255
		 * Fires immediately after updating metadata of a specific type.
256
		 *
257
		 * The dynamic portion of the hook, `$meta_type`, refers to the meta
258
		 * object type (comment, post, or user).
259
		 *
260
		 * @since 2.9.0
261
		 *
262
		 * @param int    $meta_id    ID of updated metadata entry.
263
		 * @param int    $object_id  Object ID.
264
		 * @param string $meta_key   Meta key.
265
		 * @param mixed  $meta_value Meta value.
266
		 */
267
		do_action( "updated_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value );
268
269
		if ( 'post' == $meta_type ) {
270
			/**
271
			 * Fires immediately after updating a post's metadata.
272
			 *
273
			 * @since 2.9.0
274
			 *
275
			 * @param int    $meta_id    ID of updated metadata entry.
276
			 * @param int    $object_id  Object ID.
277
			 * @param string $meta_key   Meta key.
278
			 * @param mixed  $meta_value Meta value.
279
			 */
280
			do_action( 'updated_postmeta', $meta_id, $object_id, $meta_key, $meta_value );
281
		}
282
	}
283
284
	return true;
285
}
286
287
/**
288
 * Delete metadata for the specified object.
289
 *
290
 * @since 2.9.0
291
 *
292
 * @global wpdb $wpdb WordPress database abstraction object.
293
 *
294
 * @param string $meta_type  Type of object metadata is for (e.g., comment, post, or user)
295
 * @param int    $object_id  ID of the object metadata is for
296
 * @param string $meta_key   Metadata key
297
 * @param mixed  $meta_value Optional. Metadata value. Must be serializable if non-scalar. If specified, only delete
298
 *                           metadata entries with this value. Otherwise, delete all entries with the specified meta_key.
299
 *                           Pass `null, `false`, or an empty string to skip this check. (For backward compatibility,
300
 *                           it is not possible to pass an empty string to delete those entries with an empty string
301
 *                           for a value.)
302
 * @param bool   $delete_all Optional, default is false. If true, delete matching metadata entries for all objects,
303
 *                           ignoring the specified object_id. Otherwise, only delete matching metadata entries for
304
 *                           the specified object_id.
305
 * @return bool True on successful delete, false on failure.
306
 */
307
function delete_metadata($meta_type, $object_id, $meta_key, $meta_value = '', $delete_all = false) {
308
	global $wpdb;
309
310
	if ( ! $meta_type || ! $meta_key || ! is_numeric( $object_id ) && ! $delete_all ) {
311
		return false;
312
	}
313
314
	$object_id = absint( $object_id );
315
	if ( ! $object_id && ! $delete_all ) {
316
		return false;
317
	}
318
319
	$table = _get_meta_table( $meta_type );
320
	if ( ! $table ) {
321
		return false;
322
	}
323
324
	$type_column = sanitize_key($meta_type . '_id');
325
	$id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
326
	// expected_slashed ($meta_key)
327
	$meta_key = wp_unslash($meta_key);
328
	$meta_value = wp_unslash($meta_value);
329
330
	/**
331
	 * Filters whether to delete metadata of a specific type.
332
	 *
333
	 * The dynamic portion of the hook, `$meta_type`, refers to the meta
334
	 * object type (comment, post, or user). Returning a non-null value
335
	 * will effectively short-circuit the function.
336
	 *
337
	 * @since 3.1.0
338
	 *
339
	 * @param null|bool $delete     Whether to allow metadata deletion of the given type.
340
	 * @param int       $object_id  Object ID.
341
	 * @param string    $meta_key   Meta key.
342
	 * @param mixed     $meta_value Meta value. Must be serializable if non-scalar.
343
	 * @param bool      $delete_all Whether to delete the matching metadata entries
344
	 *                              for all objects, ignoring the specified $object_id.
345
	 *                              Default false.
346
	 */
347
	$check = apply_filters( "delete_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, $delete_all );
348
	if ( null !== $check )
349
		return (bool) $check;
350
351
	$_meta_value = $meta_value;
352
	$meta_value = maybe_serialize( $meta_value );
353
354
	$query = $wpdb->prepare( "SELECT $id_column FROM $table WHERE meta_key = %s", $meta_key );
355
356
	if ( !$delete_all )
357
		$query .= $wpdb->prepare(" AND $type_column = %d", $object_id );
358
359
	if ( '' !== $meta_value && null !== $meta_value && false !== $meta_value )
360
		$query .= $wpdb->prepare(" AND meta_value = %s", $meta_value );
361
362
	$meta_ids = $wpdb->get_col( $query );
363
	if ( !count( $meta_ids ) )
364
		return false;
365
366
	if ( $delete_all ) {
367
		$value_clause = '';
368
		if ( '' !== $meta_value && null !== $meta_value && false !== $meta_value ) {
369
			$value_clause = $wpdb->prepare( " AND meta_value = %s", $meta_value );
370
		}
371
372
		$object_ids = $wpdb->get_col( $wpdb->prepare( "SELECT $type_column FROM $table WHERE meta_key = %s $value_clause", $meta_key ) );
373
	}
374
375
	/**
376
	 * Fires immediately before deleting metadata of a specific type.
377
	 *
378
	 * The dynamic portion of the hook, `$meta_type`, refers to the meta
379
	 * object type (comment, post, or user).
380
	 *
381
	 * @since 3.1.0
382
	 *
383
	 * @param array  $meta_ids   An array of metadata entry IDs to delete.
384
	 * @param int    $object_id  Object ID.
385
	 * @param string $meta_key   Meta key.
386
	 * @param mixed  $meta_value Meta value.
387
	 */
388
	do_action( "delete_{$meta_type}_meta", $meta_ids, $object_id, $meta_key, $_meta_value );
389
390
	// Old-style action.
391
	if ( 'post' == $meta_type ) {
392
		/**
393
		 * Fires immediately before deleting metadata for a post.
394
		 *
395
		 * @since 2.9.0
396
		 *
397
		 * @param array $meta_ids An array of post metadata entry IDs to delete.
398
		 */
399
		do_action( 'delete_postmeta', $meta_ids );
400
	}
401
402
	$query = "DELETE FROM $table WHERE $id_column IN( " . implode( ',', $meta_ids ) . " )";
403
404
	$count = $wpdb->query($query);
405
406
	if ( !$count )
407
		return false;
408
409
	if ( $delete_all ) {
410
		foreach ( (array) $object_ids as $o_id ) {
0 ignored issues
show
The variable $object_ids does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
411
			wp_cache_delete($o_id, $meta_type . '_meta');
412
		}
413
	} else {
414
		wp_cache_delete($object_id, $meta_type . '_meta');
415
	}
416
417
	/**
418
	 * Fires immediately after deleting metadata of a specific type.
419
	 *
420
	 * The dynamic portion of the hook name, `$meta_type`, refers to the meta
421
	 * object type (comment, post, or user).
422
	 *
423
	 * @since 2.9.0
424
	 *
425
	 * @param array  $meta_ids   An array of deleted metadata entry IDs.
426
	 * @param int    $object_id  Object ID.
427
	 * @param string $meta_key   Meta key.
428
	 * @param mixed  $meta_value Meta value.
429
	 */
430
	do_action( "deleted_{$meta_type}_meta", $meta_ids, $object_id, $meta_key, $_meta_value );
431
432
	// Old-style action.
433
	if ( 'post' == $meta_type ) {
434
		/**
435
		 * Fires immediately after deleting metadata for a post.
436
		 *
437
		 * @since 2.9.0
438
		 *
439
		 * @param array $meta_ids An array of deleted post metadata entry IDs.
440
		 */
441
		do_action( 'deleted_postmeta', $meta_ids );
442
	}
443
444
	return true;
445
}
446
447
/**
448
 * Retrieve metadata for the specified object.
449
 *
450
 * @since 2.9.0
451
 *
452
 * @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
453
 * @param int    $object_id ID of the object metadata is for
454
 * @param string $meta_key  Optional. Metadata key. If not specified, retrieve all metadata for
455
 * 		                    the specified object.
456
 * @param bool   $single    Optional, default is false.
457
 *                          If true, return only the first value of the specified meta_key.
458
 *                          This parameter has no effect if meta_key is not specified.
459
 * @return mixed Single metadata value, or array of values
460
 */
461
function get_metadata($meta_type, $object_id, $meta_key = '', $single = false) {
462
	if ( ! $meta_type || ! is_numeric( $object_id ) ) {
463
		return false;
464
	}
465
466
	$object_id = absint( $object_id );
467
	if ( ! $object_id ) {
468
		return false;
469
	}
470
471
	/**
472
	 * Filters whether to retrieve metadata of a specific type.
473
	 *
474
	 * The dynamic portion of the hook, `$meta_type`, refers to the meta
475
	 * object type (comment, post, or user). Returning a non-null value
476
	 * will effectively short-circuit the function.
477
	 *
478
	 * @since 3.1.0
479
	 *
480
	 * @param null|array|string $value     The value get_metadata() should return - a single metadata value,
481
	 *                                     or an array of values.
482
	 * @param int               $object_id Object ID.
483
	 * @param string            $meta_key  Meta key.
484
	 * @param bool              $single    Whether to return only the first value of the specified $meta_key.
485
	 */
486
	$check = apply_filters( "get_{$meta_type}_metadata", null, $object_id, $meta_key, $single );
487
	if ( null !== $check ) {
488
		if ( $single && is_array( $check ) )
489
			return $check[0];
490
		else
491
			return $check;
492
	}
493
494
	$meta_cache = wp_cache_get($object_id, $meta_type . '_meta');
495
496 View Code Duplication
	if ( !$meta_cache ) {
497
		$meta_cache = update_meta_cache( $meta_type, array( $object_id ) );
498
		$meta_cache = $meta_cache[$object_id];
499
	}
500
501
	if ( ! $meta_key ) {
502
		return $meta_cache;
503
	}
504
505
	if ( isset($meta_cache[$meta_key]) ) {
506
		if ( $single )
507
			return maybe_unserialize( $meta_cache[$meta_key][0] );
508
		else
509
			return array_map('maybe_unserialize', $meta_cache[$meta_key]);
510
	}
511
512
	if ($single)
513
		return '';
514
	else
515
		return array();
516
}
517
518
/**
519
 * Determine if a meta key is set for a given object
520
 *
521
 * @since 3.3.0
522
 *
523
 * @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
524
 * @param int    $object_id ID of the object metadata is for
525
 * @param string $meta_key  Metadata key.
526
 * @return bool True of the key is set, false if not.
527
 */
528
function metadata_exists( $meta_type, $object_id, $meta_key ) {
529
	if ( ! $meta_type || ! is_numeric( $object_id ) ) {
530
		return false;
531
	}
532
533
	$object_id = absint( $object_id );
534
	if ( ! $object_id ) {
535
		return false;
536
	}
537
538
	/** This filter is documented in wp-includes/meta.php */
539
	$check = apply_filters( "get_{$meta_type}_metadata", null, $object_id, $meta_key, true );
540
	if ( null !== $check )
541
		return (bool) $check;
542
543
	$meta_cache = wp_cache_get( $object_id, $meta_type . '_meta' );
544
545 View Code Duplication
	if ( !$meta_cache ) {
546
		$meta_cache = update_meta_cache( $meta_type, array( $object_id ) );
547
		$meta_cache = $meta_cache[$object_id];
548
	}
549
550
	if ( isset( $meta_cache[ $meta_key ] ) )
551
		return true;
552
553
	return false;
554
}
555
556
/**
557
 * Get meta data by meta ID
558
 *
559
 * @since 3.3.0
560
 *
561
 * @global wpdb $wpdb WordPress database abstraction object.
562
 *
563
 * @param string $meta_type Type of object metadata is for (e.g., comment, post, term, or user).
564
 * @param int    $meta_id   ID for a specific meta row
565
 * @return object|false Meta object or false.
566
 */
567
function get_metadata_by_mid( $meta_type, $meta_id ) {
568
	global $wpdb;
569
570
	if ( ! $meta_type || ! is_numeric( $meta_id ) ) {
571
		return false;
572
	}
573
574
	$meta_id = absint( $meta_id );
575
	if ( ! $meta_id ) {
576
		return false;
577
	}
578
579
	$table = _get_meta_table( $meta_type );
580
	if ( ! $table ) {
581
		return false;
582
	}
583
584
	$id_column = ( 'user' == $meta_type ) ? 'umeta_id' : 'meta_id';
585
586
	$meta = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table WHERE $id_column = %d", $meta_id ) );
587
588
	if ( empty( $meta ) )
589
		return false;
590
591
	if ( isset( $meta->meta_value ) )
592
		$meta->meta_value = maybe_unserialize( $meta->meta_value );
593
594
	return $meta;
595
}
596
597
/**
598
 * Update meta data by meta ID
599
 *
600
 * @since 3.3.0
601
 *
602
 * @global wpdb $wpdb WordPress database abstraction object.
603
 *
604
 * @param string $meta_type  Type of object metadata is for (e.g., comment, post, or user)
605
 * @param int    $meta_id    ID for a specific meta row
606
 * @param string $meta_value Metadata value
607
 * @param string $meta_key   Optional, you can provide a meta key to update it
608
 * @return bool True on successful update, false on failure.
609
 */
610
function update_metadata_by_mid( $meta_type, $meta_id, $meta_value, $meta_key = false ) {
611
	global $wpdb;
612
613
	// Make sure everything is valid.
614
	if ( ! $meta_type || ! is_numeric( $meta_id ) ) {
615
		return false;
616
	}
617
618
	$meta_id = absint( $meta_id );
619
	if ( ! $meta_id ) {
620
		return false;
621
	}
622
623
	$table = _get_meta_table( $meta_type );
624
	if ( ! $table ) {
625
		return false;
626
	}
627
628
	$column = sanitize_key($meta_type . '_id');
629
	$id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
630
631
	// Fetch the meta and go on if it's found.
632
	if ( $meta = get_metadata_by_mid( $meta_type, $meta_id ) ) {
633
		$original_key = $meta->meta_key;
634
		$object_id = $meta->{$column};
635
636
		// If a new meta_key (last parameter) was specified, change the meta key,
637
		// otherwise use the original key in the update statement.
638
		if ( false === $meta_key ) {
639
			$meta_key = $original_key;
640
		} elseif ( ! is_string( $meta_key ) ) {
641
			return false;
642
		}
643
644
		// Sanitize the meta
645
		$_meta_value = $meta_value;
646
		$meta_value = sanitize_meta( $meta_key, $meta_value, $meta_type );
647
		$meta_value = maybe_serialize( $meta_value );
648
649
		// Format the data query arguments.
650
		$data = array(
651
			'meta_key' => $meta_key,
652
			'meta_value' => $meta_value
653
		);
654
655
		// Format the where query arguments.
656
		$where = array();
657
		$where[$id_column] = $meta_id;
658
659
		/** This action is documented in wp-includes/meta.php */
660
		do_action( "update_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value );
661
662
		if ( 'post' == $meta_type ) {
663
			/** This action is documented in wp-includes/meta.php */
664
			do_action( 'update_postmeta', $meta_id, $object_id, $meta_key, $meta_value );
665
		}
666
667
		// Run the update query, all fields in $data are %s, $where is a %d.
668
		$result = $wpdb->update( $table, $data, $where, '%s', '%d' );
669
		if ( ! $result )
670
			return false;
671
672
		// Clear the caches.
673
		wp_cache_delete($object_id, $meta_type . '_meta');
674
675
		/** This action is documented in wp-includes/meta.php */
676
		do_action( "updated_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value );
677
678
		if ( 'post' == $meta_type ) {
679
			/** This action is documented in wp-includes/meta.php */
680
			do_action( 'updated_postmeta', $meta_id, $object_id, $meta_key, $meta_value );
681
		}
682
683
		return true;
684
	}
685
686
	// And if the meta was not found.
687
	return false;
688
}
689
690
/**
691
 * Delete meta data by meta ID
692
 *
693
 * @since 3.3.0
694
 *
695
 * @global wpdb $wpdb WordPress database abstraction object.
696
 *
697
 * @param string $meta_type Type of object metadata is for (e.g., comment, post, term, or user).
698
 * @param int    $meta_id   ID for a specific meta row
699
 * @return bool True on successful delete, false on failure.
700
 */
701
function delete_metadata_by_mid( $meta_type, $meta_id ) {
702
	global $wpdb;
703
704
	// Make sure everything is valid.
705
	if ( ! $meta_type || ! is_numeric( $meta_id ) ) {
706
		return false;
707
	}
708
709
	$meta_id = absint( $meta_id );
710
	if ( ! $meta_id ) {
711
		return false;
712
	}
713
714
	$table = _get_meta_table( $meta_type );
715
	if ( ! $table ) {
716
		return false;
717
	}
718
719
	// object and id columns
720
	$column = sanitize_key($meta_type . '_id');
721
	$id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
722
723
	// Fetch the meta and go on if it's found.
724
	if ( $meta = get_metadata_by_mid( $meta_type, $meta_id ) ) {
725
		$object_id = $meta->{$column};
726
727
		/** This action is documented in wp-includes/meta.php */
728
		do_action( "delete_{$meta_type}_meta", (array) $meta_id, $object_id, $meta->meta_key, $meta->meta_value );
729
730
		// Old-style action.
731
		if ( 'post' == $meta_type || 'comment' == $meta_type ) {
732
			/**
733
			 * Fires immediately before deleting post or comment metadata of a specific type.
734
			 *
735
			 * The dynamic portion of the hook, `$meta_type`, refers to the meta
736
			 * object type (post or comment).
737
			 *
738
			 * @since 3.4.0
739
			 *
740
			 * @param int $meta_id ID of the metadata entry to delete.
741
			 */
742
			do_action( "delete_{$meta_type}meta", $meta_id );
743
		}
744
745
		// Run the query, will return true if deleted, false otherwise
746
		$result = (bool) $wpdb->delete( $table, array( $id_column => $meta_id ) );
747
748
		// Clear the caches.
749
		wp_cache_delete($object_id, $meta_type . '_meta');
750
751
		/** This action is documented in wp-includes/meta.php */
752
		do_action( "deleted_{$meta_type}_meta", (array) $meta_id, $object_id, $meta->meta_key, $meta->meta_value );
753
754
		// Old-style action.
755
		if ( 'post' == $meta_type || 'comment' == $meta_type ) {
756
			/**
757
			 * Fires immediately after deleting post or comment metadata of a specific type.
758
			 *
759
			 * The dynamic portion of the hook, `$meta_type`, refers to the meta
760
			 * object type (post or comment).
761
			 *
762
			 * @since 3.4.0
763
			 *
764
			 * @param int $meta_ids Deleted metadata entry ID.
765
			 */
766
			do_action( "deleted_{$meta_type}meta", $meta_id );
767
		}
768
769
		return $result;
770
771
	}
772
773
	// Meta id was not found.
774
	return false;
775
}
776
777
/**
778
 * Update the metadata cache for the specified objects.
779
 *
780
 * @since 2.9.0
781
 *
782
 * @global wpdb $wpdb WordPress database abstraction object.
783
 *
784
 * @param string    $meta_type  Type of object metadata is for (e.g., comment, post, or user)
785
 * @param int|array $object_ids Array or comma delimited list of object IDs to update cache for
786
 * @return array|false Metadata cache for the specified objects, or false on failure.
787
 */
788
function update_meta_cache($meta_type, $object_ids) {
789
	global $wpdb;
790
791
	if ( ! $meta_type || ! $object_ids ) {
792
		return false;
793
	}
794
795
	$table = _get_meta_table( $meta_type );
796
	if ( ! $table ) {
797
		return false;
798
	}
799
800
	$column = sanitize_key($meta_type . '_id');
801
802
	if ( !is_array($object_ids) ) {
803
		$object_ids = preg_replace('|[^0-9,]|', '', $object_ids);
804
		$object_ids = explode(',', $object_ids);
805
	}
806
807
	$object_ids = array_map('intval', $object_ids);
808
809
	$cache_key = $meta_type . '_meta';
810
	$ids = array();
811
	$cache = array();
812
	foreach ( $object_ids as $id ) {
813
		$cached_object = wp_cache_get( $id, $cache_key );
814
		if ( false === $cached_object )
815
			$ids[] = $id;
816
		else
817
			$cache[$id] = $cached_object;
818
	}
819
820
	if ( empty( $ids ) )
821
		return $cache;
822
823
	// Get meta info
824
	$id_list = join( ',', $ids );
825
	$id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
826
	$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 );
827
828
	if ( !empty($meta_list) ) {
829
		foreach ( $meta_list as $metarow) {
830
			$mpid = intval($metarow[$column]);
831
			$mkey = $metarow['meta_key'];
832
			$mval = $metarow['meta_value'];
833
834
			// Force subkeys to be array type:
835 View Code Duplication
			if ( !isset($cache[$mpid]) || !is_array($cache[$mpid]) )
836
				$cache[$mpid] = array();
837
			if ( !isset($cache[$mpid][$mkey]) || !is_array($cache[$mpid][$mkey]) )
838
				$cache[$mpid][$mkey] = array();
839
840
			// Add a value to the current pid/key:
841
			$cache[$mpid][$mkey][] = $mval;
842
		}
843
	}
844
845
	foreach ( $ids as $id ) {
846
		if ( ! isset($cache[$id]) )
847
			$cache[$id] = array();
848
		wp_cache_add( $id, $cache[$id], $cache_key );
849
	}
850
851
	return $cache;
852
}
853
854
/**
855
 * Retrieves the queue for lazy-loading metadata.
856
 *
857
 * @since 4.5.0
858
 *
859
 * @return WP_Metadata_Lazyloader $lazyloader Metadata lazyloader queue.
860
 */
861
function wp_metadata_lazyloader() {
862
	static $wp_metadata_lazyloader;
863
864
	if ( null === $wp_metadata_lazyloader ) {
865
		$wp_metadata_lazyloader = new WP_Metadata_Lazyloader();
866
	}
867
868
	return $wp_metadata_lazyloader;
869
}
870
871
/**
872
 * Given a meta query, generates SQL clauses to be appended to a main query.
873
 *
874
 * @since 3.2.0
875
 *
876
 * @see WP_Meta_Query
877
 *
878
 * @param array $meta_query         A meta query.
879
 * @param string $type              Type of meta.
880
 * @param string $primary_table     Primary database table name.
881
 * @param string $primary_id_column Primary ID column name.
882
 * @param object $context           Optional. The main query object
883
 * @return array Associative array of `JOIN` and `WHERE` SQL.
884
 */
885
function get_meta_sql( $meta_query, $type, $primary_table, $primary_id_column, $context = null ) {
886
	$meta_query_obj = new WP_Meta_Query( $meta_query );
887
	return $meta_query_obj->get_sql( $type, $primary_table, $primary_id_column, $context );
888
}
889
890
/**
891
 * Retrieve the name of the metadata table for the specified object type.
892
 *
893
 * @since 2.9.0
894
 *
895
 * @global wpdb $wpdb WordPress database abstraction object.
896
 *
897
 * @param string $type Type of object to get metadata table for (e.g., comment, post, or user)
898
 * @return string|false Metadata table name, or false if no metadata table exists
899
 */
900
function _get_meta_table($type) {
901
	global $wpdb;
902
903
	$table_name = $type . 'meta';
904
905
	if ( empty($wpdb->$table_name) )
906
		return false;
907
908
	return $wpdb->$table_name;
909
}
910
911
/**
912
 * Determine whether a meta key is protected.
913
 *
914
 * @since 3.1.3
915
 *
916
 * @param string      $meta_key Meta key
917
 * @param string|null $meta_type
918
 * @return bool True if the key is protected, false otherwise.
919
 */
920
function is_protected_meta( $meta_key, $meta_type = null ) {
921
	$protected = ( '_' == $meta_key[0] );
922
923
	/**
924
	 * Filters whether a meta key is protected.
925
	 *
926
	 * @since 3.2.0
927
	 *
928
	 * @param bool   $protected Whether the key is protected. Default false.
929
	 * @param string $meta_key  Meta key.
930
	 * @param string $meta_type Meta type.
931
	 */
932
	return apply_filters( 'is_protected_meta', $protected, $meta_key, $meta_type );
933
}
934
935
/**
936
 * Sanitize meta value.
937
 *
938
 * @since 3.1.3
939
 *
940
 * @param string $meta_key       Meta key.
941
 * @param mixed  $meta_value     Meta value to sanitize.
942
 * @param string $object_type    Type of object the meta is registered to.
943
 *
944
 * @return mixed Sanitized $meta_value.
945
 */
946
function sanitize_meta( $meta_key, $meta_value, $object_type ) {
947
	/**
948
	 * Filters the sanitization of a specific meta key of a specific meta type.
949
	 *
950
	 * The dynamic portions of the hook name, `$meta_type`, and `$meta_key`,
951
	 * refer to the metadata object type (comment, post, or user) and the meta
952
	 * key value, respectively.
953
	 *
954
	 * @since 3.3.0
955
	 *
956
	 * @param mixed  $meta_value      Meta value to sanitize.
957
	 * @param string $meta_key        Meta key.
958
	 * @param string $object_type     Object type.
959
	 */
960
	return apply_filters( "sanitize_{$object_type}_meta_{$meta_key}", $meta_value, $meta_key, $object_type );
961
}
962
963
/**
964
 * Registers a meta key.
965
 *
966
 * @since 3.3.0
967
 * @since 4.6.0 {@link https://make.wordpress.org/core/2016/07/08/enhancing-register_meta-in-4-6/ Modified
968
 *              to support an array of data to attach to registered meta keys}. Previous arguments for
969
 *              `$sanitize_callback` and `$auth_callback` have been folded into this array.
970
 *
971
 * @param string $object_type    Type of object this meta is registered to.
972
 * @param string $meta_key       Meta key to register.
973
 * @param array  $args {
974
 *     Data used to describe the meta key when registered.
975
 *
976
 *     @type string $type              The type of data associated with this meta key.
977
 *     @type string $description       A description of the data attached to this meta key.
978
 *     @type bool   $single            Whether the meta key has one value per object, or an array of values per object.
979
 *     @type string $sanitize_callback A function or method to call when sanitizing `$meta_key` data.
980
 *     @type string $auth_callback     Optional. A function or method to call when performing edit_post_meta, add_post_meta, and delete_post_meta capability checks.
981
 *     @type bool   $show_in_rest      Whether data associated with this meta key can be considered public.
982
 * }
983
 * @param string|array $deprecated Deprecated. Use `$args` instead.
984
 *
985
 * @return bool True if the meta key was successfully registered in the global array, false if not.
986
 *                       Registering a meta key with distinct sanitize and auth callbacks will fire those
987
 *                       callbacks, but will not add to the global registry.
988
 */
989
function register_meta( $object_type, $meta_key, $args, $deprecated = null ) {
990
	global $wp_meta_keys;
991
992
	if ( ! is_array( $wp_meta_keys ) ) {
993
		$wp_meta_keys = array();
994
	}
995
996
	$defaults = array(
997
		'type'              => 'string',
998
		'description'       => '',
999
		'single'            => false,
1000
		'sanitize_callback' => null,
1001
		'auth_callback'     => null,
1002
		'show_in_rest'      => false,
1003
	);
1004
1005
	// There used to be individual args for sanitize and auth callbacks
1006
	$has_old_sanitize_cb = false;
1007
	$has_old_auth_cb = false;
1008
1009
	if ( is_callable( $args ) ) {
1010
		$args = array(
1011
			'sanitize_callback' => $args,
1012
		);
1013
1014
		$has_old_sanitize_cb = true;
1015
	} else {
1016
		$args = (array) $args;
1017
	}
1018
1019
	if ( is_callable( $deprecated ) ) {
1020
		$args['auth_callback'] = $deprecated;
1021
		$has_old_auth_cb = true;
1022
	}
1023
1024
	/**
1025
	 * Filters the registration arguments when registering meta.
1026
	 *
1027
	 * @since 4.6.0
1028
	 *
1029
	 * @param array  $args        Array of meta registration arguments.
1030
	 * @param array  $defaults    Array of default arguments.
1031
	 * @param string $object_type Object type.
1032
	 * @param string $meta_key    Meta key.
1033
	 */
1034
	$args = apply_filters( 'register_meta_args', $args, $defaults, $object_type, $meta_key );
1035
	$args = wp_parse_args( $args, $defaults );
1036
1037
	// If `auth_callback` is not provided, fall back to `is_protected_meta()`.
1038
	if ( empty( $args['auth_callback'] ) ) {
1039
		if ( is_protected_meta( $meta_key, $object_type ) ) {
1040
			$args['auth_callback'] = '__return_false';
1041
		} else {
1042
			$args['auth_callback'] = '__return_true';
1043
		}
1044
	}
1045
1046
	// Back-compat: old sanitize and auth callbacks are applied to all of an object type.
1047 View Code Duplication
	if ( is_callable( $args['sanitize_callback'] ) ) {
1048
		add_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'], 10, 3 );
1049
	}
1050
1051 View Code Duplication
	if ( is_callable( $args['auth_callback'] ) ) {
1052
		add_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'], 10, 6 );
1053
	}
1054
1055
	// Global registry only contains meta keys registered with the array of arguments added in 4.6.0.
1056
	if ( ! $has_old_auth_cb && ! $has_old_sanitize_cb ) {
1057
		$wp_meta_keys[ $object_type ][ $meta_key ] = $args;
1058
1059
		return true;
1060
	}
1061
1062
	return false;
1063
}
1064
1065
/**
1066
 * Checks if a meta key is registered.
1067
 *
1068
 * @since 4.6.0
1069
 *
1070
 * @param string $object_type    The type of object.
1071
 * @param string $meta_key       The meta key.
1072
 *
1073
 * @return bool True if the meta key is registered to the object type. False if not.
1074
 */
1075
function registered_meta_key_exists( $object_type, $meta_key ) {
1076
	global $wp_meta_keys;
1077
1078
	if ( ! is_array( $wp_meta_keys ) ) {
1079
		return false;
1080
	}
1081
1082
	if ( ! isset( $wp_meta_keys[ $object_type ] ) ) {
1083
		return false;
1084
	}
1085
1086
	if ( isset( $wp_meta_keys[ $object_type ][ $meta_key ] ) ) {
1087
		return true;
1088
	}
1089
1090
	return false;
1091
}
1092
1093
/**
1094
 * Unregisters a meta key from the list of registered keys.
1095
 *
1096
 * @since 4.6.0
1097
 *
1098
 * @param string $object_type The type of object.
1099
 * @param string $meta_key    The meta key.
1100
 * @return bool True if successful. False if the meta key was not registered.
1101
 */
1102
function unregister_meta_key( $object_type, $meta_key ) {
1103
	global $wp_meta_keys;
1104
1105
	if ( ! registered_meta_key_exists( $object_type, $meta_key ) ) {
1106
		return false;
1107
	}
1108
1109
	$args = $wp_meta_keys[ $object_type ][ $meta_key ];
1110
1111 View Code Duplication
	if ( isset( $args['sanitize_callback'] ) && is_callable( $args['sanitize_callback'] ) ) {
1112
		remove_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'] );
1113
	}
1114
1115 View Code Duplication
	if ( isset( $args['auth_callback'] ) && is_callable( $args['auth_callback'] ) ) {
1116
		remove_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'] );
1117
	}
1118
1119
	unset( $wp_meta_keys[ $object_type ][ $meta_key ] );
1120
1121
	// Do some clean up
1122
	if ( empty( $wp_meta_keys[ $object_type ] ) ) {
1123
		unset( $wp_meta_keys[ $object_type ] );
1124
	}
1125
1126
	return true;
1127
}
1128
1129
/**
1130
 * Retrieves a list of registered meta keys for an object type.
1131
 *
1132
 * @since 4.6.0
1133
 *
1134
 * @param string $object_type The type of object. Post, comment, user, term.
1135
 * @return array List of registered meta keys.
1136
 */
1137
function get_registered_meta_keys( $object_type ) {
1138
	global $wp_meta_keys;
1139
1140
	if ( ! is_array( $wp_meta_keys ) || ! isset( $wp_meta_keys[ $object_type ] ) ) {
1141
		return array();
1142
	}
1143
1144
	return $wp_meta_keys[ $object_type ];
1145
}
1146
1147
/**
1148
 * Retrieves registered metadata for a specified object.
1149
 *
1150
 * @since 4.6.0
1151
 *
1152
 * @param string $object_type Type of object to request metadata for. (e.g. comment, post, term, user)
1153
 * @param int    $object_id   ID of the object the metadata is for.
1154
 * @param string $meta_key    Optional. Registered metadata key. If not specified, retrieve all registered
1155
 *                            metadata for the specified object.
1156
 * @return mixed A single value or array of values for a key if specified. An array of all registered keys
1157
 *               and values for an object ID if not.
1158
 */
1159
function get_registered_metadata( $object_type, $object_id, $meta_key = '' ) {
1160
	if ( ! empty( $meta_key ) ) {
1161
		if ( ! registered_meta_key_exists( $object_type, $meta_key ) ) {
1162
			return false;
1163
		}
1164
		$meta_keys = get_registered_meta_keys( $object_type );
1165
		$meta_key_data = $meta_keys[ $meta_key ];
1166
1167
		$data = get_metadata( $object_type, $object_id, $meta_key, $meta_key_data['single'] );
1168
1169
		return $data;
1170
	}
1171
1172
	$data = get_metadata( $object_type, $object_id );
1173
1174
	$meta_keys = get_registered_meta_keys( $object_type );
1175
	$registered_data = array();
1176
1177
	// Someday, array_filter()
1178
	foreach ( $meta_keys as $k => $v ) {
1179
		if ( isset( $data[ $k ] ) ) {
1180
			$registered_data[ $k ] = $data[ $k ];
1181
		}
1182
	}
1183
1184
	return $registered_data;
1185
}
1186
1187
/**
1188
 * Filter out `register_meta()` args based on a whitelist.
1189
 * `register_meta()` args may change over time, so requiring the whitelist
1190
 * to be explicitly turned off is a warranty seal of sorts.
1191
 *
1192
 * @access private
1193
 * @since  4.6.0
1194
 *
1195
 * @param  array $args         Arguments from `register_meta()`.
1196
 * @param  array $default_args Default arguments for `register_meta()`.
1197
 *
1198
 * @return array Filtered arguments.
1199
 */
1200
function _wp_register_meta_args_whitelist( $args, $default_args ) {
1201
	$whitelist = array_keys( $default_args );
1202
1203
	// In an anonymous function world, this would be better as an array_filter()
1204
	foreach ( $args as $key => $value ) {
1205
		if ( ! in_array( $key, $whitelist ) ) {
1206
			unset( $args[ $key ] );
1207
		}
1208
	}
1209
1210
	return $args;
1211
}
1212