Time for action – Roll into the blogroll

We want to hook up into the blogroll filter and modify the links on the fly, fetching the latest post from the RSS feed and replacing it into the blogroll.

  1. Create a new folder for the plugin, called live-blogroll. We will have more than one file in our final plugin, so that we can keep everything neatly in one folder.
  2. Create a new file called wp-live-blogroll.php. This will be our main file and should contain the plugin information. We can also re-use our version check code:
    <?php
            
    /*
    Plugin Name: Live Blogroll
    Version: 0.1
    Description: Shows a number of 'recent posts' for each link in your Blogroll using Ajax.
    Author: Vladimir Prelovac
    Author URI: http://www.prelovac.com/vladimir
    Plugin URI: http://www.prelovac.com/vladimir/wordpress-plugins/live-blogroll
    */
            
    /* Version check */
    global $wp_version;
            
    $exit_msg='Live BlogRoll requires WordPress 2.3 or newer. <a href="http://codex.wordpress.org/Upgrading_WordPress">Please update!</a>';
            
    if (version_compare($wp_version,"2.3","<"))
    {
        exit ($exit_msg);
    }
            
            
    ?>
    
  3. We will also define a plugin path that we will use later:
    $wp_live_blogroll_plugin_url = trailingslashitWP_PLUGIN_DIR.'/'. dirname( plugin_basename(__FILE__) );
  4. Include the rss.php file, which contains functions, which are needed for parsing RSS feeds:
    require_once(ABSPATH . WPINC . '/rss.php');
    
  5. Next, we want to hook to get_bookmarks in order to change the blogroll display:
    add_filter('get_bookmarks', WPLiveRoll_GetBookmarksFilter);
    
    
  6. Now, let's add the filter function:
    function WPLiveRoll_GetBookmarksFilter($items)
    {
        // do nothing if in the admin menu
      if (is_admin()) {
        return $items;
      }
    
        
      // parse all blogroll items
      foreach($items as $item)
      {
        // check if the link is public
        if ($item->link_visible=='Y'){
          $link_url=trailingslashit($item->link_url);
        
          // simple feed guessing
          if (strstr($link_url,"blogspot")){
            // blogspot blog
            $feed_url=$link_url."feeds/posts/default/";
          } else if (strstr($link_url,"typepad")){
            // typepad blog
            $feed_url=$link_url."atom.xml";
          } else {
            // own domain or wordpress blog
            $feed_url=$link_url."feed/"; 
          }
            
         // use WordPress to fetch the RSS feed
         $feedfile = fetch_rss($feed_url);
        
         // check if we got valid response
         if (is_array($feedfile->items )&& !empty($feedfile->items ) ){
           // this is the last post
           $feeditem=$feedfile->items[0];
           // replace name and url with post link and title
           $item->link_url=$feeditem['link'];
           $item->link_name=$feeditem['title'];
         }
       }
      }
      // return the items back
      return $items;
    }
  7. Upload your whole plugin folder live-blogroll to the wp-content/plugins folder on your server.
  8. Activate the plugin and check your blogroll. The new blogroll is shown with a fresh new look which displays all the latest posts.

What just happened?

When the page is loaded, the get_bookmarks filter is executed:

add_filter('get_bookmarks', WPLiveRoll_GetBookmarksFilter);

At this point, our filter function WPLiveRoll_GetBookmarksFilter() takes care of the blogroll processing:

function WPLiveRoll_GetBookmarksFilter($items)
{
    // do nothing if in the admin menu
 
 if (is_admin())
     {
        return $items;
     }

Since the get_bookmarks filter is activated on the administration pages (where we do not want to do anything), we are making a check by using the conditional tag is_admin. It will return true if the user is currently viewing the admin panel pages, in which case, we simply return the unprocessed items.

Next, we loop through all the links in the blogroll, and check to see if they are enabled:

    // parse all blogroll items
    foreach($items as $item)
    {
         // check if the link is public
 if ($item->link_visible=='Y') 
          {

Now, when we have a published link we need to find the RSS feed from the site.

A detailed approach would involve loading the content of the page and processing it for the <link> tags and searching for one of the possible RSS formats.

For the purpose of this example, we will keep it simple by guessing the feed based on the site name, which will work for most blogs (you can develop a more comprehensive RSS discovery function as an exercise):

  $link_url=trailingslashit($item->link_url);

  // simple feed guessing
  if (strstr($link_url,"blogspot.com"))
  {
    // blogspot blog
    $feed_url=$link_url."feeds/posts/default/";
  }
  elseif (strstr($link_url,"typepad.com"))
  {
    // typepad blog
    $feed_url=$link_url."atom.xml";
  }
  else
  {
    // own domain or wordpress blog
    $feed_url=$link_url."feed/";
  }

Now that we have the feed URL, we can fetch the contents of the feed using the WordPress function fetch_rss():

  // use WordPress to fetch the RSS feed
  $feedfile = fetch_rss($feed_url);

The result should be an array of objects; each one representing information about a single post sorted by date.

First, we check to see if we get a valid response,

  // check if we got valid response
  if (is_array($feedfile->items )
  && !empty($feedfile->items ) )
  {

And then replace the blogroll URL and name with latest post's URL and title:

    // this is the last post
    $feeditem=$feedfile->items[0];
    // replace name and url with post link and title
      $item->link_url=$feeditem['link'];
      $item->link_name=$feeditem['title'];
    }
   }
  }
  // return the items back
  return $items;
}

In the end we return the items. Note that if we do not get a valid response, the original link will stay intact. It is a very simple automatic fallback in case we cannot parse the feed for some reason.

Our code needs RSS functionality, which comes through the rss.php file of the WordPress installation:

require_once(ABSPATH . WPINC . '/rss.php');

We included it using two WordPress defines, ABSPATH and WPINC, which contain the absolute path to the WordPress installation and the path to the WordPress includes folder.

Note

Quick reference

fetch_rss(): Parses RSS feed, and requires rss.php file to be included.

is_admin(): Checks to see if the current page is an administration page.

ABSPATH: A variable which contains the absolute path to WordPress installation.

WPINC: A variable which contains the name of the includes folder.

get_bookmarks: A filter used to parse blogroll items.

WP_PLUGIN_URL: Contains the URL to the WordPress plugin folder

RSS Feed Processing

WordPress provides a very easy to use function, fetch_rss(), to process the RSS feeds. The function relies internally on RSS feed library that comes included with WordPress, and takes care of the all the related work.

The function returns an array of feed items, which you can easily loop through to extract the information you need:

$feedfile = fetch_rss($feed_url);

foreach($feedfile->items as $item )
{

You may have noticed a pause when loading the blogroll for the first time. This is caused by the fetching of the feeds and is especially noticeable if you have many links in your blogroll.

This delay exists only for the first time when new feeds are parsed. The RSS library has a built-in mechanism for caching the feeds. That means that for the next request, the feed will be served from the local cache if it has not been updated in the meantime.

The method we use is simple and effective, but now we want more interactivity. We do not want any delay in loading; we want to show more recent posts, and show them in a pop-up window. In order to achieve all this, we need to use a language specifically written to handle events on a web page—JavaScript.