]> scripts.mit.edu Git - autoinstalls/wordpress.git/blobdiff - wp-includes/capabilities.php
Wordpress 3.0.4-scripts
[autoinstalls/wordpress.git] / wp-includes / capabilities.php
index ab6ec3524d7e9a813673337207c4b4018bf3cc51..57a7cd7838bbdf134cd3ba82c75b1827c4ddb858 100644 (file)
@@ -85,7 +85,7 @@ class WP_Roles {
        }
 
        /**
-        * Setup the object properties.
+        * Set up the object properties.
         *
         * The role key is set to the current prefix for the $wpdb object with
         * 'user_roles' appended. If the $wp_user_roles global is set, then it will
@@ -97,8 +97,7 @@ class WP_Roles {
         * @global array $wp_user_roles Used to set the 'roles' property value.
         */
        function _init () {
-               global $wpdb;
-               global $wp_user_roles;
+               global $wpdb, $wp_user_roles;
                $this->role_key = $wpdb->prefix . 'user_roles';
                if ( ! empty( $wp_user_roles ) ) {
                        $this->roles = $wp_user_roles;
@@ -123,12 +122,15 @@ class WP_Roles {
         *
         * Updates the list of roles, if the role doesn't already exist.
         *
+        * The capabilities are defined in the following format `array( 'read' => true );`
+        * To explicitly deny a role a capability you set the value for that capability to false.
+        *
         * @since 2.0.0
         * @access public
         *
         * @param string $role Role name.
         * @param string $display_name Role display name.
-        * @param array $capabilities List of role capabilities.
+        * @param array $capabilities List of role capabilities in the above format.
         * @return null|WP_Role WP_Role object if role is added, null if already exists.
         */
        function add_role( $role, $display_name, $capabilities = array() ) {
@@ -174,7 +176,7 @@ class WP_Roles {
         *
         * @param string $role Role name.
         * @param string $cap Capability name.
-        * @param bool $grant Optional, default is true. Whether role is capable of preforming capability.
+        * @param bool $grant Optional, default is true. Whether role is capable of performing capability.
         */
        function add_cap( $role, $cap, $grant = true ) {
                $this->roles[$role]['capabilities'][$cap] = $grant;
@@ -267,10 +269,10 @@ class WP_Role {
        var $capabilities;
 
        /**
-        * PHP4 Constructor - Setup object properties.
+        * PHP4 Constructor - Set up object properties.
         *
         * The list of capabilities, must have the key as the name of the capability
-        * and the value a boolean of whether it is granted to the role or not.
+        * and the value a boolean of whether it is granted to the role.
         *
         * @since 2.0.0
         * @access public
@@ -448,6 +450,15 @@ class WP_User {
         */
        var $last_name = '';
 
+       /**
+        * The filter context applied to user data fields.
+        *
+        * @since 2.9.0
+        * @access private
+        * @var string
+        */
+       var $filter = null;
+
        /**
         * PHP4 Constructor - Sets up the object properties.
         *
@@ -489,7 +500,7 @@ class WP_User {
        }
 
        /**
-        * Setup capability object properties.
+        * Set up capability object properties.
         *
         * Will set the value for the 'cap_key' property to current database table
         * prefix, followed by 'capabilities'. Will then check to see if the
@@ -497,11 +508,16 @@ class WP_User {
         * used.
         *
         * @since 2.1.0
+        *
+        * @param string $cap_key Optional capability key
         * @access protected
         */
-       function _init_caps() {
+       function _init_caps( $cap_key = '' ) {
                global $wpdb;
-               $this->cap_key = $wpdb->prefix . 'capabilities';
+               if ( empty($cap_key) )
+                       $this->cap_key = $wpdb->prefix . 'capabilities';
+               else
+                       $this->cap_key = $cap_key;
                $this->caps = &$this->{$this->cap_key};
                if ( ! is_array( $this->caps ) )
                        $this->caps = array();
@@ -533,10 +549,10 @@ class WP_User {
                //Build $allcaps from role caps, overlay user's $caps
                $this->allcaps = array();
                foreach ( (array) $this->roles as $role ) {
-                       $role =& $wp_roles->get_role( $role );
-                       $this->allcaps = array_merge( $this->allcaps, $role->capabilities );
+                       $the_role =& $wp_roles->get_role( $role );
+                       $this->allcaps = array_merge( (array) $this->allcaps, (array) $the_role->capabilities );
                }
-               $this->allcaps = array_merge( $this->allcaps, $this->caps );
+               $this->allcaps = array_merge( (array) $this->allcaps, (array) $this->caps );
        }
 
        /**
@@ -551,7 +567,7 @@ class WP_User {
         */
        function add_role( $role ) {
                $this->caps[$role] = true;
-               update_usermeta( $this->ID, $this->cap_key, $this->caps );
+               update_user_meta( $this->ID, $this->cap_key, $this->caps );
                $this->get_role_caps();
                $this->update_user_level_from_caps();
        }
@@ -565,11 +581,12 @@ class WP_User {
         * @param string $role Role name.
         */
        function remove_role( $role ) {
-               if ( empty( $this->roles[$role] ) || ( count( $this->roles ) <= 1 ) )
+               if ( !in_array($role, $this->roles) )
                        return;
                unset( $this->caps[$role] );
-               update_usermeta( $this->ID, $this->cap_key, $this->caps );
+               update_user_meta( $this->ID, $this->cap_key, $this->caps );
                $this->get_role_caps();
+               $this->update_user_level_from_caps();
        }
 
        /**
@@ -593,9 +610,10 @@ class WP_User {
                } else {
                        $this->roles = false;
                }
-               update_usermeta( $this->ID, $this->cap_key, $this->caps );
+               update_user_meta( $this->ID, $this->cap_key, $this->caps );
                $this->get_role_caps();
                $this->update_user_level_from_caps();
+               do_action( 'set_user_role', $this->ID, $role );
        }
 
        /**
@@ -639,7 +657,7 @@ class WP_User {
        function update_user_level_from_caps() {
                global $wpdb;
                $this->user_level = array_reduce( array_keys( $this->allcaps ), array( &$this, 'level_reduction' ), 0 );
-               update_usermeta( $this->ID, $wpdb->prefix.'user_level', $this->user_level );
+               update_user_meta( $this->ID, $wpdb->prefix . 'user_level', $this->user_level );
        }
 
        /**
@@ -653,7 +671,7 @@ class WP_User {
         */
        function add_cap( $cap, $grant = true ) {
                $this->caps[$cap] = $grant;
-               update_usermeta( $this->ID, $this->cap_key, $this->caps );
+               update_user_meta( $this->ID, $this->cap_key, $this->caps );
        }
 
        /**
@@ -665,9 +683,10 @@ class WP_User {
         * @param string $cap Capability name.
         */
        function remove_cap( $cap ) {
-               if ( empty( $this->caps[$cap] ) ) return;
+               if ( empty( $this->caps[$cap] ) )
+                       return;
                unset( $this->caps[$cap] );
-               update_usermeta( $this->ID, $this->cap_key, $this->caps );
+               update_user_meta( $this->ID, $this->cap_key, $this->caps );
        }
 
        /**
@@ -679,8 +698,8 @@ class WP_User {
        function remove_all_caps() {
                global $wpdb;
                $this->caps = array();
-               update_usermeta( $this->ID, $this->cap_key, '' );
-               update_usermeta( $this->ID, $wpdb->prefix.'user_level', '' );
+               delete_user_meta( $this->ID, $this->cap_key );
+               delete_user_meta( $this->ID, $wpdb->prefix . 'user_level' );
                $this->get_role_caps();
        }
 
@@ -699,12 +718,22 @@ class WP_User {
         * @return bool True, if user has capability; false, if user does not have capability.
         */
        function has_cap( $cap ) {
-               if ( is_numeric( $cap ) )
+               if ( is_numeric( $cap ) ) {
+                       _deprecated_argument( __FUNCTION__, '2.0', __('Usage of user levels by plugins and themes is deprecated. Use roles and capabilities instead.') );
                        $cap = $this->translate_level_to_cap( $cap );
+               }
 
                $args = array_slice( func_get_args(), 1 );
                $args = array_merge( array( $cap, $this->ID ), $args );
                $caps = call_user_func_array( 'map_meta_cap', $args );
+
+               // Multisite super admin has all caps by definition, Unless specifically denied.
+               if ( is_multisite() && is_super_admin( $this->ID ) ) {
+                       if ( in_array('do_not_allow', $caps) )
+                               return false;
+                       return true;
+               }
+
                // Must have ALL requested caps
                $capabilities = apply_filters( 'user_has_cap', $this->allcaps, $caps, $args );
                foreach ( (array) $caps as $cap ) {
@@ -731,6 +760,21 @@ class WP_User {
                return 'level_' . $level;
        }
 
+       /**
+        * Set the blog to operate on. Defaults to the current blog.
+        *
+        * @since 3.0.0
+        *
+        * @param int $blog_id Optional Blog ID, defaults to current blog.
+        */
+       function for_blog( $blog_id = '' ) {
+               global $wpdb;
+               if ( ! empty( $blog_id ) )
+                       $cap_key = $wpdb->get_blog_prefix( $blog_id ) . 'capabilities';
+               else
+                       $cap_key = '';
+               $this->_init_caps( $cap_key );
+       }
 }
 
 /**
@@ -738,8 +782,8 @@ class WP_User {
  *
  * This does not actually compare whether the user ID has the actual capability,
  * just what the capability or capabilities are. Meta capability list value can
- * be 'delete_user', 'edit_user', 'delete_post', 'delete_page', 'edit_post',
- * 'edit_page', 'read_post', or 'read_page'.
+ * be 'delete_user', 'edit_user', 'remove_user', 'promote_user', 'delete_post',
+ * 'delete_page', 'edit_post', 'edit_page', 'read_post', or 'read_page'.
  *
  * @since 2.0.0
  *
@@ -752,32 +796,53 @@ function map_meta_cap( $cap, $user_id ) {
        $caps = array();
 
        switch ( $cap ) {
-       case 'delete_user':
-               $caps[] = 'delete_users';
+       case 'remove_user':
+               $caps[] = 'remove_users';
+               break;
+       case 'promote_user':
+               $caps[] = 'promote_users';
                break;
        case 'edit_user':
-               if ( !isset( $args[0] ) || $user_id != $args[0] ) {
-                       $caps[] = 'edit_users';
-               }
+               // Allow user to edit itself
+               if ( isset( $args[0] ) && $user_id == $args[0] )
+                       break;
+               // Fall through
+       case 'edit_users':
+               // If multisite these caps are allowed only for super admins.
+               if ( is_multisite() && !is_super_admin( $user_id ) )
+                       $caps[] = 'do_not_allow';
+               else
+                       $caps[] = 'edit_users'; // Explicit due to primitive fall through
                break;
        case 'delete_post':
                $author_data = get_userdata( $user_id );
                //echo "post ID: {$args[0]}<br />";
                $post = get_post( $args[0] );
-               if ( 'page' == $post->post_type ) {
-                       $args = array_merge( array( 'delete_page', $user_id ), $args );
+               $post_type = get_post_type_object( $post->post_type );
+               if ( $post_type && 'post' != $post_type->capability_type ) {
+                       $args = array_merge( array( $post_type->cap->delete_post, $user_id ), $args );
                        return call_user_func_array( 'map_meta_cap', $args );
                }
-               $post_author_data = get_userdata( $post->post_author );
-               //echo "current user id : $user_id, post author id: " . $post_author_data->ID . "<br />";
+
+               if ( '' != $post->post_author ) {
+                       $post_author_data = get_userdata( $post->post_author );
+               } else {
+                       //No author set yet so default to current user for cap checks
+                       $post_author_data = $author_data;
+               }
+
                // If the user is the author...
-               if ( $user_id == $post_author_data->ID ) {
+               if ( is_object( $post_author_data ) && $user_id == $post_author_data->ID ) {
                        // If the post is published...
-                       if ( 'publish' == $post->post_status )
+                       if ( 'publish' == $post->post_status ) {
                                $caps[] = 'delete_published_posts';
-                       else
+                       } elseif ( 'trash' == $post->post_status ) {
+                               if ('publish' == get_post_meta($post->ID, '_wp_trash_meta_status', true) )
+                                       $caps[] = 'delete_published_posts';
+                       } else {
                                // If the post is draft...
                                $caps[] = 'delete_posts';
+                       }
                } else {
                        // The user is trying to edit someone else's post.
                        $caps[] = 'delete_others_posts';
@@ -795,13 +860,25 @@ function map_meta_cap( $cap, $user_id ) {
                $page_author_data = get_userdata( $page->post_author );
                //echo "current user id : $user_id, page author id: " . $page_author_data->ID . "<br />";
                // If the user is the author...
-               if ( $user_id == $page_author_data->ID ) {
+
+               if ('' != $page->post_author) {
+                       $page_author_data = get_userdata( $page->post_author );
+               } else {
+                       //No author set yet so default to current user for cap checks
+                       $page_author_data = $author_data;
+               }
+
+               if ( is_object( $page_author_data ) && $user_id == $page_author_data->ID ) {
                        // If the page is published...
-                       if ( $page->post_status == 'publish' )
+                       if ( $page->post_status == 'publish' ) {
                                $caps[] = 'delete_published_pages';
-                       else
+                       } elseif ( 'trash' == $page->post_status ) {
+                               if ('publish' == get_post_meta($page->ID, '_wp_trash_meta_status', true) )
+                                       $caps[] = 'delete_published_pages';
+                       } else {
                                // If the page is draft...
                                $caps[] = 'delete_pages';
+                       }
                } else {
                        // The user is trying to edit someone else's page.
                        $caps[] = 'delete_others_pages';
@@ -818,20 +895,25 @@ function map_meta_cap( $cap, $user_id ) {
                $author_data = get_userdata( $user_id );
                //echo "post ID: {$args[0]}<br />";
                $post = get_post( $args[0] );
-               if ( 'page' == $post->post_type ) {
-                       $args = array_merge( array( 'edit_page', $user_id ), $args );
+               $post_type = get_post_type_object( $post->post_type );
+               if ( $post_type && 'post' != $post_type->capability_type ) {
+                       $args = array_merge( array( $post_type->cap->edit_post, $user_id ), $args );
                        return call_user_func_array( 'map_meta_cap', $args );
                }
                $post_author_data = get_userdata( $post->post_author );
                //echo "current user id : $user_id, post author id: " . $post_author_data->ID . "<br />";
                // If the user is the author...
-               if ( $user_id == $post_author_data->ID ) {
+               if ( is_object( $post_author_data ) && $user_id == $post_author_data->ID ) {
                        // If the post is published...
-                       if ( 'publish' == $post->post_status )
+                       if ( 'publish' == $post->post_status ) {
                                $caps[] = 'edit_published_posts';
-                       else
+                       } elseif ( 'trash' == $post->post_status ) {
+                               if ('publish' == get_post_meta($post->ID, '_wp_trash_meta_status', true) )
+                                       $caps[] = 'edit_published_posts';
+                       } else {
                                // If the post is draft...
                                $caps[] = 'edit_posts';
+                       }
                } else {
                        // The user is trying to edit someone else's post.
                        $caps[] = 'edit_others_posts';
@@ -849,13 +931,17 @@ function map_meta_cap( $cap, $user_id ) {
                $page_author_data = get_userdata( $page->post_author );
                //echo "current user id : $user_id, page author id: " . $page_author_data->ID . "<br />";
                // If the user is the author...
-               if ( $user_id == $page_author_data->ID ) {
+               if ( is_object( $page_author_data ) && $user_id == $page_author_data->ID ) {
                        // If the page is published...
-                       if ( 'publish' == $page->post_status )
+                       if ( 'publish' == $page->post_status ) {
                                $caps[] = 'edit_published_pages';
-                       else
+                       } elseif ( 'trash' == $page->post_status ) {
+                               if ('publish' == get_post_meta($page->ID, '_wp_trash_meta_status', true) )
+                                       $caps[] = 'edit_published_pages';
+                       } else {
                                // If the page is draft...
                                $caps[] = 'edit_pages';
+                       }
                } else {
                        // The user is trying to edit someone else's page.
                        $caps[] = 'edit_others_pages';
@@ -868,8 +954,9 @@ function map_meta_cap( $cap, $user_id ) {
                break;
        case 'read_post':
                $post = get_post( $args[0] );
-               if ( 'page' == $post->post_type ) {
-                       $args = array_merge( array( 'read_page', $user_id ), $args );
+               $post_type = get_post_type_object( $post->post_type );
+               if ( $post_type && 'post' != $post_type->capability_type ) {
+                       $args = array_merge( array( $post_type->cap->read_post, $user_id ), $args );
                        return call_user_func_array( 'map_meta_cap', $args );
                }
 
@@ -880,7 +967,7 @@ function map_meta_cap( $cap, $user_id ) {
 
                $author_data = get_userdata( $user_id );
                $post_author_data = get_userdata( $post->post_author );
-               if ( $user_id == $post_author_data->ID )
+               if ( is_object( $post_author_data ) && $user_id == $post_author_data->ID )
                        $caps[] = 'read';
                else
                        $caps[] = 'read_private_posts';
@@ -895,17 +982,69 @@ function map_meta_cap( $cap, $user_id ) {
 
                $author_data = get_userdata( $user_id );
                $page_author_data = get_userdata( $page->post_author );
-               if ( $user_id == $page_author_data->ID )
+               if ( is_object( $page_author_data ) && $user_id == $page_author_data->ID )
                        $caps[] = 'read';
                else
                        $caps[] = 'read_private_pages';
                break;
+       case 'unfiltered_upload':
+               if ( defined('ALLOW_UNFILTERED_UPLOADS') && ALLOW_UNFILTERED_UPLOADS && ( !is_multisite() || is_super_admin( $user_id ) )  )
+                       $caps[] = $cap;
+               else
+                       $caps[] = 'do_not_allow';
+               break;
+       case 'edit_files':
+       case 'edit_plugins':
+       case 'edit_themes':
+               if ( defined('DISALLOW_FILE_EDIT') && DISALLOW_FILE_EDIT ) {
+                       $caps[] = 'do_not_allow';
+                       break;
+               }
+               // Fall through if not DISALLOW_FILE_EDIT.
+       case 'update_plugins':
+       case 'delete_plugins':
+       case 'install_plugins':
+       case 'update_themes':
+       case 'delete_themes':
+       case 'install_themes':
+       case 'update_core':
+               // Disallow anything that creates, deletes, or edits core, plugin, or theme files.
+               // Files in uploads are excepted.
+               if ( defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS ) {
+                       $caps[] = 'do_not_allow';
+                       break;
+               }
+               // Fall through if not DISALLOW_FILE_MODS.
+       case 'unfiltered_html':
+               // Disallow unfiltered_html for all users, even admins and super admins.
+               if ( defined('DISALLOW_UNFILTERED_HTML') && DISALLOW_UNFILTERED_HTML ) {
+                       $caps[] = 'do_not_allow';
+                       break;
+               }
+               // Fall through if not DISALLOW_UNFILTERED_HTML
+       case 'delete_user':
+       case 'delete_users':
+               // If multisite these caps are allowed only for super admins.
+               if ( is_multisite() && !is_super_admin( $user_id ) ) {
+                       $caps[] = 'do_not_allow';
+               } else {
+                       if ( 'delete_user' == $cap )
+                               $cap = 'delete_users';
+                       $caps[] = $cap;
+               }
+               break;
+       case 'create_users':
+               if ( is_multisite() && !get_site_option( 'add_new_users' ) )
+                       $caps[] = 'do_not_allow';
+               else
+                       $caps[] = $cap;
+               break;
        default:
                // If no meta caps match, return the original cap.
                $caps[] = $cap;
        }
 
-       return $caps;
+       return apply_filters('map_meta_cap', $caps, $cap, $user_id, $args);
 }
 
 /**
@@ -928,6 +1067,57 @@ function current_user_can( $capability ) {
        return call_user_func_array( array( &$current_user, 'has_cap' ), $args );
 }
 
+/**
+ * Whether current user has a capability or role for a given blog.
+ *
+ * @since 3.0.0
+ *
+ * @param int $blog_id Blog ID
+ * @param string $capability Capability or role name.
+ * @return bool
+ */
+function current_user_can_for_blog( $blog_id, $capability ) {
+       $current_user = wp_get_current_user();
+
+       if ( empty( $current_user ) )
+               return false;
+
+       // Create new object to avoid stomping the global current_user.
+       $user = new WP_User( $current_user->id) ;
+
+       // Set the blog id.  @todo add blog id arg to WP_User constructor?
+       $user->for_blog( $blog_id );
+
+       $args = array_slice( func_get_args(), 2 );
+       $args = array_merge( array( $capability ), $args );
+
+       return call_user_func_array( array( &$user, 'has_cap' ), $args );
+}
+
+/**
+ * Whether author of supplied post has capability or role.
+ *
+ * @since 2.9.0
+ *
+ * @param int|object $post Post ID or post object.
+ * @param string $capability Capability or role name.
+ * @return bool
+ */
+function author_can( $post, $capability ) {
+       if ( !$post = get_post($post) )
+               return false;
+
+       $author = new WP_User( $post->post_author );
+
+       if ( empty( $author->ID ) )
+               return false;
+
+       $args = array_slice( func_get_args(), 2 );
+       $args = array_merge( array( $capability ), $args );
+
+       return call_user_func_array( array( &$author, 'has_cap' ), $args );
+}
+
 /**
  * Retrieve role object.
  *
@@ -984,4 +1174,53 @@ function remove_role( $role ) {
        return $wp_roles->remove_role( $role );
 }
 
+/**
+ * Retrieve a list of super admins.
+ *
+ * @since 3.0.0
+ *
+ * @uses $super_admins Super admins global variable, if set.
+ *
+ * @return array List of super admin logins
+ */
+function get_super_admins() {
+       global $super_admins;
+
+       if ( isset($super_admins) )
+               return $super_admins;
+       else
+               return get_site_option( 'site_admins', array('admin') );
+}
+
+/**
+ * Determine if user is a site admin.
+ *
+ * @since 3.0.0
+ *
+ * @param int $user_id (Optional) The ID of a user. Defaults to the current user.
+ * @return bool True if the user is a site admin.
+ */
+function is_super_admin( $user_id = false ) {
+       if ( ! $user_id ) {
+               $current_user = wp_get_current_user();
+               $user_id = ! empty($current_user) ? $current_user->id : 0;
+       }
+
+       if ( ! $user_id )
+               return false;
+
+       $user = new WP_User($user_id);
+
+       if ( is_multisite() ) {
+               $super_admins = get_super_admins();
+               if ( is_array( $super_admins ) && in_array( $user->user_login, $super_admins ) )
+                       return true;
+       } else {
+               if ( $user->has_cap('delete_users') )
+                       return true;
+       }
+
+       return false;
+}
+
 ?>