The situation

Running on MU, I'm writing an open source/publically and freely available plugin. As I used add_screen_option() to allow users to easily setup the admin page to their likings, I'm left with a bunch of user meta data. Now the page itself is restricted to users with the manage_options capability, so only those have got this meta entry when they adjusted the per page value for a list table.

The "per page" Screen Option

The task

To allow the plugin to leave a clean state in case some chooses to remove the plugin, I added a deactivation and an uninstall hook callback that should loop through user data and remove the meta entries. Now I could simply loop through all users, check their meta value and so on, but this would hardly fail on sites with lots of users and end in a time out (remember, Meta tables are JOINed).

The idea (so far)

To make it short, here's what I thought: The MU install has a user and a usermeta table. And from what I can see, there're not really capabilities saved, but role names - WordPress makes no difference between roles and capabilities here. Fun as it is, it seems that there're different things I have to consider:

User can be…

  • superadmin
  • registered on multiple sites
  • registered on multiple sites with different roles
  • registered on multiple sites with the same role, but role has different capabilities on different sites
  • ...?

The problem starts with those different possibilities and goes further, when you look at ho the capabilities are saved in a Network/MU setup:




So for what would one query?

$query_args = array(
$query = new WP_User_Query( $query_args );
$users = $query->results;
if ( empty( $users ) )

var_dump( $users );


Just a first attempt to query for role names with a specific capability:

    $roles = new WP_Roles();
    $roles = wp_list_pluck( $roles->role_objects, 'capabilities' );
    $results = array();
    foreach ( $roles as $role => $caps )
        array_key_exists( 'manage_options', $caps )
            AND $results[] = $role;
    var_dump( $results );

    # Even if it's smarter then above loop, it won't work and 
    # throw an error in core files.
    $roles = array_filter( wp_list_pluck( $roles, 'manage_options' ) );

1 Answer 1


It was actually much easier than I originally thought - just doing a WP_User_Query for a meta value (meta arrays are supported as well, like for the other query classes).

public function on_deactivate()
    $meta_key = 'tools_page_tsi_per_page';
    $query = new WP_User_Query( array( 'meta_key' => $meta_key ) );

    if ( empty( $query->results ) )

    foreach ( wp_list_pluck( $query->results, 'ID' ) as $user_id )
        delete_user_meta( $user_id, $meta_key );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.