PluginProbe
FeedWordPress / 2010.0903
FeedWordPress v2010.0903
trunk 0.8 0.9 0.91 0.95 0.96 0.97 0.98 0.981 0.99 0.991 0.992 0.993 2008.1030 2008.1101 2008.1105 2008.1214 2009.0612 2009.0613 2009.0618 2009.0707 2009.1111 2009.1112 2010.0127 2010.0528 All 65 releases
← All changes | feedwordpress.php +895 -364 2010.05282010.0903 View file →
@@ -2,9 +2,9 @@
2 2 /*
3 3 Plugin Name: FeedWordPress
4 4 Plugin URI: http://feedwordpress.radgeek.com/
5 5 Description: simple and flexible Atom/RSS syndication for WordPress
6 -Version: 2010.0528
6 +Version: 2010.0903
7 7 Author: Charles Johnson
8 8 Author URI: http://radgeek.com/
9 9 License: GPL
10 10 */
@@ -10,15 +10,16 @@
10 10 */
11 11
12 12 /**
13 13 * @package FeedWordPress
14 - * @version 2010.0528
14 + * @version 2010.0903
15 15 */
16 16
17 17 # This uses code derived from:
18 18 # - wp-rss-aggregate.php by Kellan Elliot-McCrea <kellan@protest.net>
19 -# - HTTP Navigator 2 by Keyvan Minoukadeh <keyvan@k1m.com>
19 +# - MagpieRSS by Kellan Elliot-McCrea <kellan@protest.net>
20 20 # - Ultra-Liberal Feed Finder by Mark Pilgrim <mark@diveintomark.org>
21 +# - WordPress Blog Tool and Publishing Platform <http://wordpress.org/>
21 22 # according to the terms of the GNU General Public License.
22 23 #
23 24 # INSTALLATION: see readme.txt or <http://projects.radgeek.com/install>
24 25 #
@@ -32,11 +33,15 @@
32 33 # or use a cron job.
33 34
34 35 # -- Don't change these unless you know what you're doing...
35 36
36 -define ('FEEDWORDPRESS_VERSION', '2010.0528');
37 +define ('FEEDWORDPRESS_VERSION', '2010.0903');
37 38 define ('FEEDWORDPRESS_AUTHOR_CONTACT', 'http://radgeek.com/contact');
38 39
40 +if (!defined('FEEDWORDPRESS_BLEG')) :
41 + define ('FEEDWORDPRESS_BLEG', true);
42 +endif;
43 +
39 44 // Defaults
40 45 define ('DEFAULT_SYNDICATION_CATEGORY', 'Contributors');
41 46 define ('DEFAULT_UPDATE_PERIOD', 60); // value in minutes
42 47
@@ -57,8 +62,9 @@
57 62
58 63 define ('FEEDWORDPRESS_FRESHNESS_INTERVAL', 10*60); // Every ten minutes
59 64
60 65 define ('FWP_SCHEMA_HAS_USERMETA', 2966);
66 +define ('FWP_SCHEMA_USES_ARGS_TAXONOMY', 12694); // Revision # for using $args['taxonomy'] to get link categories
61 67 define ('FWP_SCHEMA_20', 3308); // Database schema # for WP 2.0
62 68 define ('FWP_SCHEMA_21', 4772); // Database schema # for WP 2.1
63 69 define ('FWP_SCHEMA_23', 5495); // Database schema # for WP 2.3
64 70 define ('FWP_SCHEMA_25', 7558); // Database schema # for WP 2.5
@@ -65,8 +71,9 @@
65 71 define ('FWP_SCHEMA_26', 8201); // Database schema # for WP 2.6
66 72 define ('FWP_SCHEMA_27', 9872); // Database schema # for WP 2.7
67 73 define ('FWP_SCHEMA_28', 11548); // Database schema # for WP 2.8
68 74 define ('FWP_SCHEMA_29', 12329); // Database schema # for WP 2.9
75 +define ('FWP_SCHEMA_30', 12694); // Database schema # for WP 3.0
69 76
70 77 if (FEEDWORDPRESS_DEBUG) :
71 78 // Help us to pick out errors, if any.
72 79 ini_set('error_reporting', E_ALL & ~E_NOTICE);
@@ -92,24 +99,23 @@
92 99 add_filter('wp_feed_cache_transient_lifetime', array('FeedWordPress', 'cache_lifetime'));
93 100
94 101 // Ensure that we have SimplePie loaded up and ready to go.
95 102 // We no longer need a MagpieRSS upgrade module. Hallelujah!
96 -require_once(ABSPATH . WPINC . '/feed.php');
103 +if (!class_exists('SimplePie')) :
104 + require_once(ABSPATH . WPINC . '/class-simplepie.php');
105 +endif;
106 +require_once(ABSPATH . WPINC . '/class-feed.php');
97 107
98 -if (isset($wp_db_version)) :
99 - if ($wp_db_version >= FWP_SCHEMA_23) :
100 - require_once (ABSPATH . WPINC . '/registration.php'); // for wp_insert_user
101 - elseif ($wp_db_version >= FWP_SCHEMA_21) : // WordPress 2.1 and 2.2, but not 2.3
102 - require_once (ABSPATH . WPINC . '/registration.php'); // for wp_insert_user
103 - require_once (ABSPATH . 'wp-admin/admin-db.php'); // for wp_insert_category
104 - elseif ($wp_db_version >= FWP_SCHEMA_20) : // WordPress 2.0
105 - require_once (ABSPATH . WPINC . '/registration-functions.php'); // for wp_insert_user
106 - require_once (ABSPATH . 'wp-admin/admin-db.php'); // for wp_insert_category
107 - endif;
108 -endif;
108 +require_once (ABSPATH . WPINC . '/registration.php'); // for wp_insert_user
109 109
110 +require_once(dirname(__FILE__) . '/admin-ui.php');
111 +require_once(dirname(__FILE__) . '/feedwordpresssyndicationpage.class.php');
110 112 require_once(dirname(__FILE__) . '/compatability.php'); // LEGACY API: Replicate or mock up functions for legacy support purposes
113 +
114 +require_once(dirname(__FILE__) . '/syndicatedpost.class.php');
115 +require_once(dirname(__FILE__) . '/syndicatedlink.class.php');
111 116 require_once(dirname(__FILE__) . '/feedwordpresshtml.class.php');
117 +require_once(dirname(__FILE__) . '/feedwordpress-content-type-sniffer.class.php');
112 118
113 119 // Magic quotes are just about the stupidest thing ever.
114 120 if (is_array($_POST)) :
115 121 $fwp_post = stripslashes_deep($_POST);
@@ -116,9 +122,9 @@
116 122 endif;
117 123
118 124 // Get the path relative to the plugins directory in which FWP is stored
119 125 preg_match (
120 - '|/wp-content/plugins/(.+)$|',
126 + '|'.preg_quote(WP_PLUGIN_DIR).'/(.+)$|',
121 127 dirname(__FILE__),
122 128 $ref
123 129 );
124 130
@@ -127,36 +133,23 @@
127 133 else : // Something went wrong. Let's just guess.
128 134 $fwp_path = 'feedwordpress';
129 135 endif;
130 136
131 -function feedwordpress_admin_scripts () {
132 - wp_enqueue_script('post'); // for magic tag and category boxes
133 - wp_enqueue_script('admin-forms'); // for checkbox selection
134 -}
135 -
136 137 // If this is a FeedWordPress admin page, queue up scripts for AJAX functions that FWP uses
137 138 // If it is a display page or a non-FeedWordPress admin page, don't.
138 -if (is_admin() and isset($_REQUEST['page']) and preg_match("|^{$fwp_path}/|", $_REQUEST['page'])) :
139 - if (function_exists('wp_enqueue_script')) :
140 - if (FeedWordPressCompatibility::test_version(FWP_SCHEMA_29)) :
141 - add_action('admin_print_scripts', 'feedwordpress_admin_scripts');
142 - elseif (FeedWordPressCompatibility::test_version(FWP_SCHEMA_25)) :
143 - wp_enqueue_script('post'); // for magic tag and category boxes
144 - wp_enqueue_script('thickbox'); // for fold-up boxes
145 - wp_enqueue_script('admin-forms'); // for checkbox selection
146 - else :
147 - wp_enqueue_script( 'ajaxcat' ); // Provides the handy-dandy new category text box
148 - endif;
149 - endif;
150 - if (function_exists('wp_enqueue_style')) :
151 - if (fwp_test_wp_version(FWP_SCHEMA_25)) :
152 - wp_enqueue_style('dashboard');
153 - endif;
154 - endif;
139 +wp_register_style('feedwordpress-elements', WP_PLUGIN_URL.'/'.$fwp_path.'/feedwordpress-elements.css');
140 +if (FeedWordPressSettingsUI::is_admin()) :
141 + // For JavaScript that needs to be generated dynamically
142 + add_action('admin_print_scripts', array('FeedWordPressSettingsUI', 'admin_scripts'));
143 +
144 + // For CSS that needs to be generated dynamically.
145 + add_action('admin_print_styles', array('FeedWordPressSettingsUI', 'admin_styles'));
146 +
147 + wp_enqueue_style('dashboard');
148 + wp_enqueue_style('feedwordpress-elements');
149 +
155 150 if (function_exists('wp_admin_css')) :
156 - if (fwp_test_wp_version(FWP_SCHEMA_25)) :
157 - wp_admin_css('css/dashboard');
158 - endif;
151 + wp_admin_css('css/dashboard');
159 152 endif;
160 153 endif;
161 154
162 155 if (!FeedWordPress::needs_upgrade()) : // only work if the conditions are safe!
@@ -179,9 +172,9 @@
179 172
180 173 add_action('atom_entry', 'feedwordpress_item_feed_data');
181 174
182 175 # Filter in original permalinks if the user wants that
183 - add_filter('post_link', 'syndication_permalink', 1);
176 + add_filter('post_link', 'syndication_permalink', /*priority=*/ 1, /*arguments=*/ 3);
184 177
185 178 # When foreign URLs are used for permalinks in feeds or display
186 179 # contexts, they need to be escaped properly.
187 180 add_filter('the_permalink', 'syndication_permalink_escaped');
@@ -202,11 +195,13 @@
202 195
203 196 add_action('admin_menu', 'feedwordpress_add_post_edit_controls');
204 197 add_action('save_post', 'feedwordpress_save_post_edit_controls');
205 198
199 + add_action('admin_footer', array('FeedWordPress', 'admin_footer'));
200 +
206 201 # Inbound XML-RPC update methods
207 - add_filter('xmlrpc_methods', 'feedwordpress_xmlrpc_hook');
208 -
202 + $feedwordpressRPC = new FeedWordPressRPC;
203 +
209 204 # Outbound XML-RPC ping reform
210 205 remove_action('publish_post', 'generic_ping'); // WP 1.5.x
211 206 remove_action('do_pings', 'do_all_pings', 10, 1); // WP 2.1, 2.2
212 207 remove_action('publish_post', '_publish_post_hook', 5, 1); // WP 2.3
@@ -215,39 +210,25 @@
215 210 add_action('do_pings', 'fwp_do_pings', 10, 1);
216 211 add_action('feedwordpress_update', 'fwp_hold_pings');
217 212 add_action('feedwordpress_update_complete', 'fwp_release_pings');
218 213
219 - # Hook in logging functions only if the logging option is ON
220 - $update_logging = get_option('feedwordpress_update_logging');
221 - if ($update_logging == 'yes') :
222 - add_action('post_syndicated_item', 'log_feedwordpress_post', 100);
223 - add_action('update_syndicated_item', 'log_feedwordpress_update_post', 100);
224 - add_action('feedwordpress_update', 'log_feedwordpress_update_feeds', 100);
225 - add_action('feedwordpress_check_feed', 'log_feedwordpress_check_feed', 100);
226 - add_action('feedwordpress_update_complete', 'log_feedwordpress_update_complete', 100);
227 - endif;
214 + add_action('syndicated_feed_error', array('FeedWordPressDiagnostic', 'feed_error'), 100, 3);
215 +
216 + add_action('wp_footer', 'debug_out_feedwordpress_footer', -100);
217 + add_action('admin_footer', 'debug_out_feedwordpress_footer', -100);
228 218
229 - if (FeedWordPress::update_requested()) :
230 - if (FEEDWORDPRESS_DEBUG) :
231 - add_action('post_syndicated_item', 'debug_out_feedwordpress_post', 100);
232 - add_action('update_syndicated_item', 'debug_out_feedwordpress_update_post', 100);
233 - add_action('feedwordpress_update', 'debug_out_feedwordpress_update_feeds', 100);
234 - add_action('feedwordpress_check_feed', 'debug_out_feedwordpress_check_feed', 100);
235 - add_action('feedwordpress_update_complete', 'debug_out_feedwordpress_update_complete', 100);
236 - endif;
219 + $feedwordpress = new FeedWordPress;
237 220
238 - add_action('feedwordpress_check_feed_complete', 'debug_out_feedwordpress_feed_error', 100, 3);
239 - endif;
240 -
241 221 # Cron-less auto-update. Hooray!
242 222 $autoUpdateHook = get_option('feedwordpress_automatic_updates');
243 223 if ($autoUpdateHook != 'init') :
244 224 $autoUpdateHook = 'shutdown';
245 225 endif;
246 - add_action($autoUpdateHook, 'feedwordpress_auto_update');
226 + add_action($autoUpdateHook, array(&$feedwordpress, 'auto_update'));
227 + add_action('init', array(&$feedwordpress, 'init'));
228 + add_action('shutdown', array(&$feedwordpress, 'email_diagnostic_log'));
229 + add_action('wp_dashboard_setup', array(&$feedwordpress, 'dashboard_setup'));
247 230
248 - add_action('init', 'feedwordpress_update_magic_url');
249 -
250 231 # Default sanitizers
251 232 add_filter('syndicated_item_content', array('SyndicatedPost', 'resolve_relative_uris'), 0, 2);
252 233 add_filter('syndicated_item_content', array('SyndicatedPost', 'sanitize_content'), 0, 2);
253 234
@@ -255,127 +236,73 @@
255 236 # Hook in the menus, which will just point to the upgrade interface
256 237 add_action('admin_menu', 'fwp_add_pages');
257 238 endif; // if (!FeedWordPress::needs_upgrade())
258 239
259 -function feedwordpress_auto_update () {
260 - if (FeedWordPress::stale()) :
261 - $feedwordpress = new FeedWordPress;
262 - $feedwordpress->update();
263 - endif;
264 -} /* feedwordpress_auto_update () */
265 -
266 -function feedwordpress_update_magic_url () {
267 - global $wpdb;
268 -
269 - // Explicit update request in the HTTP request (e.g. from a cron job)
270 - if (FeedWordPress::update_requested()) :
271 - $feedwordpress = new FeedWordPress;
272 - $feedwordpress->update(FeedWordPress::update_requested_url());
273 -
274 - if (FEEDWORDPRESS_DEBUG and count($wpdb->queries) > 0) :
275 - $mysqlTime = 0.0;
276 - $byTime = array();
277 - foreach ($wpdb->queries as $query) :
278 - $time = $query[1] * 1000000.0;
279 - $mysqlTime += $query[1];
280 - if (!isset($byTime[$time])) : $byTime[$time] = array(); endif;
281 - $byTime[$time][] = $query[0]. ' // STACK: ' . $query[2];
282 - endforeach;
283 - krsort($byTime);
284 -
285 - foreach ($byTime as $time => $querySet) :
286 - foreach ($querySet as $query) :
287 - print "[".(sprintf('%4.4f', $time/1000.0)) . "ms] $query\n";
288 - endforeach;
289 - endforeach;
290 - echo "[feedwordpress] $wpdb->num_queries queries. $mysqlTime seconds in MySQL. Total of "; timer_stop(1); print " seconds.";
291 - endif;
292 -
293 -
294 - // Magic URL should return nothing but a 200 OK header packet
295 - // when successful.
296 - exit;
297 - endif;
298 -} /* feedwordpress_magic_update_url () */
299 -
300 240 ################################################################################
301 241 ## LOGGING FUNCTIONS: log status updates to error_log if you want it ###########
302 242 ################################################################################
303 243
304 -function log_feedwordpress_post ($id) {
305 - $post = wp_get_single_post($id);
306 - error_log("[".date('Y-m-d H:i:s')."][feedwordpress] posted "
307 - ."'{$post->post_title}' ({$post->post_date})");
308 -}
244 +class FeedWordPressDiagnostic {
245 + function feed_error ($error, $old, $link) {
246 + $wpError = $error['object'];
247 + $url = $link->uri();
248 +
249 + $mesgs = $wpError->get_error_messages();
250 + foreach ($mesgs as $mesg) :
251 + $mesg = esc_html($mesg);
252 + FeedWordPress::diagnostic(
253 + 'updated_feeds:errors',
254 + "Feed Error: [${url}] update returned error: $mesg"
255 + );
256 + if ($error['ts'] > $error['since']) :
257 + $since = date('r', $error['since']);
258 + $mostRecent = date('r', $error['ts']);
259 + FeedWordPress::diagnostic(
260 + 'updated_feeds:errors:persistent',
261 + "Feed Update Error: [${url}] returning errors"
262 + ." since ${since}:<br/><code>$mesg</code>",
263 + $url, $error['since'], $error['ts']
264 + );
265 + endif;
266 + endforeach;
267 + }
309 268
310 -function log_feedwordpress_update_post ($id) {
311 - $post = wp_get_single_post($id);
312 - error_log("[".date('Y-m-d H:i:s')."][feedwordpress] updated "
313 - ."'{$post->post_title}' ({$post->post_date})"
314 - ." (as of {$post->post_modified})");
315 -}
269 + function admin_emails ($id = '') {
270 + $users = get_users_of_blog($id);
271 + $recipients = array();
272 + foreach ($users as $user) :
273 + $dude = new WP_User($user->user_id);
274 + if ($dude->has_cap('administrator')) :
275 + if ($dude->user_email) :
276 + $recipients[] = $dude->user_email;
277 + endif;
278 + endif;
279 + endforeach;
280 + return $recipients;
281 + }
282 +} /* class FeedWordPressDiagnostic */
316 283
317 -function log_feedwordpress_update_feeds ($uri) {
318 - error_log("[".date('Y-m-d H:i:s')."][feedwordpress] update('$uri')");
284 +function debug_out_human_readable_bytes ($quantity) {
285 + $quantity = (int) $quantity;
286 + $magnitude = 'B';
287 + $orders = array('KB', 'MB', 'GB', 'TB');
288 + while (($quantity > (1024*100)) and (count($orders) > 0)) :
289 + $quantity = floor($quantity / 1024);
290 + $magnitude = array_shift($orders);
291 + endwhile;
292 + return "${quantity} ${magnitude}";
319 293 }
320 294
321 -function log_feedwordpress_check_feed ($feed) {
322 - $uri = $feed['link/uri']; $name = $feed['link/name'];
323 - error_log("[".date('Y-m-d H:i:s')."][feedwordpress] Examining $name <$uri>");
324 -}
325 -
326 -function log_feedwordpress_update_complete ($delta) {
327 - $mesg = array();
328 - if (isset($delta['new'])) $mesg[] = 'added '.$delta['new'].' new posts';
329 - if (isset($delta['updated'])) $mesg[] = 'updated '.$delta['updated'].' existing posts';
330 - if (empty($mesg)) $mesg[] = 'nothing changed';
331 -
332 - error_log("[".date('Y-m-d H:i:s')."][feedwordpress] "
333 - .(is_null($delta) ? "Error: I don't syndicate that URI"
334 - : implode(' and ', $mesg)));
335 -}
336 -
337 -function debug_out_feedwordpress_post ($id) {
338 - $post = wp_get_single_post($id);
339 - print ("[".date('Y-m-d H:i:s')."][feedwordpress] posted "
340 - ."'{$post->post_title}' ({$post->post_date})\n");
341 -}
342 -
343 -function debug_out_feedwordpress_update_post ($id) {
344 - $post = wp_get_single_post($id);
345 - print ("[".date('Y-m-d H:i:s')."][feedwordpress] updated "
346 - ."'{$post->post_title}' ({$post->post_date})"
347 - ." (as of {$post->post_modified})\n");
348 -}
349 -
350 -function debug_out_feedwordpress_update_feeds ($uri) {
351 - print ("[".date('Y-m-d H:i:s')."][feedwordpress] update('$uri')\n");
352 -}
353 -
354 -function debug_out_feedwordpress_check_feed ($feed) {
355 - $uri = $feed['link/uri']; $name = $feed['link/name'];
356 - print ("[".date('Y-m-d H:i:s')."][feedwordpress] Examining $name <$uri>\n");
357 -}
358 -
359 -function debug_out_feedwordpress_update_complete ($delta) {
360 - $mesg = array();
361 - if (isset($delta['new'])) $mesg[] = 'added '.$delta['new'].' new posts';
362 - if (isset($delta['updated'])) $mesg[] = 'updated '.$delta['updated'].' existing posts';
363 - if (empty($mesg)) $mesg[] = 'nothing changed';
364 -
365 - print ("[".date('Y-m-d H:i:s')."][feedwordpress] "
366 - .(is_null($delta) ? "Error: I don't syndicate that URI"
367 - : implode(' and ', $mesg))."\n");
368 -}
369 -
370 -function debug_out_feedwordpress_feed_error ($feed, $added, $dt) {
371 - if (is_wp_error($added)) :
372 - $mesgs = $added->get_error_messages();
373 - foreach ($mesgs as $mesg) :
374 - echo "[feedwordpress] Error updating [{$feed['link/uri']}]: $mesg\n";
375 - endforeach;
295 +function debug_out_feedwordpress_footer () {
296 + if (FeedWordPress::diagnostic_on('memory_usage')) :
297 + if (function_exists('memory_get_usage')) :
298 + FeedWordPress::diagnostic ('memory_usage', "Memory: Current usage: ".debug_out_human_readable_bytes(memory_get_usage()));
299 + endif;
300 + if (function_exists('memory_get_peak_usage')) :
301 + FeedWordPress::diagnostic ('memory_usage', "Memory: Peak usage: ".debug_out_human_readable_bytes(memory_get_peak_usage()));
302 + endif;
376 303 endif;
377 -}
304 +} /* debug_out_feedwordpress_footer() */
378 305
379 306 ################################################################################
380 307 ## TEMPLATE API: functions to make your templates syndication-aware ############
381 308 ################################################################################
@@ -392,34 +319,16 @@
392 319 function is_syndicated ($id = NULL) {
393 320 return (strlen(get_syndication_feed_id($id)) > 0);
394 321 } /* function is_syndicated() */
395 322
396 -function get_syndication_source_link ($original = NULL, $id = NULL) {
397 - if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
398 - endif;
399 -
400 - if ($original) : $vals = get_post_custom_values('syndication_source_uri_original', $id);
401 - else : $vals = array();
402 - endif;
403 -
404 - if (count($vals) == 0) : $vals = get_post_custom_values('syndication_source_uri', $id);
405 - endif;
406 -
407 - if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
408 -
409 - return $ret;
410 -} /* function get_syndication_source_link() */
411 -
412 -function the_syndication_source_link ($original = NULL, $id = NULL) {
413 - echo get_syndication_source_link($original, $id);
414 -}
415 -
416 323 function feedwordpress_display_url ($url, $before = 60, $after = 0) {
417 324 $bits = parse_url($url);
418 325
419 326 // Strip out crufty subdomains
420 - $bits['host'] = preg_replace('/^www[0-9]*\./i', '', $bits['host']);
421 -
327 + if (isset($bits['host'])) :
328 + $bits['host'] = preg_replace('/^www[0-9]*\./i', '', $bits['host']);
329 + endif;
330 +
422 331 // Reassemble bit-by-bit with minimum of crufty elements
423 332 $url = (isset($bits['user'])?$bits['user'].'@':'')
424 333 .(isset($bits['host'])?$bits['host']:'')
425 334 .(isset($bits['path'])?$bits['path']:'')
@@ -430,77 +339,59 @@
430 339 $url = substr($url, 0, $before).'…'.substr($url, 0 - $after, $after);
431 340 endif;
432 341
433 342 return $url;
434 -}
343 +} /* feedwordpress_display_url () */
435 344
436 -function get_syndication_source ($original = NULL, $id = NULL) {
345 +function get_syndication_source_property ($original, $id, $local, $remote = NULL) {
346 + $ret = NULL;
437 347 if (is_null($original)) :
438 348 $original = FeedWordPress::use_aggregator_source_data();
439 349 endif;
440 -
441 - if ($original) :
442 - $vals = get_post_custom_values('syndication_source_original', $id);
443 - else :
444 - $vals = array();
350 +
351 + if (is_null($remote)) :
352 + $remote = $local . '_original';
445 353 endif;
446 354
447 - if (count($vals) == 0) :
448 - $vals = get_post_custom_values('syndication_source', $id);
355 + $vals = ($original ? get_post_custom_values($remote, $id) : array());
356 + if (count($vals) < 1) :
357 + $vals = get_post_custom_values($local, $id);
449 358 endif;
450 359
451 360 if (count($vals) > 0) :
452 361 $ret = $vals[0];
453 - else :
454 - $ret = NULL;
455 362 endif;
363 + return $ret;
364 +} /* function get_syndication_source_property () */
456 365
457 - if (is_null($ret) or strlen(trim($ret)) == 0) :
458 - // Fall back to URL of blog
366 +function the_syndication_source_link ($original = NULL, $id = NULL) { echo get_syndication_source_link($original, $id); }
367 +function get_syndication_source_link ($original = NULL, $id = NULL) {
368 + return get_syndication_source_property($original, $id, 'syndication_source_uri');
369 +} /* function get_syndication_source_link() */
370 +
371 +function the_syndication_source ($original = NULL, $id = NULL) { echo get_syndication_source($original, $id); }
372 +function get_syndication_source ($original = NULL, $id = NULL) {
373 + $ret = get_syndication_source_property($original, $id, 'syndication_source');
374 + if (is_null($ret) or strlen(trim($ret)) == 0) : // Fall back to URL of blog
459 375 $ret = feedwordpress_display_url(get_syndication_source_link());
460 376 endif;
461 -
462 377 return $ret;
463 378 } /* function get_syndication_source() */
464 379
465 -function the_syndication_source ($original = NULL, $id = NULL) { echo get_syndication_source($original, $id); }
466 -
380 +function the_syndication_feed ($original = NULL, $id = NULL) { echo get_syndication_feed($original, $id); }
467 381 function get_syndication_feed ($original = NULL, $id = NULL) {
468 - if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
469 - endif;
470 -
471 - if ($original) : $vals = get_post_custom_values('syndication_feed_original', $id);
472 - else : $vals = array();
473 - endif;
474 -
475 - if (count($vals) == 0) : $vals = get_post_custom_values('syndication_feed', $id);
476 - endif;
477 -
478 - if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
479 -
480 - return $ret;
382 + return get_syndication_source_property($original, $id, 'syndication_feed');
481 383 } /* function get_syndication_feed() */
482 384
483 -function the_syndication_feed ($original = NULL, $id = NULL) { echo get_syndication_feed($original, $id); }
484 -
385 +function the_syndication_feed_guid ($original = NULL, $id = NULL) { echo get_syndication_feed_guid($original, $id); }
485 386 function get_syndication_feed_guid ($original = NULL, $id = NULL) {
486 - if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
387 + $ret = get_syndication_source_property($original, $id, 'syndication_source_id');
388 + if (is_null($ret) or strlen(trim($ret))==0) : // Fall back to URL of feed
389 + $ret = get_syndication_feed();
487 390 endif;
488 -
489 - if ($original) : $vals = get_post_custom_values('syndication_source_id_original', $id);
490 - else : $vals = array();
491 - endif;
492 -
493 - if (count($vals) == 0) : $vals = array(get_feed_meta('feed/id', $id));
494 - endif;
495 -
496 - if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
497 -
498 391 return $ret;
499 392 } /* function get_syndication_feed_guid () */
500 393
501 -function the_syndication_feed_guid ($original = NULL, $id = NULL) { echo get_syndication_feed_guid($original, $id); }
502 -
503 394 function get_syndication_feed_id ($id = NULL) { list($u) = get_post_custom_values('syndication_feed_id', $id); return $u; }
504 395 function the_syndication_feed_id ($id = NULL) { echo get_syndication_feed_id($id); }
505 396
506 397 $feedwordpress_linkcache = array (); // only load links from database once
@@ -647,30 +538,43 @@
647 538 * @return string The new permalink. Same as the old if the post is not
648 539 * syndicated, or if FWP is set to use internal permalinks, or if the post
649 540 * was syndicated, but didn't have a proper permalink recorded.
650 541 *
651 - * @uses FeedWordPress::munge_permalinks()
542 + * @uses SyndicatedLink::setting()
652 543 * @uses get_syndication_permalink()
544 + * @uses get_syndication_feed_object()
545 + * @uses url_to_postid()
546 + * @global $id
653 547 * @global $feedwordpress_the_original_permalink
654 - */
655 -function syndication_permalink ($permalink = '') {
548 + */
549 +function syndication_permalink ($permalink = '', $post = null, $leavename = false) {
550 + global $id;
656 551 global $feedwordpress_the_original_permalink;
657 552
658 553 // Save the local permalink in case we need to retrieve it later.
659 554 $feedwordpress_the_original_permalink = $permalink;
660 555
661 - // Map this permalink to a post ID so we can get the correct permalink
662 - // even outside of the Post Loop. Props Björn.
663 - $id = url_to_postid($permalink);
556 + if (is_object($post) and isset($post->ID) and !empty($post->ID)) :
557 + // Use the post ID we've been provided with.
558 + $postId = $post->ID;
559 + elseif (is_string($permalink) and strlen($permalink) > 0) :
560 + // Map this permalink to a post ID so we can get the correct
561 + // permalink even outside of the Post Loop. Props Björn.
562 + $postId = url_to_postid($permalink);
563 + else :
564 + // If the permalink string is empty but Post Loop context
565 + // provides an id.
566 + $postId = $id;
567 + endif;
664 568
665 569 $munge = false;
666 - $link = get_syndication_feed_object($id);
570 + $link = get_syndication_feed_object($postId);
667 571 if (is_object($link)) :
668 572 $munge = ($link->setting('munge permalink', 'munge_permalink', 'yes') != 'no');
669 573 endif;
670 574
671 575 if ($munge):
672 - $uri = get_syndication_permalink($id);
576 + $uri = get_syndication_permalink($postId);
673 577 $permalink = ((strlen($uri) > 0) ? $uri : $permalink);
674 578 endif;
675 579 return $permalink;
676 580 } /* function syndication_permalink () */
@@ -686,8 +590,9 @@
686 590 * @uses FeedWordPress::munge_permalinks()
687 591 *
688 592 */
689 593 function syndication_permalink_escaped ($permalink) {
594 + /* FIXME: This should review link settings not just global settings */
690 595 if (is_syndicated() and FeedWordPress::munge_permalinks()) :
691 596 // This is a foreign link; WordPress can't vouch for its not
692 597 // having any entities that need to be &-escaped. So we'll do
693 598 // it here.
@@ -764,23 +669,23 @@
764 669 ## ADMIN MENU ADD-ONS: register Dashboard management pages #####################
765 670 ################################################################################
766 671
767 672 function fwp_add_pages () {
768 - global $fwp_capability;
769 673 global $fwp_path;
770 674
771 - $menu = array('Syndicated Sites', 'Syndication', $fwp_capability['manage_links'], $fwp_path.'/syndication.php', NULL);
772 - if (fwp_test_wp_version(FWP_SCHEMA_27)) :
773 - // add icon parameter
774 - $menu[] = WP_PLUGIN_URL.'/'.$fwp_path.'/feedwordpress-tiny.png';
775 - endif;
776 -
777 - call_user_func_array('add_menu_page', $menu);
778 - add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Feeds & Updates', 'Feeds & Updates', $fwp_capability['manage_options'], $fwp_path.'/feeds-page.php');
779 - add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Posts & Links', 'Posts & Links', $fwp_capability['manage_options'], $fwp_path.'/posts-page.php');
780 - add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Authors', 'Authors', $fwp_capability['manage_options'], $fwp_path.'/authors-page.php');
781 - add_submenu_page($fwp_path.'/syndication.php', 'Categories'.FEEDWORDPRESS_AND_TAGS, 'Categories'.FEEDWORDPRESS_AND_TAGS, $fwp_capability['manage_options'], $fwp_path.'/categories-page.php');
782 - add_submenu_page($fwp_path.'/syndication.php', 'FeedWordPress Back End', 'Back End', $fwp_capability['manage_options'], $fwp_path.'/backend-page.php');
675 + add_menu_page('Syndicated Sites', 'Syndication', 'manage_links', $fwp_path.'/syndication.php', NULL, WP_PLUGIN_URL.'/'.$fwp_path.'/feedwordpress-tiny.png');
676 + do_action('feedwordpress_admin_menu_pre_feeds');
677 + add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Feeds & Updates', 'Feeds & Updates', 'manage_options', $fwp_path.'/feeds-page.php');
678 + do_action('feedwordpress_admin_menu_pre_posts');
679 + add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Posts & Links', 'Posts & Links', 'manage_options', $fwp_path.'/posts-page.php');
680 + do_action('feedwordpress_admin_menu_pre_authors');
681 + add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Authors', 'Authors', 'manage_options', $fwp_path.'/authors-page.php');
682 + do_action('feedwordpress_admin_menu_pre_categories');
683 + add_submenu_page($fwp_path.'/syndication.php', 'Categories'.FEEDWORDPRESS_AND_TAGS, 'Categories'.FEEDWORDPRESS_AND_TAGS, 'manage_options', $fwp_path.'/categories-page.php');
684 + do_action('feedwordpress_admin_menu_pre_performance');
685 + add_submenu_page($fwp_path.'/syndication.php', 'FeedWordPress Performance', 'Performance', 'manage_options', $fwp_path.'/performance-page.php');
686 + do_action('feedwordpress_admin_menu_pre_diagnostics');
687 + add_submenu_page($fwp_path.'/syndication.php', 'FeedWordPress Diagnostics', 'Diagnostics', 'manage_options', $fwp_path.'/diagnostics-page.php');
783 688 } /* function fwp_add_pages () */
784 689
785 690 function fwp_check_debug () {
786 691 // This is a horrible fucking kludge that I have to do because the
@@ -909,14 +814,16 @@
909 814 endif;
910 815
911 816 // OK, we're golden. Now let's save some data.
912 817 if (isset($_POST['freeze_updates'])) :
913 - update_post_meta($post_id, '_syndication_freeze_updates', $_POST['freeze_updates']);
818 + update_post_meta($post_id, '_syndication_freeze_updates', $_POST['freeze_updates']);
819 + $ret = $_POST['freeze_updates'];
914 820 else :
915 821 delete_post_meta($post_id, '_syndication_freeze_updates');
822 + $ret = NULL;
916 823 endif;
917 824
918 - return $_POST['freeze_updates'];
825 + return $ret;
919 826 } // function feedwordpress_save_edit_controls
920 827
921 828 ################################################################################
922 829 ## class FeedWordPress #########################################################
@@ -1022,9 +929,9 @@
1022 929 if (FeedWordPress::needs_upgrade()) : // Will make duplicate posts if we don't hold off
1023 930 return NULL;
1024 931 endif;
1025 932
1026 - if (!is_null($uri)) :
933 + if (!is_null($uri) and $uri != '*') :
1027 934 $uri = trim($uri);
1028 935 else : // Update all
1029 936 update_option('feedwordpress_last_update_all', time());
1030 937 endif;
@@ -1038,13 +945,15 @@
1038 945 else :
1039 946 $crash_ts = NULL;
1040 947 endif;
1041 948 endif;
1042 -
949 +
1043 950 // Randomize order for load balancing purposes
1044 951 $feed_set = $this->feeds;
1045 952 shuffle($feed_set);
1046 953
954 + $feed_set = apply_filters('feedwordpress_update_feeds', $feed_set, $uri);
955 +
1047 956 // Loop through and check for new posts
1048 957 $delta = NULL;
1049 958 foreach ($feed_set as $feed) :
1050 959 if (!is_null($crash_ts) and (time() > $crash_ts)) : // Check whether we've exceeded the time limit
@@ -1058,9 +967,9 @@
1058 967 else :
1059 968 $timely = $feed->stale();
1060 969 endif;
1061 970
1062 - if ($pinged_that and is_null($delta)) : // If at least one feed was hit for updating...
971 + if ($pinged_that and is_null($delta)) : // If at least one feed was hit for updating...
1063 972 $delta = array('new' => 0, 'updated' => 0); // ... don't return error condition
1064 973 endif;
1065 974
1066 975 if ($pinged_that and $timely) :
@@ -1110,9 +1019,118 @@
1110 1019 $ret = false;
1111 1020 endif;
1112 1021 return $ret;
1113 1022 } // FeedWordPress::stale()
1023 +
1024 + function init () {
1025 + $this->clear_cache_magic_url();
1026 + $this->update_magic_url();
1027 + } /* FeedWordPress::init() */
1114 1028
1029 + function dashboard_setup () {
1030 + // Get the stylesheet
1031 + wp_enqueue_style('feedwordpress-elements');
1032 +
1033 + $widget_id = 'feedwordpress_dashboard';
1034 + $widget_name = __('Syndicated Sources');
1035 + $column = 'side';
1036 + $priority = 'core';
1037 +
1038 + // I would love to use wp_add_dashboard_widget() here and save
1039 + // myself some trouble. But WP 3 does not yet have any way to
1040 + // push a dashboard widget onto the side, or to give it a default
1041 + // location.
1042 + add_meta_box(
1043 + /*id=*/ $widget_id,
1044 + /*title=*/ $widget_name,
1045 + /*callback=*/ array(&$this, 'dashboard'),
1046 + /*page=*/ 'dashboard',
1047 + /*context=*/ $column,
1048 + /*priority=*/ $priority
1049 + );
1050 + /*control_callback= array(&$this, 'dashboard_control') */
1051 +
1052 + // This is kind of rude, I know, but the dashboard widget isn't
1053 + // worth much if users don't know that it exists, and I don't
1054 + // know of any better way to reorder the boxen.
1055 + //
1056 + // Gleefully ripped off of codex.wordpress.org/Dashboard_Widgets_API
1057 +
1058 + // Globalize the metaboxes array, this holds all the widgets for wp-admin
1059 + global $wp_meta_boxes;
1060 +
1061 + // Get the regular dashboard widgets array
1062 + // (which has our new widget already but at the end)
1063 +
1064 + $normal_dashboard = $wp_meta_boxes['dashboard'][$column][$priority];
1065 +
1066 + // Backup and delete our new dashbaord widget from the end of the array
1067 + if (isset($normal_dashboard[$widget_id])) :
1068 + $backup = array();
1069 + $backup[$widget_id] = $normal_dashboard[$widget_id];
1070 + unset($normal_dashboard[$widget_id]);
1071 +
1072 + // Merge the two arrays together so our widget is at the
1073 + // beginning
1074 + $sorted_dashboard = array_merge($backup, $normal_dashboard);
1075 +
1076 + // Save the sorted array back into the original metaboxes
1077 + $wp_meta_boxes['dashboard'][$column][$priority] = $sorted_dashboard;
1078 + endif;
1079 + } /* FeedWordPress::dashboard_setup () */
1080 +
1081 + function dashboard () {
1082 + $syndicationPage = new FeedWordPressSyndicationPage(dirname(__FILE__).'/syndication.php');
1083 + $syndicationPage->dashboard_box($syndicationPage);
1084 + } /* FeedWordPress::dashboard () */
1085 +
1086 + function update_magic_url () {
1087 + global $wpdb;
1088 +
1089 + // Explicit update request in the HTTP request (e.g. from a cron job)
1090 + if ($this->update_requested()) :
1091 + $this->update($this->update_requested_url());
1092 +
1093 + if (FEEDWORDPRESS_DEBUG and count($wpdb->queries) > 0) :
1094 + $mysqlTime = 0.0;
1095 + $byTime = array();
1096 + foreach ($wpdb->queries as $query) :
1097 + $time = $query[1] * 1000000.0;
1098 + $mysqlTime += $query[1];
1099 + if (!isset($byTime[$time])) : $byTime[$time] = array(); endif;
1100 + $byTime[$time][] = $query[0]. ' // STACK: ' . $query[2];
1101 + endforeach;
1102 + krsort($byTime);
1103 +
1104 + foreach ($byTime as $time => $querySet) :
1105 + foreach ($querySet as $query) :
1106 + print "[".(sprintf('%4.4f', $time/1000.0)) . "ms] $query\n";
1107 + endforeach;
1108 + endforeach;
1109 + echo $this->log_prefix()."$wpdb->num_queries queries. $mysqlTime seconds in MySQL. Total of "; timer_stop(1); print " seconds.";
1110 + endif;
1111 +
1112 + debug_out_feedwordpress_footer();
1113 +
1114 + // Magic URL should return nothing but a 200 OK header packet
1115 + // when successful.
1116 + exit;
1117 + endif;
1118 + } /* FeedWordPress::magic_update_url () */
1119 +
1120 + function clear_cache_magic_url () {
1121 + if ($this->clear_cache_requested()) :
1122 + $this->clear_cache();
1123 + endif;
1124 + } /* FeedWordPress::clear_cache_magic_url() */
1125 +
1126 + function clear_cache_requested () {
1127 + return (
1128 + isset($_GET['clear_cache'])
1129 + and $_GET['clear_cache']
1130 + );
1131 + } /* FeedWordPress::clear_cache_requested() */
1132 +
1115 1133 function update_requested () {
1116 1134 return (
1117 1135 isset($_REQUEST['update_feedwordpress'])
1118 1136 and $_REQUEST['update_feedwordpress']
@@ -1119,60 +1137,56 @@
1119 1137 );
1120 1138 } // FeedWordPress::update_requested()
1121 1139
1122 1140 function update_requested_url () {
1123 - $ret = null;
1124 -
1125 - if (($_REQUEST['update_feedwordpress']=='*')
1126 - or (preg_match('|^http://.*|i', $_REQUEST['update_feedwordpress']))) :
1127 - $ret = $_REQUEST['update_feedwordpress'];
1128 - endif;
1141 + $ret = null;
1142 +
1143 + if (($_REQUEST['update_feedwordpress']=='*')
1144 + or (preg_match('|^http://.*|i', $_REQUEST['update_feedwordpress']))) :
1145 + $ret = $_REQUEST['update_feedwordpress'];
1146 + endif;
1129 1147
1130 - return $ret;
1148 + return $ret;
1131 1149 } // FeedWordPress::update_requested_url()
1132 1150
1133 - function syndicate_link ($name, $uri, $rss) {
1151 + function auto_update () {
1152 + if ($this->stale()) :
1153 + $this->update();
1154 + endif;
1155 + } /* FeedWordPress::auto_update () */
1156 +
1157 + function find_link ($uri, $field = 'link_rss') {
1134 1158 global $wpdb;
1135 1159
1160 + $unslashed = untrailingslashit($uri);
1161 + $slashed = trailingslashit($uri);
1162 + $link_id = $wpdb->get_var($wpdb->prepare("
1163 + SELECT link_id FROM $wpdb->links WHERE $field IN ('%s', '%s')
1164 + LIMIT 1", $unslashed, $slashed
1165 + ));
1166 +
1167 + return $link_id;
1168 + } /* FeedWordPress::find_link () */
1169 +
1170 + function syndicate_link ($name, $uri, $rss) {
1136 1171 // Get the category ID#
1137 1172 $cat_id = FeedWordPress::link_category_id();
1138 1173
1139 1174 // WordPress gets cranky if there's no homepage URI
1140 - if (!isset($uri) or strlen($uri)<1) : $uri = $rss; endif;
1175 + if (!is_string($uri) or strlen($uri)<1) : $uri = $rss; endif;
1141 1176
1142 - if (function_exists('wp_insert_link')) : // WordPress 2.x
1143 - if (FeedWordPressCompatibility::test_version(0, FWP_SCHEMA_21)) :
1144 - // Morons.
1145 - $name = $wpdb->escape($name);
1146 - $uri = $wpdb->escape($uri);
1147 - $rss = $wpdb->escape($rss);
1148 -
1149 - // Comes in as a single category
1150 - $linkCats = $cat_id;
1151 - else :
1152 - // Comes in as an array of categories
1153 - $linkCats = array($cat_id);
1154 - endif;
1177 + // Check if this feed URL is already being syndicated.
1178 + $link_id = wp_insert_link(array(
1179 + "link_id" => FeedWordPress::find_link($rss), // insert if nothing was found; else update
1180 + "link_rss" => $rss,
1181 + "link_name" => $name,
1182 + "link_url" => $uri,
1183 + "link_category" => array($cat_id),
1184 + "link_visible" => 'Y', // reactivate if inactivated
1185 + ));
1155 1186
1156 - $link_id = wp_insert_link(array(
1157 - "link_name" => $name,
1158 - "link_url" => $uri,
1159 - "link_category" => $linkCats,
1160 - "link_rss" => $rss
1161 - ));
1162 - else : // WordPress 1.5.x
1163 - $result = $wpdb->query("
1164 - INSERT INTO $wpdb->links
1165 - SET
1166 - link_name = '".$wpdb->escape($name)."',
1167 - link_url = '".$wpdb->escape($uri)."',
1168 - link_category = '".$wpdb->escape($cat_id)."',
1169 - link_rss = '".$wpdb->escape($rss)."'
1170 - ");
1171 - $link_id = $wpdb->insert_id;
1172 - endif;
1173 1187 return $link_id;
1174 - } // function FeedWordPress::syndicate_link()
1188 + } /* function FeedWordPress::syndicate_link() */
1175 1189
1176 1190 /*static*/ function syndicated_status ($what, $default) {
1177 1191 $ret = get_option("feedwordpress_syndicated_{$what}_status");
1178 1192 if (!$ret) :
@@ -1180,28 +1194,16 @@
1180 1194 endif;
1181 1195 return $ret;
1182 1196 } /* FeedWordPress::syndicated_status() */
1183 1197
1184 - function on_unfamiliar ($what = 'author', $override = NULL) {
1185 - $set = array(
1186 - 'author' => array('create', 'default', 'filter'),
1187 - 'category' => array('create', 'tag', 'default', 'filter'),
1188 - );
1198 + function on_unfamiliar ($what = 'author') {
1199 + switch ($what) :
1200 + case 'category' : $suffix = ':category'; break;
1201 + case 'post_tag' : $suffix = ':post_tag'; break;
1202 + default: $suffix = '';
1203 + endswitch;
1189 1204
1190 - if (is_string($override)) :
1191 - $ret = strtolower($override);
1192 - else :
1193 - $ret = NULL;
1194 - endif;
1195 -
1196 - if (!is_numeric($override) and !in_array($ret, $set[$what])) :
1197 - $ret = get_option('feedwordpress_unfamiliar_'.$what);
1198 - if (!is_numeric($ret) and !in_array($ret, $set[$what])) :
1199 - $ret = 'create';
1200 - endif;
1201 - endif;
1202 -
1203 - return $ret;
1205 + return get_option('feedwordpress_unfamiliar_'.$what, 'create'.$suffix);
1204 1206 } // function FeedWordPress::on_unfamiliar()
1205 1207
1206 1208 function null_email_set () {
1207 1209 $base = get_option('feedwordpress_null_email_set');
@@ -1238,15 +1240,14 @@
1238 1240 /*static*/ function munge_permalinks () {
1239 1241 return (get_option('feedwordpress_munge_permalink', /*default=*/ 'yes') != 'no');
1240 1242 } /* FeedWordPress::munge_permalinks() */
1241 1243
1242 - function syndicated_links () {
1244 + function syndicated_links ($args = array()) {
1243 1245 $contributors = FeedWordPress::link_category_id();
1244 - if (function_exists('get_bookmarks')) :
1245 - $links = get_bookmarks(array("category" => $contributors));
1246 - else:
1247 - $links = get_linkobjects($contributors); // deprecated as of WP 2.1
1248 - endif;
1246 + $links = get_bookmarks(array_merge(
1247 + array("category" => $contributors),
1248 + $args
1249 + ));
1249 1250 return $links;
1250 1251 } // function FeedWordPress::syndicated_links()
1251 1252
1252 1253 function link_category_id () {
@@ -1301,15 +1302,47 @@
1301 1302 update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
1302 1303 endif;
1303 1304 elseif ($fwp_db_version < 2009.0707) :
1304 1305 // We need to clear out any busted AJAX crap
1305 - if (fwp_test_wp_version(FWP_SCHEMA_HAS_USERMETA)) :
1306 - $wpdb->query("
1307 - DELETE FROM $wpdb->usermeta
1308 - WHERE LOCATE('feedwordpress', meta_key)
1309 - AND LOCATE('box', meta_key);
1310 - ");
1306 + $wpdb->query("
1307 + DELETE FROM $wpdb->usermeta
1308 + WHERE LOCATE('feedwordpress', meta_key)
1309 + AND LOCATE('box', meta_key);
1310 + ");
1311 +
1312 + update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
1313 + elseif ($fwp_db_version < 2010.0814) :
1314 + // Change in terminology.
1315 + if (get_option('feedwordpress_unfamiliar_category', 'create')=='default') :
1316 + update_option('feedwordpress_unfamiliar_category', 'null');
1311 1317 endif;
1318 + foreach (FeedWordPress::syndicated_links() as $link) :
1319 + $sub = new SyndicatedLink($link);
1320 +
1321 + $remap_uf = array(
1322 + 'default' => 'null',
1323 + 'filter' => 'null',
1324 + 'create' => 'create:category',
1325 + 'tag' => 'create:post_tag'
1326 + );
1327 + if (isset($sub->settings['unfamiliar category'])) :
1328 + if ($sub->settings['unfamiliar category']=='filter') :
1329 + $sub->settings['match/filter'] = array('category');
1330 + endif;
1331 + foreach ($remap_uf as $from => $to) :
1332 + if ($sub->settings['unfamiliar category']==$from) :
1333 + $sub->settings['unfamiliar category'] = $to;
1334 + endif;
1335 + endforeach;
1336 + endif;
1337 +
1338 + if (isset($sub->settings['add global categories'])) :
1339 + $sub->settings['add/category'] = $sub->settings['add global categories'];
1340 + unset($sub->settings['add global categories']);
1341 + endif;
1342 +
1343 + $sub->save_settings(/*reload=*/ true);
1344 + endforeach;
1312 1345 update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
1313 1346 else :
1314 1347 // No. Just brand it with the new version.
1315 1348 update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
@@ -1370,14 +1403,17 @@
1370 1403 DROP INDEX {$wpdb->posts}_guid_idx ON {$wpdb->posts}
1371 1404 ");
1372 1405 }
1373 1406
1374 - /*static*/ function fetch ($url) {
1375 - require_once (ABSPATH . WPINC . '/class-feed.php');
1407 + /*static*/ function fetch ($url, $force_feed = true) {
1376 1408 $feed = new SimplePie();
1377 1409 $feed->set_feed_url($url);
1378 1410 $feed->set_cache_class('WP_Feed_Cache');
1379 1411 $feed->set_file_class('WP_SimplePie_File');
1412 + $feed->set_content_type_sniffer_class('FeedWordPress_Content_Type_Sniffer');
1413 + $feed->set_file_class('FeedWordPress_File');
1414 + $feed->set_parser_class('FeedWordPress_Parser');
1415 + $feed->force_feed($force_feed);
1380 1416 $feed->set_cache_duration(FeedWordPress::cache_duration());
1381 1417 $feed->init();
1382 1418 $feed->handle_content_type();
1383 1419
@@ -1391,8 +1427,14 @@
1391 1427
1392 1428 function clear_cache () {
1393 1429 global $wpdb;
1394 1430
1431 + // Just in case, clear out any old MagpieRSS cache records.
1432 + $magpies = $wpdb->query("
1433 + DELETE FROM {$wpdb->options}
1434 + WHERE option_name LIKE 'rss_%' AND LENGTH(option_name) > 32
1435 + ");
1436 +
1395 1437 // The WordPress SimplePie module stores its cached feeds as
1396 1438 // transient records in the options table. The data itself is
1397 1439 // stored in `_transient_feed_{md5 of url}` and the last-modified
1398 1440 // timestamp in `_transient_feed_mod_{md5 of url}`. Timeouts for
@@ -1398,12 +1440,15 @@
1398 1440 // timestamp in `_transient_feed_mod_{md5 of url}`. Timeouts for
1399 1441 // these records are stored in `_transient_timeout_feed_{md5}`.
1400 1442 // Since the md5 is always 32 characters in length, the
1401 1443 // option_name is always over 32 characters.
1402 - $wpdb->query("
1444 + $simplepies = $wpdb->query("
1403 1445 DELETE FROM {$wpdb->options}
1404 1446 WHERE option_name LIKE '_transient%_feed_%' AND LENGTH(option_name) > 32
1405 1447 ");
1448 + $simplepies = (int) ($simplepies / 4); // Each transient has 4 rows: the data, the modified timestamp; and the timeouts for each
1449 +
1450 + return ($magpies + $simplepies);
1406 1451 } /* FeedWordPress::clear_cache () */
1407 1452
1408 1453 function cache_duration () {
1409 1454 $duration = NULL;
@@ -1436,9 +1481,8 @@
1436 1481 $affirmo = array ('y', 'yes', 't', 'true', 1);
1437 1482 return (isset($f[$setting]) and in_array(strtolower($f[$setting]), $affirmo));
1438 1483 }
1439 1484
1440 -
1441 1485 # Internal debugging functions
1442 1486 function critical_bug ($varname, $var, $line) {
1443 1487 global $wp_version;
1444 1488
@@ -1457,37 +1501,524 @@
1457 1501 if (FEEDWORDPRESS_DEBUG) : // halt only when we are doing debugging
1458 1502 FeedWordPress::critical_bug($varname, $var, $line);
1459 1503 endif;
1460 1504 }
1505 +
1506 + function val ($v, $no_newlines = false) {
1507 + ob_start();
1508 + var_dump($v);
1509 + $out = ob_get_contents(); ob_end_clean();
1510 +
1511 + if ($no_newlines) :
1512 + $out = preg_replace('/\s+/', " ", $out);
1513 + endif;
1514 + return $out;
1515 + } /* FeedWordPress::val () */
1516 +
1517 + function diagnostic_on ($level) {
1518 + $show = get_option('feedwordpress_diagnostics_show', array());
1519 + return (in_array($level, $show));
1520 + } /* FeedWordPress::diagnostic_on () */
1521 +
1522 + function diagnostic ($level, $out, $persist = NULL, $since = NULL, $mostRecent = NULL) {
1523 + global $feedwordpress_admin_footer;
1524 +
1525 + $output = get_option('feedwordpress_diagnostics_output', array());
1526 + $dlog = get_option('feedwordpress_diagnostics_log', array());
1527 +
1528 + $diagnostic_nesting = count(explode(":", $level));
1529 +
1530 + if (FeedWordPress::diagnostic_on($level)) :
1531 + foreach ($output as $method) :
1532 + switch ($method) :
1533 + case 'echo' :
1534 + echo "<div><pre><strong>Diag".str_repeat('====', $diagnostic_nesting-1).'|</strong> '.$out."</pre></div>";
1535 + break;
1536 + case 'echo_in_cronjob' :
1537 + if (FeedWordPress::update_requested()) :
1538 + echo FeedWordPress::log_prefix()." ".$out."\n";
1539 + endif;
1540 + break;
1541 + case 'admin_footer' :
1542 + $feedwordpress_admin_footer[] = $out;
1543 + break;
1544 + case 'error_log' :
1545 + error_log(FeedWordPress::log_prefix().' '.$out);
1546 + break;
1547 + case 'email' :
1548 + if (is_null($persist)) :
1549 + $sect = 'occurrent';
1550 + $hook = (isset($dlog['mesg'][$sect]) ? count($dlog['mesg'][$sect]) : 0);
1551 + $line = array("Time" => time(), "Message" => $out);
1552 + else :
1553 + $sect = 'persistent';
1554 + $hook = md5($level."\n".$persist);
1555 + $line = array("Since" => $since, "Message" => $out, "Most Recent" => $mostRecent);
1556 + endif;
1557 +
1558 + if (!isset($dlog['mesg'])) : $dlog['mesg'] = array(); endif;
1559 + if (!isset($dlog['mesg'][$sect])) : $dlog['mesg'][$sect] = array(); endif;
1560 +
1561 + $dlog['mesg'][$sect][$hook] = $line;
1562 + endswitch;
1563 + endforeach;
1564 + endif;
1565 +
1566 + update_option('feedwordpress_diagnostics_log', $dlog);
1567 + } /* FeedWordPress::diagnostic () */
1568 +
1569 + function email_diagnostic_log () {
1570 + $dlog = get_option('feedwordpress_diagnostics_log', array());
1571 +
1572 + $recipients = get_option('feedwordpress_diagnostics_log_recipients', NULL);
1573 + if (is_null($recipients)) :
1574 + $recipients = FeedWordPressDiagnostic::admin_emails();
1575 + endif;
1576 +
1577 + if (isset($dlog['schedule']) and isset($dlog['schedule']['last'])) :
1578 + if (time() > ($dlog['schedule']['last'] + $dlog['schedule']['freq'])) :
1579 + // No news is good news; only send if
1580 + // there are some messages to send.
1581 + $body = NULL;
1582 + foreach ($dlog['mesg'] as $sect => $mesgs) :
1583 + if (count($mesgs) > 0) :
1584 + if (is_null($body)) : $body = ''; endif;
1585 +
1586 + $paradigm = reset($mesgs);
1587 + $body .= "<h2>".ucfirst($sect)." issues</h2>\n"
1588 + ."<table>\n"
1589 + ."<thead><tr>\n";
1590 + foreach ($paradigm as $col => $value) :
1591 + $body .= '<th scope="col">'.$col."</th>\n";
1592 + endforeach;
1593 + $body .= "</tr></thead>\n"
1594 + ."<tbody>\n";
1595 +
1596 + foreach ($mesgs as $line) :
1597 + $body .= "<tr>\n";
1598 + foreach ($line as $col => $cell) :
1599 + if (is_numeric($cell)) :
1600 + $cell = date('j-M-y, h:i a', $cell);
1601 + endif;
1602 + $class = strtolower(preg_replace('/\s+/', '-', $col));
1603 + $body .= "<td class=\"$class\">${cell}</td>";
1604 + endforeach;
1605 + $body .= "</tr>\n";
1606 + endforeach;
1607 +
1608 + $body .= "</tbody>\n</table>\n\n";
1609 + endif;
1610 + endforeach;
1611 +
1612 + if (!is_null($body)) :
1613 + $home = feedwordpress_display_url(get_bloginfo('url'));
1614 + $subj = $home . " syndication issues for ".date('j-M-y', time());
1615 + $agent = 'FeedWordPress '.FEEDWORDPRESS_VERSION;
1616 + $body = <<<EOMAIL
1617 +<html>
1618 +<head>
1619 +<title>$subj</title>
1620 +<style type="text/css">
1621 + body { background-color: white; color: black; }
1622 + table { width: 100%; border: 1px solid black; }
1623 + table thead tr th { background-color: #ff7700; color: white; border-bottom: 1px solid black; }
1624 + table thead tr { border-bottom: 1px solid black; }
1625 + table tr { vertical-align: top; }
1626 + table .since { width: 20%; }
1627 + table .time { width: 20%; }
1628 + table .most-recently { width: 20%; }
1629 + table .message { width: auto; }
1630 +</style>
1631 +</head>
1632 +<body>
1633 +<h1>Syndication Issues encountered by $agent on $home</h1>
1634 +$body
1635 +</body>
1636 +</html>
1637 +
1638 +EOMAIL;
1639 + foreach ($recipients as $email) :
1640 + add_filter('wp_mail_content_type', array('FeedWordPress', 'allow_html_mail'));
1641 + wp_mail($email, $subj, $body);
1642 + remove_filter('wp_mail_content_type', array('FeedWordPress', 'allow_html_mail'));
1643 + endforeach;
1644 + endif;
1645 +
1646 + // Clear the logs
1647 + $dlog['mesg']['persistent'] = array();
1648 + $dlog['mesg']['occurrent'] = array();
1649 +
1650 + // Set schedule for next update
1651 + $dlog['schedule']['last'] = time();
1652 + endif;
1653 + else :
1654 + $dlog['schedule'] = array(
1655 + 'freq' =>24 /*hr*/ * 60 /*min*/ * 60 /*s*/,
1656 + 'last' => time(),
1657 + );
1658 + endif;
1659 +
1660 + update_option('feedwordpress_diagnostics_log', $dlog);
1661 + } /* FeedWordPress::email_diagnostic_log () */
1662 +
1663 + function allow_html_mail () {
1664 + return 'text/html';
1665 + } /* FeedWordPress::allow_html_mail () */
1666 +
1667 + function admin_footer () {
1668 + global $feedwordpress_admin_footer;
1669 + foreach ($feedwordpress_admin_footer as $line) :
1670 + echo '<div><pre>'.$line.'</pre></div>';
1671 + endforeach;
1672 + } /* FeedWordPress::admin_footer () */
1673 +
1674 + function log_prefix ($date = false) {
1675 + $home = get_bloginfo('url');
1676 + $prefix = '['.feedwordpress_display_url($home).'] [feedwordpress] ';
1677 + if ($date) :
1678 + $prefix = "[".date('Y-m-d H:i:s')."]".$prefix;
1679 + endif;
1680 + return $prefix;
1681 + } /* FeedWordPress::log_prefix () */
1461 1682 } // class FeedWordPress
1462 1683
1463 -require_once(dirname(__FILE__) . '/syndicatedpost.class.php');
1464 -require_once(dirname(__FILE__) . '/syndicatedlink.class.php');
1684 +class FeedWordPress_File extends WP_SimplePie_File {
1685 + function FeedWordPress_File ($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false) {
1686 + WP_SimplePie_File::WP_SimplePie_File($url, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
1465 1687
1688 + // SimplePie makes a strongly typed check against integers with
1689 + // this, but WordPress puts a string in. Which causes caching
1690 + // to break and fall on its ass when SimplePie is getting a 304,
1691 + // but doesn't realize it because this member is "304" instead.
1692 + $this->status_code = (int) $this->status_code;
1693 + }
1694 +} /* class FeedWordPress_File () */
1695 +
1696 +class FeedWordPress_Parser extends SimplePie_Parser {
1697 + function parse (&$data, $encoding) {
1698 + // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
1699 + if (strtoupper($encoding) === 'US-ASCII')
1700 + {
1701 + $this->encoding = 'UTF-8';
1702 + }
1703 + else
1704 + {
1705 + $this->encoding = $encoding;
1706 + }
1707 +
1708 + // Strip BOM:
1709 + // UTF-32 Big Endian BOM
1710 + if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
1711 + {
1712 + $data = substr($data, 4);
1713 + }
1714 + // UTF-32 Little Endian BOM
1715 + elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
1716 + {
1717 + $data = substr($data, 4);
1718 + }
1719 + // UTF-16 Big Endian BOM
1720 + elseif (substr($data, 0, 2) === "\xFE\xFF")
1721 + {
1722 + $data = substr($data, 2);
1723 + }
1724 + // UTF-16 Little Endian BOM
1725 + elseif (substr($data, 0, 2) === "\xFF\xFE")
1726 + {
1727 + $data = substr($data, 2);
1728 + }
1729 + // UTF-8 BOM
1730 + elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
1731 + {
1732 + $data = substr($data, 3);
1733 + }
1734 +
1735 + if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
1736 + {
1737 + $declaration =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
1738 + if ($declaration->parse())
1739 + {
1740 + $data = substr($data, $pos + 2);
1741 + $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
1742 + }
1743 + else
1744 + {
1745 + $this->error_string = 'SimplePie bug! Please report this!';
1746 + return false;
1747 + }
1748 + }
1749 +
1750 + $return = true;
1751 +
1752 + static $xml_is_sane = null;
1753 + if ($xml_is_sane === null)
1754 + {
1755 + $parser_check = xml_parser_create();
1756 + xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
1757 + xml_parser_free($parser_check);
1758 + $xml_is_sane = isset($values[0]['value']);
1759 + }
1760 +
1761 + // Create the parser
1762 + if ($xml_is_sane)
1763 + {
1764 + $xml = xml_parser_create_ns($this->encoding, $this->separator);
1765 + xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
1766 + xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
1767 + xml_set_object($xml, $this);
1768 + xml_set_character_data_handler($xml, 'cdata');
1769 + xml_set_element_handler($xml, 'tag_open', 'tag_close');
1770 + xml_set_start_namespace_decl_handler($xml, 'start_xmlns');
1771 +
1772 + // Parse!
1773 + if (!xml_parse($xml, $data, true))
1774 + {
1775 + $this->error_code = xml_get_error_code($xml);
1776 + $this->error_string = xml_error_string($this->error_code);
1777 + $return = false;
1778 + }
1779 +
1780 + $this->current_line = xml_get_current_line_number($xml);
1781 + $this->current_column = xml_get_current_column_number($xml);
1782 + $this->current_byte = xml_get_current_byte_index($xml);
1783 + xml_parser_free($xml);
1784 +
1785 + return $return;
1786 + }
1787 + else
1788 + {
1789 + libxml_clear_errors();
1790 + $xml =& new XMLReader();
1791 + $xml->xml($data);
1792 + while (@$xml->read())
1793 + {
1794 + switch ($xml->nodeType)
1795 + {
1796 +
1797 + case constant('XMLReader::END_ELEMENT'):
1798 + if ($xml->namespaceURI !== '')
1799 + {
1800 + $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
1801 + }
1802 + else
1803 + {
1804 + $tagName = $xml->localName;
1805 + }
1806 + $this->tag_close(null, $tagName);
1807 + break;
1808 + case constant('XMLReader::ELEMENT'):
1809 + $empty = $xml->isEmptyElement;
1810 + if ($xml->namespaceURI !== '')
1811 + {
1812 + $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
1813 + }
1814 + else
1815 + {
1816 + $tagName = $xml->localName;
1817 + }
1818 + $attributes = array();
1819 + while ($xml->moveToNextAttribute())
1820 + {
1821 + if ($xml->namespaceURI !== '')
1822 + {
1823 + $attrName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
1824 + }
1825 + else
1826 + {
1827 + $attrName = $xml->localName;
1828 + }
1829 + $attributes[$attrName] = $xml->value;
1830 + }
1831 +
1832 + foreach ($attributes as $attr => $value) :
1833 + list($ns, $local) = $this->split_ns($attr);
1834 + if ($ns=='http://www.w3.org/2000/xmlns/') :
1835 + if ('xmlns' == $local) : $local = false; endif;
1836 + $this->start_xmlns(null, $local, $value);
1837 + endif;
1838 + endforeach;
1839 +
1840 + $this->tag_open(null, $tagName, $attributes);
1841 + if ($empty)
1842 + {
1843 + $this->tag_close(null, $tagName);
1844 + }
1845 + break;
1846 + case constant('XMLReader::TEXT'):
1847 +
1848 + case constant('XMLReader::CDATA'):
1849 + $this->cdata(null, $xml->value);
1850 + break;
1851 + }
1852 + }
1853 + if ($error = libxml_get_last_error())
1854 + {
1855 + $this->error_code = $error->code;
1856 + $this->error_string = $error->message;
1857 + $this->current_line = $error->line;
1858 + $this->current_column = $error->column;
1859 + return false;
1860 + }
1861 + else
1862 + {
1863 + return true;
1864 + }
1865 + }
1866 + } /* FeedWordPress_Parser::parse() */
1867 +
1868 + var $xmlns_stack = array();
1869 + var $xmlns_current = array();
1870 + function tag_open ($parser, $tag, $attributes) {
1871 + $ret = parent::tag_open($parser, $tag, $attributes);
1872 + if ($this->current_xhtml_construct < 0) :
1873 + $this->data['xmlns'] = $this->xmlns_current;
1874 + $this->xmlns_stack[] = $this->xmlns_current;
1875 + endif;
1876 + return $ret;
1877 + }
1878 +
1879 + function tag_close($parser, $tag) {
1880 + if ($this->current_xhtml_construct < 0) :
1881 + $this->xmlns_current = array_pop($this->xmlns_stack);
1882 + endif;
1883 + $ret = parent::tag_close($parser, $tag);
1884 + return $ret;
1885 + }
1886 +
1887 + function start_xmlns ($parser, $prefix, $uri) {
1888 + if (!$prefix) :
1889 + $prefix = '';
1890 + endif;
1891 + if ($this->current_xhtml_construct < 0) :
1892 + $this->xmlns_current[$prefix] = $uri;
1893 + endif;
1894 + return true;
1895 + } /* FeedWordPress_Parser::start_xmlns() */
1896 +}
1897 +
1898 +$feedwordpress_admin_footer = array();
1899 +
1466 1900 ################################################################################
1467 1901 ## XML-RPC HOOKS: accept XML-RPC update pings from Contributors ################
1468 1902 ################################################################################
1469 1903
1470 -function feedwordpress_xmlrpc_hook ($args = array ()) {
1471 - $args['weblogUpdates.ping'] = 'feedwordpress_pong';
1472 - return $args;
1473 -}
1904 +class FeedWordPressRPC {
1905 + function FeedWordPressRPC () {
1906 + add_filter('xmlrpc_methods', array(&$this, 'xmlrpc_methods'));
1907 + }
1908 +
1909 + function xmlrpc_methods ($args = array()) {
1910 + $args['weblogUpdates.ping'] = array(&$this, 'ping');
1911 + $args['feedwordpress.subscribe'] = array(&$this, 'subscribe');
1912 + $args['feedwordpress.deactivate'] = array(&$this, 'deactivate');
1913 + $args['feedwordpress.delete'] = array(&$this, 'delete');
1914 + $args['feedwordpress.nuke'] = array(&$this, 'nuke');
1915 + return $args;
1916 + }
1917 +
1918 + function ping ($args) {
1919 + global $feedwordpress;
1920 +
1921 + $delta = @$feedwordpress->update($args[1]);
1922 + if (is_null($delta)):
1923 + return array('flerror' => true, 'message' => "Sorry. I don't syndicate <$args[1]>.");
1924 + else:
1925 + $mesg = array();
1926 + if (isset($delta['new'])) { $mesg[] = ' '.$delta['new'].' new posts were syndicated'; }
1927 + if (isset($delta['updated'])) { $mesg[] = ' '.$delta['updated'].' existing posts were updated'; }
1928 +
1929 + return array('flerror' => false, 'message' => "Thanks for the ping.".implode(' and', $mesg));
1930 + endif;
1931 + }
1932 +
1933 + function validate (&$args) {
1934 + global $wp_xmlrpc_server;
1474 1935
1475 -function feedwordpress_pong ($args) {
1476 - $feedwordpress = new FeedWordPress;
1477 - $delta = @$feedwordpress->update($args[1]);
1478 - if (is_null($delta)):
1479 - return array('flerror' => true, 'message' => "Sorry. I don't syndicate <$args[1]>.");
1480 - else:
1481 - $mesg = array();
1482 - if (isset($delta['new'])) { $mesg[] = ' '.$delta['new'].' new posts were syndicated'; }
1483 - if (isset($delta['updated'])) { $mesg[] = ' '.$delta['updated'].' existing posts were updated'; }
1936 + // First two params are username/password
1937 + $username = $wp_xmlrpc_server->escape(array_shift($args));
1938 + $password = $wp_xmlrpc_server->escape(array_shift($args));
1484 1939
1485 - return array('flerror' => false, 'message' => "Thanks for the ping.".implode(' and', $mesg));
1486 - endif;
1487 -}
1940 + $ret = array();
1941 + if ( !$user = $wp_xmlrpc_server->login($username, $password) ) :
1942 + $ret = $wp_xmlrpc_server->error;
1943 + elseif (!current_user_can('manage_links')) :
1944 + $ret = new IXR_Error(401, 'Sorry, you cannot change the subscription list.');
1945 + endif;
1946 + return $ret;
1947 + }
1488 1948
1489 -require_once(dirname(__FILE__) . '/relative_uri.class.php');
1949 + function subscribe ($args) {
1950 + $ret = $this->validate($args);
1951 + if (is_array($ret)) : // Success
1952 + // The remaining params are feed URLs
1953 + foreach ($args as $arg) :
1954 + $finder = new FeedFinder($arg, /*verify=*/ false, /*fallbacks=*/ 1);
1955 + $feeds = array_values(array_unique($finder->find()));
1956 +
1957 + if (count($feeds) > 0) :
1958 + $link_id = FeedWordPress::syndicate_link(
1959 + /*title=*/ feedwordpress_display_url($feeds[0]),
1960 + /*homepage=*/ $feeds[0],
1961 + /*feed=*/ $feeds[0]
1962 + );
1963 + $ret[] = array(
1964 + 'added',
1965 + $feeds[0],
1966 + $arg,
1967 + );
1968 + else :
1969 + $ret[] = array(
1970 + 'error',
1971 + $arg
1972 + );
1973 + endif;
1974 + endforeach;
1975 + endif;
1976 + return $ret;
1977 + } /* FeedWordPressRPC::subscribe () */
1978 +
1979 + function unsubscribe ($method, $args) {
1980 + $ret = $this->validate($args);
1981 + if (is_array($ret)) : // Success
1982 + // The remaining params are feed URLs
1983 + foreach ($args as $arg) :
1984 + $link_id = FeedWordPress::find_link($arg);
1985 +
1986 + if (!$link_id) :
1987 + $link_id = FeedWordPress::find_link($arg, 'link_url');
1988 + endif;
1989 +
1990 + if ($link_id) :
1991 + $link = new SyndicatedLink($link_id);
1992 +
1993 + $link->{$method}();
1994 + $ret[] = array(
1995 + 'deactivated',
1996 + $arg,
1997 + );
1998 + else :
1999 + $ret[] = array(
2000 + 'error',
2001 + $arg,
2002 + );
2003 + endif;
2004 + endforeach;
2005 + endif;
2006 + return $ret;
2007 + } /* FeedWordPress::unsubscribe () */
2008 +
2009 + function deactivate ($args) {
2010 + return $this->unsubscribe('deactivate', $args);
2011 + } /* FeedWordPressRPC::deactivate () */
2012 +
2013 + function delete ($args) {
2014 + return $this->unsubscribe('delete', $args);
2015 + } /* FeedWordPressRPC::delete () */
2016 +
2017 + function nuke ($args) {
2018 + return $this->unsubscribe('nuke', $args);
2019 + } /* FeedWordPressRPC::nuke () */
2020 +} /* class FeedWordPressRPC */
1490 2021
1491 2022 // take your best guess at the realname and e-mail, given a string
1492 2023 define('FWP_REGEX_EMAIL_ADDY', '([^@"(<\s]+@[^"@(<\s]+\.[^"@(<\s]+)');
1493 2024 define('FWP_REGEX_EMAIL_NAME', '("([^"]*)"|([^"<(]+\S))');