Skip to content

Instantly share code, notes, and snippets.

@dnaber-de
Created August 24, 2012 17:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dnaber-de/3453209 to your computer and use it in GitHub Desktop.
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').
<?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