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

9

Essa é uma péssima prática que devo dizer. Passou as duas últimas horas encontrando 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 pai, e eu 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 );
});

Conseguiu resposta de toscho , tocou muito, mas não ajuda. Então, existe alguma outra alternativa que irá remover ações / filtros adicionados através de funções anônimas?

Obrigado

    
por Abhik 12.03.2014 / 12:44

3 respostas

9

O problema é que você não pode distinguir entre uma função anônima e outra, então sim, é possível remover um fechamento (isto é, função anônima) mas se mais de um fechamento agir no mesmo filtro com a mesma prioridade você tem que fazer uma escolha, removê-los todos, ou remover apenas um (sem saber exatamente qual).

Eu mostrarei como removê-los todos usando uma função altamente derivada daquela na resposta do @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] );
      }
    }
  }
}

Renomei a função remove_object_filter porque ela pode remover todos os tipos de filtros de objeto: métodos de classe estática, métodos de objeto dinâmico e encerramentos.

O argumento $priority é opcional, mas ao remover closures ele deve ser sempre usado; caso contrário, a função removerá qualquer encerramento adicionado ao filtro, independentemente de qual prioridade, porque quando $priority for omitido, todos os filtros usando a classe de destino / método ou fechamento são removidos.

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 );
    
por gmazzap 11.04.2014 / 08:37
2

E se você adicionar seu filtro, com a prioridade 11, para que ele seja depois? 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 );
    
por tivnet 23.03.2014 / 22:37
2

Filtros anônimos e ações 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, ele removerá o filtro ou ação mais recente que foi adicionado. Se houver um que você precise manter, você terá que remover todos os filtros até o que você precisa remover e 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 retornará às práticas recomendadas. Sempre usarei 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 ou plug-in público que desenvolvo, usarei uma fábrica para inicializar uma classe, adicionar todos os meus filtros e ações e, em seguida, armazená-la como uma variável estática.

    
por Shaun Cockerill 07.08.2017 / 09:33