O que é a temporização válida de usar current_user_can () e funções relacionadas?

10

Durante o carregamento principal do WP vanilla, o usuário atual está sendo configurado em $wp-init() , que é após a carga do tema e antes do init hook. Isso está de acordo com a boa prática de ficar viciado em init ou mais tarde.

No entanto, também é prática comum chamar funções relacionadas, como current_user_can() anterior . É, por definição, necessário para plugins que funcionam com estágios anteriores do processo de carregamento (meu plugin Toolbar Theme Switcher seria um exemplo).

A documentação não faz reivindicações a favor ou contra essa prática (que eu encontrei).

No entanto, alguns plug-ins parecem se conectar à funcionalidade relacionada ao usuário e esperam o estado post- init em todos os momentos.

Por exemplo, o bbPress lança o seguinte 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 demonstração rápida, jogue isso na definição básica de current_user_can() :

function current_user_can( $capability ) {

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

Quem está "certo" nesta situação? Existe uma determinação canônica sobre o uso permitido / proibido de funções relacionadas ao usuário antes de init ?

    
por Rarst 10.08.2015 / 14:32

3 respostas

7

O único pré-requisito para current_user_can() é um wp_get_current_user() existente. Este último é definido em pluggable.php , então você pode usá-lo após plugins_loaded .

A chamada _doing_it_wrong() que você está citando em sua pergunta está errada por si mesma. Meu palpite é que você tirou isso do BuddyPress ou do bbPress. Ambos estão correndo em uma recursão se não esperarem tanto tempo. Existem outras maneiras melhores de impedir a recursão.

Em alguns casos, como alterando a localidade , você tem para acessar o objeto de usuário atual mais cedo, então esperar por after_setup_theme não é nem uma opção.

    
por fuxia 10.08.2015 / 15:03
2

Se você verificar a capacidade do usuário antes de init , significa que há chances você de serem responsáveis pela configuração do objeto de usuário atual.

Se você acessar o usuário após init , então você tem certeza de que algo mais já configurou o usuário, na maioria das vezes o próprio núcleo.

É por isso que acessar o usuário após init é considerado seguro .

Na verdade, o acesso antecipado pode possivelmente quebrar algum filtro em execução no determine_current_user .

Vale a pena dizer que se trata de um gancho "frágil", porque há chances de que ele nunca seja executado, sendo acionado apenas em funções conectáveis.

No entanto, há casos (como @toscho disse) onde você não pode esperar até o init, nesses casos você não tem escolha.

A única maneira de resolver qualquer incompatibilidade é caso a caso, se você tiver vontade.

Uma solução que pode funcionar na maioria dos casos (incluindo o bbPress / BuddyPress) é usar a seguinte função em vez 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 );
}

Isto permite checar antecipadamente a capacidade atual do usuário sem configurar o usuário global, portanto, em teoria seguro para ser executado antes de init .

O problema é que, como dito acima, qualquer código que sobreponha funções plugáveis e não ative determine_current_user o quebra.

    
por gmazzap 10.08.2015 / 21:31
1

Estou inclinado a pensar que o BuddyPress e o bbPress devem estar verificando algo antes de emitir a mensagem _doing_it_wrong

Eu alterei as duas rotinas para verificar também a configuração atual de $ current_user.

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

Os avisos não foram mais exibidos.

O teste para did_action( "after_setup_theme" ) torna-se o aparelho que acompanha o cinto.

    
por bobbingwide 10.08.2015 / 15:49