3

I was wondering if there is a way to actually limit the amount of users that can register to a Wordpress site?

As an example, I am wanting to create a small site that will hold information for a customer, where they can only have a maximum of (for example) 50 users. The idea is that you will need to log in to view the site and only a set amount of users are allowed to be created. Maybe somebody knows of a plugin that might do this?

  • Craig, any progress on that question? – kaiser Aug 19 '13 at 17:33
  • At the moment, the site we're developing is still in it's smaller stages, this will probably come later on and so I haven't been able to try it out just yet. However, it was important to know that this was possible. – Craig Jones Aug 20 '13 at 8:44
  • Please always add comments/feedback to the answers. If you got a solution that works, come back and mark it as such, etc. Else the question stays in the queue of unanswered questions forever. – kaiser Aug 20 '13 at 9:39
  • Ahh ok. I have accepted your answer, as so it doesn't go unanswered. Thanks for your advice. – Craig Jones Aug 20 '13 at 9:43
  • Sorry, Craig. I didn't meant "go accept". I meant: for the future please always go and comment. And if you have tried it and can confirm that it's working, then please mark the working answer as solution. Until then it's ok to leave it open, just come back and don't forget about it :) - you can just uncheck it again. – kaiser Aug 20 '13 at 9:45
4

As you can see in the WordPress Option Reference, there's an option called users_can_register. You can - per default - set it in your (network-)sites settings.

  • 1 => Yes
  • 0 => No

As usual: There's a filter to intercept that from a plugin.

"option_{$option_name}"

So you can simply attach a callback to this filter and check the amount of users with a WP_User_Query for the get_current_blog_id().

<?php

namespace WPSE;
/** Plugin Name: WPSE (#110036) Limit Total Users per page */
defined( 'ABSPATH' ) or exit;

\add_filter( 'option_users_can_register', 'limit_total_users' );
function limit_total_users( $option )
{
    // Nothing to do here
    if ( 0 === $option )
        return $option;

    static $users = null;
    $limit = 50;

    if ( null === $users )
    {
        $users_query = new \WP_User_Query( array(
            'blog_id' => get_current_blog_id()
        ) );
        $users = $users_query->get_total();
    }

    // Abort if we're above the limit
    if ( $limit > $users )
        return 0;

    return $option;
}

The nice thing about this mini plugin is, that it doesn't do an additional query if the registration is already turned off.

3

Piggybacking off Kaiser's answer:

add_filter( 'option_users_can_register', 'limit_total_users' );
function limit_total_users( $option )
{
    // Registration turned off manually. Nothing to do here.
    if ( 0 === $option )
        return $option;

    $user_count = count_users();

    // Abort if we're above the limit
    if ( $user_count['total_users'] > 50 ) {
        return 0;
    } 

    // The threshold wasn't reached yet.
    return $option;
}

Interesting bit of info on that count_users() function is it actually returns an array with a count for each role. You may wish to identify which role you are limiting, or simply add/subtract to account for the difference in, for example, the number of admins - as you may not wish to count yourself in the total.

2

This solution differs from the others in that the primary work in done on user registration. After a user registers the total users are counted and the users_can_register option is updated if necessary. That seems to be the best way to minimize front-end processing time. A related function hooked to pre_option_users_can_register prevents blog admins from cheating by toggling the switch in "General Settings" and getting an extra user thereby. Technically only that function is necessary but I have explained the reasons for the other function.

function count_reg_users_wpse_110036() {
  global $wpdb;
  $users = $wpdb->get_var("SELECT COUNT(ID) FROM {$wpdb->users}");
  return $users;
}

function limit_users_wpse_110036() {
  $count = apply_filters('limit_user_count',4);
  $users = count_reg_users_wpse_110036();
  if ($users >= $count) {
    update_option('users_can_register',0);
  }
}
add_action('user_register','limit_users_wpse_110036');

function limit_user_option_wpse_110036($option) {
  remove_filter('pre_option_users_can_register','limit_user_option_wpse_110036');
  $reg = get_option('users_can_register');
  if (0 === $reg) {
    return 0;
  }
  $count = apply_filters('limit_user_count',4);
  $users = count_reg_users_wpse_110036();
  if ($users >= $count) {
    update_option('users_can_register',0);
    return 0;
  } else {
    return $option;
  }
}
add_filter('pre_option_users_can_register','limit_user_option_wpse_110036');
  • +1 Nice solution. Only drawback: It doesn't take Network installs into account. You'd have to a JOIN for the usermeta table and then check based on get_current_blog_id() and blog_id key if the user belongs to the current site. – kaiser Aug 14 '13 at 14:19
  • Yeah, network installs are a weakness. I don't use them. I'll see what I can do though. Thanks for the heads-up. – s_ha_dum Aug 14 '13 at 14:24
  • Oh, really? Any reason why? Asking because it's the opposite for me: Using nothing than Networks even for single installs. – kaiser Aug 14 '13 at 14:26
  • I deal with very small businesses who will never need a network and I deal with business owners with limited technical knowledge for the most part. I have never seen the need to enable a network. Plus, server requirements are higher for networks. – s_ha_dum Aug 14 '13 at 14:31
  • I wanted to suggest the following to get it compatible with Network installs, but found out that there's no blog_id in the user meta table. After taking a look at the WP_User_Query internals I found out that there's some pretty nasty stuff inside, so the following might work... in maybe 90% of all cases... and in theory :/ $wpdb->prepare( "INNER JOIN {$wpdb->usermeta} as m ON ({$wpdb->users}.ID = m.user_id) WHERE {$wpdb->usermeta}.%s = %s", absint( "{$wpdb->get_blog_prefix( $GLOBALS['blog_id'] )}user_level" ), $GLOBALS['blog_id'] ); – kaiser Aug 14 '13 at 18:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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