Supprimer les actions / filtres ajoutés via les fonctions anonymes

9

Je dois dire que c’est une mauvaise pratique. Passé les deux dernières heures à trouver une solution pour supprimer les actions et les filtres ajoutés via les fonctions anonymes.

Il s'agit du code utilisé sur un thème parent et je dois le supprimer.

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

Vous avez la réponse de toscho , qui a joué énormément, mais sans aide. Alors, y a-t-il une autre alternative pour supprimer les actions / filtres ajoutés via des fonctions anonymes?

Merci

    
posée Abhik 12.03.2014 - 12:44

3 réponses

9

Le problème est que vous ne pouvez pas distinguer une fonction anonyme et une autre. Donc, oui, il est possible de supprimer une fermeture (c'est-à-dire une fonction anonyme) mais si plusieurs fermetures agissent sur le même filtre avec la même priorité vous devez faire un choix, les supprimer tous, ou ne supprimer qu'un seul (sans savoir lequel exactement).

Je vais vous montrer comment les supprimer à l'aide d'une fonction hautement dérivée de celle de la réponse @toscho que vous avez publiée:

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

J'ai renommé la fonction remove_object_filter car elle peut supprimer tous les types de filtres d'objet: méthodes de classe statique, méthodes d'objet dynamique et fermetures.

L'argument $priority est optionnel, mais lors de la suppression des fermetures, il doit toujours être utilisé. Sinon, la fonction supprimera toute fermeture ajoutée au filtre, quelle que soit sa priorité. En effet, lorsque $priority est omis, tous les filtres utilisant la classe / méthode cible ou la fermeture sont supprimés.

Comment utiliser

// 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 );
    
réponse donnée gmazzap 11.04.2014 - 08:37
2

Et si vous ajoutez votre filtre, avec la priorité 11, alors il va après? C'est moche, mais pourrait fonctionner dans votre cas.

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

    return $default;
}, 11, 1 );
    
réponse donnée tivnet 23.03.2014 - 22:37
2

Les filtres et actions anonymes peuvent être supprimés de manière native à l'aide des éléments suivants:

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

Lors de la génération de l'identifiant unique à l'aide de spl_object_hash() , les fonctions anonymes sont comparables les unes aux autres. Par conséquent, il n'est pas nécessaire de recréer l'objet de fermeture complète.

Si plusieurs filtres ou actions sont connectés à la même balise avec la même priorité, cela supprimera le dernier filtre ou l'action ajouté. S'il en existe un que vous devez conserver, vous devrez supprimer tous les filtres jusqu'à celui que vous souhaitez supprimer, puis rajouter les autres au besoin.

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

Cela reviendra généralement aux meilleures pratiques. J'utiliserai uniquement des fonctions anonymes dans le cadre d'un thème personnalisé que je développe pour un client et pour lequel je ne souhaite pas que le filtre soit écrasé ou supprimé. Dans tout thème public ou plug-in que je développe, j'utilise une fabrique pour initialiser une classe, ajouter tous mes filtres et actions, puis stocker l'instance sous forme de variable statique.

    
réponse donnée Shaun Cockerill 07.08.2017 - 09:33

Lire d'autres questions sur les étiquettes