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

10

Pendant le chargement de base de WP vanilla, l'utilisateur actuel est configuré dans $wp-init()lequel est après le chargement du thème et avant le initcrochet. Cela est conforme à la bonne pratique consistant à accrocher les fonctionnalités initou ultérieurement.

Cependant, il est également courant d'appeler des fonctions connexes, telles que current_user_can() plus tôt que cela. 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 en serait un exemple).

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

Cependant, certains plugins semblent se connecter à des fonctionnalités liées à l'utilisateur et attendent l' initétat postérieur à tout moment.

Par exemple, bbPress lance 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, insérez 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 sur l'utilisation autorisée / interdite des fonctions liées à l'utilisateur auparavant init?

Rarst
la source

Réponses:

7

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

L' _doing_it_wrong()appel que vous citez dans votre question est faux en soi. Je suppose que vous l'avez emprunté à BuddyPress ou bbPress. Les deux se heurtent à une récursivité s'ils n'attendent pas aussi longtemps. Il existe d'autres moyens plus efficaces d'empêcher la récursivité.

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

fuxia
la source
2

Si vous vérifiez la capacité de l' utilisateur avant des initmoyens il sont les chances que vous êtes le responsable du réglage de l'objet utilisateur.

Si vous accédez à l'utilisateur par la suite init , vous êtes sûr que quelque chose d'autre a déjà configuré l'utilisateur, la plupart du temps lui-même.

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

En fait, un accès anticipé peut éventuellement casser certains filtres en cours d'exécution determine_current_user.

Il vaut la peine de dire que l'un est un crochet "fragile", car il y a des chances qu'il ne fonctionne jamais, étant uniquement tiré dans des fonctions enfichables.

Cependant, il y a des cas (comme l' a dit @toscho ) où vous ne pouvez pas attendre jusqu'à init, dans ces cas, vous n'avez pas le choix.

La seule façon de résoudre toute incompatibilité est au cas par cas, si vous le souhaitez.

Une solution qui peut fonctionner dans la plupart des cas (y compris bbPress / BuddyPress) consiste à utiliser la fonction suivante au lieu 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 la capacité de l'utilisateur actuel tôt sans définir d'utilisateur global, donc en théorie sûr à exécuter avant init.

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

gmazzap
la source
Je pense que votre fonction a des variables un peu gâchées. :)
Rarst
Oui ... tapé trop vite avant le dîner: merci P @ialocin pour la fixation.
gmazzap
Ne le mentionne pas. De plus, ne vous contentez pas de dire ce qui ne va pas, corrigez-le @Rarst :)
Nicolai
1

Je suis enclin à penser que BuddyPress et bbPress devraient vérifier autre chose avant d'émettre le _doing_it_wrongmessage

J'ai changé les deux routines pour vérifier également le paramètre réel de $ current_user.

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

Les avis n'étaient plus affichés.

Le test did_action( "after_setup_theme" )devient les accolades pour aller avec la ceinture.

danser partout
la source