WordPress gallery ‘post_gallery’ filter doesn’t work with feeds?

We can use the post_gallery filter to modify/replace the default WordPress gallery template (AKA output code) to suit our needs. But this doesn’t seem to affect the markup in RSS feeds.

No matter what I do, the markup for gallery images in my RSS feed is simply like this:

Read More
<a href="#1">
   <img src="#2" />
</a>

<a href="#3">
   <img src="#4" />
</a>

So, is there a way (something like a filter, function, etc.) to modify the default WordPress gallery markup in RSS feeds?

What I’ve tried

For a start (just to check), all I had to do was comment out this bit in wp-includes/media.php core file:

if ( is_feed() ) {
    $output = "n";
    foreach ( $attachments as $att_id => $attachment )
        $output .= wp_get_attachment_link($att_id, $size, true) . "n";
    return $output;
}

And it kinda worked. Now the gallery markup in my RSS feeds is the same as what you see on the front-end of my site (i.e. in posts).

But when I do the same using the post_gallery filter, it doesn’t work—the markup in RSS feeds is unaffected. I have no idea why!

On the whole, this is the code (related to post_gallery) in my functions.php. Am I doing something wrong?


Since I am frequently asked what I am trying to do—in this case, I want to modify the markup for WordPress galleries in RSS feeds to look like this:

<section class="fl-slideshow">
  <figure>
    <img src="#2" width="1200" height="900">
    <figcaption>Puppies are cute</figcaption>
  </figure>
  <figure>
    <img src="#4" width="900" height="1200">
    <figcaption>Kittens are too</figcaption>
  </figure>
</section>

Related posts

Leave a Reply

3 comments

  1. Without knowing what your post_gallery filter function does, there’s no way to give a proper answer.

    However, if you are using the post_gallery filter, and returning new markup, then yes, it will be used in feeds too. The code you mention commenting out happens after the post_gallery filter, and won’t get executed at all if you’re returning a different output from that filter, as per the following code:

    // Allow plugins/themes to override the default gallery template.
    $output = apply_filters('post_gallery', '', $attr);
    if ( $output != '' )
        return $output;
    

    If the post_gallery filter returns anything at all, then that is what is output, period. The if is_feed code you mention will not apply since it never makes it that far.

    Examine your post_gallery hooked function. The problem probably lies there somewhere.

    Edit: Found the link to your code at the bottom of your post. It was sorta hidden.

    You have two major problems. Firstly, you had the if is_feed code inside your own function, and commenting it out was indeed the correct thing to do. Your function is supposed to produce your output. If you’re producing different output, then you need to change that, obviously.

    Second, this is incorrect:

    add_shortcode('post_gallery', 'flipboard_gallery_shortcode', 10, 2);
    

    The post_gallery hook is a filter hook, not a shortcode. Change that line to this:

    add_filter('post_gallery', 'flipboard_gallery_shortcode', 10, 2);
    
  2. It should be as simple as this…

    function wpse63980_gallery_shortcode( $html, $attr )
    {
        // We don't want to intercept non feed galleries
        if ( ! is_feed() )
            return '';
    
        extract( shortcode_atts( array(
            'order'      => 'ASC',
            'orderby'    => 'menu_order ID',
            'id'         => $post->ID,
            'itemtag'    => 'dl',
            'icontag'    => 'dt',
            'captiontag' => 'dd',
            'columns'    => 3,
            'size'       => 'thumbnail',
            'include'    => '',
            'exclude'    => ''
        ), $attr ) );
    
        // get_posts(), get_attachments(), etc. here
    
        return $html;
    }
    add_filter( 'post_gallery', 'wpse63980_gallery_shortcode', 99999, 2 );
    

    …as the whole gallery shortcode gets bypassed, when the second argument isn’t ''. As you can see, I added a pretty high priority for the filter, just in case other plugins are interferring.

  3. Based on Otto’s suggestions, I modified my function as such (see below), and it worked!

    // Custom Gallery Code For Flipboard/Pulse/Google Currents Feeds
    add_filter('post_gallery', 'flipboard_gallery_shortcode', 10, 2);
    function flipboard_gallery_shortcode($output, $attr) {
        global $post;
    
        static $instance = 0;
        $instance++;
    
        // We're trusting author input, so let's at least make sure it looks like a valid orderby statement
        if ( isset( $attr['orderby'] ) ) {
            $attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
            if ( !$attr['orderby'] )
                unset( $attr['orderby'] );
        }
    
        extract(shortcode_atts(array(
            'order'      => 'ASC',
            'orderby'    => 'menu_order ID',
            'id'         => $post->ID,
            'itemtag'    => 'dl',
            'icontag'    => 'dt',
            'captiontag' => 'dd',
            'columns'    => 3,
            'size'       => 'full',
            'include'    => '',
            'exclude'    => ''
        ), $attr));
    
        $id = intval($id);
        if ( 'RAND' == $order )
            $orderby = 'none';
    
        if ( !empty($include) ) {
            $include = preg_replace( '/[^0-9,]+/', '', $include );
            $_attachments = get_posts( array('include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
    
            $attachments = array();
            foreach ( $_attachments as $key => $val ) {
                $attachments[$val->ID] = $_attachments[$key];
            }
        } elseif ( !empty($exclude) ) {
            $exclude = preg_replace( '/[^0-9,]+/', '', $exclude );
            $attachments = get_children( array('post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
        } else {
            $attachments = get_children( array('post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
        }
    
        if ( empty($attachments) )
            return '';
    
        // Modifying for a different gallery output ONLY in my custom feed
        if ( is_feed( 'flipboard_feed' ) ) {
            $output = '<section class="fl-slideshow">';
            foreach ( $attachments as $att_id => $attachment )
                $output .= '<figure>' . wp_get_attachment_image($att_id, 'full') . '<figcaption>' . wptexturize($attachment->post_excerpt) . '</figcaption></figure>';
            $output .= '</section>';
            return $output;
        }
    
        // Let the original function return the default output for other feeds and posts
        return '';
    }
    

    EDIT: For a minor speed improvement, the same code above can be rewritten as (thanks to Otto!):

    // Custom Gallery Code For Flipboard/Pulse/Google Currents Feeds
    add_filter('post_gallery', 'flipboard_gallery_shortcode', 10, 2);
    function flipboard_gallery_shortcode($output, $attr) {
    
        // Modifying for a different gallery output ONLY in my custom feed
        if ( is_feed( 'flipboard_feed' ) ) {
            global $post;
    
            static $instance = 0;
            $instance++;
    
            // We're trusting author input, so let's at least make sure it looks like a valid orderby statement
            if ( isset( $attr['orderby'] ) ) {
                $attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
                if ( !$attr['orderby'] )
                    unset( $attr['orderby'] );
            }
    
            extract(shortcode_atts(array(
                'order'      => 'ASC',
                'orderby'    => 'menu_order ID',
                'id'         => $post->ID,
                'itemtag'    => 'dl',
                'icontag'    => 'dt',
                'captiontag' => 'dd',
                'columns'    => 3,
                'size'       => 'thumbnail',
                'include'    => '',
                'exclude'    => ''
            ), $attr));
    
            $id = intval($id);
            if ( 'RAND' == $order )
                $orderby = 'none';
    
            if ( !empty($include) ) {
                $include = preg_replace( '/[^0-9,]+/', '', $include );
                $_attachments = get_posts( array('include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
    
                $attachments = array();
                foreach ( $_attachments as $key => $val ) {
                    $attachments[$val->ID] = $_attachments[$key];
                }
            } elseif ( !empty($exclude) ) {
                $exclude = preg_replace( '/[^0-9,]+/', '', $exclude );
                $attachments = get_children( array('post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
            } else {
                $attachments = get_children( array('post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
            }
    
            if ( empty($attachments) )
                return '';
    
                // Essentially these are only changes I've made
                $output = '<section class="fl-slideshow">';
                foreach ( $attachments as $att_id => $attachment )
                    $output .= '<figure>' . wp_get_attachment_image($att_id, 'full') . '<figcaption>' . wptexturize($attachment->post_excerpt) . '</figcaption></figure>';
                    $output .= '</section>';
                return $output;
        }
    
        // Let the original function return the default output for other feeds and posts
        return '';
    
    }
    

    PS: Anyone using Jetpack Carousel need not worry. The function above only modifies the output only in the custom feed, and therefore doesn’t mess with any frontend plugins as far as I can see.