WebSub/PubSubHubbub - Version 1.3

Version Description

Download this release

Release Info

Developer joshfraz
Plugin Icon 128x128 WebSub/PubSubHubbub
Version 1.3
Comparing to
See all releases

Version 1.3

Files changed (4) hide show
  1. publisher.php +86 -0
  2. pubsubhubbub.php +221 -0
  3. readme.txt +66 -0
  4. screenshot-1.png +0 -0
publisher.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // a PHP client library for pubsubhubbub
4
+ // as defined at http://code.google.com/p/pubsubhubbub/
5
+ // written by Josh Fraser | joshfraser.com | joshfraz@gmail.com
6
+ // Released under Apache License 2.0
7
+
8
+ class Publisher {
9
+
10
+ protected $hub_url;
11
+ protected $last_response;
12
+
13
+ // create a new Publisher
14
+ public function __construct($hub_url) {
15
+
16
+ if (!isset($hub_url))
17
+ throw new Exception('Please specify a hub url');
18
+
19
+ if (!preg_match("|^https?://|i",$hub_url))
20
+ throw new Exception('The specified hub url does not appear to be valid: '.$hub_url);
21
+
22
+ $this->hub_url = $hub_url;
23
+ }
24
+
25
+ // accepts either a single url or an array of urls
26
+ public function publish_update($topic_urls, $http_function = false) {
27
+ if (!isset($topic_urls))
28
+ throw new Exception('Please specify a topic url');
29
+
30
+ // check that we're working with an array
31
+ if (!is_array($topic_urls)) {
32
+ $topic_urls = array($topic_urls);
33
+ }
34
+
35
+ // set the mode to publish
36
+ $post_string = "hub.mode=publish";
37
+ // loop through each topic url
38
+ foreach ($topic_urls as $topic_url) {
39
+
40
+ // lightweight check that we're actually working w/ a valid url
41
+ if (!preg_match("|^https?://|i",$topic_url))
42
+ throw new Exception('The specified topic url does not appear to be valid: '.$topic_url);
43
+
44
+ // append the topic url parameters
45
+ $post_string .= "&hub.url=".urlencode($topic_url);
46
+ }
47
+
48
+ // make the http post request and return true/false
49
+ // easy to over-write to use your own http function
50
+ if ($http_function)
51
+ return $http_function($this->hub_url,$post_string);
52
+ else
53
+ return $this->http_post($this->hub_url,$post_string);
54
+ }
55
+
56
+ // returns any error message from the latest request
57
+ public function last_response() {
58
+ return $this->last_response;
59
+ }
60
+
61
+ // default http function that uses curl to post to the hub endpoint
62
+ private function http_post($url, $post_string) {
63
+
64
+ // add any additional curl options here
65
+ $options = array(CURLOPT_URL => $url,
66
+ CURLOPT_POST => true,
67
+ CURLOPT_POSTFIELDS => $post_string,
68
+ CURLOPT_USERAGENT => "PubSubHubbub-Publisher-PHP/1.0");
69
+
70
+ $ch = curl_init();
71
+ curl_setopt_array($ch, $options);
72
+
73
+ $response = curl_exec($ch);
74
+ $this->last_response = $response;
75
+ $info = curl_getinfo($ch);
76
+
77
+ curl_close($ch);
78
+
79
+ // all good
80
+ if ($info['http_code'] == 204)
81
+ return true;
82
+ return false;
83
+ }
84
+ }
85
+
86
+ ?>
pubsubhubbub.php ADDED
@@ -0,0 +1,221 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: PubSubHubbub
4
+ Plugin URI: http://code.google.com/p/pubsubhubbub/
5
+ Description: A better way to tell the world when your blog is updated.
6
+ Version: 1.3
7
+ Author: Josh Fraser
8
+ Author Email: joshfraz@gmail.com
9
+ Author URI: http://www.joshfraser.com
10
+ */
11
+
12
+ include("publisher.php");
13
+
14
+ // function that is called whenever a new post is published
15
+ function publish_to_hub($post_id) {
16
+
17
+ // we want to notify the hub for every feed
18
+ $feed_urls = array();
19
+ $feed_urls[] = get_bloginfo('atom_url');
20
+ $feed_urls[] = get_bloginfo('rss_url');
21
+ $feed_urls[] = get_bloginfo('rdf_url');
22
+ $feed_urls[] = get_bloginfo('rss2_url');
23
+ // remove dups (ie. they all point to feedburner)
24
+ $feed_urls = array_unique($feed_urls);
25
+ // get the list of hubs
26
+ $hub_urls = get_pubsub_endpoints();
27
+ // loop through each hub
28
+ foreach ($hub_urls as $hub_url) {
29
+ $p = new Publisher($hub_url);
30
+ // publish the update to each hub
31
+ if (!$p->publish_update($feed_urls, "http_post_wp")) {
32
+ // TODO: add better error handling here
33
+ }
34
+ }
35
+ return $post_id;
36
+ }
37
+
38
+ function add_atom_link_tag() {
39
+ $hub_urls = get_pubsub_endpoints();
40
+ foreach ($hub_urls as $hub_url) {
41
+ echo '<link rel="hub" href="'.$hub_url.'" />';
42
+ }
43
+ }
44
+
45
+ function add_rss_link_tag() {
46
+ $hub_urls = get_pubsub_endpoints();
47
+ foreach ($hub_urls as $hub_url) {
48
+ echo '<atom:link rel="hub" href="'.$hub_url.'"/>';
49
+ }
50
+ }
51
+
52
+ function add_rdf_ns_link() {
53
+ echo 'xmlns:atom="http://www.w3.org/2005/Atom"';
54
+ }
55
+
56
+ // hack to add the atom definition to the RSS feed
57
+ // start capturing the feed output. this is run at priority 9 (before output)
58
+ function start_rss_link_tag() {
59
+ ob_start();
60
+ }
61
+
62
+ // this is run at priority 11 (after output)
63
+ // add in the xmlns atom definition link
64
+ function end_rss_link_tag() {
65
+ $feed = ob_get_clean();
66
+ $pattern = '/<rss version="(.+)">/i';
67
+ $replacement = '<rss version="$1" xmlns:atom="http://www.w3.org/2005/Atom">';
68
+ // change <rss version="X.XX"> to <rss version="X.XX" xmlns:atom="http://www.w3.org/2005/Atom">
69
+ echo preg_replace($pattern, $replacement, $feed);
70
+ }
71
+
72
+ // add a link to our settings page in the WP menu
73
+ function add_plugin_menu() {
74
+ add_options_page('PubSubHubbub Settings', 'PubSubHubbub', 8, __FILE__, 'add_settings_page');
75
+ }
76
+
77
+ // get the endpoints from the wordpress options table
78
+ // valid parameters are "publish" or "subscribe"
79
+ function get_pubsub_endpoints() {
80
+ $endpoints = get_option('pubsub_endpoints');
81
+ $hub_urls = explode("\n",$endpoints);
82
+
83
+ // if no values have been set, revert to the defaults (pubsubhubbub on app engine & superfeedr)
84
+ if (!$endpoints) {
85
+ $hub_urls[] = "http://pubsubhubbub.appspot.com";
86
+ $hub_urls[] = "http://pubsubhubbub.superfeedr.com";
87
+ }
88
+
89
+ // clean out any blank values
90
+ foreach ($hub_urls as $key => $value) {
91
+ if (is_null($value) || $value=="") {
92
+ unset($hub_urls[$key]);
93
+ } else {
94
+ $hub_urls[$key] = trim($hub_urls[$key]);
95
+ }
96
+ }
97
+
98
+ return $hub_urls;
99
+ }
100
+
101
+ // write the content for our settings page that allows you to define your endpoints
102
+ function add_settings_page() { ?>
103
+ <div class="wrap">
104
+ <h2>Define custom hubs</h2>
105
+
106
+ <form method="post" action="options.php">
107
+ <?php //wp_nonce_field('update-options'); ?>
108
+ <!-- starting -->
109
+ <?php settings_fields('my_settings_group'); ?>
110
+ <?php do_settings_sections('my_settings_section'); ?>
111
+ <!-- ending -->
112
+
113
+ <?php
114
+
115
+ // load the existing pubsub endpoint list from the wordpress options table
116
+ $pubsub_endpoints = trim(implode("\n",get_pubsub_endpoints()),"\n");
117
+
118
+ ?>
119
+
120
+ <table class="form-table">
121
+
122
+ <tr valign="top">
123
+ <th scope="row">Hubs (one per line)</th>
124
+ <td><textarea name="pubsub_endpoints" style='width:600px;height:100px'><?php echo $pubsub_endpoints; ?></textarea></td>
125
+ </tr>
126
+
127
+ </table>
128
+
129
+ <input type="hidden" name="action" value="update" />
130
+ <input type="hidden" name="page_options" value="pubsub_endpoints" />
131
+
132
+ <p class="submit">
133
+ <input type="submit" class="button-primary" value="<?php _e('Save Changes') ?>" />
134
+ </p>
135
+
136
+ </form>
137
+
138
+ <br /><br />
139
+ <div style='background-color:#FFFEEB;border:1px solid #CCCCCC;padding:12px'>
140
+ <strong>Thanks for using PubSubHubbub!</strong><br />
141
+ Visit these links to learn more about PubSubHubbub and the author of this plugin:<br />
142
+ <ul>
143
+ <li><a href='http://www.onlineaspect.com'>Subscribe to Online Aspect</a></li>
144
+ <li><a href='http://www.twitter.com/joshfraser'>Follow Josh Fraser on twitter</a></li>
145
+ <li><a href='http://code.google.com/p/pubsubhubbub/'>Learn more about the PubSubHubbub protocol</a></li>
146
+ </ul>
147
+ </div>
148
+
149
+ </div>
150
+
151
+ <?php }
152
+
153
+
154
+ // helper function to use the WP-friendly snoopy library
155
+ if (!function_exists('get_snoopy')) {
156
+ function get_snoopy() {
157
+ include_once(ABSPATH.'/wp-includes/class-snoopy.php');
158
+ return new Snoopy;
159
+ }
160
+ }
161
+
162
+ // over-ride the default curl http function to post to the hub endpoints
163
+ function http_post_wp($url, $post_vars) {
164
+
165
+ // turn the query string into an array for snoopy
166
+ parse_str($post_vars);
167
+ $post_vars = array();
168
+ $post_vars['hub.mode'] = $hub_mode; // PHP converts the periods to underscores
169
+ $post_vars['hub.url'] = $hub_url;
170
+
171
+ // more universal than curl
172
+ $snoopy = get_snoopy();
173
+ $snoopy->agent = "(PubSubHubbub-Publisher-WP/1.0)";
174
+ $snoopy->submit($url,$post_vars);
175
+ $response = $snoopy->results;
176
+ // TODO: store the last_response. requires a litle refactoring work.
177
+ $response_code = $snoopy->response_code;
178
+ if ($response_code == 204)
179
+ return true;
180
+ return false;
181
+ }
182
+
183
+ // add a settings link next to deactive / edit
184
+ function add_settings_link( $links, $file ) {
185
+ if( $file == 'pubsubhubbub/pubsubhubbub.php' && function_exists( "admin_url" ) ) {
186
+ $settings_link = '<a href="' . admin_url( 'options-general.php?page=pubsubhubbub/pubsubhubbub' ) . '">' . __('Settings') . '</a>';
187
+ array_unshift( $links, $settings_link ); // before other links
188
+ }
189
+ return $links;
190
+ }
191
+
192
+ // attach the handler that gets called every time you publish a post
193
+ add_action('publish_post', 'publish_to_hub');
194
+ // add the link to our settings page in the WP menu structure
195
+ add_action('admin_menu', 'add_plugin_menu');
196
+
197
+ // keep WPMU happy
198
+ add_action('admin_init', 'register_my_settings');
199
+ function register_my_settings() {
200
+ register_setting('my_settings_group','pubsub_endpoints');
201
+ }
202
+
203
+ // add the link tag that points to the hub in the header of our template...
204
+
205
+ // to our atom feed
206
+ add_action('atom_head', 'add_atom_link_tag');
207
+ // to our RSS 0.92 feed (requires a bit of a hack to include the ATOM namespace definition)
208
+ add_action('do_feed_rss', 'start_rss_link_tag', 9); // run before output
209
+ add_action('do_feed_rss', 'end_rss_link_tag', 11); // run after output
210
+ add_action('rss_head', 'add_rss_link_tag');
211
+ // to our RDF / RSS 1 feed
212
+ add_action('rdf_ns', 'add_rdf_ns_link');
213
+ add_action('rdf_header', 'add_rss_link_tag');
214
+ // to our RSS 2 feed
215
+ add_action('rss2_head', 'add_rss_link_tag');
216
+ // to our main HTML header -- not sure if we want to include this long-term or not.
217
+ add_action('wp_head', 'add_atom_link_tag');
218
+
219
+ add_filter('plugin_action_links', 'add_settings_link', 10, 2);
220
+
221
+ ?>
readme.txt ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Plugin Name ===
2
+ Contributors: joshfraz
3
+ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5426516
4
+ Tags: pubsubhubbub
5
+ Requires at least: 2.5
6
+ Tested up to: 2.9.1
7
+ Stable tag: /trunk/
8
+
9
+ A better way to tell the world when your blog is updated.
10
+
11
+ == Description ==
12
+
13
+ This [PubSubHubbub](http://code.google.com/p/pubsubhubbub/ "PubSubHubbub") plugin is a simple way to let people know in real-time when your blog is updated. PubSubHubbub is quickly gaining adoption and is already being used by Google Reader, Google Alerts, FriendFeed and more.
14
+
15
+ This plugin:
16
+
17
+ * Supports multi-user installations (NEW!)
18
+ * Supports multiple hubs
19
+ * Supports all of the feed formats used by WordPress, not just ATOM and RSS2
20
+ * Announces which hubs you are using by adding `<link rel="hub" ...>` declarations to your template header and ATOM feed
21
+ * Adds `<atom:link rel="hub" ...>` to your RSS feeds along with the necessary XMLNS declaration for RSS 0.92/1.0
22
+
23
+ By default this plugin will ping the following hubs:
24
+
25
+ * [Demo hub on Google App Engine](http://pubsubhubbub.appspot.com "Demo hub on Google App Engine")
26
+ * [SuperFeedr](http://pubsubhubbub.superfeedr.com "SuperFeedr")
27
+
28
+ Please contact me if you operate a hub that you would like to be included as a default option.
29
+
30
+ == Installation ==
31
+
32
+ 1. Upload the `pubsubhubbub` directory to your `/wp-content/plugins/` directory
33
+ 2. Activate the plugin through the 'Plugins' menu in WordPress
34
+ 3. Select custom hubs under your PubSubHubbub Settings (optional)
35
+
36
+ Note: PHP 5.0 or better is required.
37
+
38
+ == Frequently Asked Questions ==
39
+
40
+ = Where can I learn more about the PubSubHubbub (PuSH) protocol? =
41
+
42
+ You can visit [PubSubHubbb on Google Code](http://code.google.com/p/pubsubhubbub/ "PubSubHubbb on Google Code")
43
+
44
+ = Where can I learn more about the author of this plugin? =
45
+
46
+ You can learn more about Josh Fraser at [Online Aspect](http://www.onlineaspect.com "Online Aspect") or follow [@joshfraser on twitter](http://www.twitter.com/joshfraser "Josh Fraser on Twitter")
47
+
48
+ = Does this plugin work with MU? =
49
+
50
+ Multi-user support was added in version 1.3
51
+
52
+ = Does this plugin work with PHP 4.x? =
53
+
54
+ Nope. Sorry. For now you must have PHP 5.0 or better.
55
+
56
+ = Blog posts don't show up right away in Google Reader. Is it broken? =
57
+
58
+ Google Reader currently supports PuSH for shared items, but not general subscriptions. Hopefully they will add that functionality soon (I hear they're working on it). In the meantime, you can check that everything is working correctly by publishing a post and then checking the status at http://pubsubhubbub.appspot.com/topic-details?hub.url=URL-OF-YOUR-FEED
59
+
60
+ = Got another question that isn't covered here? =
61
+
62
+ Visit [my contact page](http://onlineaspect.com/contact/ "Contact Josh Fraser") to see various ways to get in touch with me.
63
+
64
+ == Screenshots ==
65
+
66
+ 1. The PubSubHubbub Settings page allows you to define which hubs you want to use
screenshot-1.png ADDED
Binary file