Google Reader account for display in a sidebar widget or within pages or posts. Easily customized with friendly interface. Embed in page or post via shortcode; can always show newest, or start at post publication date! Version: 4.0.4 Author: Jacob M Goldman (C. Murray Consulting) Author URI: http://www.cmurrayconsulting.com Plugin: Copyright 2009 C. Murray Consulting (email : jake@cmurrayconsulting.com) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** * rr_grs_activation() handles plugin activation */ function rr_grs_activation() { //BACKWARDS COMPATABILITY FROM PRE 4.0 if (get_option('gr_sid')) { //connection conversion $grs_conn = array(); $grs_conn['id'] = get_option('gr_sid'); delete_option('gr_sid'); $grs_conn['item_count'] = get_option('gr_num'); delete_option('gr_num'); update_option('rr_grs_connection',$grs_conn); //preference conversion $grs_prefs = array(); $grs_prefs['link_love'] = (get_option('gr_credit')) ? 1 : 0; delete_option('gr_credit'); $grs_prefs['content_show'] = (get_option('gr_content')) ? 1 : 0; delete_option('gr_content'); $grs_prefs['content_truncate'] = intval(get_option('gr_trim')); delete_option('gr_trim'); $grs_prefs['date_format'] = get_option('gr_date'); delete_option('gr_date'); $grs_prefs['date_preface'] = get_option('gr_datep'); delete_option('gr_datep'); $grs_prefs['source_show'] = (get_option('gr_source')) ? 1 : 0; delete_option('gr_source'); $grs_prefs['source_preface'] = get_option('gr_sourcep'); delete_option('gr_sourcep'); $grs_prefs['new_window'] = (get_option('gr_open')) ? 1 : 0; delete_option('gr_open'); $grs_prefs['no_follow'] = (get_option('gr_nofollow')) ? 1 : 0; delete_option('gr_nofollow'); $grs_prefs['feed_link_text'] = get_option('gr_read_more_text'); delete_option('gr_read_more_text'); $grs_prefs['feed_link_show'] = (get_option('gr_read_more_feed')) ? 1 : 0; delete_option('gr_read_more_feed'); $grs_prefs['notes_show'] = (get_option('gr_notes')) ? 1 : 0; delete_option('gr_notes'); $grs_prefs['notes_preface'] = get_option('gr_notesp'); delete_option('gr_notep'); update_option('rr_grs_prefs',$grs_prefs); //shortcode conversion $grs_shortcode = array(); $grs_shortcode['as_of_publish_date'] = (get_option('gr_publish_date')) ? 1 : 0; delete_option('gr_publish_date'); $grs_shortcode['up_to_last_post'] = (get_option('gr_publish_upto')) ? 1 : 0; delete_option('gr_publish_upto'); $grs_shortcode['truncate_override'] = (get_option('gr_sc_trim')) ? 1 : 0; delete_option('gr_sc_trim'); $grs_shortcode['html_show'] = (get_option('gr_sc_html')) ? 1 : 0; delete_option('gr_sc_html'); $grs_shortcode['html_simple'] = (get_option('gr_sc_simplehtml')) ? 1 : 0; delete_option('gr_sc_simplehtml'); $grs_shortcode['html_noimg'] = (get_option('gr_sc_strpimg')) ? 1 : 0; delete_option('gr_sc_strpimg'); $grs_shortcode['styles'] = (get_option('gr_sc_styles')) ? 1 : 0; delete_option('gr_sc_styles'); update_option('rr_grs_shortcode',$grs_shortcode); //widget update update_option('rr_grs_widget_options',get_option('setup_widget_grs')); delete_option('setup_widget_grs'); //delete other old options delete_option('gr_lastupdate'); delete_option('gr_sc_lastupdate'); delete_option('gr_skipnote'); //TEMPORARY delete_option('gr_sc_cache'); delete_option('gr_cache'); } //default settings $rr_grs_prefs = get_option('rr_grs_prefs'); if (!$rr_grs_prefs) { $rr_grs_prefs['link_love'] = 1; update_option('rr_grs_prefs', $rr_grs_prefs); return true; } rr_grs_flush(); //flush the cache } register_activation_hook(__FILE__,'rr_grs_activation'); /** * rr_grs_flush() clears all of the caching * * @param bool $connection_info indicates whether the widget cache needs to be cleared too */ function rr_grs_flush($connection_info = true) { //may not be necessary to clean up connection info if settings are being updated already if ($connection_info) { //flush last update timestamps $rr_grs_connection = get_option('rr_grs_connection'); $rr_grs_connection['widget_lastupdate'] = ''; $rr_grs_connection['widget_cache'] = ''; update_option('rr_grs_connection', $rr_grs_connection); } //clear shortcode cache(s) global $wpdb; $wpdb->query("DELETE FROM $wpdb->postmeta WHERE meta_key = '_rr_grs_cache' OR meta_key = '_rr_grs_cache_date';"); } /** * rr_grs_options_init() initializes plugin options * * @return */ function rr_grs_options_init() { register_setting('rr_grs_options','rr_grs_connection','rr_grs_connection_validate'); //array of fundamental options including ID and caching info register_setting('rr_grs_options','rr_grs_prefs','rr_grs_prefs_validate'); //generic preferences array register_setting('rr_grs_options','rr_grs_shortcode','rr_grs_shortcode_validate'); //array of shortcode options } add_action('admin_init','rr_grs_options_init'); /** * rr_grs_connection_validate() handles validation of connection options */ function rr_grs_connection_validate($input) { rr_grs_flush(false); //flush cache; not necessary to flush info updated here too $input['id'] = (is_numeric($input['id'])) ? $input['id'] : ''; //ID must be numeric $input['item_count'] = intval($input['item_count']); //item count must be integer return $input; //pass back to save } /** * rr_grs_prefs_validate() handles validation of general preferences */ function rr_grs_prefs_validate($input) { $input['link_love'] = ($input['link_love'] == 1) ? 1 : 0; $input['content_show'] = ($input['content_show'] == 1) ? 1 : 0; $input['content_truncate'] = intval($input['content_truncate']); $input['source_show'] = ($input['source_show'] == 1) ? 1 : 0; $input['new_window'] = ($input['new_window'] == 1) ? 1 : 0; $input['no_follow'] = ($input['no_follow'] == 1) ? 1 : 0; $input['feed_link_show'] = ($input['feed_link_show'] == 1) ? 1 : 0; $input['notes_show'] = ($input['notes_show'] == 1) ? 1 : 0; // $input['notes_skip'] = ($input['notes_skip'] == 1) ? 1 : 0; // no sanitization: date_format, date_preface, source_preface, feed_link_text, notes_preface return $input; } /** * rr_grs_shortcode_validate() handles sanitization of shortcode options */ function rr_grs_shortcode_validate($input) { $input['as_of_publish_date'] = ($input['as_of_publish_date'] == 1) ? 1 : 0; $input['up_to_last_post'] = ($input['up_to_last_post'] == 1) ? 1 : 0; $input['truncate_override'] = ($input['truncate_override'] == 1) ? 1 : 0; $input['html_show'] = ($input['html_show'] == 1) ? 1 : 0; $input['html_simple'] = ($input['html_simple'] == 1) ? 1 : 0; $input['html_noimg'] = ($input['html_noimg'] == 1) ? 1 : 0; $input['styles'] = ($input['styles'] == 1) ? 1 : 0; return $input; } /** * cache handling function... hooks feed transient time and returns 15 secs for aggressive users */ function rr_grs_cache_override($age) { return 15; } /** * rr_grs_fetch_items() is the core function that handles processing of the feed * * @param bool $shortcode determines whether this should be handled as a shortcode entry * @param integer $maxcnt is used when a count parameter is passed via shortcode tag * @return is the output ready for display */ function rr_grs_fetch_items($shortcode = false, $maxcnt = 0) { if ($shortcode) { $shortcode = get_option('rr_grs_shortcode'); //get shortcode options //if using "as of publish date" feature if ($shortcode['as_of_publish_date']) { //since new items can't really be added to the feed in the past, we can assume we're done if there's a cache (rarely untrue, solved by cache flush) $grs_cache = get_post_meta(get_the_ID(),"_rr_grs_cache",true); //cache store in post meta for shortcode if ($grs_cache) return $grs_cache; $post_date = get_the_time('U'); //fetch post date in pure unix time //get the date of the last shortcode post if we only want to display up to previous post using shortcode if($shortcode['up_to_last_post']) { global $wpdb; $last_post = $wpdb->get_var("SELECT post_date FROM $wpdb->posts WHERE post_date < '".date("Y-m-d H:i:s", $post_date)."' AND (post_type = 'post' OR post_type = 'page') AND post_content LIKE '%[recreading%]%' ORDER BY post_date DESC LIMIT 1;"); $last_post = (is_null($last_post)) ? false : strtotime($last_post); //convert to false or friendly date format } } } //retrieve connection info and stop this if core connection id has not been set $grs_conn = get_option('rr_grs_connection'); if (!$grs_conn['id']) return 'Recommended Reading: Google Reader Shared plug-in has not been configured.'; //if we are not using shortcode with "as of publish date feature", we can limit the feed to the number of items we want to show; otherwise need all (note post_date only set here under shortcode as of pub date condition) $item_count = 0; if ($maxcnt && !isset($post_date)) $item_count = $maxcnt; //if a count provided by shortcode, and not using as of publish date feature elseif (!isset($post_date)) $item_count = $grs_conn['item_count']; //otherwise use configured counter, unless using as of publish date feature //tentatively reduce cache to 15 seconds for aggressive users... will be an option in the future add_filter('wp_feed_cache_transient_lifetime', 'rr_grs_cache_override'); //url for shared items feed $url = "http://www.google.com/reader/public/atom/user%2F".$grs_conn['id']."%2Fstate%2Fcom.google%2Fbroadcast?n=".$item_count; if (isset($last_post) && $last_post) $url .= "&ot=".$last_post; //only return items shared since last post EXPERIMENTAL //now using wordpress built in fetch feed feature include_once(ABSPATH. WPINC.'/feed.php'); $grs_feed = fetch_feed($url); if(is_wp_error($grs_feed)) return "No Google Reader feed was found with the provided ID. Please validate the ID in plug-in configuration."; //error catch //remove tentative filter remove_filter('wp_feed_cache_transient_lifetime','rr_grs_cache_override'); $grs_entries = $grs_feed->get_feed_tags('http://www.w3.org/2005/Atom','entry'); //get the array of items if (!$grs_entries || count($grs_entries) <= 0) return "There are no items in your shared Google Reader feed."; //if the feed is empty, lets stop while we're ahead //basic caching handling $feedupdate = $grs_feed->get_feed_tags('http://www.w3.org/2005/Atom','updated'); $feedupdate = $feedupdate[0]['data']; $lastupdate = ($shortcode) ? get_post_meta(get_the_ID(),"_rr_grs_cache_date",true) : $grs_conn['widget_lastupdate']; //conditions under which we use the cache if($lastupdate && $lastupdate == $feedupdate) { $gr_cache = ($shortcode) ? get_post_meta(get_the_ID(),"_rr_grs_cache",true) : $grs_conn['widget_cache']; return $gr_cache; } //otherwise we need to generate everything $grs_prefs = get_option('rr_grs_prefs'); //time to get the full preferences $grs_new_window = ($grs_prefs['new_window']) ? ' target="_blank"' : ' '; //HTML for opening link in new window $grs_no_follow = ($grs_prefs['no_follow']) ? ' rel="nofollow"' : ' '; //HTML for nofollow rel $content_truncate = ($shortcode && $shortcode['truncate_override']) ? "" : $grs_prefs['content_truncate']; // if($grs_prefs['notes_skip']) $skipped_notes = 0; //need to keep track of stand alone notes in case we need more items later //gr_cache variable will hold all the output /***** hiro45jp del ***** $gr_cache = '"; /***** hiro45jp end *****/ //cache storing for shortcode if($shortcode) { update_post_meta(get_the_ID(),"_rr_grs_cache",$gr_cache); update_post_meta(get_the_ID(),"_rr_grs_cache_date",$feedupdate); } //cache storing for widget else { $grs_conn['widget_cache'] = $gr_cache; $grs_conn['widget_lastupdate'] = $feedupdate; update_option('rr_grs_connection',$grs_conn); } return $gr_cache; } /** * google_reader_shared() echos the content of the google reader shared * * @param bool $is_shortcode determines whether to use shortcode type output * @return is true upon success (content itself is echoed)... use rr_grs_fetch_items to store output and not echo */ function google_reader_shared($is_shortcode = false) { echo rr_grs_fetch_items($is_shortcode); return true; } /** * rr_grs_widget_control() initializes the widget for admin */ function rr_grs_widget_control() { // We need to grab any preset options $options = get_option("rr_grs_widget_options"); if (!is_array($options)) $options = array('title' => 'Recommended Reading'); // No options? No problem! We set them here. if (isset($_POST['rr_grs_widget_submit'])) { $options['title'] = htmlspecialchars($_POST['rr_grs_widget_title']); update_option("rr_grs_widget_options", $options); // And we also update the options in the Wordpress Database } echo ' '; } /** * rr_grs_widget_output() handles widget output */ function rr_grs_widget_output($args) { extract($args); $options = get_option("rr_grs_widget_options"); if (!is_array($options)) $options = array('title' => 'Recommended Reading'); if (!$options['title']) $options['title'] = "Recommended Reading"; echo $before_widget; echo $before_title.$options['title'].$after_title; echo rr_grs_fetch_items(); echo $after_widget; } /** * rr_grs_widget_init() registers the widget */ function rr_grs_widget_init() { register_sidebar_widget('Rec. Reading', 'rr_grs_widget_output'); register_widget_control('Rec Reading', 'rr_grs_widget_control'); } add_action("plugins_loaded", "rr_grs_widget_init"); /** * rr_grs_shortcode() processes the [recreading] shortcode */ function rr_grs_shortcode($atts) { extract(shortcode_atts(array('items' => ''),$atts)); return rr_grs_fetch_items(true, $atts['items']); } add_shortcode('recreading', 'rr_grs_shortcode'); /** * clear_rr_grs_shortcode_cache() clears the shortcode cache for the current page when updated or saved */ function clear_rr_grs_shortcode_cache($post_ID) { delete_post_meta($post_ID,"_rr_grs_cache"); delete_post_meta($post_ID,"_rr_grs_cache_date"); } add_action('save_post','clear_rr_grs_shortcode_cache'); /** * rr_grs_stylize() adds the prefabbed / generic stylesheet for shortcode output if desired to possible templates */ function rr_grs_stylize() { $shortcode = get_option('rr_grs_shortcode'); if($shortcode['styles'] && (is_singular() || is_home() || is_archive())) wp_enqueue_style('rr_grs_styles',WP_PLUGIN_URL.'/'.basename(dirname(__FILE__)).'/css/recreading.css'); } add_action('get_header', 'rr_grs_stylize'); /** * rr_grs_plugin_actlinks() adds the settings link to the plugin page */ function rr_grs_plugin_actlinks( $links ) { // Add a link to this plugin's settings page $plugin = plugin_basename(__FILE__); $settings_link = sprintf( '%s', $plugin, __('Settings') ); array_unshift( $links, $settings_link ); return $links; } if(is_admin()) add_filter("plugin_action_links_".$plugin, 'rr_grs_plugin_actlinks' ); /** * rr_grs_admin_menu() sets up the menu link in the admin */ function rr_grs_admin_menu() { $plugin_page = add_options_page('Recommended Reading: Google Reader Shared Configuration', 'Rec. Reading', 8, __FILE__, 'rr_grs_options_page'); add_action('admin_head-'.$plugin_page,'rr_grs_header'); } function rr_grs_header() { add_filter('contextual_help','rr_grs_context_help'); } function rr_grs_context_help() { echo '
Recommended Reading: Google Reader Shared

Recommended Reading: Google Reader Shared gets the shared items from your Google Reader account.

To learn more about any of the options below, simply click the question mark next to the field label.

Frequently Asked Questions

Q: Why won\'t my ID validate, even though I\'m absolutely positive that it is right or it was looked up?

A: The most common reason for ID validation faillure is a bad ID! If you are certain it is valid, make certain that your shared items are set for public sharing (not private) in your settings.

Q: How do I share posts?

A: Click the "Share" button at the bottom of any post from within Google Reader.

Q: How do I make posts show only the items I shared before I published my post?

A: You can embed your shared items in pages or posts by using the shortcode: just type in "[recreading]" (sans quotes) where you want it to appear. In the "Display on page / post (shortcode)" options at the bottom of this settings page, check the "As of publish date" option to only show items shared before you published your post.

Q: I want to regularly share my latest items in my posts. Can Recommended Reading automatically show all the shared posts between the publication date of the current post and the last post that showed my shared items?

A: Yes! First, check off the "As of publish date" option (discussed in the previous question). You can check the next option, "up to last post" to do just that!

Q: Do I need to be at my computer to update my recommended reading list?

A: Nope! Since the plug in gets posts from the Google Reader shared feed, you can update your feed from any Google Reader interface that supports sharing items. You can even recommend items from your mobile phone using Google\'s free mobile version or third party clients (I personally recommend Byline and MobileRSS for the iPhone).

Q: I don\'t want to include my shared notes. Can I hide those?

A: Yes... mostly. Uncheck the "show notes" option to hide the notes attached to shared items. Before version 4.0, you could also skip "standalone" notes. Google Reader treated standalone notes (a rarely used feature) as shared items, not annotations. Skipping them would dramatically reduce the performance benefits introduce in 4.0. Although we suspect this feature was rarely used, if there is interested, please let us know by leaving a comment on the plug-in support page.

Support

Recommended Reading: Google Reader Shared support

This plug-in was developed by C. Muray Consulting, Web Development & Strategy Experts located in Providence, Rhode Island in the United States. We develop plug-ins because we love working with systems like WordPress, and to generate interest in our business. If you like our plug-in, and know someone who needs web development work, be in touch!

'; } add_action('admin_menu', 'rr_grs_admin_menu'); /** * rr_grs_options_page() displays the administrative configuration page */ function rr_grs_options_page() { ?>

Recommended Reading: Google Reader Shared Configuration

Support us

Help support continued development of Recommended Reading and other plugins.

The best thing you can do is refer someone looking for web development or strategy work to our company.

Short of that, here are other ways you can help:


/> Include link to us [?]

Help & support

My Google Reader ID

Google Reader ID [?]
Look up my Google Reader ID
Google Username
Google Password
Your server does not have cURL enabled. cURL is a widely supported PHP module used to load and process external web pages behind the scenes. While the WordPress API will let this plugin perform most operations without cURL, cURL is needed for the more complicated process of looking up your ID. You may still manually find and enter your ID. Click the question mark link above for instructions.

Display Settings

> >
Quick Set
Number of Posts [?]
Show Post Content [?] onchange="secondaryOption(this);" />
Truncate Content [?]
Show Date [?]
Use PHP date format.
Preface Date [?]
Show Blog Source [?] onchange="secondaryOption(this);" />
Preface Source [?]
Open Links in New Window />
rel="nofollow" [?] />
Read More Link [?]
Link to Feed [?] />

Shared Item Notes

> */ ?>
Show Notes [?] onchange="secondaryOption(this);" />
Preface Note [?]

Note: "stand alone" notes (notes not attached to posts) placed in your feed are handled by Google as shared items, not annotations, and will still appear.

Skip Standalone Notes [?] />

Display on page / post (shortcode)

You can display shared items on a page or post by simply typing [recreading] in the content (this is called "shortcode"). An optional attribute, 'items', sets the number of entries to display; for example, [recreading items=5]. Shortcode output uses the settings above, in addition the options below.

>
As of publish date [?] onchange="secondaryOption(this);" />
... up to last post [?] />
Don't truncate content [?] />
... and show HTML [?] />
... ... but only simple tags [?] />
... ... and hide images [?] />
Use special styles [?] />