Created
August 24, 2012 17:29
-
-
Save dnaber-de/3453209 to your computer and use it in GitHub Desktop.
WP Multisite Plugin: non-super-admins can edit users in blog context (if they have the capabilities 'edit_users' and 'promote_users').
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Plugin Name: dna User edit Users | |
* Description: Multisite Plugin: non-super-admins can edit users in blog context (if they have the capabilities 'edit_users', 'edit_user' and 'network_manage_users' ). It also fixes <a href="https://core.trac.wordpress.org/ticket/20221">#20221</a>. Requires PHP 5.3! | |
* Plugin URI: http://dnaber.de/p1649 | |
* Version: 2012.08.25 | |
* Author: David Naber | |
* Author URI: http://dnaber.de/ | |
* License: MIT | |
* License URI: http://www.opensource.org/licenses/mit-license.php | |
*/ | |
namespace dna\user_edit_users; | |
if ( ! function_exists( 'add_filter' ) ) | |
exit( 'Where\'s my WP?' ); | |
add_action( 'plugins_loaded', __NAMESPACE__ . '\init' ); | |
/** | |
* start the plugin | |
* | |
* @wp-hook plugins_loaded | |
* @return void | |
*/ | |
function init() { | |
if ( ! is_multisite() || is_super_admin() ) | |
return; | |
#unblock WP restriction for anyone except super-admins to edit users | |
add_filter( 'map_meta_cap', __NAMESPACE__ . '\filter_map_meta_cap', 10, 4 ); | |
add_filter( 'wp_redirect', __NAMESPACE__ . '\rediret_to_user_list' ); | |
/** | |
* allow normal admins to add a user directly (without sending an activtaion-email) | |
* affects user-new.php | |
* | |
* @link https://core.trac.wordpress.org/ticket/20221 | |
*/ | |
#called on insert request | |
add_action( 'admin_action_createuser', __NAMESPACE__ . '\temporary_super_admin' ); | |
add_action( 'admin_action_adduser', __NAMESPACE__ . '\temporary_super_admin' ); | |
#called when showing the insert formular | |
add_action( 'user_new_form_tag', __NAMESPACE__ . '\temporary_super_admin' ); | |
} | |
/** | |
* grant 'edit_users' to non-super-admins | |
* by default WP inhibits this in map_meta_cap() | |
* | |
* @wp-hook map_meta_cap | |
* @param array $caps bunch of (meta)capabilities | |
* @param string $cap current capability to check for | |
* @param int $user_id | |
* @param array $args | |
* @return array | |
*/ | |
function filter_map_meta_cap( $caps, $cap, $user_id, $args ) { | |
# user manage caps which are necessary on multisite | |
$user_caps = array( | |
'edit_user', | |
'edit_users', | |
'manage_network_users', | |
'remove_user' | |
); | |
if ( ! in_array( $cap, $user_caps ) ) | |
return $caps; | |
$user = get_user_by( 'id', $user_id ); | |
if ( ! is_a( $user, 'WP_User' ) ) | |
return $caps; | |
# re-map the capabilities | |
switch ( $cap ) { | |
case 'edit_user' : | |
$cap = 'edit_users'; | |
if ( empty( $user->allcaps[ $cap ] ) ) | |
return $caps; # user can't edit users, nothing to do | |
$blog_id = get_current_blog_id(); | |
$user_to_edit = $args[ 0 ]; | |
if ( ! is_user_member_of_blog( $user_to_edit, $blog_id ) || is_super_admin( $user_to_edit ) ) | |
return $caps; # the user to edit is not a user of the current blog. | |
break; | |
case 'remove_user' : | |
$user_to_remove = $args[ 0 ]; | |
if ( is_super_admin( $user_to_remove ) ) { | |
$caps[] = 'do_not_allow'; | |
return $caps; | |
} | |
$cap = 'remove_users'; | |
break; | |
case 'manage_network_users' : | |
# map user-handling caps to 'manage_network_users' | |
if ( ! $user->allcaps[ 'edit_users' ] | |
|| ! $user->allcaps[ 'promote_users' ] | |
|| ! $user->allcaps[ 'remove_users' ] | |
) | |
return $caps; | |
break; | |
default : | |
if ( empty( $user->allcaps[ $cap ] ) ) | |
return $caps; | |
break; | |
} | |
# At this point, there can be a 'do_not_allow' inside the $caps array | |
# to force revoking rights for super-admins. We shouldn't remove it! | |
# But WP_User::has_cap() checks for *all* caps inside the array whether they are | |
# exists in WP_User::allcaps so we have to add it | |
add_filter( | |
'user_has_cap', | |
__NAMESPACE__ . '\add_interim_user_cap', | |
10, | |
3 | |
); | |
$caps[] = $cap; | |
return $caps; | |
} | |
/** | |
* add the 'do_not_allow' cap to a users list of capabilities | |
* | |
* @wp-hook user_has_cap | |
* @param array $allcaps | |
* @param array $caps (caps to check for) | |
* @param mixed $args | |
* @return array | |
*/ | |
function add_interim_user_cap( $allcaps, $caps, $args ) { | |
remove_filter( | |
'user_has_cap', | |
__FUNCTION__, | |
10, | |
3 | |
); | |
$allcaps[ 'do_not_allow' ] = TRUE; | |
if ( in_array( 'manage_network_users', $caps ) ) | |
$allcaps[ 'manage_network_users' ] = TRUE; | |
return $allcaps; | |
} | |
/** | |
* call the filter to make the current user super admin | |
* if he can 'create_users' and 'promote_users' | |
* | |
* @wp-hook admin_action_createuser, admin_action_adduser, user_new_form_tag | |
* @return void | |
*/ | |
function temporary_super_admin() { | |
# check for the theoretical permissions | |
if ( ! current_user_can( 'create_users' ) && ! current_user_can( 'promote_users' ) ) | |
return; | |
add_filter( 'site_option_site_admins', __NAMESPACE__ . '\add_user_to_admin_list' ); | |
} | |
/** | |
* Add the current user to the list of super-admins | |
* | |
* @wp-hook site_option_site_admins | |
* @param array $admins | |
* @return array | |
*/ | |
function add_user_to_admin_list( $admins ) { | |
$user = wp_get_current_user(); | |
if ( ! is_a( $user, 'WP_User' ) ) | |
return; | |
$admins[] =$user->user_login; | |
return $admins; | |
} | |
/** | |
* redirect to the user overview if the update | |
* removed the user from the currend blog | |
* | |
* @since 2012.08.25 | |
* @wp-hook wp-redirect | |
* @param string $location | |
* @param int $status | |
* @retun string | |
*/ | |
function rediret_to_user_list( $location, $status = 301 ) { | |
$url = parse_url( $location ); | |
if ( empty( $url[ 'path' ] ) | |
|| 'user-edit.php' !== $url[ 'path' ] | |
|| empty( $url[ 'query' ] ) | |
) | |
return $location; | |
$query = array(); | |
parse_str( $url[ 'query' ], $query ); | |
if ( empty( $query[ 'user_id' ] ) || empty( $query[ 'updated' ] ) ) | |
return $location; | |
$user_to_edit = $query[ 'user_id' ]; | |
$blog_id = get_current_blog_id(); | |
if ( 'true' !== $query[ 'updated' ] || is_user_member_of_blog( $user_to_edit, $blog_id ) ) | |
return $location; | |
#redirect to the referer if this woun't end up in an infinite loop | |
if ( ! empty( $query[ 'wp_http_referer' ] ) && FALSE === strpos( $query[ 'wp_http_referer' ], 'user-edit.php' ) ) | |
$location = home_url( $query[ 'wp_http_referer' ] ); | |
else | |
$location = admin_url( 'users.php' ); # the user list | |
return $location; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment