Entfernen Sie Aktionen / Filter, die über anonyme Funktionen hinzugefügt wurden

10

Das ist eine verdammt schlechte Praxis, muss ich sagen. Verbrachte die letzten zwei Stunden damit, eine Lösung zu finden, um Aktionen und Filter zu entfernen, die über anonyme Funktionen hinzugefügt wurden.

Dies ist der Code, der für ein übergeordnetes Thema verwendet wird, und ich muss ihn entfernen.

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

Ich habe toschos Antwort bekommen , habe heftig damit gespielt, aber keine Hilfe. Gibt es also eine andere Alternative, mit der Aktionen / Filter entfernt werden, die über anonyme Funktionen hinzugefügt wurden?

Vielen Dank

Abhik
quelle
Ich würde vorschlagen, den Autor des Themas zu kontaktieren. Es ist für ihn / sie eine relativ einfache Lösung, eine benannte Funktion anstelle der anonymen zu verwenden, und würde den Code verbessern.
Helgatheviking
gmazzap es sieht so aus, als hätte @ vishalbasnet23 es hier gemacht: gist.github.com/vishalbasnet23/5f74df4c800681199ab0246bc037d1d5 Ich teste es und bis jetzt funktioniert es perfekt.
Renan Oliveira

Antworten:

10

Das Problem ist, dass Sie nicht zwischen einer anonymen und einer anderen Funktion unterscheiden können. Ja, es ist möglich, einen Abschluss (dh eine anonyme Funktion) zu entfernen. Wenn jedoch mehr als ein Abschluss mit derselben Priorität auf denselben Filter wirkt, müssen Sie eine Auswahl treffen , entferne sie alle, oder entferne nur eine (ohne genau zu wissen, welche).

Ich werde zeigen, wie Sie sie alle mit einer Funktion entfernen können, die stark von der in der von Ihnen geposteten @ toscho-Antwort abgeleiteten Funktion abweicht:

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

Ich habe die Funktion umbenannt, remove_object_filterweil sie alle Arten von Objektfiltern entfernen kann: statische Klassenmethoden, dynamische Objektmethoden und Schließungen.

Das $priorityArgument ist optional, sollte jedoch beim Entfernen von Closures immer verwendet werden. Andernfalls entfernt die Funktion $priorityalle dem Filter hinzugefügten Closures, unabhängig von der Priorität, da alle Filter, die die Zielklasse / Methode oder den Closure verwenden, verwendet werden , wenn sie weggelassen werden entfernt.

Wie benutzt man

// 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
quelle
Ich habe dieses und viele andere ausprobiert, aber es funktioniert einfach nicht
Adamj
@adamj Seit Version 4.7 hat WordPress eine neue Methode für den Umgang mit Hooks eingeführt, sodass dies nicht mehr funktioniert ...
gmazzap
Kennen Sie zufällig Alternativen?
Adamj
1
@adamj Ich könnte dies für 4.7+ aktualisieren, aber jetzt keine Zeit und nicht sicher, wann ich haben werde. Es ist in Ordnung, eine neue Frage zu öffnen, in der Sie auf diese Frage / Antwort verweisen und sagen, dass diese veraltet ist. Auf diese Weise kann jeder antworten. Wenn ich also keine Zeit habe, wird es vielleicht jemand anderes tun. Alternativ können Sie diesem Q ein Kopfgeld geben und erklären, dass die meisten Antworten hier in der aktuellen Version von WP nicht funktionieren ...
gmazzap
3

Was ist, wenn Sie Ihren Filter mit der Priorität 11 hinzufügen, damit er nachgeht? Das ist hässlich, könnte aber in Ihrem Fall funktionieren.

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

    return $default;
}, 11, 1 );
tivnet
quelle
2

Anonyme Filter und Aktionen können nativ wie folgt entfernt werden:

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

Bei der Generierung der eindeutigen ID mit spl_object_hash()sind anonyme Funktionen miteinander vergleichbar, sodass das Objekt zum vollständigen Schließen nicht erneut erstellt werden muss.

Wenn mehrere Filter oder Aktionen mit derselben Priorität mit demselben Tag verbunden sind, wird der zuletzt hinzugefügte Filter oder die zuletzt hinzugefügte Aktion entfernt. Wenn Sie einen behalten müssen, müssen Sie alle Filter bis zu dem Filter entfernen, den Sie entfernen müssen, und die anderen nach Bedarf erneut hinzufügen.

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

Dies wird im Allgemeinen zu Best Practices zurückkehren. Ich verwende immer nur anonyme Funktionen als Teil eines benutzerdefinierten Themas, das ich für einen Client entwickle, bei dem der Filter nicht überschrieben oder entfernt werden soll. In jedem öffentlichen Thema oder Plugin, das ich entwickle, initialisiere ich eine Klasse mithilfe einer Factory, füge alle meine Filter und Aktionen hinzu und speichere die Instanz als statische Variable.

Shaun Cockerill
quelle