PluginProbe
FeedWordPress / 2010.0528
FeedWordPress v2010.0528
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 +624 -317 2009.07072010.0528 View file →
@@ -1,15 +1,20 @@
1 1 <?php
2 2 /*
3 3 Plugin Name: FeedWordPress
4 -Plugin URI: http://projects.radgeek.com/feedwordpress
4 +Plugin URI: http://feedwordpress.radgeek.com/
5 5 Description: simple and flexible Atom/RSS syndication for WordPress
6 -Version: 2009.0707
6 +Version: 2010.0528
7 7 Author: Charles Johnson
8 8 Author URI: http://radgeek.com/
9 9 License: GPL
10 10 */
11 11
12 +/**
13 + * @package FeedWordPress
14 + * @version 2010.0528
15 + */
16 +
12 17 # This uses code derived from:
13 18 # - wp-rss-aggregate.php by Kellan Elliot-McCrea <kellan@protest.net>
14 19 # - HTTP Navigator 2 by Keyvan Minoukadeh <keyvan@k1m.com>
15 20 # - Ultra-Liberal Feed Finder by Mark Pilgrim <mark@diveintomark.org>
@@ -27,15 +32,22 @@
27 32 # or use a cron job.
28 33
29 34 # -- Don't change these unless you know what you're doing...
30 35
31 -define ('FEEDWORDPRESS_VERSION', '2009.0707');
36 +define ('FEEDWORDPRESS_VERSION', '2010.0528');
32 37 define ('FEEDWORDPRESS_AUTHOR_CONTACT', 'http://radgeek.com/contact');
38 +
39 +// Defaults
33 40 define ('DEFAULT_SYNDICATION_CATEGORY', 'Contributors');
41 +define ('DEFAULT_UPDATE_PERIOD', 60); // value in minutes
34 42
35 -$feedwordpress_debug = get_option('feedwordpress_debug');
36 -if (is_string($feedwordpress_debug)) :
37 - $feedwordpress_debug = ($feedwordpress_debug == 'yes');
43 +if (isset($_REQUEST['feedwordpress_debug'])) :
44 + $feedwordpress_debug = $_REQUEST['feedwordpress_debug'];
45 +else :
46 + $feedwordpress_debug = get_option('feedwordpress_debug');
47 + if (is_string($feedwordpress_debug)) :
48 + $feedwordpress_debug = ($feedwordpress_debug == 'yes');
49 + endif;
38 50 endif;
39 51 define ('FEEDWORDPRESS_DEBUG', $feedwordpress_debug);
40 52
41 53 define ('FEEDWORDPRESS_CAT_SEPARATOR_PATTERN', '/[:\n]/');
@@ -52,14 +64,14 @@
52 64 define ('FWP_SCHEMA_25', 7558); // Database schema # for WP 2.5
53 65 define ('FWP_SCHEMA_26', 8201); // Database schema # for WP 2.6
54 66 define ('FWP_SCHEMA_27', 9872); // Database schema # for WP 2.7
55 67 define ('FWP_SCHEMA_28', 11548); // Database schema # for WP 2.8
68 +define ('FWP_SCHEMA_29', 12329); // Database schema # for WP 2.9
56 69
57 70 if (FEEDWORDPRESS_DEBUG) :
58 71 // Help us to pick out errors, if any.
59 72 ini_set('error_reporting', E_ALL & ~E_NOTICE);
60 73 ini_set('display_errors', true);
61 - define('MAGPIE_DEBUG', true);
62 74
63 75 // When testing we don't want cache issues to interfere. But this is
64 76 // a VERY BAD SETTING for a production server. Webmasters will eat your
65 77 // face for breakfast if you use it, and the baby Jesus will cry. So
@@ -64,22 +76,25 @@
64 76 // a VERY BAD SETTING for a production server. Webmasters will eat your
65 77 // face for breakfast if you use it, and the baby Jesus will cry. So
66 78 // make sure FEEDWORDPRESS_DEBUG is FALSE for any site that will be
67 79 // used for more than testing purposes!
68 - define('MAGPIE_CACHE_AGE', 1);
80 + define('FEEDWORDPRESS_CACHE_AGE', 1);
81 + define('FEEDWORDPRESS_CACHE_LIFETIME', 1);
82 + define('FEEDWORDPRESS_FETCH_TIME_OUT', 60);
69 83 else :
70 - define('MAGPIE_DEBUG', false);
84 + // Hold onto data all day for conditional GET purposes,
85 + // but consider it stale after 1 min (requiring a conditional GET)
86 + define('FEEDWORDPRESS_CACHE_LIFETIME', 24*60*60);
87 + define('FEEDWORDPRESS_CACHE_AGE', 1*60);
88 + define('FEEDWORDPRESS_FETCH_TIME_OUT', 10);
71 89 endif;
72 90
73 -// Note that the rss-functions.php that comes prepackaged with WordPress is
74 -// old & busted. For the new hotness, drop a copy of rss.php from
75 -// this archive into wp-includes/rss.php
91 +// Use our the cache settings that we want.
92 +add_filter('wp_feed_cache_transient_lifetime', array('FeedWordPress', 'cache_lifetime'));
76 93
77 -if (is_readable(ABSPATH . WPINC . '/rss.php')) :
78 - require_once (ABSPATH . WPINC . '/rss.php');
79 -else :
80 - require_once (ABSPATH . WPINC . '/rss-functions.php');
81 -endif;
94 +// Ensure that we have SimplePie loaded up and ready to go.
95 +// We no longer need a MagpieRSS upgrade module. Hallelujah!
96 +require_once(ABSPATH . WPINC . '/feed.php');
82 97
83 98 if (isset($wp_db_version)) :
84 99 if ($wp_db_version >= FWP_SCHEMA_23) :
85 100 require_once (ABSPATH . WPINC . '/registration.php'); // for wp_insert_user
@@ -112,13 +127,20 @@
112 127 else : // Something went wrong. Let's just guess.
113 128 $fwp_path = 'feedwordpress';
114 129 endif;
115 130
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 +
116 136 // If this is a FeedWordPress admin page, queue up scripts for AJAX functions that FWP uses
117 137 // If it is a display page or a non-FeedWordPress admin page, don't.
118 138 if (is_admin() and isset($_REQUEST['page']) and preg_match("|^{$fwp_path}/|", $_REQUEST['page'])) :
119 139 if (function_exists('wp_enqueue_script')) :
120 - if (isset($wp_db_version) and $wp_db_version >= FWP_SCHEMA_25) :
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)) :
121 143 wp_enqueue_script('post'); // for magic tag and category boxes
122 144 wp_enqueue_script('thickbox'); // for fold-up boxes
123 145 wp_enqueue_script('admin-forms'); // for checkbox selection
124 146 else :
@@ -159,8 +181,15 @@
159 181
160 182 # Filter in original permalinks if the user wants that
161 183 add_filter('post_link', 'syndication_permalink', 1);
162 184
185 + # When foreign URLs are used for permalinks in feeds or display
186 + # contexts, they need to be escaped properly.
187 + add_filter('the_permalink', 'syndication_permalink_escaped');
188 + add_filter('the_permalink_rss', 'syndication_permalink_escaped');
189 +
190 + add_filter('post_comments_feed_link', 'syndication_comments_feed_link');
191 +
163 192 # WTF? By default, wp_insert_link runs incoming link_url and link_rss
164 193 # URIs through default filters that include `wp_kses()`. But `wp_kses()`
165 194 # just happens to escape any occurrence of & to &amp; -- which just
166 195 # happens to fuck up any URI with a & to separate GET parameters.
@@ -169,10 +198,12 @@
169 198
170 199 # Admin menu
171 200 add_action('admin_menu', 'fwp_add_pages');
172 201 add_action('admin_notices', 'fwp_check_debug');
173 - add_action('admin_notices', 'fwp_check_magpie');
174 202
203 + add_action('admin_menu', 'feedwordpress_add_post_edit_controls');
204 + add_action('save_post', 'feedwordpress_save_post_edit_controls');
205 +
175 206 # Inbound XML-RPC update methods
176 207 add_filter('xmlrpc_methods', 'feedwordpress_xmlrpc_hook');
177 208
178 209 # Outbound XML-RPC ping reform
@@ -193,13 +224,30 @@
193 224 add_action('feedwordpress_update', 'log_feedwordpress_update_feeds', 100);
194 225 add_action('feedwordpress_check_feed', 'log_feedwordpress_check_feed', 100);
195 226 add_action('feedwordpress_update_complete', 'log_feedwordpress_update_complete', 100);
196 227 endif;
197 -
228 +
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;
237 +
238 + add_action('feedwordpress_check_feed_complete', 'debug_out_feedwordpress_feed_error', 100, 3);
239 + endif;
240 +
198 241 # Cron-less auto-update. Hooray!
199 - add_action('init', 'feedwordpress_auto_update');
200 - add_action('init', 'feedwordpress_check_for_magpie_fix');
201 -
242 + $autoUpdateHook = get_option('feedwordpress_automatic_updates');
243 + if ($autoUpdateHook != 'init') :
244 + $autoUpdateHook = 'shutdown';
245 + endif;
246 + add_action($autoUpdateHook, 'feedwordpress_auto_update');
247 +
248 + add_action('init', 'feedwordpress_update_magic_url');
249 +
202 250 # Default sanitizers
203 251 add_filter('syndicated_item_content', array('SyndicatedPost', 'resolve_relative_uris'), 0, 2);
204 252 add_filter('syndicated_item_content', array('SyndicatedPost', 'sanitize_content'), 0, 2);
205 253
@@ -207,43 +255,48 @@
207 255 # Hook in the menus, which will just point to the upgrade interface
208 256 add_action('admin_menu', 'fwp_add_pages');
209 257 endif; // if (!FeedWordPress::needs_upgrade())
210 258
211 -function feedwordpress_check_for_magpie_fix () {
212 - if (isset($_POST['action']) and $_POST['action']=='fix_magpie_version') :
213 - FeedWordPressCompatibility::validate_http_request(/*action=*/ 'feedwordpress_fix_magpie', /*capability=*/ 'edit_files');
259 +function feedwordpress_auto_update () {
260 + if (FeedWordPress::stale()) :
261 + $feedwordpress = new FeedWordPress;
262 + $feedwordpress->update();
263 + endif;
264 +} /* feedwordpress_auto_update () */
214 265
215 - $back_to = $_SERVER['REQUEST_URI'];
216 - if (isset($_POST['ignore'])) :
217 - // kill error message by telling it we ignored the upgrade request for this version
218 - update_option('feedwordpress_magpie_ignored_upgrade_to', EXPECTED_MAGPIE_VERSION);
219 - $ret = 'ignored';
220 - elseif (isset($_POST['upgrade'])) :
221 - $source = dirname(__FILE__)."/MagpieRSS-upgrade/rss.php";
222 - $destination = ABSPATH . WPINC . '/rss.php';
223 - $success = @copy($source, $destination);
224 - $ret = (int) $success;
225 - endif;
266 +function feedwordpress_update_magic_url () {
267 + global $wpdb;
226 268
227 - if (strpos($back_to, '?')===false) : $sep = '?';
228 - else : $sep = '&';
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.";
229 291 endif;
230 292
231 - header("Location: {$back_to}{$sep}feedwordpress_magpie_fix=".$ret);
232 - exit;
233 - endif;
234 -} /* feedwordpress_check_for_magpie_fix() */
235 293
236 -function feedwordpress_auto_update () {
237 - if (FeedWordPress::stale()) :
238 - $feedwordpress =& new FeedWordPress;
239 - $feedwordpress->update();
240 - endif;
241 -
242 - if (FeedWordPress::update_requested()) :
294 + // Magic URL should return nothing but a 200 OK header packet
295 + // when successful.
243 296 exit;
244 297 endif;
245 -} /* feedwordpress_auto_update () */
298 +} /* feedwordpress_magic_update_url () */
246 299
247 300 ################################################################################
248 301 ## LOGGING FUNCTIONS: log status updates to error_log if you want it ###########
249 302 ################################################################################
@@ -280,23 +333,76 @@
280 333 .(is_null($delta) ? "Error: I don't syndicate that URI"
281 334 : implode(' and ', $mesg)));
282 335 }
283 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;
376 + endif;
377 +}
378 +
284 379 ################################################################################
285 380 ## TEMPLATE API: functions to make your templates syndication-aware ############
286 381 ################################################################################
287 382
288 -function is_syndicated () { return (strlen(get_syndication_feed_id()) > 0); }
383 +/**
384 + * is_syndicated: Tests whether the current post in a Loop context, or a post
385 + * given by ID number, was syndicated by FeedWordPress. Useful for templates
386 + * to determine whether or not to retrieve syndication-related meta-data in
387 + * displaying a post.
388 + *
389 + * @param int $id The post to check for syndicated status. Defaults to the current post in a Loop context.
390 + * @return bool TRUE if the post's meta-data indicates it was syndicated; FALSE otherwise
391 + */
392 +function is_syndicated ($id = NULL) {
393 + return (strlen(get_syndication_feed_id($id)) > 0);
394 +} /* function is_syndicated() */
289 395
290 -function get_syndication_source_link ($original = NULL) {
396 +function get_syndication_source_link ($original = NULL, $id = NULL) {
291 397 if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
292 398 endif;
293 399
294 - if ($original) : $vals = get_post_custom_values('syndication_source_uri_original');
400 + if ($original) : $vals = get_post_custom_values('syndication_source_uri_original', $id);
295 401 else : $vals = array();
296 402 endif;
297 403
298 - if (count($vals) == 0) : $vals = get_post_custom_values('syndication_source_uri');
404 + if (count($vals) == 0) : $vals = get_post_custom_values('syndication_source_uri', $id);
299 405 endif;
300 406
301 407 if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
302 408
@@ -302,37 +408,72 @@
302 408
303 409 return $ret;
304 410 } /* function get_syndication_source_link() */
305 411
306 -function the_syndication_source_link ($original = NULL) { echo get_syndication_source_link($original); }
412 +function the_syndication_source_link ($original = NULL, $id = NULL) {
413 + echo get_syndication_source_link($original, $id);
414 +}
307 415
308 -function get_syndication_source ($original = NULL) {
309 - if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
416 +function feedwordpress_display_url ($url, $before = 60, $after = 0) {
417 + $bits = parse_url($url);
418 +
419 + // Strip out crufty subdomains
420 + $bits['host'] = preg_replace('/^www[0-9]*\./i', '', $bits['host']);
421 +
422 + // Reassemble bit-by-bit with minimum of crufty elements
423 + $url = (isset($bits['user'])?$bits['user'].'@':'')
424 + .(isset($bits['host'])?$bits['host']:'')
425 + .(isset($bits['path'])?$bits['path']:'')
426 + .(isset($uri_bits['port'])?':'.$uri_bits['port']:'')
427 + .(isset($bits['query'])?'?'.$bits['query']:'');
428 +
429 + if (strlen($url) > ($before+$after)) :
430 + $url = substr($url, 0, $before).'…'.substr($url, 0 - $after, $after);
310 431 endif;
311 432
312 - if ($original) : $vals = get_post_custom_values('syndication_source_original');
313 - else : $vals = array();
433 + return $url;
434 +}
435 +
436 +function get_syndication_source ($original = NULL, $id = NULL) {
437 + if (is_null($original)) :
438 + $original = FeedWordPress::use_aggregator_source_data();
314 439 endif;
440 +
441 + if ($original) :
442 + $vals = get_post_custom_values('syndication_source_original', $id);
443 + else :
444 + $vals = array();
445 + endif;
315 446
316 - if (count($vals) == 0) : $vals = get_post_custom_values('syndication_source');
447 + if (count($vals) == 0) :
448 + $vals = get_post_custom_values('syndication_source', $id);
317 449 endif;
318 450
319 - if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
451 + if (count($vals) > 0) :
452 + $ret = $vals[0];
453 + else :
454 + $ret = NULL;
455 + endif;
320 456
457 + if (is_null($ret) or strlen(trim($ret)) == 0) :
458 + // Fall back to URL of blog
459 + $ret = feedwordpress_display_url(get_syndication_source_link());
460 + endif;
461 +
321 462 return $ret;
322 463 } /* function get_syndication_source() */
323 464
324 -function the_syndication_source ($original = NULL) { echo get_syndication_source($original); }
465 +function the_syndication_source ($original = NULL, $id = NULL) { echo get_syndication_source($original, $id); }
325 466
326 -function get_syndication_feed ($original = NULL) {
467 +function get_syndication_feed ($original = NULL, $id = NULL) {
327 468 if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
328 469 endif;
329 470
330 - if ($original) : $vals = get_post_custom_values('syndication_feed_original');
471 + if ($original) : $vals = get_post_custom_values('syndication_feed_original', $id);
331 472 else : $vals = array();
332 473 endif;
333 -
334 - if (count($vals) == 0) : $vals = get_post_custom_values('syndication_feed');
474 +
475 + if (count($vals) == 0) : $vals = get_post_custom_values('syndication_feed', $id);
335 476 endif;
336 477
337 478 if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
338 479
@@ -338,19 +479,19 @@
338 479
339 480 return $ret;
340 481 } /* function get_syndication_feed() */
341 482
342 -function the_syndication_feed ($original = NULL) { echo get_syndication_feed ($original); }
483 +function the_syndication_feed ($original = NULL, $id = NULL) { echo get_syndication_feed($original, $id); }
343 484
344 -function get_syndication_feed_guid ($original = NULL) {
485 +function get_syndication_feed_guid ($original = NULL, $id = NULL) {
345 486 if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
346 487 endif;
347 488
348 - if ($original) : $vals = get_post_custom_values('syndication_source_id_original');
489 + if ($original) : $vals = get_post_custom_values('syndication_source_id_original', $id);
349 490 else : $vals = array();
350 491 endif;
351 492
352 - if (count($vals) == 0) : $vals = array(get_feed_meta('feed/id'));
493 + if (count($vals) == 0) : $vals = array(get_feed_meta('feed/id', $id));
353 494 endif;
354 495
355 496 if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
356 497
@@ -356,45 +497,95 @@
356 497
357 498 return $ret;
358 499 } /* function get_syndication_feed_guid () */
359 500
360 -function the_syndication_feed_guid ($original = NULL) { echo get_syndication_feed_guid($original); }
501 +function the_syndication_feed_guid ($original = NULL, $id = NULL) { echo get_syndication_feed_guid($original, $id); }
361 502
362 -function get_syndication_feed_id () { list($u) = get_post_custom_values('syndication_feed_id'); return $u; }
363 -function the_syndication_feed_id () { echo get_syndication_feed_id(); }
503 +function get_syndication_feed_id ($id = NULL) { list($u) = get_post_custom_values('syndication_feed_id', $id); return $u; }
504 +function the_syndication_feed_id ($id = NULL) { echo get_syndication_feed_id($id); }
364 505
365 506 $feedwordpress_linkcache = array (); // only load links from database once
507 +function get_syndication_feed_object ($id = NULL) {
508 + global $feedwordpress_linkcache;
366 509
367 -function get_feed_meta ($key) {
368 - global $wpdb, $feedwordpress_linkcache;
369 - $feed_id = get_syndication_feed_id();
510 + $link = NULL;
370 511
371 - $ret = NULL;
512 + $feed_id = get_syndication_feed_id($id);
372 513 if (strlen($feed_id) > 0):
373 514 if (isset($feedwordpress_linkcache[$feed_id])) :
374 515 $link = $feedwordpress_linkcache[$feed_id];
375 516 else :
376 - $link =& new SyndicatedLink($feed_id);
517 + $link = new SyndicatedLink($feed_id);
377 518 $feedwordpress_linkcache[$feed_id] = $link;
378 519 endif;
520 + endif;
521 + return $link;
522 +}
379 523
524 +function get_feed_meta ($key, $id = NULL) {
525 + $ret = NULL;
526 +
527 + $link = get_syndication_feed_object($id);
528 + if (is_object($link) and isset($link->settings[$key])) :
380 529 $ret = $link->settings[$key];
381 530 endif;
382 531 return $ret;
383 532 } /* get_feed_meta() */
384 533
385 -function get_syndication_permalink () {
386 - list($u) = get_post_custom_values('syndication_permalink'); return $u;
534 +function get_syndication_permalink ($id = NULL) {
535 + list($u) = get_post_custom_values('syndication_permalink', $id); return $u;
387 536 }
388 -function the_syndication_permalink () {
389 - echo get_syndication_permalink();
537 +function the_syndication_permalink ($id = NULL) {
538 + echo get_syndication_permalink($id);
390 539 }
391 540
541 +/**
542 + * get_local_permalink: returns a string containing the internal permalink
543 + * for a post (whether syndicated or not) on your local WordPress installation.
544 + * This may be useful if you want permalinks to point to the original source of
545 + * an article for most purposes, but want to retrieve a URL for the local
546 + * representation of the post for one or two limited purposes (for example,
547 + * linking to a comments page on your local aggregator site).
548 + *
549 + * @param $id The numerical ID of the post to get the permalink for. If empty,
550 + * defaults to the current post in a Loop context.
551 + * @return string The URL of the local permalink for this post.
552 + *
553 + * @uses get_permalink()
554 + * @global $feedwordpress_the_original_permalink
555 + *
556 + * @since 2010.0217
557 + */
558 +function get_local_permalink ($id = NULL) {
559 + global $feedwordpress_the_original_permalink;
560 +
561 + // get permalink, and thus activate filter and force global to be filled
562 + // with original URL.
563 + $url = get_permalink($id);
564 + return $feedwordpress_the_original_permalink;
565 +} /* get_local_permalink() */
566 +
567 +/**
568 + * the_original_permalink: displays the contents of get_original_permalink()
569 + *
570 + * @param $id The numerical ID of the post to get the permalink for. If empty,
571 + * defaults to the current post in a Loop context.
572 + *
573 + * @uses get_local_permalinks()
574 + * @uses apply_filters
575 + *
576 + * @since 2010.0217
577 + */
578 +function the_local_permalink ($id = NULL) {
579 + print apply_filters('the_permalink', get_local_permalink($id));
580 +} /* function the_local_permalink() */
581 +
392 582 ################################################################################
393 583 ## FILTERS: syndication-aware handling of post data for templates and feeds ####
394 584 ################################################################################
395 585
396 586 $feedwordpress_the_syndicated_content = NULL;
587 +$feedwordpress_the_original_permalink = NULL;
397 588
398 589 function feedwordpress_preserve_syndicated_content ($text) {
399 590 global $feedwordpress_the_syndicated_content;
400 591
@@ -424,16 +615,16 @@
424 615 // In a post context....
425 616 if (is_syndicated()) :
426 617 ?>
427 618 <source>
428 - <title><?php the_syndication_source(); ?></title>
429 - <link rel="alternate" type="text/html" href="<?php the_syndication_source_link(); ?>" />
430 - <link rel="self" href="<?php the_syndication_feed(); ?>" />
619 + <title><?php print htmlspecialchars(get_syndication_source()); ?></title>
620 + <link rel="alternate" type="text/html" href="<?php print htmlspecialchars(get_syndication_source_link()); ?>" />
621 + <link rel="self" href="<?php print htmlspecialchars(get_syndication_feed()); ?>" />
431 622 <?php
432 623 $id = get_syndication_feed_guid();
433 624 if (strlen($id) > 0) :
434 625 ?>
435 - <id><?php print $id; ?></id>
626 + <id><?php print htmlspecialchars($id); ?></id>
436 627 <?php
437 628 endif;
438 629 $updated = get_feed_meta('feed/updated');
439 630 if (strlen($updated) > 0) : ?>
@@ -445,17 +636,131 @@
445 636 <?php
446 637 endif;
447 638 }
448 639
640 +/**
641 + * syndication_permalink: Allow WordPress to use the original remote URL of
642 + * syndicated posts as their permalink. Can be turned on or off by by setting in
643 + * Syndication => Posts & Links. Saves the old internal permalink in a global
644 + * variable for later use.
645 + *
646 + * @param string $permalink The internal permalink
647 + * @return string The new permalink. Same as the old if the post is not
648 + * syndicated, or if FWP is set to use internal permalinks, or if the post
649 + * was syndicated, but didn't have a proper permalink recorded.
650 + *
651 + * @uses FeedWordPress::munge_permalinks()
652 + * @uses get_syndication_permalink()
653 + * @global $feedwordpress_the_original_permalink
654 + */
449 655 function syndication_permalink ($permalink = '') {
450 - if (get_option('feedwordpress_munge_permalink') != 'no'):
451 - $uri = get_syndication_permalink();
452 - return ((strlen($uri) > 0) ? $uri : $permalink);
453 - else:
454 - return $permalink;
656 + global $feedwordpress_the_original_permalink;
657 +
658 + // Save the local permalink in case we need to retrieve it later.
659 + $feedwordpress_the_original_permalink = $permalink;
660 +
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);
664 +
665 + $munge = false;
666 + $link = get_syndication_feed_object($id);
667 + if (is_object($link)) :
668 + $munge = ($link->setting('munge permalink', 'munge_permalink', 'yes') != 'no');
455 669 endif;
456 -} // function syndication_permalink ()
457 670
671 + if ($munge):
672 + $uri = get_syndication_permalink($id);
673 + $permalink = ((strlen($uri) > 0) ? $uri : $permalink);
674 + endif;
675 + return $permalink;
676 +} /* function syndication_permalink () */
677 +
678 +/**
679 + * syndication_permalink_escaped: Escape XML special characters in syndicated
680 + * permalinks when used in feed contexts and HTML display contexts.
681 + *
682 + * @param string $permalink
683 + * @return string
684 + *
685 + * @uses is_syndicated()
686 + * @uses FeedWordPress::munge_permalinks()
687 + *
688 + */
689 +function syndication_permalink_escaped ($permalink) {
690 + if (is_syndicated() and FeedWordPress::munge_permalinks()) :
691 + // This is a foreign link; WordPress can't vouch for its not
692 + // having any entities that need to be &-escaped. So we'll do
693 + // it here.
694 + $permalink = esc_html($permalink);
695 + endif;
696 + return $permalink;
697 +} /* function syndication_permalink_escaped() */
698 +
699 +/**
700 + * syndication_comments_feed_link: Escape XML special characters in comments
701 + * feed links
702 + *
703 + * @param string $link
704 + * @return string
705 + *
706 + * @uses is_syndicated()
707 + * @uses FeedWordPress::munge_permalinks()
708 + */
709 +function syndication_comments_feed_link ($link) {
710 + global $feedwordpress_the_original_permalink, $id;
711 +
712 + if (is_syndicated() and FeedWordPress::munge_permalinks()) :
713 + // If the source post provided a comment feed URL using
714 + // wfw:commentRss or atom:link/@rel="replies" we can make use of
715 + // that value here.
716 + $source = get_syndication_feed_object();
717 + $replacement = NULL;
718 + if ($source->setting('munge comments feed links', 'munge_comments_feed_links', 'yes') != 'no') :
719 + $commentFeeds = get_post_custom_values('wfw:commentRSS');
720 + if (
721 + is_array($commentFeeds)
722 + and (count($commentFeeds) > 0)
723 + and (strlen($commentFeeds[0]) > 0)
724 + ) :
725 + $replacement = $commentFeeds[0];
726 +
727 + // This is a foreign link; WordPress can't vouch for its not
728 + // having any entities that need to be &-escaped. So we'll do it
729 + // here.
730 + $replacement = esc_html($replacement);
731 + endif;
732 + endif;
733 +
734 + if (is_null($replacement)) :
735 + // Q: How can we get the proper feed format, since the
736 + // format is, stupidly, not passed to the filter?
737 + // A: Kludge kludge kludge kludge!
738 + $fancy_permalinks = ('' != get_option('permalink_structure'));
739 + if ($fancy_permalinks) :
740 + preg_match('|/feed(/([^/]+))?/?$|', $link, $ref);
741 +
742 + $format = (isset($ref[2]) ? $ref[2] : '');
743 + if (strlen($format) == 0) : $format = get_default_feed(); endif;
744 +
745 + $replacement = trailingslashit($feedwordpress_the_original_permalink) . 'feed';
746 + if ($format != get_default_feed()) :
747 + $replacement .= '/'.$format;
748 + endif;
749 + $replacement = user_trailingslashit($replacement, 'single_feed');
750 + else :
751 + // No fancy permalinks = no problem
752 + // WordPress doesn't call get_permalink() to
753 + // generate the comment feed URL, so the
754 + // comments feed link is never munged by FWP.
755 + endif;
756 + endif;
757 +
758 + if (!is_null($replacement)) : $link = $replacement; endif;
759 + endif;
760 + return $link;
761 +} /* function syndication_comments_feed_link() */
762 +
458 763 ################################################################################
459 764 ## ADMIN MENU ADD-ONS: register Dashboard management pages #####################
460 765 ################################################################################
461 766
@@ -468,23 +773,14 @@
468 773 // add icon parameter
469 774 $menu[] = WP_PLUGIN_URL.'/'.$fwp_path.'/feedwordpress-tiny.png';
470 775 endif;
471 776
472 - if (fwp_test_wp_version(FWP_SCHEMA_26)) :
473 - $options = __('Settings');
474 - $longoptions = __('Syndication Settings');
475 - else :
476 - $options = __('Options');
477 - $longoptions = __('Syndication Options');
478 - endif;
479 -
480 777 call_user_func_array('add_menu_page', $menu);
481 - add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Posts', 'Posts', $fwp_capability['manage_options'], $fwp_path.'/posts-page.php');
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');
482 780 add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Authors', 'Authors', $fwp_capability['manage_options'], $fwp_path.'/authors-page.php');
483 - add_submenu_page($fwp_path.'/syndication.php', 'Categories & Tags', 'Categories & Tags', $fwp_capability['manage_options'], $fwp_path.'/categories-page.php');
484 - add_submenu_page($fwp_path.'/syndication.php', $longoptions, $options, $fwp_capability['manage_options'], $fwp_path.'/syndication-options.php');
485 -
486 - add_options_page($longoptions, 'Syndication', $fwp_capability['manage_options'], $fwp_path.'/syndication-options.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');
487 783 } /* function fwp_add_pages () */
488 784
489 785 function fwp_check_debug () {
490 786 // This is a horrible fucking kludge that I have to do because the
@@ -507,97 +803,8 @@
507 803 <?php
508 804 endif;
509 805 } /* function fwp_check_debug () */
510 806
511 -define('EXPECTED_MAGPIE_VERSION', '2009.0618');
512 -function fwp_check_magpie () {
513 - if (isset($_REQUEST['feedwordpress_magpie_fix'])) :
514 - if ($_REQUEST['feedwordpress_magpie_fix']=='ignored') :
515 -?>
516 -<div class="updated fade">
517 -<p>O.K., we'll ignore the problem for now. FeedWordPress will not display any
518 -more error messages.</p>
519 -</div>
520 -<?php
521 - elseif ((bool) $_REQUEST['feedwordpress_magpie_fix']) :
522 -?>
523 -<div class="updated fade">
524 -<p>Congratulations! Your MagpieRSS has been successfully upgraded to the version
525 -shipped with FeedWordPress.</p>
526 -</div>
527 -<?php
528 - else :
529 - $source = dirname(__FILE__)."/MagpieRSS-upgrade/rss.php";
530 - $destination = ABSPATH . WPINC . '/rss.php';
531 - $cmd = "cp '".htmlspecialchars(addslashes($source))."' '".htmlspecialchars(addslashes($destination))."'";
532 - $cmd = wordwrap($cmd, /*width=*/ 75, /*break=*/ " \\\n\t");
533 -
534 -?>
535 -<div class="error">
536 -<p><strong>FeedWordPress was unable to automatically upgrade your copy of MagpieRSS.</strong></p>
537 -<p>It's likely that you need to change the file permissions on <code><?php print htmlspecialchars($source); ?></code>
538 -to allow FeedWordPress to overwrite it.</p>
539 -<p><strong>To perform the upgrade manually,</strong> you can
540 -use a SFTP or FTP client to upload a copy of <code>rss.php</code> from the
541 -<code>MagpieRSS-upgrades/</code> directory of your FeedWordPress archive so that
542 -it overwrites <code><?php print htmlspecialchars($destination); ?></code>. Or,
543 -if your web host provides shell access, you can issue the following command from
544 -a command prompt to perform the upgrade:</p>
545 -<pre>
546 -<samp>$</samp> <kbd><?php print $cmd; ?></kbd>
547 -</pre>
548 -<p><strong>If you've fixed the file permissions,</strong> you can try the
549 -automatic upgrade again.</p>
550 -
551 -<?php feedwordpress_upgrade_old_and_busted_buttons(); ?>
552 -</div>
553 -<?php
554 - endif;
555 - else :
556 - $magpie_version = FeedWordPress::magpie_version();
557 -
558 - $ignored = get_option('feedwordpress_magpie_ignored_upgrade_to');
559 - if (EXPECTED_MAGPIE_VERSION != $magpie_version and EXPECTED_MAGPIE_VERSION != $ignored) :
560 - if (current_user_can('edit_files')) :
561 - $youAre = 'you are';
562 - $itIsRecommendedThatYou = 'It is <strong>strongly recommended</strong> that you';
563 - else :
564 - $youAre = 'this site is';
565 - $itIsRecommendedThatYou = 'You may want to contact the administrator of the site; it is <strong>strongly recommended</strong> that they';
566 - endif;
567 - print '<div class="error">';
568 -?>
569 -<p style="font-style: italic"><strong>FeedWordPress has detected that <?php print $youAre; ?> currently using a version of
570 -MagpieRSS other than the upgraded version that ships with this version of FeedWordPress.</strong></p>
571 -<ul>
572 -<li><strong>Currently running:</strong> MagpieRSS <?php print $magpie_version; ?></li>
573 -<li><strong>Version included with FeedWordPress <?php print FEEDWORDPRESS_VERSION; ?>:</strong> MagpieRSS <?php print EXPECTED_MAGPIE_VERSION; ?></li>
574 -</ul>
575 -<p><?php print $itIsRecommendedThatYou; ?> install the upgraded
576 -version of MagpieRSS supplied with FeedWordPress. The version of
577 -MagpieRSS that ships with WordPress is very old and buggy, and
578 -encounters a number of errors when trying to parse modern Atom
579 -and RSS feeds.</p>
580 -<?php
581 - feedwordpress_upgrade_old_and_busted_buttons();
582 - print '</div>';
583 - endif;
584 - endif;
585 -}
586 -
587 -function feedwordpress_upgrade_old_and_busted_buttons() {
588 - if (current_user_can('edit_files')) :
589 -?>
590 -<form action="" method="post"><div>
591 -<?php FeedWordPressCompatibility::stamp_nonce('feedwordpress_fix_magpie'); ?>
592 -<input type="hidden" name="action" value="fix_magpie_version" />
593 -<input class="button-secondary" type="submit" name="ignore" value="<?php _e('Ignore this problem'); ?>" />
594 -<input class="button-primary" type="submit" name="upgrade" value="<?php _e('Upgrade'); ?>" />
595 -</div></form>
596 -<?php
597 - endif;
598 -}
599 -
600 807 ################################################################################
601 808 ## fwp_hold_pings() and fwp_release_pings(): Outbound XML-RPC ping reform ####
602 809 ## ... 'coz it's rude to send 500 pings the first time your aggregator runs ####
603 810 ################################################################################
@@ -653,8 +860,65 @@
653 860 endif;
654 861 endif;
655 862 }
656 863
864 + function feedwordpress_add_post_edit_controls () {
865 + add_meta_box('feedwordpress-post-controls', __('Syndication'), 'feedwordpress_post_edit_controls', 'post', 'side', 'high');
866 + } // function FeedWordPress::postEditControls
867 +
868 + function feedwordpress_post_edit_controls () {
869 + global $post;
870 +
871 + $frozen_values = get_post_custom_values('_syndication_freeze_updates', $post->ID);
872 + $frozen_post = (count($frozen_values) > 0 and 'yes' == $frozen_values[0]);
873 +
874 + if (is_syndicated($post->ID)) :
875 + ?>
876 + <p>This is a syndicated post, which originally appeared at
877 + <cite><?php print esc_html(get_syndication_source(NULL, $post->ID)); ?></cite>.
878 + <a href="<?php print esc_html(get_syndication_permalink($post->ID)); ?>">View original post</a>.</p>
879 +
880 + <p><input type="hidden" name="feedwordpress_noncename" id="feedwordpress_noncename" value="<?php print wp_create_nonce(plugin_basename(__FILE__)); ?>" />
881 + <label><input type="checkbox" name="freeze_updates" value="yes" <?php if ($frozen_post) : ?>checked="checked"<?php endif; ?> /> <strong>Manual editing.</strong>
882 + If set, FeedWordPress will not overwrite the changes you make manually
883 + to this post, if the syndicated content is updated on the
884 + feed.</label></p>
885 + <?php
886 + else :
887 + ?>
888 + <p>This post was created locally at this website.</p>
889 + <?php
890 + endif;
891 + } // function feedwordpress_post_edit_controls () */
892 +
893 + function feedwordpress_save_post_edit_controls ( $post_id ) {
894 + global $post;
895 +
896 + if (!isset($_POST['feedwordpress_noncename']) or !wp_verify_nonce($_POST['feedwordpress_noncename'], plugin_basename(__FILE__))) :
897 + return $post_id;
898 + endif;
899 +
900 + // Verify if this is an auto save routine. If it is our form has
901 + // not been submitted, so we don't want to do anything.
902 + if ( defined('DOING_AUTOSAVE') and DOING_AUTOSAVE ) :
903 + return $post_id;
904 + endif;
905 +
906 + // Check permissions
907 + if ( !current_user_can( 'edit_'.$_POST['post_type'], $post_id) ) :
908 + return $post_id;
909 + endif;
910 +
911 + // OK, we're golden. Now let's save some data.
912 + if (isset($_POST['freeze_updates'])) :
913 + update_post_meta($post_id, '_syndication_freeze_updates', $_POST['freeze_updates']);
914 + else :
915 + delete_post_meta($post_id, '_syndication_freeze_updates');
916 + endif;
917 +
918 + return $_POST['freeze_updates'];
919 + } // function feedwordpress_save_edit_controls
920 +
657 921 ################################################################################
658 922 ## class FeedWordPress #########################################################
659 923 ################################################################################
660 924
@@ -698,9 +962,9 @@
698 962 function FeedWordPress () {
699 963 $this->feeds = array ();
700 964 $links = FeedWordPress::syndicated_links();
701 965 if ($links): foreach ($links as $link):
702 - $this->feeds[] =& new SyndicatedLink($link);
966 + $this->feeds[] = new SyndicatedLink($link);
703 967 endforeach; endif;
704 968 } // FeedWordPress::FeedWordPress ()
705 969
706 970 # function update (): polls for updates on one or more Contributor feeds
@@ -786,9 +1050,9 @@
786 1050 if (!is_null($crash_ts) and (time() > $crash_ts)) : // Check whether we've exceeded the time limit
787 1051 break;
788 1052 endif;
789 1053
790 - $pinged_that = (is_null($uri) or in_array($uri, array($feed->uri(), $feed->homepage())));
1054 + $pinged_that = (is_null($uri) or ($uri=='*') or in_array($uri, array($feed->uri(), $feed->homepage())));
791 1055
792 1056 if (!is_null($uri)) : // A site-specific ping always updates
793 1057 $timely = true;
794 1058 else :
@@ -804,10 +1068,12 @@
804 1068 $start_ts = time();
805 1069 $added = $feed->poll($crash_ts);
806 1070 do_action('feedwordpress_check_feed_complete', $feed->settings, $added, time() - $start_ts);
807 1071
808 - if (isset($added['new'])) : $delta['new'] += $added['new']; endif;
809 - if (isset($added['updated'])) : $delta['updated'] += $added['updated']; endif;
1072 + if (is_array($added)) : // Success
1073 + if (isset($added['new'])) : $delta['new'] += $added['new']; endif;
1074 + if (isset($added['updated'])) : $delta['updated'] += $added['updated']; endif;
1075 + endif;
810 1076 endif;
811 1077 endforeach;
812 1078
813 1079 do_action('feedwordpress_update_complete', $delta);
@@ -816,8 +1082,11 @@
816 1082 }
817 1083
818 1084 function stale () {
819 1085 if (get_option('feedwordpress_automatic_updates')) :
1086 + // Do our best to avoid possible simultaneous
1087 + // updates by getting up-to-the-minute settings.
1088 +
820 1089 $last = get_option('feedwordpress_last_update_all');
821 1090
822 1091 // If we haven't updated all yet, give it a time window
823 1092 if (false === $last) :
@@ -836,12 +1105,8 @@
836 1105 else :
837 1106 FeedWordPress::critical_bug('FeedWordPress::stale::last', $last, __LINE__);
838 1107 endif;
839 1108
840 - // Explicit request for an update (e.g. from a cron job).
841 - elseif (FeedWordPress::update_requested()) :
842 - $ret = true;
843 -
844 1109 else :
845 1110 $ret = false;
846 1111 endif;
847 1112 return $ret;
@@ -847,11 +1112,25 @@
847 1112 return $ret;
848 1113 } // FeedWordPress::stale()
849 1114
850 1115 function update_requested () {
851 - return (isset($_REQUEST['update_feedwordpress']) and $_REQUEST['update_feedwordpress']);
1116 + return (
1117 + isset($_REQUEST['update_feedwordpress'])
1118 + and $_REQUEST['update_feedwordpress']
1119 + );
852 1120 } // FeedWordPress::update_requested()
853 1121
1122 + 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;
1129 +
1130 + return $ret;
1131 + } // FeedWordPress::update_requested_url()
1132 +
854 1133 function syndicate_link ($name, $uri, $rss) {
855 1134 global $wpdb;
856 1135
857 1136 // Get the category ID#
@@ -859,16 +1138,29 @@
859 1138
860 1139 // WordPress gets cranky if there's no homepage URI
861 1140 if (!isset($uri) or strlen($uri)<1) : $uri = $rss; endif;
862 1141
863 - if (function_exists('wp_insert_link')) { // WordPress 2.x
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;
1155 +
864 1156 $link_id = wp_insert_link(array(
865 1157 "link_name" => $name,
866 1158 "link_url" => $uri,
867 - "link_category" => (fwp_test_wp_version(0, FWP_SCHEMA_21) ? $cat_id : array($cat_id)),
1159 + "link_category" => $linkCats,
868 1160 "link_rss" => $rss
869 1161 ));
870 - } else { // WordPress 1.5.x
1162 + else : // WordPress 1.5.x
871 1163 $result = $wpdb->query("
872 1164 INSERT INTO $wpdb->links
873 1165 SET
874 1166 link_name = '".$wpdb->escape($name)."',
@@ -876,12 +1168,20 @@
876 1168 link_category = '".$wpdb->escape($cat_id)."',
877 1169 link_rss = '".$wpdb->escape($rss)."'
878 1170 ");
879 1171 $link_id = $wpdb->insert_id;
880 - } // if
1172 + endif;
881 1173 return $link_id;
882 1174 } // function FeedWordPress::syndicate_link()
883 1175
1176 + /*static*/ function syndicated_status ($what, $default) {
1177 + $ret = get_option("feedwordpress_syndicated_{$what}_status");
1178 + if (!$ret) :
1179 + $ret = $default;
1180 + endif;
1181 + return $ret;
1182 + } /* FeedWordPress::syndicated_status() */
1183 +
884 1184 function on_unfamiliar ($what = 'author', $override = NULL) {
885 1185 $set = array(
886 1186 'author' => array('create', 'default', 'filter'),
887 1187 'category' => array('create', 'tag', 'default', 'filter'),
@@ -888,8 +1188,10 @@
888 1188 );
889 1189
890 1190 if (is_string($override)) :
891 1191 $ret = strtolower($override);
1192 + else :
1193 + $ret = NULL;
892 1194 endif;
893 1195
894 1196 if (!is_numeric($override) and !in_array($ret, $set[$what])) :
895 1197 $ret = get_option('feedwordpress_unfamiliar_'.$what);
@@ -925,8 +1227,19 @@
925 1227 $ret = get_option('feedwordpress_use_aggregator_source_data');
926 1228 return apply_filters('syndicated_post_use_aggregator_source_data', ($ret=='yes'));
927 1229 }
928 1230
1231 + /**
1232 + * FeedWordPress::munge_permalinks: check whether or not FeedWordPress
1233 + * should rewrite permalinks for syndicated items to reflect their
1234 + * original location.
1235 + *
1236 + * @return bool TRUE if FeedWordPress SHOULD rewrite permalinks; FALSE otherwise
1237 + */
1238 + /*static*/ function munge_permalinks () {
1239 + return (get_option('feedwordpress_munge_permalink', /*default=*/ 'yes') != 'no');
1240 + } /* FeedWordPress::munge_permalinks() */
1241 +
929 1242 function syndicated_links () {
930 1243 $contributors = FeedWordPress::link_category_id();
931 1244 if (function_exists('get_bookmarks')) :
932 1245 $links = get_bookmarks(array("category" => $contributors));
@@ -940,61 +1253,31 @@
940 1253 global $wpdb, $wp_db_version;
941 1254
942 1255 $cat_id = get_option('feedwordpress_cat_id');
943 1256
944 - // If we don't yet *have* the category, we'll have to create it
945 - if ($cat_id === false) :
946 - $cat = $wpdb->escape(DEFAULT_SYNDICATION_CATEGORY);
947 -
948 - // Look for something with the right name...
949 - // -----------------------------------------
1257 + // If we don't yet have the category ID stored, search by name
1258 + if (!$cat_id) :
1259 + $cat_id = FeedWordPressCompatibility::link_category_id(DEFAULT_SYNDICATION_CATEGORY);
950 1260
951 - // WordPress 2.3 introduces a new taxonomy/term API
952 - if (function_exists('is_term')) :
953 - $cat_id = is_term($cat, 'link_category');
954 - // WordPress 2.1 and 2.2 use a common table for both link and post categories
955 - elseif (fwp_test_wp_version(FWP_SCHEMA_21, FWP_SCHEMA_23)) :
956 - $cat_id = $wpdb->get_var("SELECT cat_id FROM {$wpdb->categories} WHERE cat_name='$cat'");
957 - // WordPress 1.5 and 2.0.x have a separate table for link categories
958 - elseif (fwp_test_wp_version(0, FWP_SCHEMA_21)):
959 - $cat_id = $wpdb->get_var("SELECT cat_id FROM {$wpdb->linkcategories} WHERE cat_name='$cat'");
960 - // This should never happen.
961 - else :
962 - FeedWordPress::critical_bug('FeedWordPress::link_category_id::wp_db_version', $wp_db_version, __LINE__);
1261 + if ($cat_id) :
1262 + // We found it; let's stamp it.
1263 + update_option('feedwordpress_cat_id', $cat_id);
963 1264 endif;
964 1265
965 - // If you still can't find anything, make it for yourself.
966 - // -------------------------------------------------------
967 - if (!$cat_id) :
968 - // WordPress 2.3+ term/taxonomy API
969 - if (function_exists('wp_insert_term')) :
970 - $term = wp_insert_term($cat, 'link_category');
971 - $cat_id = $term['term_id'];
972 - // WordPress 2.1, 2.2 category API. By the way, why the fuck is this API function only available in a wp-admin module?
973 - elseif (function_exists('wp_insert_category') and !fwp_test_wp_version(FWP_SCHEMA_20, FWP_SCHEMA_21)) :
974 - $cat_id = wp_insert_category(array('cat_name' => $cat));
975 - // WordPress 1.5 and 2.0.x
976 - elseif (fwp_test_wp_version(0, FWP_SCHEMA_21)) :
977 - $result = $wpdb->query("
978 - INSERT INTO $wpdb->linkcategories
979 - SET
980 - cat_id = 0,
981 - cat_name='$cat',
982 - show_images='N',
983 - show_description='N',
984 - show_rating='N',
985 - show_updated='N',
986 - sort_order='name'
987 - ");
988 - $cat_id = $wpdb->insert_id;
989 - // This should never happen.
990 - else :
991 - FeedWordPress::critical_bug('FeedWordPress::link_category_id::wp_db_version', $wp_db_version, __LINE__);
992 - endif;
993 - endif;
1266 + // If we *do* have the category ID stored, verify that it exists
1267 + else :
1268 + $cat_id = FeedWordPressCompatibility::link_category_id((int) $cat_id, 'cat_id');
1269 + endif;
1270 +
1271 + // If we could not find an appropriate link category,
1272 + // make a new one for ourselves.
1273 + if (!$cat_id) :
1274 + $cat_id = FeedWordPressCompatibility::insert_link_category(DEFAULT_SYNDICATION_CATEGORY);
994 1275
1276 + // Stamp it
995 1277 update_option('feedwordpress_cat_id', $cat_id);
996 1278 endif;
1279 +
997 1280 return $cat_id;
998 1281 } // function FeedWordPress::link_category_id()
999 1282
1000 1283 # Upgrades and maintenance...
@@ -1040,56 +1323,14 @@
1040 1323
1041 1324 if (is_null($from) or $from <= 0.96) : $from = 0.96; endif;
1042 1325
1043 1326 switch ($from) :
1044 - case 0.96: // account for changes to syndication custom values and guid
1045 - echo "<p>Upgrading database from {$from} to ".FEEDWORDPRESS_VERSION."...</p>\n";
1327 + case 0.96:
1328 + // Dropping legacy upgrade code. If anyone is still
1329 + // using 0.96 and just now decided to upgrade, well, I'm
1330 + // sorry about that. You'll just have to cope with a few
1331 + // duplicate posts.
1046 1332
1047 - $cat_id = FeedWordPress::link_category_id();
1048 -
1049 - // Avoid duplicates
1050 - $wpdb->query("DELETE FROM `{$wpdb->postmeta}` WHERE meta_key = 'syndication_feed_id'");
1051 -
1052 - // Look up all the link IDs
1053 - $wpdb->query("
1054 - CREATE TEMPORARY TABLE tmp_custom_values
1055 - SELECT
1056 - NULL AS meta_id,
1057 - post_id,
1058 - 'syndication_feed_id' AS meta_key,
1059 - link_id AS meta_value
1060 - FROM `{$wpdb->postmeta}`, `{$wpdb->links}`
1061 - WHERE
1062 - meta_key='syndication_feed'
1063 - AND meta_value=link_rss
1064 - AND link_category = {$cat_id}
1065 - ");
1066 -
1067 - // Now attach them to their posts
1068 - $wpdb->query("INSERT INTO `{$wpdb->postmeta}` SELECT * FROM tmp_custom_values");
1069 -
1070 - // And clean up after ourselves.
1071 - $wpdb->query("DROP TABLE tmp_custom_values");
1072 -
1073 - // Now fix the guids to avoid duplicate posts
1074 - echo "<ul>";
1075 - foreach ($this->feeds as $feed) :
1076 - echo "<li>Fixing post meta-data for <cite>".$feed['link/name']."</cite> &#8230; "; flush();
1077 - $rss = @fetch_rss($feed['link/uri']);
1078 - if (is_array($rss->items)) :
1079 - foreach ($rss->items as $item) :
1080 - $guid = $wpdb->escape(FeedWordPress::guid($item, $feed)); // new GUID algorithm
1081 - $link = $wpdb->escape($item['link']);
1082 -
1083 - $wpdb->query("
1084 - UPDATE `{$wpdb->posts}` SET guid='{$guid}' WHERE guid='{$link}'
1085 - ");
1086 - endforeach;
1087 - endif;
1088 - echo "<strong>complete.</strong></li>\n";
1089 - endforeach;
1090 - echo "</ul>\n";
1091 -
1092 1333 // Mark the upgrade as successful.
1093 1334 update_option('feedwordpress_version', FEEDWORDPRESS_VERSION);
1094 1335 endswitch;
1095 1336 echo "<p>Upgrade complete. FeedWordPress is now ready to use again.</p>";
@@ -1094,8 +1335,27 @@
1094 1335 endswitch;
1095 1336 echo "<p>Upgrade complete. FeedWordPress is now ready to use again.</p>";
1096 1337 } /* FeedWordPress::upgrade_database() */
1097 1338
1339 + function has_guid_index () {
1340 + global $wpdb;
1341 +
1342 + $found = false; // Guilty until proven innocent.
1343 +
1344 + $results = $wpdb->get_results("
1345 + SHOW INDEXES FROM {$wpdb->posts}
1346 + ");
1347 + if ($results) :
1348 + foreach ($results as $index) :
1349 + if (isset($index->Column_name)
1350 + and ('guid' == $index->Column_name)) :
1351 + $found = true;
1352 + endif;
1353 + endforeach;
1354 + endif;
1355 + return $found;
1356 + } /* FeedWordPress::has_guid_index () */
1357 +
1098 1358 function create_guid_index () {
1099 1359 global $wpdb;
1100 1360
1101 1361 $wpdb->query("
@@ -1102,15 +1362,71 @@
1102 1362 CREATE INDEX {$wpdb->posts}_guid_idx ON {$wpdb->posts}(guid)
1103 1363 ");
1104 1364 } /* FeedWordPress::create_guid_index () */
1105 1365
1106 - function magpie_version () {
1107 - if (!defined('MAGPIE_VERSION')) : $magpie_version = $GLOBALS['wp_version'].'-default';
1108 - else : $magpie_version = MAGPIE_VERSION;
1366 + function remove_guid_index () {
1367 + global $wpdb;
1368 +
1369 + $wpdb->query("
1370 + DROP INDEX {$wpdb->posts}_guid_idx ON {$wpdb->posts}
1371 + ");
1372 + }
1373 +
1374 + /*static*/ function fetch ($url) {
1375 + require_once (ABSPATH . WPINC . '/class-feed.php');
1376 + $feed = new SimplePie();
1377 + $feed->set_feed_url($url);
1378 + $feed->set_cache_class('WP_Feed_Cache');
1379 + $feed->set_file_class('WP_SimplePie_File');
1380 + $feed->set_cache_duration(FeedWordPress::cache_duration());
1381 + $feed->init();
1382 + $feed->handle_content_type();
1383 +
1384 + if ($feed->error()) :
1385 + $ret = new WP_Error('simplepie-error', $feed->error());
1386 + else :
1387 + $ret = $feed;
1109 1388 endif;
1110 - return $magpie_version;
1389 + return $ret;
1390 + } /* FeedWordPress::fetch () */
1391 +
1392 + function clear_cache () {
1393 + global $wpdb;
1394 +
1395 + // The WordPress SimplePie module stores its cached feeds as
1396 + // transient records in the options table. The data itself is
1397 + // stored in `_transient_feed_{md5 of url}` and the last-modified
1398 + // timestamp in `_transient_feed_mod_{md5 of url}`. Timeouts for
1399 + // these records are stored in `_transient_timeout_feed_{md5}`.
1400 + // Since the md5 is always 32 characters in length, the
1401 + // option_name is always over 32 characters.
1402 + $wpdb->query("
1403 + DELETE FROM {$wpdb->options}
1404 + WHERE option_name LIKE '_transient%_feed_%' AND LENGTH(option_name) > 32
1405 + ");
1406 + } /* FeedWordPress::clear_cache () */
1407 +
1408 + function cache_duration () {
1409 + $duration = NULL;
1410 + if (defined('FEEDWORDPRESS_CACHE_AGE')) :
1411 + $duration = FEEDWORDPRESS_CACHE_AGE;
1412 + endif;
1413 + return $duration;
1111 1414 }
1415 + function cache_lifetime ($duration) {
1416 + // Check for explicit setting of a lifetime duration
1417 + if (defined('FEEDWORDPRESS_CACHE_LIFETIME')) :
1418 + $duration = FEEDWORDPRESS_CACHE_LIFETIME;
1112 1419
1420 + // Fall back to the cache freshness duration
1421 + elseif (defined('FEEDWORDPRESS_CACHE_AGE')) :
1422 + $duration = FEEDWORDPRESS_CACHE_AGE;
1423 + endif;
1424 +
1425 + // Fall back to WordPress default
1426 + return $duration;
1427 + } /* FeedWordPress::cache_lifetime () */
1428 +
1113 1429 # Utility functions for handling text settings
1114 1430 function negative ($f, $setting) {
1115 1431 $nego = array ('n', 'no', 'f', 'false');
1116 1432 return (isset($f[$setting]) and in_array(strtolower($f[$setting]), $nego));
@@ -1125,17 +1441,12 @@
1125 1441 # Internal debugging functions
1126 1442 function critical_bug ($varname, $var, $line) {
1127 1443 global $wp_version;
1128 1444
1129 - if (defined('MAGPIE_VERSION')) : $mv = MAGPIE_VERSION;
1130 - else : $mv = 'WordPress '.$wp_version.' default.';
1131 - endif;
1132 -
1133 1445 echo '<p>There may be a bug in FeedWordPress. Please <a href="'.FEEDWORDPRESS_AUTHOR_CONTACT.'">contact the author</a> and paste the following information into your e-mail:</p>';
1134 1446 echo "\n<plaintext>";
1135 1447 echo "Triggered at line # ".$line."\n";
1136 1448 echo "FeedWordPress version: ".FEEDWORDPRESS_VERSION."\n";
1137 - echo "MagpieRSS version: {$mv}\n";
1138 1449 echo "WordPress version: {$wp_version}\n";
1139 1450 echo "PHP version: ".phpversion()."\n";
1140 1451 echo "\n";
1141 1452 echo $varname.": "; var_dump($var); echo "\n";
@@ -1161,9 +1472,9 @@
1161 1472 return $args;
1162 1473 }
1163 1474
1164 1475 function feedwordpress_pong ($args) {
1165 - $feedwordpress =& new FeedWordPress;
1476 + $feedwordpress = new FeedWordPress;
1166 1477 $delta = @$feedwordpress->update($args[1]);
1167 1478 if (is_null($delta)):
1168 1479 return array('flerror' => true, 'message' => "Sorry. I don't syndicate <$args[1]>.");
1169 1480 else:
@@ -1174,13 +1485,9 @@
1174 1485 return array('flerror' => false, 'message' => "Thanks for the ping.".implode(' and', $mesg));
1175 1486 endif;
1176 1487 }
1177 1488
1178 -# The upgraded MagpieRSS also uses this class. So if we have it loaded
1179 -# in, don't load it again.
1180 -if (!class_exists('Relative_URI')) {
1181 - require_once(dirname(__FILE__) . '/relative_uri.class.php');
1182 -}
1489 +require_once(dirname(__FILE__) . '/relative_uri.class.php');
1183 1490
1184 1491 // take your best guess at the realname and e-mail, given a string
1185 1492 define('FWP_REGEX_EMAIL_ADDY', '([^@"(<\s]+@[^"@(<\s]+\.[^"@(<\s]+)');
1186 1493 define('FWP_REGEX_EMAIL_NAME', '("([^"]*)"|([^"<(]+\S))');