]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-includes/capabilities.php
WordPress 4.4
[autoinstalls/wordpress.git] / wp-includes / capabilities.php
1 <?php
2 /**
3  * Core User Role & Capabilities API
4  *
5  * @package WordPress
6  * @subpackage Users
7  */
8
9 /**
10  * Map meta capabilities to primitive capabilities.
11  *
12  * This does not actually compare whether the user ID has the actual capability,
13  * just what the capability or capabilities are. Meta capability list value can
14  * be 'delete_user', 'edit_user', 'remove_user', 'promote_user', 'delete_post',
15  * 'delete_page', 'edit_post', 'edit_page', 'read_post', or 'read_page'.
16  *
17  * @since 2.0.0
18  *
19  * @param string $cap       Capability name.
20  * @param int    $user_id   User ID.
21  * @param int    $object_id Optional. ID of the specific object to check against if `$cap` is a "meta" cap.
22  *                          "Meta" capabilities, e.g. 'edit_post', 'edit_user', etc., are capabilities used
23  *                          by map_meta_cap() to map to other "primitive" capabilities, e.g. 'edit_posts',
24  *                          'edit_others_posts', etc. The parameter is accessed via func_get_args().
25  * @return array Actual capabilities for meta capability.
26  */
27 function map_meta_cap( $cap, $user_id ) {
28         $args = array_slice( func_get_args(), 2 );
29         $caps = array();
30
31         switch ( $cap ) {
32         case 'remove_user':
33                 $caps[] = 'remove_users';
34                 break;
35         case 'promote_user':
36         case 'add_users':
37                 $caps[] = 'promote_users';
38                 break;
39         case 'edit_user':
40         case 'edit_users':
41                 // Allow user to edit itself
42                 if ( 'edit_user' == $cap && isset( $args[0] ) && $user_id == $args[0] )
43                         break;
44
45                 // In multisite the user must have manage_network_users caps. If editing a super admin, the user must be a super admin.
46                 if ( is_multisite() && ( ( ! is_super_admin( $user_id ) && 'edit_user' === $cap && is_super_admin( $args[0] ) ) || ! user_can( $user_id, 'manage_network_users' ) ) ) {
47                         $caps[] = 'do_not_allow';
48                 } else {
49                         $caps[] = 'edit_users'; // edit_user maps to edit_users.
50                 }
51                 break;
52         case 'delete_post':
53         case 'delete_page':
54                 $post = get_post( $args[0] );
55                 if ( ! $post ) {
56                         $caps[] = 'do_not_allow';
57                         break;
58                 }
59
60                 if ( 'revision' == $post->post_type ) {
61                         $post = get_post( $post->post_parent );
62                         if ( ! $post ) {
63                                 $caps[] = 'do_not_allow';
64                                 break;
65                         }
66                 }
67
68                 $post_type = get_post_type_object( $post->post_type );
69                 if ( ! $post_type ) {
70                         /* translators: 1: post type, 2: capability name */
71                         _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' );
72                         $caps[] = 'edit_others_posts';
73                         break;
74                 }
75
76                 if ( ! $post_type->map_meta_cap ) {
77                         $caps[] = $post_type->cap->$cap;
78                         // Prior to 3.1 we would re-call map_meta_cap here.
79                         if ( 'delete_post' == $cap )
80                                 $cap = $post_type->cap->$cap;
81                         break;
82                 }
83
84                 // If the post author is set and the user is the author...
85                 if ( $post->post_author && $user_id == $post->post_author ) {
86                         // If the post is published or scheduled...
87                         if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
88                                 $caps[] = $post_type->cap->delete_published_posts;
89                         } elseif ( 'trash' == $post->post_status ) {
90                                 $status = get_post_meta( $post->ID, '_wp_trash_meta_status', true );
91                                 if ( in_array( $status, array( 'publish', 'future' ), true ) ) {
92                                         $caps[] = $post_type->cap->delete_published_posts;
93                                 } else {
94                                         $caps[] = $post_type->cap->delete_posts;
95                                 }
96                         } else {
97                                 // If the post is draft...
98                                 $caps[] = $post_type->cap->delete_posts;
99                         }
100                 } else {
101                         // The user is trying to edit someone else's post.
102                         $caps[] = $post_type->cap->delete_others_posts;
103                         // The post is published or scheduled, extra cap required.
104                         if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
105                                 $caps[] = $post_type->cap->delete_published_posts;
106                         } elseif ( 'private' == $post->post_status ) {
107                                 $caps[] = $post_type->cap->delete_private_posts;
108                         }
109                 }
110                 break;
111                 // edit_post breaks down to edit_posts, edit_published_posts, or
112                 // edit_others_posts
113         case 'edit_post':
114         case 'edit_page':
115                 $post = get_post( $args[0] );
116                 if ( ! $post ) {
117                         $caps[] = 'do_not_allow';
118                         break;
119                 }
120
121                 if ( 'revision' == $post->post_type ) {
122                         $post = get_post( $post->post_parent );
123                         if ( ! $post ) {
124                                 $caps[] = 'do_not_allow';
125                                 break;
126                         }
127                 }
128
129                 $post_type = get_post_type_object( $post->post_type );
130                 if ( ! $post_type ) {
131                         /* translators: 1: post type, 2: capability name */
132                         _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' );
133                         $caps[] = 'edit_others_posts';
134                         break;
135                 }
136
137                 if ( ! $post_type->map_meta_cap ) {
138                         $caps[] = $post_type->cap->$cap;
139                         // Prior to 3.1 we would re-call map_meta_cap here.
140                         if ( 'edit_post' == $cap )
141                                 $cap = $post_type->cap->$cap;
142                         break;
143                 }
144
145                 // If the post author is set and the user is the author...
146                 if ( $post->post_author && $user_id == $post->post_author ) {
147                         // If the post is published or scheduled...
148                         if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
149                                 $caps[] = $post_type->cap->edit_published_posts;
150                         } elseif ( 'trash' == $post->post_status ) {
151                                 $status = get_post_meta( $post->ID, '_wp_trash_meta_status', true );
152                                 if ( in_array( $status, array( 'publish', 'future' ), true ) ) {
153                                         $caps[] = $post_type->cap->edit_published_posts;
154                                 } else {
155                                         $caps[] = $post_type->cap->edit_posts;
156                                 }
157                         } else {
158                                 // If the post is draft...
159                                 $caps[] = $post_type->cap->edit_posts;
160                         }
161                 } else {
162                         // The user is trying to edit someone else's post.
163                         $caps[] = $post_type->cap->edit_others_posts;
164                         // The post is published or scheduled, extra cap required.
165                         if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
166                                 $caps[] = $post_type->cap->edit_published_posts;
167                         } elseif ( 'private' == $post->post_status ) {
168                                 $caps[] = $post_type->cap->edit_private_posts;
169                         }
170                 }
171                 break;
172         case 'read_post':
173         case 'read_page':
174                 $post = get_post( $args[0] );
175                 if ( ! $post ) {
176                         $caps[] = 'do_not_allow';
177                         break;
178                 }
179
180                 if ( 'revision' == $post->post_type ) {
181                         $post = get_post( $post->post_parent );
182                         if ( ! $post ) {
183                                 $caps[] = 'do_not_allow';
184                                 break;
185                         }
186                 }
187
188                 $post_type = get_post_type_object( $post->post_type );
189                 if ( ! $post_type ) {
190                         /* translators: 1: post type, 2: capability name */
191                         _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' );
192                         $caps[] = 'edit_others_posts';
193                         break;
194                 }
195
196                 if ( ! $post_type->map_meta_cap ) {
197                         $caps[] = $post_type->cap->$cap;
198                         // Prior to 3.1 we would re-call map_meta_cap here.
199                         if ( 'read_post' == $cap )
200                                 $cap = $post_type->cap->$cap;
201                         break;
202                 }
203
204                 $status_obj = get_post_status_object( $post->post_status );
205                 if ( $status_obj->public ) {
206                         $caps[] = $post_type->cap->read;
207                         break;
208                 }
209
210                 if ( $post->post_author && $user_id == $post->post_author ) {
211                         $caps[] = $post_type->cap->read;
212                 } elseif ( $status_obj->private ) {
213                         $caps[] = $post_type->cap->read_private_posts;
214                 } else {
215                         $caps = map_meta_cap( 'edit_post', $user_id, $post->ID );
216                 }
217                 break;
218         case 'publish_post':
219                 $post = get_post( $args[0] );
220                 if ( ! $post ) {
221                         $caps[] = 'do_not_allow';
222                         break;
223                 }
224
225                 $post_type = get_post_type_object( $post->post_type );
226                 if ( ! $post_type ) {
227                         /* translators: 1: post type, 2: capability name */
228                         _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' );
229                         $caps[] = 'edit_others_posts';
230                         break;
231                 }
232
233                 $caps[] = $post_type->cap->publish_posts;
234                 break;
235         case 'edit_post_meta':
236         case 'delete_post_meta':
237         case 'add_post_meta':
238                 $post = get_post( $args[0] );
239                 if ( ! $post ) {
240                         $caps[] = 'do_not_allow';
241                         break;
242                 }
243
244                 $caps = map_meta_cap( 'edit_post', $user_id, $post->ID );
245
246                 $meta_key = isset( $args[ 1 ] ) ? $args[ 1 ] : false;
247
248                 if ( $meta_key && has_filter( "auth_post_meta_{$meta_key}" ) ) {
249                         /**
250                          * Filter whether the user is allowed to add post meta to a post.
251                          *
252                          * The dynamic portion of the hook name, `$meta_key`, refers to the
253                          * meta key passed to {@see map_meta_cap()}.
254                          *
255                          * @since 3.3.0
256                          *
257                          * @param bool   $allowed  Whether the user can add the post meta. Default false.
258                          * @param string $meta_key The meta key.
259                          * @param int    $post_id  Post ID.
260                          * @param int    $user_id  User ID.
261                          * @param string $cap      Capability name.
262                          * @param array  $caps     User capabilities.
263                          */
264                         $allowed = apply_filters( "auth_post_meta_{$meta_key}", false, $meta_key, $post->ID, $user_id, $cap, $caps );
265                         if ( ! $allowed )
266                                 $caps[] = $cap;
267                 } elseif ( $meta_key && is_protected_meta( $meta_key, 'post' ) ) {
268                         $caps[] = $cap;
269                 }
270                 break;
271         case 'edit_comment':
272                 $comment = get_comment( $args[0] );
273                 if ( ! $comment ) {
274                         $caps[] = 'do_not_allow';
275                         break;
276                 }
277
278                 $post = get_post( $comment->comment_post_ID );
279
280                 /*
281                  * If the post doesn't exist, we have an orphaned comment.
282                  * Fall back to the edit_posts capability, instead.
283                  */
284                 if ( $post ) {
285                         $caps = map_meta_cap( 'edit_post', $user_id, $post->ID );
286                 } else {
287                         $caps = map_meta_cap( 'edit_posts', $user_id );
288                 }
289                 break;
290         case 'unfiltered_upload':
291                 if ( defined('ALLOW_UNFILTERED_UPLOADS') && ALLOW_UNFILTERED_UPLOADS && ( !is_multisite() || is_super_admin( $user_id ) )  )
292                         $caps[] = $cap;
293                 else
294                         $caps[] = 'do_not_allow';
295                 break;
296         case 'unfiltered_html' :
297                 // Disallow unfiltered_html for all users, even admins and super admins.
298                 if ( defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML )
299                         $caps[] = 'do_not_allow';
300                 elseif ( is_multisite() && ! is_super_admin( $user_id ) )
301                         $caps[] = 'do_not_allow';
302                 else
303                         $caps[] = $cap;
304                 break;
305         case 'edit_files':
306         case 'edit_plugins':
307         case 'edit_themes':
308                 // Disallow the file editors.
309                 if ( defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT )
310                         $caps[] = 'do_not_allow';
311                 elseif ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS )
312                         $caps[] = 'do_not_allow';
313                 elseif ( is_multisite() && ! is_super_admin( $user_id ) )
314                         $caps[] = 'do_not_allow';
315                 else
316                         $caps[] = $cap;
317                 break;
318         case 'update_plugins':
319         case 'delete_plugins':
320         case 'install_plugins':
321         case 'upload_plugins':
322         case 'update_themes':
323         case 'delete_themes':
324         case 'install_themes':
325         case 'upload_themes':
326         case 'update_core':
327                 // Disallow anything that creates, deletes, or updates core, plugin, or theme files.
328                 // Files in uploads are excepted.
329                 if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS ) {
330                         $caps[] = 'do_not_allow';
331                 } elseif ( is_multisite() && ! is_super_admin( $user_id ) ) {
332                         $caps[] = 'do_not_allow';
333                 } elseif ( 'upload_themes' === $cap ) {
334                         $caps[] = 'install_themes';
335                 } elseif ( 'upload_plugins' === $cap ) {
336                         $caps[] = 'install_plugins';
337                 } else {
338                         $caps[] = $cap;
339                 }
340                 break;
341         case 'activate_plugins':
342                 $caps[] = $cap;
343                 if ( is_multisite() ) {
344                         // update_, install_, and delete_ are handled above with is_super_admin().
345                         $menu_perms = get_site_option( 'menu_items', array() );
346                         if ( empty( $menu_perms['plugins'] ) )
347                                 $caps[] = 'manage_network_plugins';
348                 }
349                 break;
350         case 'delete_user':
351         case 'delete_users':
352                 // If multisite only super admins can delete users.
353                 if ( is_multisite() && ! is_super_admin( $user_id ) )
354                         $caps[] = 'do_not_allow';
355                 else
356                         $caps[] = 'delete_users'; // delete_user maps to delete_users.
357                 break;
358         case 'create_users':
359                 if ( !is_multisite() )
360                         $caps[] = $cap;
361                 elseif ( is_super_admin( $user_id ) || get_site_option( 'add_new_users' ) )
362                         $caps[] = $cap;
363                 else
364                         $caps[] = 'do_not_allow';
365                 break;
366         case 'manage_links' :
367                 if ( get_option( 'link_manager_enabled' ) )
368                         $caps[] = $cap;
369                 else
370                         $caps[] = 'do_not_allow';
371                 break;
372         case 'customize' :
373                 $caps[] = 'edit_theme_options';
374                 break;
375         case 'delete_site':
376                 $caps[] = 'manage_options';
377                 break;
378         default:
379                 // Handle meta capabilities for custom post types.
380                 $post_type_meta_caps = _post_type_meta_capabilities();
381                 if ( isset( $post_type_meta_caps[ $cap ] ) ) {
382                         $args = array_merge( array( $post_type_meta_caps[ $cap ], $user_id ), $args );
383                         return call_user_func_array( 'map_meta_cap', $args );
384                 }
385
386                 // If no meta caps match, return the original cap.
387                 $caps[] = $cap;
388         }
389
390         /**
391          * Filter a user's capabilities depending on specific context and/or privilege.
392          *
393          * @since 2.8.0
394          *
395          * @param array  $caps    Returns the user's actual capabilities.
396          * @param string $cap     Capability name.
397          * @param int    $user_id The user ID.
398          * @param array  $args    Adds the context to the cap. Typically the object ID.
399          */
400         return apply_filters( 'map_meta_cap', $caps, $cap, $user_id, $args );
401 }
402
403 /**
404  * Whether the current user has a specific capability.
405  *
406  * While checking against particular roles in place of a capability is supported
407  * in part, this practice is discouraged as it may produce unreliable results.
408  *
409  * @since 2.0.0
410  *
411  * @see WP_User::has_cap()
412  * @see map_meta_cap()
413  *
414  * @param string $capability Capability name.
415  * @param int    $object_id  Optional. ID of the specific object to check against if `$capability` is a "meta" cap.
416  *                           "Meta" capabilities, e.g. 'edit_post', 'edit_user', etc., are capabilities used
417  *                           by map_meta_cap() to map to other "primitive" capabilities, e.g. 'edit_posts',
418  *                           'edit_others_posts', etc. Accessed via func_get_args() and passed to WP_User::has_cap(),
419  *                           then map_meta_cap().
420  * @return bool Whether the current user has the given capability. If `$capability` is a meta cap and `$object_id` is
421  *              passed, whether the current user has the given meta capability for the given object.
422  */
423 function current_user_can( $capability ) {
424         $current_user = wp_get_current_user();
425
426         if ( empty( $current_user ) )
427                 return false;
428
429         $args = array_slice( func_get_args(), 1 );
430         $args = array_merge( array( $capability ), $args );
431
432         return call_user_func_array( array( $current_user, 'has_cap' ), $args );
433 }
434
435 /**
436  * Whether current user has a capability or role for a given blog.
437  *
438  * @since 3.0.0
439  *
440  * @param int $blog_id Blog ID
441  * @param string $capability Capability or role name.
442  * @return bool
443  */
444 function current_user_can_for_blog( $blog_id, $capability ) {
445         $switched = is_multisite() ? switch_to_blog( $blog_id ) : false;
446
447         $current_user = wp_get_current_user();
448
449         if ( empty( $current_user ) ) {
450                 if ( $switched ) {
451                         restore_current_blog();
452                 }
453                 return false;
454         }
455
456         $args = array_slice( func_get_args(), 2 );
457         $args = array_merge( array( $capability ), $args );
458
459         $can = call_user_func_array( array( $current_user, 'has_cap' ), $args );
460
461         if ( $switched ) {
462                 restore_current_blog();
463         }
464
465         return $can;
466 }
467
468 /**
469  * Whether author of supplied post has capability or role.
470  *
471  * @since 2.9.0
472  *
473  * @param int|object $post Post ID or post object.
474  * @param string $capability Capability or role name.
475  * @return bool
476  */
477 function author_can( $post, $capability ) {
478         if ( !$post = get_post($post) )
479                 return false;
480
481         $author = get_userdata( $post->post_author );
482
483         if ( ! $author )
484                 return false;
485
486         $args = array_slice( func_get_args(), 2 );
487         $args = array_merge( array( $capability ), $args );
488
489         return call_user_func_array( array( $author, 'has_cap' ), $args );
490 }
491
492 /**
493  * Whether a particular user has capability or role.
494  *
495  * @since 3.1.0
496  *
497  * @param int|object $user User ID or object.
498  * @param string $capability Capability or role name.
499  * @return bool
500  */
501 function user_can( $user, $capability ) {
502         if ( ! is_object( $user ) )
503                 $user = get_userdata( $user );
504
505         if ( ! $user || ! $user->exists() )
506                 return false;
507
508         $args = array_slice( func_get_args(), 2 );
509         $args = array_merge( array( $capability ), $args );
510
511         return call_user_func_array( array( $user, 'has_cap' ), $args );
512 }
513
514 /**
515  * Retrieves the global WP_Roles instance and instantiates it if necessary.
516  *
517  * @since 4.3.0
518  *
519  * @global WP_Roles $wp_roles WP_Roles global instance.
520  *
521  * @return WP_Roles WP_Roles global instance if not already instantiated.
522  */
523 function wp_roles() {
524         global $wp_roles;
525
526         if ( ! isset( $wp_roles ) ) {
527                 $wp_roles = new WP_Roles();
528         }
529         return $wp_roles;
530 }
531
532 /**
533  * Retrieve role object.
534  *
535  * @since 2.0.0
536  *
537  * @param string $role Role name.
538  * @return WP_Role|null WP_Role object if found, null if the role does not exist.
539  */
540 function get_role( $role ) {
541         return wp_roles()->get_role( $role );
542 }
543
544 /**
545  * Add role, if it does not exist.
546  *
547  * @since 2.0.0
548  *
549  * @param string $role Role name.
550  * @param string $display_name Display name for role.
551  * @param array $capabilities List of capabilities, e.g. array( 'edit_posts' => true, 'delete_posts' => false );
552  * @return WP_Role|null WP_Role object if role is added, null if already exists.
553  */
554 function add_role( $role, $display_name, $capabilities = array() ) {
555         if ( empty( $role ) ) {
556                 return;
557         }
558         return wp_roles()->add_role( $role, $display_name, $capabilities );
559 }
560
561 /**
562  * Remove role, if it exists.
563  *
564  * @since 2.0.0
565  *
566  * @param string $role Role name.
567  */
568 function remove_role( $role ) {
569         wp_roles()->remove_role( $role );
570 }
571
572 /**
573  * Retrieve a list of super admins.
574  *
575  * @since 3.0.0
576  *
577  * @global array $super_admins
578  *
579  * @return array List of super admin logins
580  */
581 function get_super_admins() {
582         global $super_admins;
583
584         if ( isset($super_admins) )
585                 return $super_admins;
586         else
587                 return get_site_option( 'site_admins', array('admin') );
588 }
589
590 /**
591  * Determine if user is a site admin.
592  *
593  * @since 3.0.0
594  *
595  * @param int $user_id (Optional) The ID of a user. Defaults to the current user.
596  * @return bool True if the user is a site admin.
597  */
598 function is_super_admin( $user_id = false ) {
599         if ( ! $user_id || $user_id == get_current_user_id() )
600                 $user = wp_get_current_user();
601         else
602                 $user = get_userdata( $user_id );
603
604         if ( ! $user || ! $user->exists() )
605                 return false;
606
607         if ( is_multisite() ) {
608                 $super_admins = get_super_admins();
609                 if ( is_array( $super_admins ) && in_array( $user->user_login, $super_admins ) )
610                         return true;
611         } else {
612                 if ( $user->has_cap('delete_users') )
613                         return true;
614         }
615
616         return false;
617 }