it-swarm.com.de

Entfernen Sie über anonyme Funktionen hinzugefügte Aktionen/Filter

Das ist eine verdammt schlechte Praxis, die ich sagen muss. Verbringen Sie die letzten zwei Stunden damit, eine Lösung zum Entfernen von Aktionen und Filtern zu finden, 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 );
});

Habe toschos Antwort , heftig damit gespielt, aber keine Hilfe. Gibt es also eine andere Alternative, mit der über anonyme Funktionen hinzugefügte Aktionen/Filter entfernt werden?

Vielen Dank

10
Abhik

Das Problem ist, dass Sie nicht zwischen einer anonymen und einer anderen Funktion unterscheiden können. Es ist also möglich, eine Schließung (dh anonyme Funktion) zu entfernen, aber wenn mehr als eine Schließung mit derselben Priorität auf denselben Filter einwirkt, müssen Sie dies tun eine Wahl, entfernen Sie sie alle, oder entfernen Sie nur eine (ohne genau zu wissen, welche).

Ich werde zeigen, wie man sie alle mit einer Funktion entfernt, die stark von der in der von Ihnen geposteten @ toscho-Antwort abgeleitet ist:

/**
 * 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 remove_object_filter umbenannt, weil sie alle Arten von Objektfiltern entfernen kann: statische Klassenmethoden, dynamische Objektmethoden und Abschlüsse.

Das Argument $priority ist optional, sollte jedoch beim Entfernen von Abschlüssen immer verwendet werden. Andernfalls entfernt die Funktion alle dem Filter hinzugefügten Abschlüsse, unabhängig von der Priorität, da alle Filter, die die Zielklasse/-methode oder verwenden, wenn $priority weggelassen werden Verschluss entfernt werden.

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 );
10
gmazzap

Anonyme Filter und Aktionen können folgendermaßen entfernt werden:

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

Bei der Generierung der eindeutigen ID mit spl_object_hash() sind anonyme Funktionen miteinander vergleichbar, sodass das vollständige Abschlussobjekt 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 es einen gibt, den Sie behalten müssen, müssen Sie alle Filter entfernen, bis zu dem, den Sie entfernen müssen, und dann die anderen nach Bedarf 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 auf Best Practices zurückgeführt. Ich werde immer nur anonyme Funktionen als Teil eines benutzerdefinierten Themas verwenden, 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, werde ich eine Factory verwenden, um eine Klasse zu initialisieren, alle meine Filter und Aktionen hinzuzufügen und dann die Instanz als statische Variable zu speichern.

2
Shaun Cockerill

Was ist, wenn Sie Ihren Filter mit der Priorität 11 hinzufügen, damit es danach geht? 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 );
2
tivnet