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

10

C'est une mauvaise pratique effrayante, je dois dire. A passé deux 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 );
});

J'ai obtenu la réponse de toscho, j'ai beaucoup joué avec, mais sans aide. Alors, existe-t-il une autre alternative qui supprimera les actions / filtres ajoutés via des fonctions anonymes?

Merci

Abhik
la source
Je suggère de contacter l'auteur du thème. C'est une solution relativement facile pour lui d'utiliser une fonction nommée à la place de l'anonyme et d'améliorer le code.
helgatheviking
gmazzap il ressemble à @ vishalbasnet23 l'a fait ici: gist.github.com/vishalbasnet23/5f74df4c800681199ab0246bc037d1d5 Je le teste et jusqu'à présent, cela fonctionne parfaitement.
Renan Oliveira

Réponses:

10

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

Je vais montrer comment les supprimer tous en utilisant une fonction très 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_filtercar elle peut supprimer tous les types de filtres d'objets: méthodes de classe statiques, méthodes d'objet dynamiques et fermetures.

L' $priorityargument 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 la priorité, car lorsqu'elle $priorityest omise, tous les filtres utilisant la classe / méthode cible ou la fermeture sont supprimé.

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 );
gmazzap
la source
J'ai essayé celui-ci et bien d'autres, mais cela ne fonctionne tout simplement pas
adamj
@adamj depuis la version 4.7, WordPress a introduit une nouvelle façon de gérer les crochets, donc cela ne fonctionne plus ...
gmazzap
connaissez-vous des alternatives par hasard?
adamj
1
@adamj Je pourrais mettre à jour ceci pour 4.7+, mais pas de temps maintenant, et je ne sais pas quand j'aurai. C'est bien d'ouvrir une nouvelle question, où vous vous connectez à cette Q / R et dites que c'est obsolète, de cette façon n'importe qui peut répondre, donc si je n'ai pas le temps, peut-être que quelqu'un d'autre le fera. Comme alternative, vous pouvez mettre une prime sur ce Q, expliquant que la réponse la plus votée ici ne fonctionne pas dans la version actuelle de WP ...
gmazzap
3

Que se passe-t-il si vous ajoutez votre filtre, avec la priorité 11, pour qu'il se poursuive? C'est moche, mais ça pourrait marcher dans votre cas.

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

    return $default;
}, 11, 1 );
tivnet
la source
2

Les filtres et actions anonymes peuvent être supprimés nativement à l'aide des éléments suivants:

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

Lors de la génération de l'identifiant unique à l'aide spl_object_hash(), les fonctions anonymes sont comparables les unes aux autres, de sorte que l'objet de fermeture complète n'a pas besoin d'être recréé à nouveau.

Si plusieurs filtres ou actions sont connectés à la même balise avec la même priorité, cela supprimera le dernier filtre ou action qui a été ajouté. S'il y en a un que vous devez conserver, vous devrez supprimer tous les filtres jusqu'à celui dont vous avez besoin, puis rajouter les autres si nécessaire.

// 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. Je n'utiliserai que des fonctions anonymes dans le cadre d'un thème personnalisé que je développe pour un client, où je ne veux pas que le filtre soit écrasé ou supprimé. Dans n'importe quel thème ou plugin public 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.

Shaun Cockerill
la source