Rimuovi azioni / filtri aggiunti tramite le funzioni anonime


10

È una pessima pratica terribile che devo dire. Ho trascorso le ultime due ore a trovare una soluzione per rimuovere azioni e filtri aggiunti tramite funzioni anonime.

Questo è il codice utilizzato su un tema principale e devo rimuoverlo.

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

Ho ricevuto la risposta di Toscho, ci ho giocato pesantemente, ma senza aiuto. Quindi, c'è qualche altra alternativa che rimuoverà le azioni / i filtri aggiunti tramite funzioni anonime?

Grazie


Suggerirei di contattare l'autore del tema. È una soluzione relativamente semplice per lui / lei utilizzare una funzione con nome al posto dell'anonimo e migliorare il codice.
Helgatheviking

gmazzap sembra che @ vishalbasnet23 l'abbia fatto qui: gist.github.com/vishalbasnet23/5f74df4c800681199ab0246bc037d1d5 Lo sto testando e finora funziona perfettamente.
Renan Oliveira,

Risposte:


10

Il problema è che non puoi distinguere tra una funzione anonima e un'altra, quindi sì, è possibile rimuovere una chiusura (cioè una funzione anonima) ma se più di una chiusura agisce sullo stesso filtro con la stessa priorità devi fare una scelta , rimuovili tutti, oppure rimuovine solo uno (senza sapere esattamente quale).

Mostrerò come rimuoverli tutti usando una funzione altamente derivata da quella nella risposta @toscho che hai pubblicato:

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

Ho rinominato la funzione remove_object_filterperché può rimuovere tutti i tipi di filtri oggetto: metodi di classe statici, metodi di oggetti dinamici e chiusure.

L' $priorityargomento è facoltativo, ma quando si rimuovono le chiusure dovrebbe essere sempre usato, altrimenti la funzione rimuoverà qualsiasi chiusura aggiunta al filtro, indipendentemente dalla priorità, perché quando $priorityviene omessa, tutti i filtri che usano la classe / metodo di destinazione o la chiusura sono rimosso.

Come usare

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

Ho provato questo e molti altri, ma semplicemente non funziona
adamj

@adamj dalla versione 4.7, WordPress ha introdotto un nuovo modo di gestire gli hook, quindi non funziona più ...
gmazzap

conosci qualche alternativa per caso?
Adamo

1
@adamj Potrei aggiornarlo per 4.7+, ma non c'è tempo ora e non sono sicuro di quando avrò. Va bene aprire una nuova domanda, in cui ti colleghi a questo Q / A e dici che è obsoleto, in questo modo chiunque può rispondere, quindi se non avrò tempo, forse lo farà qualcun altro. In alternativa, potresti mettere una taglia su questo Q, spiegando che la risposta più votata qui non funziona nella versione corrente di WP ...
gmazzap

3

Che cosa succede se aggiungi il filtro, con la priorità 11, quindi dopo? È brutto, ma potrebbe funzionare nel tuo caso.

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

    return $default;
}, 11, 1 );

2

I filtri e le azioni anonime possono essere rimossi in modo nativo utilizzando quanto segue:

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

Quando si genera l'id univoco utilizzando spl_object_hash(), le funzioni anonime sono comparabili tra loro, quindi non è necessario ricreare nuovamente l'oggetto di chiusura completa.

Se più filtri o azioni sono collegati allo stesso tag con la stessa priorità, rimuoverà l'ultimo filtro o l'azione che è stata aggiunta. Se ce n'è uno che devi conservare, dovresti rimuovere tutti i filtri fino a quello che devi rimuovere, quindi aggiungere nuovamente gli altri se necessario.

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

Questo tornerà generalmente alle migliori pratiche. Userò sempre e solo funzioni anonime come parte di un tema personalizzato che sto sviluppando per un client, in cui non voglio che il filtro venga sovrascritto o rimosso. In qualsiasi tema o plugin pubblico che svilupperò, userò una factory per inizializzare una classe, aggiungere tutti i miei filtri e azioni, quindi memorizzare l'istanza come variabile statica.

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.