Qual é o tempo válido para usar o current_user_can () e funções relacionadas?

10

Durante o carregamento principal do WP vanilla, o usuário atual está sendo configurado, $wp-init()após o carregamento do tema e antes do initgancho. Isso está de acordo com as boas práticas de funcionalidade conectadas initou posteriores.

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

A documentação não faz nenhuma reivindicação a favor ou contra essa prática (que eu pude encontrar).

No entanto, alguns plugins parecem se conectar à funcionalidade relacionada ao usuário e esperam o initestado pós- estado o tempo todo.

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 uma demonstração rápida, jogue isso na definição principal de current_user_can():

function current_user_can( $capability ) {

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

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

Rarst
fonte

Respostas:

7

O único pré-requisito current_user_can()é um existente wp_get_current_user(). O último é definido em pluggable.php, para que você possa usá-lo depois plugins_loaded.

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

Em alguns casos, como alterar a localidade , é necessário acessar o objeto de usuário atual mais cedo, portanto, aguardar after_setup_themenem é uma opção.

fuxia
fonte
2

Se você verificar a capacidade do usuário antes, initsignifica que há chances de você ser o responsável pela configuração do objeto de usuário atual.

Se você acessar o usuário depois init , terá certeza de que alguma outra coisa já configurou o usuário, na maioria das vezes o próprio núcleo.

É por isso que acessar o usuário depois inité considerado seguro .

De fato, o acesso antecipado pode possivelmente quebrar algum filtro em execução determine_current_user.

Vale dizer que um é um gancho "frágil", porque há chances de ele nunca funcionar, sendo acionado apenas em funções conectáveis.

No entanto, existem casos (como o @toscho disse) em que 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ê desejar.

Uma solução que pode funcionar na maioria dos casos (incluindo 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 );
}

Isso permite verificar antecipadamente a capacidade do usuário atual sem definir o usuário global; portanto, em teoria, é seguro executá-lo antes init.

O problema é que, como dito acima, qualquer código que substitua funções conectáveis ​​e não aciona o determine_current_userquebra.

gmazzap
fonte
Eu acho que sua função tem variáveis ​​um pouco bagunçadas. :)
Rarst
Sim ... digitou rápido demais antes do jantar: P obrigado @ialocin pela correção.
gmazzap
Não mencione isso. Além de não apenas dizer o que está errado, corrigi-lo @Rarst :)
Nicolai
1

Estou inclinado a pensar que o BuddyPress e o bbPress devem verificar outra coisa antes de emitir a _doing_it_wrongmensagem

Alterei as duas rotinas para também verificar a configuração real de $ current_user.

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

Os avisos não eram mais exibidos.

O teste did_action( "after_setup_theme" )torna-se o aparelho para ir com o cinto.

balançando
fonte