Completed
Push — master ( a7cd2a...eabd6c )
by Stephen
38:42
created

WP_User::remove_all_caps()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 6

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 7
rs 9.4285
cc 1
eloc 6
nc 1
nop 0
1
<?php
2
/**
3
 * User API: WP_User class
4
 *
5
 * @package WordPress
6
 * @subpackage Users
7
 * @since 4.4.0
8
 */
9
10
/**
11
 * Core class used to implement the WP_User object.
12
 *
13
 * @since 2.0.0
14
 *
15
 * @property string $nickname
16
 * @property string $description
17
 * @property string $user_description
18
 * @property string $first_name
19
 * @property string $user_firstname
20
 * @property string $last_name
21
 * @property string $user_lastname
22
 * @property string $user_login
23
 * @property string $user_pass
24
 * @property string $user_nicename
25
 * @property string $user_email
26
 * @property string $user_url
27
 * @property string $user_registered
28
 * @property string $user_activation_key
29
 * @property string $user_status
30
 * @property string $display_name
31
 * @property string $spam
32
 * @property string $deleted
33
 */
34
class WP_User {
35
	/**
36
	 * User data container.
37
	 *
38
	 * @since 2.0.0
39
	 * @var object
40
	 */
41
	public $data;
42
43
	/**
44
	 * The user's ID.
45
	 *
46
	 * @since 2.1.0
47
	 * @access public
48
	 * @var int
49
	 */
50
	public $ID = 0;
51
52
	/**
53
	 * The individual capabilities the user has been given.
54
	 *
55
	 * @since 2.0.0
56
	 * @access public
57
	 * @var array
58
	 */
59
	public $caps = array();
60
61
	/**
62
	 * User metadata option name.
63
	 *
64
	 * @since 2.0.0
65
	 * @access public
66
	 * @var string
67
	 */
68
	public $cap_key;
69
70
	/**
71
	 * The roles the user is part of.
72
	 *
73
	 * @since 2.0.0
74
	 * @access public
75
	 * @var array
76
	 */
77
	public $roles = array();
78
79
	/**
80
	 * All capabilities the user has, including individual and role based.
81
	 *
82
	 * @since 2.0.0
83
	 * @access public
84
	 * @var array
85
	 */
86
	public $allcaps = array();
87
88
	/**
89
	 * The filter context applied to user data fields.
90
	 *
91
	 * @since 2.9.0
92
	 * @access private
93
	 * @var string
94
	 */
95
	var $filter = null;
96
97
	/**
98
	 * @static
99
	 * @access private
100
	 * @var array
101
	 */
102
	private static $back_compat_keys;
103
104
	/**
105
	 * Constructor.
106
	 *
107
	 * Retrieves the userdata and passes it to WP_User::init().
108
	 *
109
	 * @since 2.0.0
110
	 * @access public
111
	 *
112
	 * @global wpdb $wpdb WordPress database abstraction object.
113
	 *
114
	 * @param int|string|stdClass|WP_User $id User's ID, a WP_User object, or a user object from the DB.
115
	 * @param string $name Optional. User's username
116
	 * @param int $blog_id Optional Site ID, defaults to current site.
117
	 */
118
	public function __construct( $id = 0, $name = '', $blog_id = '' ) {
119
		if ( ! isset( self::$back_compat_keys ) ) {
120
			$prefix = $GLOBALS['wpdb']->prefix;
121
			self::$back_compat_keys = array(
122
				'user_firstname' => 'first_name',
123
				'user_lastname' => 'last_name',
124
				'user_description' => 'description',
125
				'user_level' => $prefix . 'user_level',
126
				$prefix . 'usersettings' => $prefix . 'user-settings',
127
				$prefix . 'usersettingstime' => $prefix . 'user-settings-time',
128
			);
129
		}
130
131
		if ( $id instanceof WP_User ) {
132
			$this->init( $id->data, $blog_id );
133
			return;
134
		} elseif ( is_object( $id ) ) {
135
			$this->init( $id, $blog_id );
136
			return;
137
		}
138
139
		if ( ! empty( $id ) && ! is_numeric( $id ) ) {
140
			$name = $id;
141
			$id = 0;
142
		}
143
144
		if ( $id ) {
145
			$data = self::get_data_by( 'id', $id );
146
		} else {
147
			$data = self::get_data_by( 'login', $name );
148
		}
149
150
		if ( $data ) {
151
			$this->init( $data, $blog_id );
152
		} else {
153
			$this->data = new stdClass;
154
		}
155
	}
156
157
	/**
158
	 * Sets up object properties, including capabilities.
159
	 *
160
	 * @param object $data    User DB row object.
161
	 * @param int    $blog_id Optional. The site ID to initialize for.
162
	 */
163
	public function init( $data, $blog_id = '' ) {
164
		$this->data = $data;
165
		$this->ID = (int) $data->ID;
166
167
		$this->for_blog( $blog_id );
168
	}
169
170
	/**
171
	 * Return only the main user fields
172
	 *
173
	 * @since 3.3.0
174
	 * @since 4.4.0 Added 'ID' as an alias of 'id' for the `$field` parameter.
175
	 *
176
	 * @static
177
	 *
178
	 * @global wpdb $wpdb WordPress database abstraction object.
179
	 *
180
	 * @param string $field The field to query against: 'id', 'ID', 'slug', 'email' or 'login'.
181
	 * @param string|int $value The field value
182
	 * @return object|false Raw user object
183
	 */
184
	public static function get_data_by( $field, $value ) {
185
		global $wpdb;
186
187
		// 'ID' is an alias of 'id'.
188
		if ( 'ID' === $field ) {
189
			$field = 'id';
190
		}
191
192
		if ( 'id' == $field ) {
193
			// Make sure the value is numeric to avoid casting objects, for example,
194
			// to int 1.
195
			if ( ! is_numeric( $value ) )
196
				return false;
197
			$value = intval( $value );
198
			if ( $value < 1 )
199
				return false;
200
		} else {
201
			$value = trim( $value );
202
		}
203
204
		if ( !$value )
205
			return false;
206
207
		switch ( $field ) {
208
			case 'id':
209
				$user_id = $value;
210
				$db_field = 'ID';
211
				break;
212
			case 'slug':
213
				$user_id = wp_cache_get($value, 'userslugs');
214
				$db_field = 'user_nicename';
215
				break;
216
			case 'email':
217
				$user_id = wp_cache_get($value, 'useremail');
218
				$db_field = 'user_email';
219
				break;
220
			case 'login':
221
				$value = sanitize_user( $value );
222
				$user_id = wp_cache_get($value, 'userlogins');
223
				$db_field = 'user_login';
224
				break;
225
			default:
226
				return false;
227
		}
228
229
		if ( false !== $user_id ) {
230
			if ( $user = wp_cache_get( $user_id, 'users' ) )
231
				return $user;
232
		}
233
234
		if ( !$user = $wpdb->get_row( $wpdb->prepare(
235
			"SELECT * FROM $wpdb->users WHERE $db_field = %s", $value
236
		) ) )
237
			return false;
238
239
		update_user_caches( $user );
240
241
		return $user;
242
	}
243
244
	/**
245
	 * Makes private/protected methods readable for backwards compatibility.
246
	 *
247
	 * @since 4.3.0
248
	 * @access public
249
	 *
250
	 * @param callable $name      Method to call.
251
	 * @param array    $arguments Arguments to pass when calling.
252
	 * @return mixed|false Return value of the callback, false otherwise.
253
	 */
254
	public function __call( $name, $arguments ) {
255
		if ( '_init_caps' === $name ) {
256
			return call_user_func_array( array( $this, $name ), $arguments );
257
		}
258
		return false;
259
	}
260
261
	/**
262
	 * Magic method for checking the existence of a certain custom field.
263
	 *
264
	 * @since 3.3.0
265
	 * @access public
266
	 *
267
	 * @param string $key User meta key to check if set.
268
	 * @return bool Whether the given user meta key is set.
269
	 */
270
	public function __isset( $key ) {
271 View Code Duplication
		if ( 'id' == $key ) {
272
			_deprecated_argument( 'WP_User->id', '2.1',
273
				sprintf(
274
					/* translators: %s: WP_User->ID */
275
					__( 'Use %s instead.' ),
276
					'<code>WP_User->ID</code>'
277
				)
278
			);
279
			$key = 'ID';
280
		}
281
282
		if ( isset( $this->data->$key ) )
283
			return true;
284
285
		if ( isset( self::$back_compat_keys[ $key ] ) )
286
			$key = self::$back_compat_keys[ $key ];
287
288
		return metadata_exists( 'user', $this->ID, $key );
289
	}
290
291
	/**
292
	 * Magic method for accessing custom fields.
293
	 *
294
	 * @since 3.3.0
295
	 * @access public
296
	 *
297
	 * @param string $key User meta key to retrieve.
298
	 * @return mixed Value of the given user meta key (if set). If `$key` is 'id', the user ID.
299
	 */
300
	public function __get( $key ) {
301 View Code Duplication
		if ( 'id' == $key ) {
302
			_deprecated_argument( 'WP_User->id', '2.1',
303
				sprintf(
304
					/* translators: %s: WP_User->ID */
305
					__( 'Use %s instead.' ),
306
					'<code>WP_User->ID</code>'
307
				)
308
			);
309
			return $this->ID;
310
		}
311
312
		if ( isset( $this->data->$key ) ) {
313
			$value = $this->data->$key;
314
		} else {
315
			if ( isset( self::$back_compat_keys[ $key ] ) )
316
				$key = self::$back_compat_keys[ $key ];
317
			$value = get_user_meta( $this->ID, $key, true );
318
		}
319
320
		if ( $this->filter ) {
321
			$value = sanitize_user_field( $key, $value, $this->ID, $this->filter );
322
		}
323
324
		return $value;
325
	}
326
327
	/**
328
	 * Magic method for setting custom user fields.
329
	 *
330
	 * This method does not update custom fields in the database. It only stores
331
	 * the value on the WP_User instance.
332
	 *
333
	 * @since 3.3.0
334
	 * @access public
335
	 *
336
	 * @param string $key   User meta key.
337
	 * @param mixed  $value User meta value.
338
	 */
339
	public function __set( $key, $value ) {
340 View Code Duplication
		if ( 'id' == $key ) {
341
			_deprecated_argument( 'WP_User->id', '2.1',
342
				sprintf(
343
					/* translators: %s: WP_User->ID */
344
					__( 'Use %s instead.' ),
345
					'<code>WP_User->ID</code>'
346
				)
347
			);
348
			$this->ID = $value;
349
			return;
350
		}
351
352
		$this->data->$key = $value;
353
	}
354
355
	/**
356
	 * Magic method for unsetting a certain custom field.
357
	 *
358
	 * @since 4.4.0
359
	 * @access public
360
	 *
361
	 * @param string $key User meta key to unset.
362
	 */
363
	public function __unset( $key ) {
364
		if ( 'id' == $key ) {
365
			_deprecated_argument( 'WP_User->id', '2.1',
366
				sprintf(
367
					/* translators: %s: WP_User->ID */
368
					__( 'Use %s instead.' ),
369
					'<code>WP_User->ID</code>'
370
				)
371
			);
372
		}
373
374
		if ( isset( $this->data->$key ) ) {
375
			unset( $this->data->$key );
376
		}
377
378
		if ( isset( self::$back_compat_keys[ $key ] ) ) {
379
			unset( self::$back_compat_keys[ $key ] );
380
		}
381
	}
382
383
	/**
384
	 * Determine whether the user exists in the database.
385
	 *
386
	 * @since 3.4.0
387
	 * @access public
388
	 *
389
	 * @return bool True if user exists in the database, false if not.
390
	 */
391
	public function exists() {
392
		return ! empty( $this->ID );
393
	}
394
395
	/**
396
	 * Retrieve the value of a property or meta key.
397
	 *
398
	 * Retrieves from the users and usermeta table.
399
	 *
400
	 * @since 3.3.0
401
	 *
402
	 * @param string $key Property
403
	 * @return mixed
404
	 */
405
	public function get( $key ) {
406
		return $this->__get( $key );
407
	}
408
409
	/**
410
	 * Determine whether a property or meta key is set
411
	 *
412
	 * Consults the users and usermeta tables.
413
	 *
414
	 * @since 3.3.0
415
	 *
416
	 * @param string $key Property
417
	 * @return bool
418
	 */
419
	public function has_prop( $key ) {
420
		return $this->__isset( $key );
421
	}
422
423
	/**
424
	 * Return an array representation.
425
	 *
426
	 * @since 3.5.0
427
	 *
428
	 * @return array Array representation.
429
	 */
430
	public function to_array() {
431
		return get_object_vars( $this->data );
432
	}
433
434
	/**
435
	 * Set up capability object properties.
436
	 *
437
	 * Will set the value for the 'cap_key' property to current database table
438
	 * prefix, followed by 'capabilities'. Will then check to see if the
439
	 * property matching the 'cap_key' exists and is an array. If so, it will be
440
	 * used.
441
	 *
442
	 * @access protected
443
	 * @since 2.1.0
444
	 *
445
	 * @global wpdb $wpdb WordPress database abstraction object.
446
	 *
447
	 * @param string $cap_key Optional capability key
448
	 */
449
	protected function _init_caps( $cap_key = '' ) {
450
		global $wpdb;
451
452
		if ( empty($cap_key) )
453
			$this->cap_key = $wpdb->get_blog_prefix() . 'capabilities';
454
		else
455
			$this->cap_key = $cap_key;
456
457
		$this->caps = get_user_meta( $this->ID, $this->cap_key, true );
0 ignored issues
show
Documentation Bug introduced by
It seems like get_user_meta($this->ID, $this->cap_key, true) of type * is incompatible with the declared type array of property $caps.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
458
459
		if ( ! is_array( $this->caps ) )
460
			$this->caps = array();
461
462
		$this->get_role_caps();
463
	}
464
465
	/**
466
	 * Retrieve all of the role capabilities and merge with individual capabilities.
467
	 *
468
	 * All of the capabilities of the roles the user belongs to are merged with
469
	 * the users individual roles. This also means that the user can be denied
470
	 * specific roles that their role might have, but the specific user isn't
471
	 * granted permission to.
472
	 *
473
	 * @since 2.0.0
474
	 * @access public
475
	 *
476
	 * @return array List of all capabilities for the user.
477
	 */
478
	public function get_role_caps() {
479
		$wp_roles = wp_roles();
480
481
		//Filter out caps that are not role names and assign to $this->roles
482
		if ( is_array( $this->caps ) )
483
			$this->roles = array_filter( array_keys( $this->caps ), array( $wp_roles, 'is_role' ) );
484
485
		//Build $allcaps from role caps, overlay user's $caps
486
		$this->allcaps = array();
487
		foreach ( (array) $this->roles as $role ) {
488
			$the_role = $wp_roles->get_role( $role );
489
			$this->allcaps = array_merge( (array) $this->allcaps, (array) $the_role->capabilities );
490
		}
491
		$this->allcaps = array_merge( (array) $this->allcaps, (array) $this->caps );
492
493
		return $this->allcaps;
494
	}
495
496
	/**
497
	 * Add role to user.
498
	 *
499
	 * Updates the user's meta data option with capabilities and roles.
500
	 *
501
	 * @since 2.0.0
502
	 * @access public
503
	 *
504
	 * @param string $role Role name.
505
	 */
506 View Code Duplication
	public function add_role( $role ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
507
		if ( empty( $role ) ) {
508
			return;
509
		}
510
511
		$this->caps[$role] = true;
512
		update_user_meta( $this->ID, $this->cap_key, $this->caps );
513
		$this->get_role_caps();
514
		$this->update_user_level_from_caps();
515
516
		/**
517
		 * Fires immediately after the user has been given a new role.
518
		 *
519
		 * @since 4.3.0
520
		 *
521
		 * @param int    $user_id The user ID.
522
		 * @param string $role    The new role.
523
		 */
524
		do_action( 'add_user_role', $this->ID, $role );
525
	}
526
527
	/**
528
	 * Remove role from user.
529
	 *
530
	 * @since 2.0.0
531
	 * @access public
532
	 *
533
	 * @param string $role Role name.
534
	 */
535 View Code Duplication
	public function remove_role( $role ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
536
		if ( !in_array($role, $this->roles) )
537
			return;
538
		unset( $this->caps[$role] );
539
		update_user_meta( $this->ID, $this->cap_key, $this->caps );
540
		$this->get_role_caps();
541
		$this->update_user_level_from_caps();
542
543
		/**
544
		 * Fires immediately after a role as been removed from a user.
545
		 *
546
		 * @since 4.3.0
547
		 *
548
		 * @param int    $user_id The user ID.
549
		 * @param string $role    The removed role.
550
		 */
551
		do_action( 'remove_user_role', $this->ID, $role );
552
	}
553
554
	/**
555
	 * Set the role of the user.
556
	 *
557
	 * This will remove the previous roles of the user and assign the user the
558
	 * new one. You can set the role to an empty string and it will remove all
559
	 * of the roles from the user.
560
	 *
561
	 * @since 2.0.0
562
	 * @access public
563
	 *
564
	 * @param string $role Role name.
565
	 */
566
	public function set_role( $role ) {
567
		if ( 1 == count( $this->roles ) && $role == current( $this->roles ) )
568
			return;
569
570
		foreach ( (array) $this->roles as $oldrole )
571
			unset( $this->caps[$oldrole] );
572
573
		$old_roles = $this->roles;
574
		if ( !empty( $role ) ) {
575
			$this->caps[$role] = true;
576
			$this->roles = array( $role => true );
577
		} else {
578
			$this->roles = false;
0 ignored issues
show
Documentation Bug introduced by
It seems like false of type false is incompatible with the declared type array of property $roles.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
579
		}
580
		update_user_meta( $this->ID, $this->cap_key, $this->caps );
581
		$this->get_role_caps();
582
		$this->update_user_level_from_caps();
583
584
		/**
585
		 * Fires after the user's role has changed.
586
		 *
587
		 * @since 2.9.0
588
		 * @since 3.6.0 Added $old_roles to include an array of the user's previous roles.
589
		 *
590
		 * @param int    $user_id   The user ID.
591
		 * @param string $role      The new role.
592
		 * @param array  $old_roles An array of the user's previous roles.
593
		 */
594
		do_action( 'set_user_role', $this->ID, $role, $old_roles );
595
	}
596
597
	/**
598
	 * Choose the maximum level the user has.
599
	 *
600
	 * Will compare the level from the $item parameter against the $max
601
	 * parameter. If the item is incorrect, then just the $max parameter value
602
	 * will be returned.
603
	 *
604
	 * Used to get the max level based on the capabilities the user has. This
605
	 * is also based on roles, so if the user is assigned the Administrator role
606
	 * then the capability 'level_10' will exist and the user will get that
607
	 * value.
608
	 *
609
	 * @since 2.0.0
610
	 * @access public
611
	 *
612
	 * @param int $max Max level of user.
613
	 * @param string $item Level capability name.
614
	 * @return int Max Level.
615
	 */
616
	public function level_reduction( $max, $item ) {
617
		if ( preg_match( '/^level_(10|[0-9])$/i', $item, $matches ) ) {
618
			$level = intval( $matches[1] );
619
			return max( $max, $level );
620
		} else {
621
			return $max;
622
		}
623
	}
624
625
	/**
626
	 * Update the maximum user level for the user.
627
	 *
628
	 * Updates the 'user_level' user metadata (includes prefix that is the
629
	 * database table prefix) with the maximum user level. Gets the value from
630
	 * the all of the capabilities that the user has.
631
	 *
632
	 * @since 2.0.0
633
	 * @access public
634
	 *
635
	 * @global wpdb $wpdb WordPress database abstraction object.
636
	 */
637
	public function update_user_level_from_caps() {
638
		global $wpdb;
639
		$this->user_level = array_reduce( array_keys( $this->allcaps ), array( $this, 'level_reduction' ), 0 );
0 ignored issues
show
Documentation introduced by
The property user_level does not exist on object<WP_User>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
640
		update_user_meta( $this->ID, $wpdb->get_blog_prefix() . 'user_level', $this->user_level );
0 ignored issues
show
Documentation introduced by
The property user_level does not exist on object<WP_User>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
641
	}
642
643
	/**
644
	 * Add capability and grant or deny access to capability.
645
	 *
646
	 * @since 2.0.0
647
	 * @access public
648
	 *
649
	 * @param string $cap Capability name.
650
	 * @param bool $grant Whether to grant capability to user.
651
	 */
652
	public function add_cap( $cap, $grant = true ) {
653
		$this->caps[$cap] = $grant;
654
		update_user_meta( $this->ID, $this->cap_key, $this->caps );
655
		$this->get_role_caps();
656
		$this->update_user_level_from_caps();
657
	}
658
659
	/**
660
	 * Remove capability from user.
661
	 *
662
	 * @since 2.0.0
663
	 * @access public
664
	 *
665
	 * @param string $cap Capability name.
666
	 */
667
	public function remove_cap( $cap ) {
668
		if ( ! isset( $this->caps[ $cap ] ) ) {
669
			return;
670
		}
671
		unset( $this->caps[ $cap ] );
672
		update_user_meta( $this->ID, $this->cap_key, $this->caps );
673
		$this->get_role_caps();
674
		$this->update_user_level_from_caps();
675
	}
676
677
	/**
678
	 * Remove all of the capabilities of the user.
679
	 *
680
	 * @since 2.1.0
681
	 * @access public
682
	 *
683
	 * @global wpdb $wpdb WordPress database abstraction object.
684
	 */
685
	public function remove_all_caps() {
686
		global $wpdb;
687
		$this->caps = array();
688
		delete_user_meta( $this->ID, $this->cap_key );
689
		delete_user_meta( $this->ID, $wpdb->get_blog_prefix() . 'user_level' );
690
		$this->get_role_caps();
691
	}
692
693
	/**
694
	 * Whether user has capability or role name.
695
	 *
696
	 * While checking against particular roles in place of a capability is supported
697
	 * in part, this practice is discouraged as it may produce unreliable results.
698
	 *
699
	 * @since 2.0.0
700
	 * @access public
701
	 *
702
	 * @see map_meta_cap()
703
	 *
704
	 * @param string $cap           Capability name.
705
	 * @param int    $object_id,... Optional. ID of the specific object to check against if `$cap` is a "meta" cap.
0 ignored issues
show
Bug introduced by
There is no parameter named $object_id,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
706
	 *                              "Meta" capabilities, e.g. 'edit_post', 'edit_user', etc., are capabilities used
707
	 *                              by map_meta_cap() to map to other "primitive" capabilities, e.g. 'edit_posts',
708
	 *                              'edit_others_posts', etc. The parameter is accessed via func_get_args() and passed
709
	 *                              to map_meta_cap().
710
	 * @return bool Whether the current user has the given capability. If `$cap` is a meta cap and `$object_id` is
711
	 *              passed, whether the current user has the given meta capability for the given object.
712
	 */
713
	public function has_cap( $cap ) {
714
		if ( is_numeric( $cap ) ) {
715
			_deprecated_argument( __FUNCTION__, '2.0', __('Usage of user levels by plugins and themes is deprecated. Use roles and capabilities instead.') );
716
			$cap = $this->translate_level_to_cap( $cap );
717
		}
718
719
		$args = array_slice( func_get_args(), 1 );
720
		$args = array_merge( array( $cap, $this->ID ), $args );
721
		$caps = call_user_func_array( 'map_meta_cap', $args );
722
723
		// Multisite super admin has all caps by definition, Unless specifically denied.
724
		if ( is_multisite() && is_super_admin( $this->ID ) ) {
725
			if ( in_array('do_not_allow', $caps) )
726
				return false;
727
			return true;
728
		}
729
730
		/**
731
		 * Dynamically filter a user's capabilities.
732
		 *
733
		 * @since 2.0.0
734
		 * @since 3.7.0 Added the user object.
735
		 *
736
		 * @param array   $allcaps An array of all the user's capabilities.
737
		 * @param array   $caps    Actual capabilities for meta capability.
738
		 * @param array   $args    Optional parameters passed to has_cap(), typically object ID.
739
		 * @param WP_User $user    The user object.
740
		 */
741
		$capabilities = apply_filters( 'user_has_cap', $this->allcaps, $caps, $args, $this );
742
743
		// Everyone is allowed to exist.
744
		$capabilities['exist'] = true;
745
746
		// Must have ALL requested caps.
747
		foreach ( (array) $caps as $cap ) {
748
			if ( empty( $capabilities[ $cap ] ) )
749
				return false;
750
		}
751
752
		return true;
753
	}
754
755
	/**
756
	 * Convert numeric level to level capability name.
757
	 *
758
	 * Prepends 'level_' to level number.
759
	 *
760
	 * @since 2.0.0
761
	 * @access public
762
	 *
763
	 * @param int $level Level number, 1 to 10.
764
	 * @return string
765
	 */
766
	public function translate_level_to_cap( $level ) {
767
		return 'level_' . $level;
768
	}
769
770
	/**
771
	 * Set the site to operate on. Defaults to the current site.
772
	 *
773
	 * @since 3.0.0
774
	 *
775
	 * @global wpdb $wpdb WordPress database abstraction object.
776
	 *
777
	 * @param int $blog_id Optional. Site ID, defaults to current site.
778
	 */
779
	public function for_blog( $blog_id = '' ) {
780
		global $wpdb;
781
		if ( ! empty( $blog_id ) )
782
			$cap_key = $wpdb->get_blog_prefix( $blog_id ) . 'capabilities';
783
		else
784
			$cap_key = '';
785
		$this->_init_caps( $cap_key );
786
	}
787
}
788