Qual è il tempismo valido dell'utilizzo di current_user_can () e delle relative funzioni?


10

Durante il caricamento del core WP vanilla l'utente corrente viene impostato in $wp-init()cui si trova dopo il caricamento del tema e prima initdell'hook. Ciò è in linea con le buone pratiche di funzionalità che vengono agganciate inito successive.

Tuttavia è anche pratica comune chiamare funzioni correlate, come current_user_can() prima . È per definizione necessario per i plug-in che funzionano con le fasi precedenti del processo di caricamento (il mio plug-in Temi barra degli strumenti sarebbe un esempio).

La documentazione non fa affermazioni a favore o contro questa pratica (che ho potuto trovare).

Tuttavia, alcuni plugin sembrano agganciarsi alla funzionalità relativa all'utente e si aspettano sempre lo initstato post .

Ad esempio bbPress genera il seguente avviso:

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

Per una rapida dimostrazione, inseriscilo nella definizione di core di current_user_can():

function current_user_can( $capability ) {

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

Chi ha "ragione" in questa situazione? Esiste una determinazione canonica sull'uso consentito / proibito delle funzioni correlate all'utente prima init?


Risposte:


7

L'unico prerequisito current_user_can()è un esistente wp_get_current_user(). Quest'ultimo è definito in pluggable.php, quindi puoi usarlo dopo plugins_loaded.

La _doing_it_wrong()chiamata che stai citando nella tua domanda è sbagliata per se stessa. La mia ipotesi è che tu l'abbia preso da BuddyPress o bbPress. Entrambi si imbattono in una ricorsione se non aspettano così a lungo. Esistono altri modi migliori per prevenire la ricorsione.

In alcuni casi, come la modifica delle impostazioni internazionali , è necessario accedere all'oggetto utente corrente in precedenza, quindi attendere after_setup_themenon è nemmeno un'opzione.



2

Se si verifica la capacità dell'utente prima initsignifica che ci sono possibilità che tu sia responsabile dell'impostazione dell'oggetto utente corrente.

Se accedi all'utente dopo init , allora sei sicuro che qualcos'altro ha già impostato l'utente, il più delle volte core stesso.

Questo è il motivo per cui l'accesso agli utenti dopo initè considerato sicuro .

In effetti, l'accesso anticipato potrebbe eventualmente rompere alcuni filtri in esecuzione determine_current_user.

Vale la pena dire che uno è un gancio "fragile", perché ci sono possibilità che non funzioni mai, sparando solo con funzioni collegabili.

Tuttavia, ci sono casi (come ha detto @toscho ) in cui non puoi aspettare fino a init, in quei casi non hai scelta.

L'unico modo per risolvere eventuali incompatibilità è caso per caso, se lo desideri.

Una soluzione che può funzionare nella maggior parte dei casi (incluso bbPress / BuddyPress) è utilizzare la seguente funzione invece di 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 );
}

Ciò consente di verificare anticipatamente la capacità dell'utente corrente senza impostare l'utente globale, quindi in teoria può essere eseguito prima init.

Il problema è che, come detto sopra, qualsiasi codice che sovrascrive le funzioni collegabili e non gli incendi lo determine_current_userrompe.


Penso che la tua funzione abbia delle variabili un po 'incasinate. :)
Rarst

Sì ... digitato troppo velocemente prima di cena: P grazie a @ialocin per il fissaggio.
gmazzap

Non dirlo. Inoltre, non solo dire cosa c'è che non va, risolvilo @Rarst :)
Nicolai,

1

Sono propenso a pensare che BuddyPress e bbPress dovrebbero controllare qualcos'altro prima di inviare il _doing_it_wrongmessaggio

Ho modificato entrambe le routine per verificare anche l'impostazione effettiva di $ current_user.

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

Le comunicazioni non erano più visualizzate.

Il test per did_action( "after_setup_theme" )diventa le parentesi graffe per andare con la cintura.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.