Question

For a plugin, I need to build my own very early post content and comment content filter. Post content/text changing works, i.e. the modifications end up in the client's browser. But my comment content/text modifications somehow are not persistent, i.e. the client receives the original comment text.

The point in time I "hook in" is defined by the template_redirect hook. I then execute something like this:

global $wp_query;

// Iterate over all posts in this query.
foreach ($wp_query->posts as $post) {
    // Edit post text
    $post->post_content = "foo"; // works: ends up at the client

    // Iterate over all approved comments belonging to this post
    $comments = get_approved_comments($post->ID);
    foreach ($comments as $comment) {
        // Edit comment text
        $comment->comment_content = "bar"; // this one is lost
        } 
    }

As indicated via the source comments above, $post->post_content = "foo"; has effect in this context, but $comment->comment_content = "bar"; doesn't.

To track this down at least a bit more, I applied a debug filter to the post content and to the comment content:

add_filter('the_content', 'var_dump');
add_filter('comment_text', 'var_dump');

After the content modification routine above, these filters print "foo" in case of post content, but the comment content is printed unchanged (the original content is printed).

Hence, $comment->comment_content = "bar"; seems to be a local modification, while $post->post_content = "foo"; works as desired: globally.

Or is the database even queried two times for comments so that my modification somehow gets overwritten at some point?

I've tried to work with $wp_query->comments, too. But this variable is NULL at the point in time I want and need to hook in.

The final and primary question is:

In my loop above, what do I have to do, to modify the comment content persistently?

FYI: I am using WordPress 3.0.1

Was it helpful?

Solution

The function that includes the comments template also (re)loads the comments. This means that whatever you do before that point, if you don't save it to the database it will not be used.

There is no way to prevent this SQL query from happening, but you can override the results by hooking into the comments_array filter. I would save your modifications in an array keyed by the comment ID, so you can do quick lookups and replace contents if needed.

$wpse4522_comments = array();

// Somewhere in your template_redirect (why not wp_head?) hook:
foreach ($wp_query->posts as $post) {
    // Edit post text
    $post->post_content = "foo"; // works: ends up at the client

    // Iterate over all approved comments belonging to this post
    $comments = get_approved_comments($post->ID);
    foreach ($comments as $comment) {
        // Edit comment text
        $GLOBALS['wpse4522_comments'][$comment->comment_ID] = 'bar';
    } 
}

// And this loads the content back into the array from comments_template()
add_filter( 'comments_array', 'wpse4522_set_comments_content' );
function wpse5422_set_comments_content( $comments, $post_id )
{
    global $wpse4522_comments;
    foreach ( $comments as &$comment_data ) {
        if ( array_key_exists( $comment_data->comment_ID, $wpse4522_comments ) ) {
            $comment_data->comment_content = $wpse4522_comments[$comment_data->comment_ID];
        }
    }
    return $comments;
}

OTHER TIPS

Without knowing much more about what you're tyring to accomplish, there are a few possible solutions.

One is to continue doing what you're currently doing to, but to also add a filter to 'comment_text' to alter the comment output. The downside with this is that you're querying the comments multiple times.

Another option is to start an output buffer on 'template_redirect' and print a placeholder on the 'wp_head' hook to mark a spot in the header. Then use the 'comment_text' and 'the_content' filters to alter the output and check for whatever markers you're looking for. Then, in the output buffer callback, have it replace that marker you put in the header with whatever css you need to add. The only issue with this solution is that the buffer size set on the server may not be enough depending on how much content you have in a single page or how small the buffer is.

Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top