1

Is there any way to change the order of filters for e.g. the_content before they are applied? What I currently have is the following ideas:

/**
 * Print all filters for some hook.
 */
function print_filters_for( $hook = '' ) {
    global $wp_filter;
    if( empty( $hook ) || !isset( $wp_filter[$hook] ) )
        return;

    print '<pre>';
    print_r( $wp_filter[$hook] );
    print '</pre>';
}

add_action('template_redirect','print_filters');

function print_filters() {
    print_r(print_filters_for('the_content'));die;
}

This gives me the filters, but I can not think of any comfortable way to change their priorities.

add_filter( 'the_content', 'my_content_filter_priority_reorder', 0 );

function my_content_filter_priority_reorder($the_content) {
    // reorder filter priorities
    return $the_content;
}

Has anybody already had this problem and knows how to possibly change this?

2 Answers 2

2

If you know the existing callback and priority you can just remove the filters and then add again at a different priority:

remove_filter( 'the_content', 'convert_smilies', 20 );
add_filter( 'the_content', 'convert_smilies', 30 );

remove_filter( 'the_content', 'capital_P_dangit', 11 );
add_filter( 'the_content', 'capital_P_dangit', 20 );
2
  • That seems basically the correct way to do it, congrats on 10K reputation 😎 Do you know a method to extract a filters registered plain names such you can proceed with reordering them?
    – Blackbam
    Jul 11, 2018 at 11:45
  • 1
    You'll need to print them out the way you have in your question. The tricky part is that hooked functions won't all just be a simple function name. Hooks are callables and can require a reference to other objects to remove. See this old question and answer on findind and removing hooks. Jul 12, 2018 at 2:00
0

If you try to change the priority of the plain function, using remove_filter() => add_filter() pattern is okay. But if you try to change it for method callback, it might be a pain since you need to somehow get an object of this method. And in a lot of cases, it's impossible.

I mean cases when the filter is created this way:

add_filter( 'the_content', array( $this, 'change_content' ) );

For such cases, it's better to change it manually by updating the $wp_filter variable.

Here is a function for it:

  /**
   * Changes the filter priority.
   *
   * @param string $hook_name
   * @param string $function_name Either function or method name
   * @param int $new_priority
   *
   * @return bool If it's changed correctly or not.
   */
   function change_filter_priority( $hook_name, $function_name, $new_priority ) {
    global $wp_filter;

    if ( empty( $wp_filter[ $hook_name ] ) ) {
        return false;
    }

    $hook = $wp_filter[ $hook_name ];

    foreach ( $hook->callbacks as $priority => $callbacks ) {
        foreach ( $callbacks as $callback_id => $callback ) {
            $current_function = $callback['function'];
            if ( is_array( $current_function ) ) { // case it's a function in the class.
                $current_function = $current_function[1];
            }

            if ( $function_name === $current_function ) {
                if ( $new_priority != $priority ) {
                    $priority_existed = isset( $hook->callbacks[ $new_priority ] );
                    $hook->callbacks[ $new_priority ][ $callback_id ] = $hook->callbacks[ $priority ][ $callback_id ];
                    unset( $hook->callbacks[ $priority ][ $callback_id ] );
                    if ( ! $priority_existed ) {
                        ksort( $hook->callbacks, SORT_NUMERIC );
                    }

                    return true;
                }
            }
        }
    }

    return false;
}

Usage example:

class My_Class {
  public function __construct() {
    add_filter( 'the_content', array( $this, 'change_content' ), 10 );
  }

  public function change_content() {
    return 'Hello World!';
  }
}

new My_Class();

change_filter_priority( 'the_content', 'change_content', 11 );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.