]> scripts.mit.edu Git - autoinstalls/wordpress.git/blobdiff - wp-includes/capabilities.php
Wordpress 3.0
[autoinstalls/wordpress.git] / wp-includes / capabilities.php
index 4a5ccec036eeae4e5e2a792e2c51a2683146a9a5..6ab08e3713f8eaf650ee75b3d77601b34a287d8a 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;
@@ -125,7 +124,7 @@ class WP_Roles {
         *
         * 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
         *
@@ -270,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
@@ -501,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
@@ -509,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();
@@ -545,8 +549,8 @@ 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( (array) $this->allcaps, (array) $role->capabilities );
+                       $the_role =& $wp_roles->get_role( $role );
+                       $this->allcaps = array_merge( (array) $this->allcaps, (array) $the_role->capabilities );
                }
                $this->allcaps = array_merge( (array) $this->allcaps, (array) $this->caps );
        }
@@ -563,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();
        }
@@ -577,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();
        }
 
        /**
@@ -605,7 +610,7 @@ 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 );
@@ -652,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 );
        }
 
        /**
@@ -666,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 );
        }
 
        /**
@@ -678,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 );
        }
 
        /**
@@ -692,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();
        }
 
@@ -712,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() ) {
+                       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 ) {
@@ -744,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 );
+       }
 }
 
 /**
@@ -751,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
  *
@@ -765,24 +796,38 @@ function map_meta_cap( $cap, $user_id ) {
        $caps = array();
 
        switch ( $cap ) {
+       case 'remove_user':
+               $caps[] = 'remove_users';
+               break;
        case 'delete_user':
                $caps[] = 'delete_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() )
+                       $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 );
                }
 
-               if ('' != $post->post_author) {
+               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
@@ -790,7 +835,7 @@ function map_meta_cap( $cap, $user_id ) {
                }
 
                // 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 ) {
                                $caps[] = 'delete_published_posts';
@@ -826,7 +871,7 @@ function map_meta_cap( $cap, $user_id ) {
                        $page_author_data = $author_data;
                }
 
-               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 ( $page->post_status == 'publish' ) {
                                $caps[] = 'delete_published_pages';
@@ -853,14 +898,15 @@ 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 ) {
                                $caps[] = 'edit_published_posts';
@@ -888,7 +934,7 @@ 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 ) {
                                $caps[] = 'edit_published_pages';
@@ -911,8 +957,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 );
                }
 
@@ -923,7 +970,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';
@@ -938,17 +985,60 @@ 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 == true )
+               if ( defined('ALLOW_UNFILTERED_UPLOADS') && ALLOW_UNFILTERED_UPLOADS && ( !is_multisite() || is_super_admin() )  )
                        $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() )
+                       $caps[] = 'do_not_allow';
+               else
+                       $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;
@@ -977,6 +1067,36 @@ 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 ( is_multisite() && is_super_admin() )
+               return true;
+
+       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.
  *
@@ -1057,4 +1177,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;
+}
+
 ?>