How to: Build and Extend a WordPress Lifestream

Introduction

Recently, I reinstalled WordPress and began blogging again.  Initially, I didn’t add many plugins—just the basics.  Since then, I’ve gone back and added some very cool and important ones.  I’ll blog about the full list and my choices thereof later.  But now, I want to highlight one plugin: wp-Lifestream by iBegin.  It creates a simple “lifestream,” which is a stream of one’s activity across different social networks.  My lifestream can be viewed here.

Wordpress Lifestream with wp-Lifestream Plugin

Wordpress Lifestream with wp-Lifestream Plugin

I looked into a couple different ways to create this lifestream, but this plugin offered the best option by far.  For one, it’s something that I didn’t have to build myself.  I could’ve easily rolled a solution using all of the APIs, but that’s kind of sloppy and certainly not elegant—at least not like this.  Secondly, it integrates with WordPress and is fast and efficient.  Plus, I really liked the way it created the stream, so very few customization was necessary.  What also impressed me was its extensibility.  It has a built-in framework for adding new feeds.  I found that most of the websites I used were already included, but I came across two that weren’t included: Readernaut and ScrnShots.  I decided to dive right in and build these two plugins.  Since the documentation was kind of confusing—at least for me—I decided to write another step-by-step guide.  Each feed had a different solution, so I’ll walk you through each.  As my Christmas present to you, I’ve also included for download my feeds.inc.php file (this is the file we’ll be appending to activate these new sites) at the end of this post, which you are free to use.

Note: I use the word “plugin” to refer to wp-Lifestream.  wp-Lifestream uses the word “plugin” to refer to the feed modules, which I refer to as extensions.  This seemed to be more apt and I hope this clarifies more than it confuses.

Readernaut

Introduction

Readernaut is a social network for readers.  You can add books you’ve read, are reading, and want to read.  Moreover, you can make and share lists of books.  You can also make recommendations and interact within the community.  I think the succinct description on their homepage is the best: “Readernaut is my library, my notebook, my book club.”[1. Readernaut]  It’s currently in beta, but I highly recommend it for any avid reader.  You can sign up for an invite on their homepage.  If you’re a member, add me as a friend.

Extension

Readernaut offers a RSS feed to syndicate when you add a book to your library.  It’s formatted with the date, title of the book, and an image of the bookcover pulled from Amazon—this is my only complaint because it’s not always the exact book cover, but it’s close enough.  I decided that it was important to pull in the title of the book and not the cover, so I followed the documentation and examples of the other extensions.  The only advanced bit of this code is the username option.  Since Readernaut’s user feeds are predictable—unlike Facebook, for example—and since I knew that I’d be publishing it for the community, I added an option to take a username.  This just adds a field for the username on the page when you’re adding the feed.  These are all functions built into the framework and documented.  The comments are inline with the code. [code] class LifeStream_ReadernautFeed extends LifeStream_Feed { // This is just a unique ID that is used internally; make sure it doesn't conflict with others. const ID = 'readernaut'; // The verbose name for your feed. This is what is displayed. const NAME = 'Readernaut'; // An optional URL for more information about this feed. This is displayed on the page to add the feed. const URL = 'http://www.readernaut.com/'; // A description for the feed, shown in the add feed and edit feed dialogs. const DESCRIPTION = 'Readernaut is my library, my notebook, my book club.'; // The label for showing a single event. It follows the <a href="http://php.net/sprintf">sprintf()</a> format and parameters are: feed url, feed name const LABEL_SINGLE = 'Added a book to his collection on <a href="%s">%s</a>.'; // The label for showing a group of events. It follows the <a href="http://php.net/sprintf">sprintf()</a> format and parameters are: number of items, feed url, feed name. const LABEL_PLURAL = 'Added books to his collection on <a href="%s">%s</a>.'; // This is for a plural form of the label. function __toString() { return $this->options['username']; } // This is what puts the form field for the username on the add feed page. This option is now available in subsequent lines. You can add other options as well. function get_options() { return array( 'username' => array('Username:', true, '', ''), ); } // This is an array of arrays that defines the options for this feed. function get_url() { return 'http://readernaut.com/rss/'.$this->options['username'].'/books/'; } // This is the actual URL that the information for the lifestream is pulled from. Like I said, the Readernaut RSS feeds are predictable so I could use the username option instead of asking for a feed URL. It's just much simpler. function get_public_url() { return 'http://readernaut.com/'.$this->options['username']; } // This is the URL that is put to the lifestream for linking purposes. Again, I used the username option. } register_lifestream_feed('LifeStream_ReadernautFeed'); // This is the last line of the extension and is what registers the extension with the plugin. [/code] The first step is to declare the class; the last step is to register the feed.  This is important.  Because of the nature of the feed and the information I wanted to pull from it, this is a relatively simple example.  I didn’t need to manipulate any of the data or switch any of the defaults.  One observation: you might want to change the gender of the entry to fit your needs.

ScrnShots

Introduction

Scrnshots is a social network to share screenshots of design for inspiration.  You can either upload from your computer through the website or from their desktop application.  I use Paparazzi, a Mac utility for making images of webpages. It’ll take a screenshot of the entire page or you can specify a crop area. It even creates thumbnails for these shots. You can add me as a contact on ScrnShots here.

Extension

This one was slightly more complicated, mainly because of the poorly organized RSS feed, but also because of the information I wanted to pull from it—namely, the screenshot.  I ran into several road blocks.  First, I couldn’t determine the exact source of the images.  I figured out that they were hosted on Amazon S3 and I knew there were suffix options for determining size—e.g. large, full-sized, medium rectangular-sized, or small square-sized.  However, I couldn’t figure out the nomenclature for the image sources—there is a unique ID and a seemingly arbitrary description (is it the automatically generated or user generated?)  There was an API, but aside from documenting the suffix options, it didn’t help much.  Finally, I just resorted to using PHP’s built-in functions and some regular expressions to build around the—again, poorly formatted—RSS feed.  Here’s the code: [code] class LifeStream_ScrnShotsFeed extends LifeStream_PhotoFeed { // A unique ID for your feed. Must not conflict with any other feed plugins. const ID = 'scrnshots'; // The verbose name for your feed. const NAME = 'Scrnshots'; // An optional URL for more information about this feed. const URL = 'http://www.scrnshots.com/'; // A description for the feed, shown in the add feed and edit feed dialogs. const DESCRIPTION = 'ScrnShots is the best way to take and share screenshots of web and screen based design. Upload as many screenshots as you want, embed them in your blog, discuss them with your contacts and become a better designer!'; // The label for showing a single event. It follows the <a href="http://php.net/sprintf">sprintf()</a> format and parameters are: feed url, feed name const LABEL_SINGLE = 'Added a new screenshot to &amp;lt;a href="%s"&amp;gt;%s&amp;lt;/a&amp;gt;.'; // The label for showing a group of events. It follows the <a href="http://php.net/sprintf">sprintf()</a> format and parameters are: number of items, feed url, feed name const LABEL_PLURAL = 'Added new screenshots to &amp;lt;a href="%s"&amp;gt;%s&amp;lt;/a&amp;gt;.'; const LABEL_SINGLE_USER = '&amp;lt;a href="%s"&amp;gt;%s&amp;lt;/a&amp;gt;.' added a new screenshot to &amp;lt;a href="%s"&amp;gt;%s&amp;lt;/a&amp;gt;.'; const LABEL_PLURAL_USER = '&amp;lt;a href="%s"&amp;gt;%s&amp;lt;/a&amp;gt;.' added new screenshots to &amp;lt;a href="%s"&amp;gt;%s&amp;lt;/a&amp;gt;.'; function __toString() { return $this-&amp;gt;options['username']; } function get_options() { return array('username' =&amp;gt; array('Username:', true, '', ''),); } function get_url() { return 'http://scrnshots.com/users/'.$this-&amp;gt;options['username'].'/screenshots.rss'; } function get_public_url() { return 'http://scrnshots.com/users/'.$this-&amp;gt;options['username']; } function yield($row) { $description = $row-&amp;gt;get_description(); $title = strip_tags($description); $img = strip_tags($description,'&amp;lt;img&amp;gt;'); $src = str_replace($title,'',$img); $large = preg_replace('/.src=([\'"])((?:(?!\1).))\1.*/si','$2',$src); $small = str_replace('large','med_rect',$large); $arr = array( 'title' =&amp;gt; strip_tags(html_entity_decode($row-&amp;gt;get_description())), 'date' =&amp;gt; $row-&amp;gt;get_date('U'), 'link' =&amp;gt; html_entity_decode($row-&amp;gt;get_link()), 'thumbnail' =&amp;gt; $small, ); return $arr; } } register_lifestream_feed('LifeStream_ScrnshotsFeed'); [/code] Most of the code is the same as Readernaut’s, save two important pieces.  First, notice that the top says extend “PhotoFeed.”  This sets it up to take the screenshots and display them in the lifestream.  The last bit—function yield($row)—is what is returning the data to the plugin to be processed.  I didn’t have to do this with Readernaut because I didn’t need to override the default entry.  Each element in the array $arr is a property of the RSS feed.  To use this function, you must return at least date and link, but there are numerous options to chose from, including title and thumbnail—which you must return for PhotoFeed.  You return this entire array to the plugin to be written to the lifestream.  At the top is where I used some PHP magic to get the content from the RSS feed I wanted. Here’s the breakdown:

$description = $row->get_description(); This gets the description from the RSS feed. $title = strip_tags($description); By default, the plugin was writing the date I uploaded the screenshot to the lifestream.  This isn’t suitable—I wanted the description of the screenshot instead.  But, the description in the RSS feed was filled with other data—e.g. the HTML image source tag.  I used the PHP strip_tags() function to get rid of this tag, and all that’s left is the description.  One hurdle down. $img = strip_tags($description,'<img><img>'); Here’s where some great stuff happens.  Like I said above, the image link is hidden within the description, so I need to strip everything else.  First, I took the description from the RSS feed and removed all of the HTML tags besides the image tag . . . $src = str_replace($title,'',$img); then I deleted the description that I already used . . . $large = preg_replace('/.src=([\'"])((?:(?!\1).))\1.*/si','$2',$src); then I used some regular expression magic to delete the HTML image tags.  I can’t use strip_tags() because it also strips the content of the tags, which I need. $small = str_replace('large','med_rect',$large); Finally, I deleted the large suffix and added the suffix which yields the medium rectangular shape.  I also edited the _lifestream.php file, line 769, to make the width of the inline image bigger.  You can see the final result at my lifestream.

Conclusion

This plugin is very well written.  It covers nearly every social network and then includes a framework for extending it to those that it didn’t include.  I congratulate the writer and thank him for such a great plugin.  I highly recommend installing this plugin and it’s definitely on my top 10 list of WordPress plugins—that article is in the works.  I hope these additions help you as they’ve helped me.  If you have any questions or can recommend a better way of doing this—I’m sure there is one—please leave a comment.

As promised, here is my feeds.inc.php file which includes the above additions.

Merry Christmas!

About Logan Leger

Logan Leger is a native Louisianaian and technologist. He is currently a computer engineering student at LSU and is employed there in the ITS department. He also works with Noteflood and NewAperio, his own startup he founded with classmates from LSMSA. You can read more about him here.
This entry was posted in Tutorial and tagged extension, how to, iBegin, introduction, lifestream, php, plugin, readernaut, scrnshots, Tutorial, wordpress, wp-Lifestream. Bookmark the permalink.

8 Responses to How to: Build and Extend a WordPress Lifestream

  1. Hi Logan! Greetings from Brazil!

    Nice article you wrote… it’s been keeping me busy for the last 2 days, as I’m struggling to find a way to display my Ipernity RSS feed thumbnails in my own lifestream. Ipernity is a service similar to Flickr, in which you can share pictures, videos and music. My RSS feed link is http://www.ipernity.com/feed/doc?user_id=danielsantos&format=rss.

    I’m not exactly very well skilled with PHP, so I wonder if you could help me finding out if is there any PHP magic you know of, that could make me display any of the two thumbnails included for every item in the feed? They are enclosed like this:

    No matter what I do, I’m not being able to succeed. You’re my best hope…

    Thanks in advance for any help or clue you might give me. Oh, my lifestream is at http://danielsantos.org/lifestream

    Best regards! Daniel

    • Logan Leger says:

      Hi, Daniel.

      I looked through the RSS feed you posted and it seems to be very similar to how Flickr rolls their RSS feeds. I would take the code from the Flickr in feeds.inc.php and change it to Ipernity’s feed URL structure per my instructions above. That should do the trick! Let me know if this doesn’t work.

    • Logan Leger says:

      Daniel,

      Did that solution work for you?

  2. Bernardo says:

    Hi. Great walkthrough, really helpful (I’m making a Wakoopa one myself). Just one question – where does the feeds.inc.php go? Into pages?

    • Logan Leger says:

      Yes, it goes into the pages folder inside the plugin folder. This one is just supposed to replace the one that comes with the plugin. One note, though: this one was built for an older version of the plugin. You should make the changes to the latest release instead of using this one.

      • Bernardo says:

        Yeah, that’s what I feared… The new feeds.inc.php doesn’t include most of that data, so I can start the scavenger hunt for all the bits and pieces >.<

        Your walkthrough mostly worked though, so thanks :)

        • Logan Leger says:

          When I first wrote this I asked the developer to include these additions, but he just ignored me. It’d be much easier now if it were. Ah, c’est la vie. Let me know how your ‘hunt’ goes.

  3. Pingback: Lifestream extensions - Bernardo Farah - my web presence and more

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>