Issues (4967)

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.

src/wp-includes/meta.php (12 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 ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $table of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
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 );
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 ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $table of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
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 );
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);
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 ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $table of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
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 ] ) )
0 ignored issues
show
This if statement, and the following return statement can be replaced with return isset($meta_cache[$meta_key]);.
Loading history...
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 View Code Duplication
	if ( ! $meta_type || ! is_numeric( $meta_id ) || floor( $meta_id ) != $meta_id ) {
571
		return false;
572
	}
573
574
	$meta_id = intval( $meta_id );
575
	if ( $meta_id <= 0 ) {
576
		return false;
577
	}
578
579
	$table = _get_meta_table( $meta_type );
580
	if ( ! $table ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $table of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
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 View Code Duplication
	if ( ! $meta_type || ! is_numeric( $meta_id ) || floor( $meta_id ) != $meta_id ) {
615
		return false;
616
	}
617
618
	$meta_id = intval( $meta_id );
619
	if ( $meta_id <= 0 ) {
620
		return false;
621
	}
622
623
	$table = _get_meta_table( $meta_type );
624
	if ( ! $table ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $table of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
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 View Code Duplication
	if ( ! $meta_type || ! is_numeric( $meta_id ) || floor( $meta_id ) != $meta_id ) {
706
		return false;
707
	}
708
709
	$meta_id = intval( $meta_id );
710
	if ( $meta_id <= 0 ) {
711
		return false;
712
	}
713
714
	$table = _get_meta_table( $meta_type );
715
	if ( ! $table ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $table of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
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 ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $table of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
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.
0 ignored issues
show
Should the return type not be false|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
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://core.trac.wordpress.org/ticket/35658 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
 *                                     Valid values are 'string', 'boolean', 'integer', and 'number'.
978
 *     @type string $description       A description of the data attached to this meta key.
979
 *     @type bool   $single            Whether the meta key has one value per object, or an array of values per object.
980
 *     @type string $sanitize_callback A function or method to call when sanitizing `$meta_key` data.
981
 *     @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.
982
 *     @type bool   $show_in_rest      Whether data associated with this meta key can be considered public.
983
 * }
984
 * @param string|array $deprecated Deprecated. Use `$args` instead.
0 ignored issues
show
Should the type for parameter $deprecated not be string|array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
985
 *
986
 * @return bool True if the meta key was successfully registered in the global array, false if not.
987
 *                       Registering a meta key with distinct sanitize and auth callbacks will fire those
988
 *                       callbacks, but will not add to the global registry.
989
 */
990
function register_meta( $object_type, $meta_key, $args, $deprecated = null ) {
991
	global $wp_meta_keys;
992
993
	if ( ! is_array( $wp_meta_keys ) ) {
994
		$wp_meta_keys = array();
995
	}
996
997
	$defaults = array(
998
		'type'              => 'string',
999
		'description'       => '',
1000
		'single'            => false,
1001
		'sanitize_callback' => null,
1002
		'auth_callback'     => null,
1003
		'show_in_rest'      => false,
1004
	);
1005
1006
	// There used to be individual args for sanitize and auth callbacks
1007
	$has_old_sanitize_cb = false;
1008
	$has_old_auth_cb = false;
1009
1010
	if ( is_callable( $args ) ) {
1011
		$args = array(
1012
			'sanitize_callback' => $args,
1013
		);
1014
1015
		$has_old_sanitize_cb = true;
1016
	} else {
1017
		$args = (array) $args;
1018
	}
1019
1020
	if ( is_callable( $deprecated ) ) {
1021
		$args['auth_callback'] = $deprecated;
1022
		$has_old_auth_cb = true;
1023
	}
1024
1025
	/**
1026
	 * Filters the registration arguments when registering meta.
1027
	 *
1028
	 * @since 4.6.0
1029
	 *
1030
	 * @param array  $args        Array of meta registration arguments.
1031
	 * @param array  $defaults    Array of default arguments.
1032
	 * @param string $object_type Object type.
1033
	 * @param string $meta_key    Meta key.
1034
	 */
1035
	$args = apply_filters( 'register_meta_args', $args, $defaults, $object_type, $meta_key );
1036
	$args = wp_parse_args( $args, $defaults );
1037
1038
	// If `auth_callback` is not provided, fall back to `is_protected_meta()`.
1039
	if ( empty( $args['auth_callback'] ) ) {
1040
		if ( is_protected_meta( $meta_key, $object_type ) ) {
1041
			$args['auth_callback'] = '__return_false';
1042
		} else {
1043
			$args['auth_callback'] = '__return_true';
1044
		}
1045
	}
1046
1047
	// Back-compat: old sanitize and auth callbacks are applied to all of an object type.
1048 View Code Duplication
	if ( is_callable( $args['sanitize_callback'] ) ) {
1049
		add_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'], 10, 3 );
1050
	}
1051
1052 View Code Duplication
	if ( is_callable( $args['auth_callback'] ) ) {
1053
		add_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'], 10, 6 );
1054
	}
1055
1056
	// Global registry only contains meta keys registered with the array of arguments added in 4.6.0.
1057
	if ( ! $has_old_auth_cb && ! $has_old_sanitize_cb ) {
1058
		$wp_meta_keys[ $object_type ][ $meta_key ] = $args;
1059
1060
		return true;
1061
	}
1062
1063
	return false;
1064
}
1065
1066
/**
1067
 * Checks if a meta key is registered.
1068
 *
1069
 * @since 4.6.0
1070
 *
1071
 * @param string $object_type    The type of object.
1072
 * @param string $meta_key       The meta key.
1073
 *
1074
 * @return bool True if the meta key is registered to the object type. False if not.
1075
 */
1076
function registered_meta_key_exists( $object_type, $meta_key ) {
1077
	global $wp_meta_keys;
1078
1079
	if ( ! is_array( $wp_meta_keys ) ) {
1080
		return false;
1081
	}
1082
1083
	if ( ! isset( $wp_meta_keys[ $object_type ] ) ) {
1084
		return false;
1085
	}
1086
1087
	if ( isset( $wp_meta_keys[ $object_type ][ $meta_key ] ) ) {
0 ignored issues
show
This if statement, and the following return statement can be replaced with return isset($wp_meta_ke...ject_type][$meta_key]);.
Loading history...
1088
		return true;
1089
	}
1090
1091
	return false;
1092
}
1093
1094
/**
1095
 * Unregisters a meta key from the list of registered keys.
1096
 *
1097
 * @since 4.6.0
1098
 *
1099
 * @param string $object_type The type of object.
1100
 * @param string $meta_key    The meta key.
1101
 * @return bool True if successful. False if the meta key was not registered.
1102
 */
1103
function unregister_meta_key( $object_type, $meta_key ) {
1104
	global $wp_meta_keys;
1105
1106
	if ( ! registered_meta_key_exists( $object_type, $meta_key ) ) {
1107
		return false;
1108
	}
1109
1110
	$args = $wp_meta_keys[ $object_type ][ $meta_key ];
1111
1112 View Code Duplication
	if ( isset( $args['sanitize_callback'] ) && is_callable( $args['sanitize_callback'] ) ) {
1113
		remove_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'] );
1114
	}
1115
1116 View Code Duplication
	if ( isset( $args['auth_callback'] ) && is_callable( $args['auth_callback'] ) ) {
1117
		remove_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'] );
1118
	}
1119
1120
	unset( $wp_meta_keys[ $object_type ][ $meta_key ] );
1121
1122
	// Do some clean up
1123
	if ( empty( $wp_meta_keys[ $object_type ] ) ) {
1124
		unset( $wp_meta_keys[ $object_type ] );
1125
	}
1126
1127
	return true;
1128
}
1129
1130
/**
1131
 * Retrieves a list of registered meta keys for an object type.
1132
 *
1133
 * @since 4.6.0
1134
 *
1135
 * @param string $object_type The type of object. Post, comment, user, term.
1136
 * @return array List of registered meta keys.
1137
 */
1138
function get_registered_meta_keys( $object_type ) {
1139
	global $wp_meta_keys;
1140
1141
	if ( ! is_array( $wp_meta_keys ) || ! isset( $wp_meta_keys[ $object_type ] ) ) {
1142
		return array();
1143
	}
1144
1145
	return $wp_meta_keys[ $object_type ];
1146
}
1147
1148
/**
1149
 * Retrieves registered metadata for a specified object.
1150
 *
1151
 * @since 4.6.0
1152
 *
1153
 * @param string $object_type Type of object to request metadata for. (e.g. comment, post, term, user)
1154
 * @param int    $object_id   ID of the object the metadata is for.
1155
 * @param string $meta_key    Optional. Registered metadata key. If not specified, retrieve all registered
1156
 *                            metadata for the specified object.
1157
 * @return mixed A single value or array of values for a key if specified. An array of all registered keys
1158
 *               and values for an object ID if not.
1159
 */
1160
function get_registered_metadata( $object_type, $object_id, $meta_key = '' ) {
1161
	if ( ! empty( $meta_key ) ) {
1162
		if ( ! registered_meta_key_exists( $object_type, $meta_key ) ) {
1163
			return false;
1164
		}
1165
		$meta_keys = get_registered_meta_keys( $object_type );
1166
		$meta_key_data = $meta_keys[ $meta_key ];
1167
1168
		$data = get_metadata( $object_type, $object_id, $meta_key, $meta_key_data['single'] );
1169
1170
		return $data;
1171
	}
1172
1173
	$data = get_metadata( $object_type, $object_id );
1174
1175
	$meta_keys = get_registered_meta_keys( $object_type );
1176
	$registered_data = array();
1177
1178
	// Someday, array_filter()
1179
	foreach ( $meta_keys as $k => $v ) {
1180
		if ( isset( $data[ $k ] ) ) {
1181
			$registered_data[ $k ] = $data[ $k ];
1182
		}
1183
	}
1184
1185
	return $registered_data;
1186
}
1187
1188
/**
1189
 * Filter out `register_meta()` args based on a whitelist.
1190
 * `register_meta()` args may change over time, so requiring the whitelist
1191
 * to be explicitly turned off is a warranty seal of sorts.
1192
 *
1193
 * @access private
1194
 * @since  4.6.0
1195
 *
1196
 * @param  array $args         Arguments from `register_meta()`.
1197
 * @param  array $default_args Default arguments for `register_meta()`.
1198
 *
1199
 * @return array Filtered arguments.
1200
 */
1201
function _wp_register_meta_args_whitelist( $args, $default_args ) {
1202
	$whitelist = array_keys( $default_args );
1203
1204
	// In an anonymous function world, this would be better as an array_filter()
1205
	foreach ( $args as $key => $value ) {
1206
		if ( ! in_array( $key, $whitelist ) ) {
1207
			unset( $args[ $key ] );
1208
		}
1209
	}
1210
1211
	return $args;
1212
}
1213