2

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:

<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>

3 Answers 3

8
+100

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);
5
  • +1 for two reasons: A) finding the link and B) being faster by seconds :)
    – kaiser
    Commented Sep 5, 2012 at 15:04
  • You said, "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" — but that means, the first one is not a problem at all, right? (since like you said, that's the way to do it.)
    – its_me
    Commented Sep 5, 2012 at 15:35
  • Following what you said, I just tried this: pastebin.com/G472yUKX — but it doesn't seem to work either. Please let me know if I am doing it wrong. EDIT: I also tried this by the way: pastebin.com/3KHkTij2
    – its_me
    Commented Sep 6, 2012 at 2:46
  • And by the way, the reason why it's not working (I think) is because the filter post_gallery is meant only for posts (as the name suggests) and not for feeds.
    – its_me
    Commented Sep 6, 2012 at 2:49
  • Feeds contain posts, and yes the filter works in feeds too. And the code you posted works once you remove the is_feed( 'flipboard_feed' ) wrapper bit. I just tried it on a local install and got exactly what I expected to get. What are you expecting to get that you're not getting?
    – Otto
    Commented Sep 6, 2012 at 12:34
1

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.

6
  • How about doing it like this? pastebin.com/JjEGqP4S
    – its_me
    Commented Sep 5, 2012 at 15:34
  • You don't need to wrap the whole function into the conditional, but yes, that should work.
    – kaiser
    Commented Sep 5, 2012 at 15:37
  • I was told that it's better, please see this: stackoverflow.com/q/12246331/1071413
    – its_me
    Commented Sep 5, 2012 at 15:40
  • I normally split between global functions and filters, as I use bootstrap wrappers (functions that sum all the stuff together and then go into the after_setup_theme hook), so never use this. You can also intercept inside the function, as you can see in my answer ↑ above. That's more a matter of taste, as WP already has ~2.5k function definitions. :)
    – kaiser
    Commented Sep 5, 2012 at 15:48
  • 1
    @Jashwant Lots of devs here have a local central repository. Naming functions like this (or docblocks) allows easy referencing to question IDs on WP.SE.
    – kaiser
    Commented Aug 29, 2016 at 12:46
1

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.

2
  • @Otto I was using the is_feed( 'flipboard_feed' ) conditional wrapper around the function because I was told that it would be better in terms of performance. Now, like you said, I removed the wrapper, but added it inside the function, and it worked! Please see the comments in the code in my answer ↑ above. Please let me know if there's any unnecessary code in the function. Thanks!
    – its_me
    Commented Sep 6, 2012 at 13:39
  • Ahh. Okay, the reason the first way didn't work was because of where you're including this code. The is_feed wrapper didn't know that it was a feed yet outside the function, because the main query had not been run. Putting it inside the function works because when post_gallery is applied, the query has already been run. You can put the is_feed check at the top of the function and wrap the entire contents of the function to get a minor speed improvement, just make sure to leave the final return ''; outside the is_feed check.
    – Otto
    Commented Sep 6, 2012 at 14:07

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.