¿Cuál es el tiempo válido para usar current_user_can () y funciones relacionadas?

10

Durante la carga principal de Vanilla WP, el usuario actual se está configurando en el $wp-init()que está después de la carga del tema y antes del initenlace. Esto está en línea con las buenas prácticas de funcionalidad enganchadas inito posteriores.

Sin embargo, también es una práctica común llamar a funciones relacionadas, como current_user_can() antes de eso. Por definición, es necesario para los complementos que funcionan con etapas anteriores del proceso de carga (mi complemento Toolbar Theme Switcher sería un ejemplo).

La documentación no hace reclamos a favor o en contra de esta práctica (que pude encontrar).

Sin embargo, algunos complementos parecen conectarse a la funcionalidad relacionada con el usuario y esperan el initestado posterior en todo momento.

Por ejemplo, bbPress lanza el siguiente aviso:

// 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' );
}

Para una demostración rápida, incluya esto en la definición central de current_user_can():

function current_user_can( $capability ) {

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

¿Quién tiene "razón" en esta situación? ¿Existe alguna determinación canónica sobre el uso permitido / prohibido de funciones relacionadas con el usuario anteriormente init?

Rarst
fuente

Respuestas:

7

El único requisito previo para current_user_can()es un existente wp_get_current_user(). Este último se define en pluggable.php, por lo que puede usarlo después plugins_loaded.

La _doing_it_wrong()llamada que está citando en su pregunta es incorrecta en sí misma. Supongo que tomaste eso de BuddyPress o bbPress. Ambos se encuentran con una recursión si no esperan tanto. Hay otras formas mejores de prevenir la recurrencia.

En algunos casos, como el cambio de la configuración regional , que tiene para acceder al objeto usuario actual antes, así que esperar a que after_setup_themeno es ni siquiera una opción.

fuxia
fuente
2

Si verifica la capacidad del usuario antes initsignifica que hay posibilidades de que usted sea ​​el responsable de la configuración del objeto de usuario actual.

Si accede al usuario después init , entonces está seguro de que algo más ya configuró al usuario, la mayoría de las veces es el núcleo mismo.

Es por eso que acceder al usuario después initse considera seguro .

De hecho, el acceso temprano puede romper algún filtro que se esté ejecutando determine_current_user.

Vale la pena decir que uno es un gancho "frágil", porque hay posibilidades de que nunca se ejecute, ya que solo se dispara en funciones conectables.

Sin embargo, hay casos (como dijo @toscho ) en los que no puede esperar hasta init, en esos casos no tiene otra opción.

La única forma de resolver cualquier incompatibilidad es caso por caso, si tiene voluntad.

Una solución que puede funcionar en la mayoría de los casos (incluyendo bbPress / BuddyPress) es usar la siguiente función en lugar de 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 );
}

Esto permite verificar la capacidad del usuario actual antes de tiempo sin configurar el usuario global, por lo que en teoría es seguro ejecutarlo antes init.

El problema es que, como se dijo anteriormente, cualquier código que anule las funciones conectables y no dispare lo determine_current_userrompe.

gmazzap
fuente
Creo que su función tiene variables un poco desordenadas. :)
Rarst
Sí ... escribí demasiado rápido antes de la cena: P gracias @ialocin por arreglarlo.
gmazzap
No lo menciones Además, no solo digas lo que está mal, arréglalo @Rarst :)
Nicolai
1

Me inclino a pensar que BuddyPress y bbPress deberían verificar otra cosa antes de emitir el _doing_it_wrongmensaje

Cambié ambas rutinas para verificar también la configuración real de $ current_user.

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

Los avisos ya no se mostraban.

La prueba se did_action( "after_setup_theme" )convierte en las llaves para ir con el cinturón.

balanceándose
fuente