So I have a plugin that appends or prepends an enhanced author biography to the content of a page/post/custom post type.

It does this by hooking to either the_content or the_excerpt and appending/prepending content according to the plugin’s configuration.

I’ve started getting support queries where the author biography is appearing in the sidebar of a site via a widget, for example via the Category Posts widget. The widget is using the_excerpt() within a custom query Loop, to pull posts according to a configured category and show the post excerpt within the context of the sidebar.

As a direct effect of this, my plugin’s the_excerpt filter hook is being called. What I’d like to do is be able to detect whether my filter hook is being invoked within the context of the sidebar or a widget and conditionally decide whether to append my plugin’s content to the post content passed to the filter hook. The pseudo-code would look something like this …

add_filter ('the_excerpt', array ($this, 'insert_biography_box'));
function insert_biography_box ($content) {
    if (in_sidebar ()) {
        return $content;
    }

    // do code stuff to append/prepend biography content
    return $content;
}

… but after a lot of searching through the WordPress core source, forums and here it doesn’t look like a function along the lines of is_sidebar or is_widget (or some other variation on the name) exists.

Is it even possible to determine whether a filter hook function is being called within the context of the sidebar or within a widget?

EDIT: Based on @toscho’s suggestion to use is_main_query, I modified my filter hook for the_content and the_excerpt to look like this …

add_filter ('the_excerpt', array ($this, 'insert_biography_box'));
add_filter ('the_content', array ($this, 'insert_biography_box'));

function insert_biography_box ($content) {
    error_log ('insert_biography_box: current filter=" . current_filter ());
    if (!is_main_query ()) {
        error_log ("Not main query, baling');
        return $content;
    }

    // do code stuff to append/prepend biography content
    $biography = 'some-magic-function-return-value';
    return $content . $biography;
}

Based on this, I was expecting to see the message Not main query, baling in my PHP error log when the Category Posts widget is calling the_excerpt() in the context of the sidebar. But I don’t.

For context, the Category Posts widget is querying for posts within the widget’s widget method like this (severely paraphrased for clarity) …

$cat_posts = new WP_Query (...);
while ($cat_posts->have_posts ()) {
    $cat_posts->the_post ();
    the_excerpt ();
}

… am I missing something (very likely) or am I just not getting the context within which I’m using is_main_query() (just as very likely) … ?

2 s
2

On a parallel thread over on the WordPress hacks forum, someone suggested using in_the_loop() and that works some of the time, with some plugins that use either the_content and/or the_excerpt, but not all of the time with all the plugins I’ve been testing against.

Likewise, I’ve now done further testing using is_main_query() and that works some of the time, with some plugins but not with all of them.

But the magic combination of testing against is_main_query() and in_the_loop() seems to do the trick.

So the (pseudo) code now looks something like this …

add_filter ('the_excerpt', array ($this, 'insert_biography_box'));
add_filter ('the_content', array ($this, 'insert_biography_box'));

function insert_biography_box ($content) {
    if (!in_the_loop () || !is_main_query ()) {
        return $content;
    }

    // do code stuff to append/prepend biography content
    $biography = 'some-magic-function-return-value';
    return $content . $biography;
}

.. which now gives me precisely the behaviour I wanted, against as many plugins that use the content or excerpt filters in the sidebar and/or footer widgets.

Leave a Reply

Your email address will not be published. Required fields are marked *