10

During the vanilla WP core load the current user is being set up in $wp-init() which is after theme load and before init hook. This is in line with good practice of functionality getting hooked to init or later.

However it is also common practice to call related functions, such as current_user_can() earlier than that. It is by definition required for plugins that work with earlier stages of load process (my Toolbar Theme Switcher plugin would be an example).

Documentation makes no claims for or against this practice (that I could find).

However some plugins seem to hook into user–related functionality and expect the post–init state at all times.

For example bbPress throws following notice:

// If the current user is being setup before the "init" action has fired,
// strange (and difficult to debug) role/capability issues will occur.
if ( ! did_action( 'after_setup_theme' ) ) {
    _doing_it_wrong( __FUNCTION__, __( 'The current user is being initialized without using $wp->init().', 'bbpress' ), '2.3' );
}

For quick demonstration throw this into core's definition of current_user_can():

function current_user_can( $capability ) {

    if ( ! did_action('after_setup_theme') ) {
        echo wp_debug_backtrace_summary();
    }

Who is “right” in this situation? Is there a canonical determination about allowed / forbidden usage of user–related functions before init ?

7

The only prerequisite for current_user_can() is an existing wp_get_current_user(). The latter is defined in pluggable.php, so you can use it after plugins_loaded.

The _doing_it_wrong() call you are citing in your question is wrong for itself. My guess is that you took that from BuddyPress or bbPress. Both are running into a recursion if they don't wait that long. There are other, better ways to prevent the recursion.

In some cases, like changing the locale, you have to access the current user object earlier, so waiting for after_setup_theme isn't even an option.

2

If you check user capability before init means there're chances you are the responsible for the setting of the current user object.

If you access user after init, then you are sure that something else already setup the user, most the times core itself.

This is why accessing user after init is considered safe.

In fact, early access may possibly break some filter running on determine_current_user.

It worth saying that one is a "fragile" hook, because there're chances it never runs, being fired only in pluggable functions.

However, there are cases (like @toscho said) where you can't wait until init, in those cases you have no choice.

Only way to solve any incompatibility is case by case, if you have will.

A solution that may work in most cases (including bbPress / BuddyPress) is to use following function instead of current_user_can:

function compat_current_user_can( $capability )
{
  if ( did_action( 'init' ) ) {
     return current_user_can( $capability );
  }

  $user_id = apply_filters( 'determine_current_user', false );

  return user_can( $user_id, $capability );
}

This allows to check current user capability early without setting global user, so in theory safe to be run before init.

Problem is that, as said above, any code that overrides pluggable functions and not fires determine_current_user breaks it.

  • I think your function has variables tad messed up. :) – Rarst Aug 10 '15 at 19:36
  • Yes... typed too fast before dinner :P thanks @ialocin for fixing. – gmazzap Aug 10 '15 at 19:45
  • Don't mention it. Besides don't just tell what is wrong, fix it @Rarst :) – Nicolai Aug 10 '15 at 19:48
1

I'm inclined to think that BuddyPress and bbPress should be checking something else before issuing the _doing_it_wrong message

I changed both routines to also check the actual setting of $current_user.

global $current_user; 
if ( is_null( $current_user ) ) {
    _doing_it_wrong( ... );
}

The Notices were no longer displayed.

The testing for did_action( "after_setup_theme" ) becomes the braces to go with the belt.

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.