web-dev-qa-db-fra.com

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

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

C'est le 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 , a joué lourdement avec, mais aucune aide. Alors, y a-t-il une autre alternative pour supprimer les actions/filtres ajoutés via des fonctions anonymes?

Merci

10
Abhik

Le problème est que vous ne pouvez pas distinguer une fonction anonyme et une autre, alors 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 en faire une un choix, supprimez-les tous, ou n'enlevez qu'un seul (sans savoir lequel exactement).

Je vais vous montrer comment les supprimer en utilisant une fonction hautement dérivée de celle de la réponse @toscho que vous avez posté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 facultatif, 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é, car lorsque $priority est omis, tous les filtres utilisant la classe/méthode cible ou fermeture sont enlevé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 );
10
gmazzap

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. Il n'est donc 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 remplacé ou supprimé. Dans n'importe quel thème public ou plugin que je développe, je vais utiliser une fabrique pour initialiser une classe, ajouter tous mes filtres et actions, puis stocker l'instance en tant que variable statique.

2
Shaun Cockerill

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 );
2
tivnet