Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm not sure how to word my question and I have been searching all day, to no avail.

I am looking for a method to create two versions of my RSS feeds, one with the full content and one with only the excerpt.

Mainly, I want to do this for the "Author" feeds. I would like two feeds created for each Author. One with the full content and one with the excerpt. If nothing else, I would like the author RSS feed to only have excerpts, but the main website RSS feed must ALWAYS be a full content feed.

The reason? The website in question is a sports website. I want to offer the RSS in full content for those who want it, but I also automatically post my own articles on my personal website (a few others do as well). When the article is posted to my own website, I want to only include the excerpt, with a link to the full original article.

I do not care the method used, whether code or plugin.

UPDATE

I have been working to try to get the methods described by Michael Ecklund and Ian Dunn to work. I have not been able to get either to work. Both methods still show the complete article in the RSS feed and not the excerpt.

I'm not sure if it makes a difference, but I just remembered I use the Advanced Excerpt plugin to manage the excerpts on my website. I have not tried disabling this plugin, as it controls the homepage, category pages, tags pages, author pages and more.

share|improve this question
    
Hi Travis, Michael and I have both submitted tested, working solutions and updated them after your last comments. Could you please try them again and accept one of them? –  Ian Dunn Aug 5 '12 at 16:09
    
Thanks. I know how the system works and the bounty does not end until tomorrow, then I have another 24 hours to award the bounty. I will do so at that time. Thanks again. –  Travis Pflanz Aug 5 '12 at 17:57
    
So, you're intentionally waiting until after the bounty expires? Is there something wrong with either of the current answers? –  Ian Dunn Aug 7 '12 at 0:40
    
@TravisPflanz Were any of these answers able to help you accomplish your task of creating multiple feeds, one with full content, and another with an excerpt? –  Michael Ecklund Oct 4 '12 at 20:19

3 Answers 3

up vote 2 down vote accepted

My approach would be to:

  1. On the Reading Options page, set the For each article in a feed, show... option to Full Text so that, by default, feeds will include the entire post.
  2. Pass a custom URL parameter to each individual feed when you want the excerpt instead of the full text. e.g., http://example.com/author/username/feed?format=excerpt. Make sure you don't use a reserved term for the parameter name.
  3. Hook into the feed creation process and modify the content based on whether or not the custom parameter is present in the current feed's URL.
  4. If it is present, override the feed's content to only display the excerpt instead of the full text.
  5. When you want the full content, just use the regular URL. e.g., http://example.com/author/username/feed.

Here's some code that does that, using format as the parameter name. You can use any parameter name you want, as long as you update each part of the code that references it. Put the code inside a functionality plugin.

function truncateFeedContent( $content )
{
    if( get_query_var( 'format' ) == 'excerpt' )
    {
        $content = get_the_excerpt();
        $content = apply_filters( 'the_excerpt_rss', $content );
    }

    return $content;
}
add_filter( 'the_content_feed', 'truncateFeedContent' );

function addFormatQueryVar( $queryVars )
{
    $queryVars[] = 'format';

    return $queryVars;
}
add_filter( 'query_vars', 'addFormatQueryVar' );

To avoid a conflict with the Advanced Excerpt plugin, add this code to the functionality plugin as well. It will disable Advanced Excerpt's functionality on feed URLs, but leave it in tact for all other pages.

function stopAdvancedExcerptOnFeeds()
{
    if( is_feed() )
        remove_filter( 'get_the_excerpt', array( 'AdvancedExcerpt', 'filter' ) );
}
add_action( 'pre_get_posts', 'stopAdvancedExcerptOnFeeds' );
share|improve this answer
    
I can't get it to work. UPDATE added to the question. –  Travis Pflanz Aug 1 '12 at 4:23
    
I just tested this and it's working for me, so I'm guessing that one of your plugins or your theme are conflicting with it. Try disabling the plugins one at a time to find the one that is conflicting, and switch to the TwentyEleven theme to test. Once you isolate the conflict, we can look at how to fix it. –  Ian Dunn Aug 1 '12 at 14:50
    
I added some code that will disable Advanced Excerpt from changing feeds, but will leave the homepage and other pages in tact. Can you test it out? –  Ian Dunn Aug 1 '12 at 16:36
    
This isn't working. It is showing the complete feed. –  Travis Pflanz Aug 7 '12 at 19:46
    
It works for me. Have you tried disabling the Advanced Excerpt plugin for a minute to see if that's causing the problem? –  Ian Dunn Aug 7 '12 at 20:00

You would access a short version with excerpt on the address: http://www.dicazine.com.br/author/admin/feed?version=short

The less the better:

add_filter('the_content','author_feed_version',10);
function author_feed_version($content) {
    if(is_feed()){
        if($_GET['version'] == 'version')
            $content = limit_words(strip_tags($content),100);
    }
    return $content;
} function limit_words($string, $word_limit){ $words = explode(" ",$string); return implode(" ",array_splice($words,0,$word_limit)); }

share|improve this answer
    
You have to change the default Feed to show "full content" on your options section within wp-admin. –  Adireto Aug 6 '12 at 19:49
    
Um, that's pretty much the answer I wrote, except you did several things wrong ;) Here are the big problems: 1) the_content_feed is the appropriate filter, not the_content; 2) the_excerpt_rss should be applied to the content to make it suitable for the RSS format; 3) get_query_var() is considered the best practice for accessing URL parameters, instead of using $_GET directly; 4) Removing the conflicting plugin's filter on feed requests is much more elegant solution than writing a custom excerpt-generating function. –  Ian Dunn Aug 7 '12 at 1:00
    
This method still shows the full content. –  Travis Pflanz Aug 7 '12 at 19:52

There is actually quite an easy approach to accomplish this particular task.

METHOD ONE

Follow these steps to easily create a custom RSS feed in your WordPress website:

  1. Create a custom page template. Name it *your_custom_feed.php*
  2. Paste the code in the first code block into *your_custom_feed.php*
  3. Upload *your_custom_feed.php* to your currently active WordPress theme directory.
  4. Paste the second code block into your currently active WordPress functions.php file.
  5. Deactivate and reactivate your theme for it to take effect.

You can now access your Custom Feed at: your-domain.com/custom-feed/user-slug/

Credits go to Joost de Valk for publishing an excellent article. However, I slightly modified his code from the original article.

<?php
/*
Template Name: Custom Feed
*/

//----------------------------------------
//  CONFIGURE THIS
//----------------------------------------
$contentType = 'excerpt';// Enter 'excerpt' or 'content'
$numposts = 5;// Enter number of posts to display for each author


//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//  NO MORE CONFIGURATION NECESSARY
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

function custom_rss_date( $timestamp = null ) {
    $timestamp = ($timestamp==null) ? time() : $timestamp;
    echo date(DATE_RSS, $timestamp);
}

function custom_rss_text_limit($string, $length, $replacer = '...') { 
    $string = strip_tags($string);
    if(strlen($string) > $length)
    return (preg_match('/^(.*)\W.*$/', substr($string, 0, $length+1), $matches) ? $matches[1] : substr($string, 0, $length)) . $replacer;   
    return $string; 
}

function custom_rss_post_id() {
    global $wp_query;
    $thePostID = $wp_query->post->ID;
    return $thePostID;
}

$thePage = get_page(custom_rss_post_id());

$posts = query_posts('showposts='.$numposts.'&author_name='.$thePage->post_name);

$lastpost = $numposts - 1;

header('Content-Type: ' . feed_content_type('rss-http') . '; charset=' . get_option('blog_charset'), true);
echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>';
?>
<rss version="2.0"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
    xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
    <?php do_action('rss2_ns'); ?>
>
    <channel>
        <title>
        <?php bloginfo_rss('name'); wp_title_rss(); ?>
        </title>
        <atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
        <link>
        <?php bloginfo_rss('url') ?>
        </link>
        <description>
            <?php bloginfo_rss("description") ?>
        </description>
        <lastBuildDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_lastpostmodified('GMT'), false); ?></lastBuildDate>
        <language>
            <?php bloginfo_rss( 'language' ); ?>
        </language>
        <sy:updatePeriod><?php echo apply_filters( 'rss_update_period', 'hourly' ); ?></sy:updatePeriod>
        <sy:updateFrequency><?php echo apply_filters( 'rss_update_frequency', '1' ); ?></sy:updateFrequency>
        <?php foreach ($posts as $post) { ?>
        <item>
        <title><?php echo get_the_title($post->ID); ?></title>
        <link>
        <?php echo get_permalink($post->ID); ?>
        </link>
        <description>
       <?php 
            if(!empty($contentType) && $contentType == 'excerpt'){
                echo '<![CDATA['.custom_rss_text_limit($post->post_content, 500).']]>';
            } elseif(!empty($contentType) && $contentType == 'content'){
                echo '<![CDATA['.apply_filters('the_content', $post->post_content).']]>';
            }         
       ?>
       </description>
        <pubDate>
            <?php custom_rss_date( strtotime($post->post_date_gmt) ); ?>
        </pubDate>
        <guid><?php echo get_permalink($post->ID); ?></guid>
        </item>
        <?php } ?>
    </channel>
</rss>

You could place this in your current active WordPress theme functions.php file:

// Tell the hourly cronjob what operation it needs to perform.
add_action('update_custom_user_feeds', 'create_custom_user_feeds');

// Create a cronjob to update our custom feeds hourly.
function cron_custom_user_feeds(){
    if(!wp_next_scheduled('update_custom_user_feeds')){
        wp_schedule_event(current_time('timestamp'), 'hourly', 'update_custom_user_feeds');
    }
}
add_action('init', 'cron_custom_user_feeds');

// Delete our hourly cronjob when the theme is changed.
function clear_custom_user_feeds(){
    wp_clear_scheduled_hook('update_custom_user_feeds');
}
add_action('switch_theme', 'clear_custom_user_feeds');

// Generate the custom user feeds
function create_custom_user_feeds(){
    // "Custom Feed" is the main feed page.
    $feedParent = get_page_by_title('Custom Feed', 'OBJECT', 'page');
    if(!$feedParent){
        $pageData = array(
            'post_title' => 'Custom Feed',
            'post_name' => 'custom-feed',
            'post_status' => 'publish',
            'post_type' => 'page'
        );
        // Create custom user feed.
        $parentID = wp_insert_post($pageData);
    } else{
        $parentID = $feedParent->ID;    
    }
    $wpUsers = get_users();
    for($i = 0; $i < count($wpUsers); $i++){
        // Check if the custom user feed already exists.
        $userFeed = get_page_by_title($wpUsers[$i]->user_nicename, 'OBJECT', 'page');
        if(!$userFeed){
            $pageData = array(
                'post_title' => $wpUsers[$i]->user_nicename,
                'post_name' => $wpUsers[$i]->user_nicename,
                'post_status' => 'publish',
                'post_type' => 'page',
                'post_parent' => $parentID
            );
            // Create custom user feed.
            $insertPage = wp_insert_post($pageData);
            if($insertPage){
                // Assign our custom feed template.
                update_post_meta($insertPage, '_wp_page_template', 'your_custom_feed.php');
            }
        }
    }
    // Attempt to flush caches
    wp_cache_flush();
    if(function_exists('w3tc_objectcache_flush')){
        w3tc_objectcache_flush();
    }
    if(function_exists('w3tc_pgcache_flush')){
        w3tc_pgcache_flush();
    }
    if(function_exists('w3tc_minify_flush')){
        w3tc_minify_flush();
    }
    if(function_exists('w3tc_dbcache_flush')){
        w3tc_dbcache_flush();
    }
}

Now, I'm not saying this solution is practical, but it works.

Alternatively, you can possibly make some usage from this class I made which uses add_feed();

METHOD TWO

Directions for using this class method within your theme. (Note: This class could easily be integrated into a plugin.)

  1. Create a sub-directory in your currently active WordPress theme. Name it: "inc". (Directory structure should look like: ./wp-content/themes/*your_theme*/inc/)
  2. Create a PHP file and place the code block below (Third/last code block in this answer) in the file. Save it as custom-feeds.php
  3. Upload custom-feeds.php into your "inc" directory.
  4. May need to deactivate and reactivate your theme for it to take effect.

You can now access your Custom Feed at: your-domain.com/feed/custom-user-slug/

Note: you can change the prefix "custom-" to anything you want. Just configure the settings in the class constructor.

<?php
if(!class_exists('custom_feeds')){
    class custom_feeds{

        private $feed_settings;
        private $feed_data;

        public function __construct(){

            // Configure the Feed
            $this->feed_settings['number_posts'] = -1;// # of feed items, -1 means all posts
            $this->feed_settings['content_type'] = 'excerpt';// Excerpt or Content
            $this->feed_settings['excerpt_length'] = 500;// if excerpt, display how many characters?
            $this->feed_settings['offset_posts'] = 0;// Skip # of recent posts
            $this->feed_settings['custom_prefix'] = 'custom';// domain.com/feed/{prefix}-feed-name/
            $this->feed_settings['signature_link'] = false;// add link back to your site after the content.

            // Specify what type of feed you want to create.
            $this->prepare_feed('user');// All users, nice names
            //$this->prepare_feed('user', 'some-user');// Specific user's nice name

            // Prepare the feed
            add_action('init', array($this, 'setup_custom_feeds')); 
        }

        public function setup_custom_feeds(){
            global $wp_rewrite;
            // Add a feed for each type.
            foreach($this->feed_data as $type => $posts){
                add_feed($this->feed_settings['custom_prefix'].'-'.$type, call_user_func_array(array($this, 'display_feed'), array($type, $posts)));
            }   
            // Flush rewrite rules.
            $wp_rewrite->flush_rules();
            // Attempt to flush caches.
            $this->flush_all_caches();          
        }

        public function prepare_feed($type, $nice_name=NULL){ 
            if($type == 'user'){
                if(!is_null($nice_name)){
                    // Get specified user.
                    $data[] = get_user_by('slug', $nice_name);
                } else{
                    // Get all users.
                    $data = get_users();
                }
                // Find posts for our request.
                for($i = 0; $i < count($data); $i++){
                    $userPosts = new WP_Query(array('posts_per_page' => intval($this->feed_settings['number_posts']), 'author_name' => $data[$i]->user_nicename, 'offset' => intval($this->feed_settings['offset_posts'])));
                    wp_reset_postdata();
                    if(!empty($userPosts->posts)){
                        $theData[$data[$i]->user_nicename] = $userPosts->posts;
                    }
                }
            } 
            $this->feed_data = $theData;
        }

        public function display_feed($type, $posts){
            $current_feed = explode('/feed/', $this->self_link());
            if($this->feed_settings['custom_prefix'].'-'.$type == $current_feed[1]){
                header('Content-Type: '.feed_content_type('rss-http').'; charset='.get_option('blog_charset'), true);
                echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>'.PHP_EOL;
                echo '<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"';
                do_action('rss2_ns');
                echo '>'.PHP_EOL;
                echo '<channel>'.PHP_EOL;
                echo '<title>';
                bloginfo_rss('name'); 
                wp_title_rss();
                echo '</title>'.PHP_EOL;
                echo '<atom:link href="'.$this->self_link().'" rel="self" type="application/rss+xml" />'.PHP_EOL;
                echo '<link>'.get_bloginfo_rss('url').'</link>'.PHP_EOL;
                echo '<description>'.get_bloginfo_rss('description').'</description>'.PHP_EOL;
                echo '<lastBuildDate>'.mysql2date('D, d M Y H:i:s +0000', get_lastpostmodified('GMT'), false).'</lastBuildDate>'.PHP_EOL;
                echo '<language>'.get_bloginfo_rss('language').'</language>'.PHP_EOL;
                echo '<sy:updatePeriod>'.apply_filters('rss_update_period', 'hourly').'</sy:updatePeriod>'.PHP_EOL;
                echo '<sy:updateFrequency>'.apply_filters('rss_update_frequency', '1').'></sy:updateFrequency>'.PHP_EOL;
                // Begin displaying posts in our feed.
                foreach($posts as $post){
                    echo '<item>'.PHP_EOL;
                    echo '<title>'.$post->post_title.'</title>'.PHP_EOL;
                    echo '<link>'.get_permalink($post->ID).'</link>'.PHP_EOL;
                    echo '<description>'.PHP_EOL;
                    if($this->feed_settings['signature_link']){
                        $feed_signature = '<h3>Original Post:<br /> <a title="'.$post->post_title.'" href="'.get_permalink($post->ID).'">'.$post->post_title.'</a></h3>';
                    } else{
                        $feed_signature = '';
                    }
                    if(!empty($this->feed_settings['content_type']) && $this->feed_settings['content_type'] == 'excerpt'){
                        echo '<![CDATA['.$this->custom_rss_text_limit($post->post_content, intval($this->feed_settings['excerpt_length'])).$feed_signature.']]>'.PHP_EOL;

                    } elseif(!empty($this->feed_settings['content_type']) && $this->feed_settings['content_type'] == 'content'){
                        echo '<![CDATA['.apply_filters('the_content', $post->post_content).$feed_signature.']]>'.PHP_EOL;
                    }         
                    echo '</description>'.PHP_EOL;
                    echo '<pubDate>'.$this->custom_rss_date(strtotime($post->post_date_gmt)).'</pubDate>'.PHP_EOL;
                    echo '<guid>'.$post->guid.'</guid>'.PHP_EOL;
                    echo '</item>'.PHP_EOL;
                }
                echo '</channel>'.PHP_EOL;
                echo '</rss>'.PHP_EOL;
            }
        }

        private function custom_rss_date($timestamp = null){
            $timestamp = ($timestamp==null) ? time() : $timestamp;
            return date(DATE_RSS, $timestamp);
        }

        private function custom_rss_text_limit($string, $length, $replacer = '...'){ 
            $string = strip_tags($string);
            if(strlen($string) > $length)
                return (preg_match('/^(.*)\W.*$/', substr($string, 0, $length+1), $matches) ? $matches[1] : substr($string, 0, $length)) . $replacer;   
            return $string; 
        }

        private function self_link(){
            $host = @parse_url(home_url());
            $host = $host['host'];
            $return = esc_url(
                'http'
                . ( (isset($_SERVER['https']) && $_SERVER['https'] == 'on') ? 's' : '' ) . '://'
                . $host
                . stripslashes($_SERVER['REQUEST_URI'])
            );
            return $return;
        }

        private function flush_all_caches(){
            wp_cache_flush();
            if(function_exists('w3tc_objectcache_flush')){
               w3tc_objectcache_flush();
            }
            if(function_exists('w3tc_pgcache_flush')){
               w3tc_pgcache_flush();
            }
            if(function_exists('w3tc_minify_flush')){
               w3tc_minify_flush();
            }
            if(function_exists('w3tc_dbcache_flush')){
               w3tc_dbcache_flush();
            }
        }

    }// END custom_feeds class.

    // Instantiate the class.
    $custom_feeds = new custom_feeds();

}// END custom_feeds class exists.
?>

Note: I don't know how well it would perform on large scale websites. Although, the way I have setup this class, allows for easy manipulation. You could use this same class for generating feeds of a custom post type, or custom taxonomy as well. My Custom Feeds class has been tested on WordPress 3.4.1 and works correctly.

If you wanted to use it the way I have it currently setup, all you would need to do is configure the feed settings in the class constructor.


share|improve this answer
    
Thanks for this. I suppose I could use this method if all else fails. I am looking more for an automatic creation of RSS feeds for each author that includes a full format and an excerpt format. I will update the question to make it more clear. –  Travis Pflanz Jul 31 '12 at 0:37
2  
Ideally, this should be isolated into a plugin, since it doesn't have anything to do with the theme. wpcandy.com/teaches/how-to-create-a-functionality-plugin –  Ian Dunn Jul 31 '12 at 0:37
    
@TravisPflanz I added an 'automatic' solution. Not exactly the most IDEAL solution, but it gets the job done. –  Michael Ecklund Jul 31 '12 at 0:38
    
I can't get it to work. UPDATE added to the question. –  Travis Pflanz Aug 1 '12 at 4:22
    
@TravisPflanz I updated my previous examples using pages and page templates. I also added a PHP class that makes use of the add_feed(); hook. –  Michael Ecklund Aug 7 '12 at 3:12

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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