web-dev-qa-db-fra.com

Quel est le moment valide pour utiliser current_user_can () et les fonctions associées?

Pendant le chargement de base de la vanille WP, l'utilisateur actuel est configuré dans la fonction $wp-init(), qui est après le chargement du thème et avant le hook init. Cela va dans le sens d'une bonne pratique consistant à rendre la fonctionnalité accrochée à init ou plus tard.

Cependant, il est également courant d'appeler des fonctions associées, telles que current_user_can() tôt que. Il est par définition requis pour les plugins qui fonctionnent avec les étapes précédentes du processus de chargement (mon plugin Toolbar Theme Switcher serait un exemple).

La documentation ne fait aucune réclamation pour ou contre cette pratique (que j'ai pu trouver).

Cependant, certains plugins semblent s’accrocher aux fonctionnalités liées à l’utilisateur et s’attendent à l’état post –init à tout moment.

Par exemple, bbPress émet l’avis suivant:

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

Pour une démonstration rapide, introduisez ceci dans la définition de base de current_user_can():

function current_user_can( $capability ) {

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

Qui a "raison" dans cette situation? Existe-t-il une détermination canonique concernant l'utilisation autorisée/interdite des fonctions liées à l'utilisateur avant init?

10
Rarst

La seule condition préalable à current_user_can() est une wp_get_current_user() existante. Ce dernier est défini dans pluggable.php, vous pouvez donc l'utiliser après plugins_loaded.

L'appel _doing_it_wrong() que vous citez dans votre question est mauvais pour lui-même. Je suppose que vous avez pris cela dans BuddyPress ou bbPress. Les deux courent dans une récursivité s'ils n'attendent pas si longtemps. Il existe d'autres moyens plus efficaces d'éviter la récursivité.

Dans certains cas, comme changer les paramètres régionaux , vous avez pour accéder à l’objet utilisateur actuel plus tôt, donc attendre after_setup_theme n’est même pas une option.

7
fuxia

Si vous vérifiez les capacités de l'utilisateur avant init, cela signifie qu'il y a des chances que {vous} _ soit responsable du paramétrage de l'objet utilisateur actuel.

Si vous accédez à l'utilisateur aprèsinit, vous êtes alors sûr que autre chose a déjà configuré l'utilisateur, la plupart du temps au centre de lui-même.

C'est pourquoi l'accès à l'utilisateur après init est considéré comme sûr.

En fait, un accès anticipé peut éventuellement casser certains filtres s’exécutant sur determine_current_user.

Cela vaut la peine de dire qu’il s’agit d’un crochet "fragile", car il ya de bonnes chances qu’il ne fonctionne jamais, étant déclenché uniquement dans des fonctions enfichables.

Cependant, il existe des cas (comme @toscho said) dans lesquels vous ne pouvez pas attendre jusqu'à init, dans ce cas, vous n'avez pas le choix.

Le seul moyen de résoudre toute incompatibilité est au cas par cas, si vous en avez la volonté.

Une solution qui peut fonctionne dans la plupart des cas (y compris bbPress/BuddyPress) consiste à utiliser la fonction suivante à la place 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 );
}

Cela permet de vérifier rapidement les capacités des utilisateurs actuels sans paramétrer l’utilisateur global. Ainsi, en théoriesans pouvoir être exécuté avant init.

Le problème est que, comme indiqué ci-dessus, tout code qui annule les fonctions enfichables et ne déclenche pas determine_current_user le rompt.

2
gmazzap

J'ai tendance à penser que BuddyPress et bbPress devraient vérifier autre chose avant d'envoyer le message _doing_it_wrong

J'ai changé les deux routines pour vérifier également le réglage actuel de $ current_user.

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

Les avis n'étaient plus affichés.

Le test de did_action( "after_setup_theme" ) devient l’attelle qui va avec la ceinture.

1
bobbingwide