Remover ações / filtros adicionados via funções anônimas

10

Essa é uma prática ruim, devo dizer. Passou as últimas duas horas procurando uma solução para remover ações e filtros adicionados por meio de funções anônimas.

Este é o código usado em um tema principal e preciso removê-lo.

/**
 * Add custom columns to admin comments grid
 *  * Rate that user set.
 */
add_filter( 'manage_edit-comments_columns', function( $default ) {
    $columns['smr_comment_rate']  = __( 'Rate', 'txtdmn' );

    return array_slice( $default, 0, 3, true ) + $columns + array_slice( $default, 2, NULL, true );
});

Recebi a resposta de toscho , brinquei muito com ela, mas sem ajuda. Então, existe alguma outra alternativa que remova ações / filtros adicionados por funções anônimas?

obrigado

Abhik
fonte
Eu sugeriria entrar em contato com o autor do tema. É uma correção relativamente fácil para ele / ela usar uma função nomeada no lugar do anônimo e melhorar o código.
helgatheviking
gmazzap parece que @ vishalbasnet23 fez aqui: gist.github.com/vishalbasnet23/5f74df4c800681199ab0246bc037d1d5 Estou testando e até agora está funcionando perfeitamente.
Renan Oliveira

Respostas:

10

O problema é que você não pode distinguir entre uma função anônima e outra; portanto, é possível remover um fechamento (ou seja, função anônima), mas se mais de um fechamento agir no mesmo filtro com a mesma prioridade, você deverá fazer uma escolha. , remova todos eles ou remova apenas um (sem saber exatamente qual).

Vou mostrar como removê-los todos usando uma função altamente derivada da resposta @toscho que você postou:

/**
 * Remove an object filter.
 *
 * @param  string $tag                Hook name.
 * @param  string $class              Class name. Use 'Closure' for anonymous functions.
 * @param  string|void $method        Method name. Leave empty for anonymous functions.
 * @param  string|int|void $priority  Priority
 * @return void
 */
function remove_object_filter( $tag, $class, $method = NULL, $priority = NULL ) {
  $filters = $GLOBALS['wp_filter'][ $tag ];
  if ( empty ( $filters ) ) {
    return;
  }
  foreach ( $filters as $p => $filter ) {
    if ( ! is_null($priority) && ( (int) $priority !== (int) $p ) ) continue;
    $remove = FALSE;
    foreach ( $filter as $identifier => $function ) {
      $function = $function['function'];
      if (
        is_array( $function )
        && (
          is_a( $function[0], $class )
          || ( is_array( $function ) && $function[0] === $class )
        )
      ) {
        $remove = ( $method && ( $method === $function[1] ) );
      } elseif ( $function instanceof Closure && $class === 'Closure' ) {
        $remove = TRUE;
      }
      if ( $remove ) {
        unset( $GLOBALS['wp_filter'][$tag][$p][$identifier] );
      }
    }
  }
}

Renomeei a função remove_object_filterporque ela pode remover todos os tipos de filtros de objetos: métodos de classe estática, métodos de objetos dinâmicos e fechamentos.

O $priorityargumento é opcional, mas ao remover fechamentos, ele sempre deve ser usado; caso contrário, a função removerá qualquer fechamento adicionado ao filtro, independentemente da prioridade, porque quando $priorityomitido, todos os filtros que usam a classe / método ou o fechamento de destino são removido.

Como usar

// remove a static method
remove_object_filter( 'a_filter_hook', 'AClass', 'a_static_method', 10 );

// remove a dynamic method
remove_object_filter( 'a_filter_hook', 'AClass', 'a_dynamic_method', 10 );

// remove a closure
remove_object_filter( 'a_filter_hook', 'Closure', NULL, 10 );
gmazzap
fonte
Eu tentei este e muitos outros, mas ele simplesmente não trabalho
adamj
@adamj desde a versão 4.7, WordPress introduziu nova forma de ganchos punho, de modo que este não funciona mais ...
gmazzap
você conhece alguma alternativa por acaso?
adamj
11
@adamj Eu poderia atualizar isso para 4.7+, mas agora não há tempo e não tenho certeza de quando terei. Não há problema em abrir uma nova pergunta, na qual você vincula esta pergunta / resposta e diz que está desatualizada, para que qualquer pessoa possa responder; portanto, se eu não tiver tempo, talvez alguém o faça. Como alternativa, você pode colocar uma recompensa por este Q, explicando que resposta mais upvoted aqui não funcionam na versão atual do WP ...
gmazzap
3

E se você adicionar seu filtro, com a prioridade 11, para continuar? Isso é feio, mas pode funcionar no seu caso.

add_filter( 'manage_edit-comments_columns', function( $default ) {
    unset( $default['smr_comment_rate'] );

    return $default;
}, 11, 1 );
tivnet
fonte
2

Os filtros e ações anônimos podem ser removidos nativamente usando o seguinte:

remove_filter( $tag, function(){}, $priority )

Ao gerar o ID exclusivo usando spl_object_hash(), as funções anônimas são comparáveis ​​entre si, portanto, o objeto de fechamento completo não precisa ser recriado novamente.

Se vários filtros ou ações estiverem conectados à mesma tag com a mesma prioridade, removerá o filtro ou a ação mais recente adicionada. Se houver um que você precise manter, será necessário remover todos os filtros até o filtro necessário e depois adicionar novamente os outros, conforme necessário.

// Filter which was added and needs to be removed
add_filter( 'manage_edit-comments_columns', function( $default ) {
    $columns['smr_comment_rate']  = __( 'Rate', 'txtdmn' );

    return array_slice( $default, 0, 3, true ) + $columns + array_slice( $default, 2, NULL, true );
} );

// Removes the last anonymous filter to be added
remove_filter( 'manage_edit-comments_columns', function(){} );

Geralmente, isso volta às melhores práticas. Somente utilizarei funções anônimas como parte de um tema personalizado que estou desenvolvendo para um cliente, onde não quero que o filtro seja substituído ou removido. Em qualquer tema público ou plug-in que eu desenvolva, usarei uma fábrica para inicializar uma classe, adicionar todos os meus filtros e ações e, em seguida, armazenar a instância como uma variável estática.

Shaun Cockerill
fonte