Видаліть дії / фільтри, додані за допомогою анонімних функцій


10

Я мушу сказати, що це хитра погана практика. Останні дві години витрачав на пошук рішення для видалення дій та фільтрів, доданих через функції Anonymous.

Це код, який використовується у батьківській темі, і мені потрібно його видалити.

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

Отримав відповідь Тошо , сильно грав з нею, але не допоможе. Отже, чи є інша альтернатива, яка видалить дії / фільтри, додані за допомогою анонімних функцій?

Дякую


Я б запропонував зв’язатися з автором теми. Використовувати названу функцію замість анонімного порівняно легко для неї / її, і це дозволить поліпшити код.
helgatheviking

gmazzap це схоже на @ vishalbasnet23 зробив це тут: gist.github.com/vishalbasnet23/5f74df4c800681199ab0246bc037d1d5 Я тестую його, і поки він працює чудово.
Ренан Олівейра

Відповіді:


10

Проблема полягає в тому, що ви не можете відрізнити форму анонімної функції та іншу, тож так, можна закрити закриття (тобто анонімну функцію), але якщо більше одного закриття діє на один і той же фільтр з однаковим пріоритетом, ви повинні зробити вибір , видаліть їх усіх, або видаліть лише один (не знаючи точно, який).

Я покажу, як вилучити їх усіх за допомогою функції, яка виходить з функції, опублікованої у відповіді @toscho:

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

Я перейменував цю функцію, remove_object_filterоскільки вона може видаляти всі типи об'єктних фільтрів: методи статичного класу, динамічні методи об'єктів та закриття.

$priorityАргумент є необов'язковим, але при видаленні замикання слід завжди використовуються, в іншому випадку функція буде видалити будь замикання доданого до фільтру, незалежно від того , на якому пріоритет, тому що , коли $priorityопущено, все фільтри , що використовують цільової клас / метод або замикання є вилучено.

Як користуватись

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

Я спробував цей і багато інших, але це просто не працює
adamj

@adamj з версії 4.7 WordPress представив новий спосіб поводження з гачками, тому це більше не працює ...
gmazzap

чи знаєте ви якісь альтернативи?
adamj

1
@adamj Я міг би оновити це для 4.7+, але зараз немає часу і не впевнений, коли у мене з’явиться. Добре відкрити нове запитання, де ви посилаєтесь на це питання / запитання та заявляєте, що це застаріло, тому кожен може відповісти, тож якщо я не матиму часу, можливо, хтось інший зробить. Як альтернативу, ви можете поставити на це питання щедро, пояснивши, що відповідь на більшість голосів тут не працює в поточній версії WP ...
gmazzap

3

Що робити, якщо ви додасте свій фільтр, з пріоритетом 11, і він продовжується? Це некрасиво, але може спрацювати у вашому випадку.

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

    return $default;
}, 11, 1 );

2

Анонімні фільтри та дії можна видалити спочатку за допомогою наступного:

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

При створенні унікального ідентифікатора за допомогою spl_object_hash()анонімних функцій можна порівняти одна з одною, тому об'єкт повного закриття не потрібно створювати заново.

Якщо кілька фільтрів або дій під’єднано до одного і того ж тегу з однаковим пріоритетом, він видалить останній фільтр або дію, які були додані. Якщо є такий, який вам потрібно зберегти, вам доведеться видалити всі фільтри до того, який вам потрібно буде видалити, а потім повторно додайте інші, якщо потрібно.

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

Це, як правило, повернеться до найкращих практик. Я коли-небудь використовуватиму анонімні функції лише як частину спеціальної теми, яку я розробляю для клієнта, де я не хочу, щоб фільтр був перезаписаний або видалений. У будь-якій публічній темі чи плагіні, який я розробляю, я буду використовувати фабрику для ініціалізації класу, додавання всіх моїх фільтрів та дій, а потім зберігати екземпляр як статичну змінну.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.