PluginProbe
FeedWordPress / 2008.1214
FeedWordPress v2008.1214
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 +359 -140 2008.10302008.1214 View file →
@@ -2,13 +2,13 @@
2 2 /*
3 3 Plugin Name: FeedWordPress
4 4 Plugin URI: http://projects.radgeek.com/feedwordpress
5 5 Description: simple and flexible Atom/RSS syndication for WordPress
6 -Version: 2008.1030
6 +Version: 2008.1214
7 7 Author: Charles Johnson
8 8 Author URI: http://radgeek.com/
9 9 License: GPL
10 -Last modified: 2008-10-30 4:14pm PDT
10 +Last modified: 2008-12-14 4:29pm PST
11 11 */
12 12
13 13 # This uses code derived from:
14 14 # - wp-rss-aggregate.php by Kellan Elliot-McCrea <kellan@protest.net>
@@ -15,20 +15,22 @@
15 15 # - HTTP Navigator 2 by Keyvan Minoukadeh <keyvan@k1m.com>
16 16 # - Ultra-Liberal Feed Finder by Mark Pilgrim <mark@diveintomark.org>
17 17 # according to the terms of the GNU General Public License.
18 18 #
19 -# INSTALLATION: see README.text or <http://projects.radgeek.com/install>
19 +# INSTALLATION: see readme.txt or <http://projects.radgeek.com/install>
20 20 #
21 21 # USAGE: once FeedWordPress is installed, you manage just about everything from
22 -# the WordPress Dashboard, under Options --> Syndication or Links --> Syndicated
23 -# To ensure that fresh content is added as it becomes available, get your
24 -# contributors to put your XML-RPC URI (if WordPress is installed at
22 +# the WordPress Dashboard, under the Syndication menu. To ensure that fresh
23 +# content is added as it becomes available, you can convince your contributors
24 +# to put your XML-RPC URI (if WordPress is installed at
25 25 # <http://www.zyx.com/blog>, XML-RPC requests should be sent to
26 -# <http://www.zyx.com/blog/xmlrpc.php>), or see `update-feeds.php`
26 +# <http://www.zyx.com/blog/xmlrpc.php>), or update manually under the
27 +# Syndication menu, or set up automatic updates under Syndication --> Settings,
28 +# or use a cron job.
27 29
28 30 # -- Don't change these unless you know what you're doing...
29 31
30 -define ('FEEDWORDPRESS_VERSION', '2008.1030');
32 +define ('FEEDWORDPRESS_VERSION', '2008.1214');
31 33 define ('FEEDWORDPRESS_AUTHOR_CONTACT', 'http://radgeek.com/contact');
32 34 define ('DEFAULT_SYNDICATION_CATEGORY', 'Contributors');
33 35
34 36 define ('FEEDWORDPRESS_DEBUG', false);
@@ -39,13 +41,15 @@
39 41 define ('FEEDVALIDATOR_URI', 'http://feedvalidator.org/check.cgi');
40 42
41 43 define ('FEEDWORDPRESS_FRESHNESS_INTERVAL', 10*60); // Every ten minutes
42 44
45 +define ('FWP_SCHEMA_HAS_USERMETA', 2966);
43 46 define ('FWP_SCHEMA_20', 3308); // Database schema # for WP 2.0
44 47 define ('FWP_SCHEMA_21', 4772); // Database schema # for WP 2.1
45 48 define ('FWP_SCHEMA_23', 5495); // Database schema # for WP 2.3
46 49 define ('FWP_SCHEMA_25', 7558); // Database schema # for WP 2.5
47 50 define ('FWP_SCHEMA_26', 8201); // Database schema # for WP 2.6
51 +define ('FWP_SCHEMA_27', 9872); // Database schema # for WP 2.7
48 52
49 53 if (FEEDWORDPRESS_DEBUG) :
50 54 // Help us to pick out errors, if any.
51 55 ini_set('error_reporting', E_ALL & ~E_NOTICE);
@@ -248,17 +252,80 @@
248 252 ################################################################################
249 253
250 254 function is_syndicated () { return (strlen(get_syndication_feed_id()) > 0); }
251 255
252 -function the_syndication_source_link () { echo get_syndication_source_link(); }
253 -function get_syndication_source_link () { list($n) = get_post_custom_values('syndication_source_uri'); return $n; }
256 +function get_syndication_source_link ($original = NULL) {
257 + if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
258 + endif;
254 259
255 -function get_syndication_source () { list($n) = get_post_custom_values('syndication_source'); return $n; }
256 -function the_syndication_source () { echo get_syndication_source(); }
260 + if ($original) : $vals = get_post_custom_values('syndication_source_uri_original');
261 + else : $vals = array();
262 + endif;
263 +
264 + if (count($vals) == 0) : $vals = get_post_custom_values('syndication_source_uri');
265 + endif;
266 +
267 + if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
257 268
258 -function get_syndication_feed () { list($u) = get_post_custom_values('syndication_feed'); return $u; }
259 -function the_syndication_feed () { echo get_syndication_feed (); }
269 + return $ret;
270 +} /* function get_syndication_source_link() */
260 271
272 +function the_syndication_source_link ($original = NULL) { echo get_syndication_source_link($original); }
273 +
274 +function get_syndication_source ($original = NULL) {
275 + if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
276 + endif;
277 +
278 + if ($original) : $vals = get_post_custom_values('syndication_source_original');
279 + else : $vals = array();
280 + endif;
281 +
282 + if (count($vals) == 0) : $vals = get_post_custom_values('syndication_source');
283 + endif;
284 +
285 + if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
286 +
287 + return $ret;
288 +} /* function get_syndication_source() */
289 +
290 +function the_syndication_source ($original = NULL) { echo get_syndication_source($original); }
291 +
292 +function get_syndication_feed ($original = NULL) {
293 + if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
294 + endif;
295 +
296 + if ($original) : $vals = get_post_custom_values('syndication_feed_original');
297 + else : $vals = array();
298 + endif;
299 +
300 + if (count($vals) == 0) : $vals = get_post_custom_values('syndication_feed');
301 + endif;
302 +
303 + if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
304 +
305 + return $ret;
306 +} /* function get_syndication_feed() */
307 +
308 +function the_syndication_feed ($original = NULL) { echo get_syndication_feed ($original); }
309 +
310 +function get_syndication_feed_guid ($original = NULL) {
311 + if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
312 + endif;
313 +
314 + if ($original) : $vals = get_post_custom_values('syndication_source_id_original');
315 + else : $vals = array();
316 + endif;
317 +
318 + if (count($vals) == 0) : $vals = array(get_feed_meta('feed/id'));
319 + endif;
320 +
321 + if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
322 +
323 + return $ret;
324 +} /* function get_syndication_feed_guid () */
325 +
326 +function the_syndication_feed_guid ($original = NULL) { echo get_syndication_feed_guid($original); }
327 +
261 328 function get_syndication_feed_id () { list($u) = get_post_custom_values('syndication_feed_id'); return $u; }
262 329 function the_syndication_feed_id () { echo get_syndication_feed_id(); }
263 330
264 331 $feedwordpress_linkcache = array (); // only load links from database once
@@ -323,9 +390,9 @@
323 390 <title><?php the_syndication_source(); ?></title>
324 391 <link rel="alternate" type="text/html" href="<?php the_syndication_source_link(); ?>" />
325 392 <link rel="self" href="<?php the_syndication_feed(); ?>" />
326 393 <?php
327 - $id = get_feed_meta('feed/id');
394 + $id = get_syndication_feed_guid();
328 395 if (strlen($id) > 0) :
329 396 ?>
330 397 <id><?php print $id; ?></id>
331 398 <?php
@@ -357,11 +424,27 @@
357 424 function fwp_add_pages () {
358 425 global $fwp_capability;
359 426 global $fwp_path;
360 427
361 - add_menu_page('Syndicated Sites', 'Syndication', $fwp_capability['manage_links'], $fwp_path.'/syndication.php');
362 - add_submenu_page($fwp_path.'/syndication.php', 'Syndication Options', 'Options', $fwp_capability['manage_options'], $fwp_path.'/syndication-options.php');
363 - add_options_page('Syndication Options', 'Syndication', $fwp_capability['manage_options'], $fwp_path.'/syndication-options.php');
428 + $menu = array('Syndicated Sites', 'Syndication', $fwp_capability['manage_links'], $fwp_path.'/syndication.php', NULL);
429 + if (fwp_test_wp_version(FWP_SCHEMA_27)) :
430 + // add icon parameter
431 + $menu[] = WP_PLUGIN_URL.'/'.$fwp_path.'/feedwordpress-tiny.png';
432 + endif;
433 +
434 + if (fwp_test_wp_version(FWP_SCHEMA_26)) :
435 + $options = __('Settings');
436 + $longoptions = __('Syndication Settings');
437 + else :
438 + $options = __('Options');
439 + $longoptions = __('Syndication Options');
440 + endif;
441 +
442 + call_user_func_array('add_menu_page', $menu);
443 + add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Authors', 'Authors', $fwp_capability['manage_options'], $fwp_path.'/authors.php');
444 + add_submenu_page($fwp_path.'/syndication.php', $longoptions, $options, $fwp_capability['manage_options'], $fwp_path.'/syndication-options.php');
445 +
446 + add_options_page($longoptions, 'Syndication', $fwp_capability['manage_options'], $fwp_path.'/syndication-options.php');
364 447 } // function fwp_add_pages () */
365 448
366 449 ################################################################################
367 450 ## fwp_hold_pings() and fwp_release_pings(): Outbound XML-RPC ping reform ####
@@ -517,9 +600,9 @@
517 600 #
518 601 # * Updates to existing posts since the last poll are mirrored in the
519 602 # WordPress store.
520 603 #
521 - function update ($uri = null) {
604 + function update ($uri = null, $crash_ts = null) {
522 605 global $wpdb;
523 606
524 607 if (FeedWordPress::needs_upgrade()) : // Will make duplicate posts if we don't hold off
525 608 return NULL;
@@ -532,11 +615,28 @@
532 615 endif;
533 616
534 617 do_action('feedwordpress_update', $uri);
535 618
619 + if (is_null($crash_ts)) :
620 + $crash_dt = (int) get_option('feedwordpress_update_time_limit');
621 + if ($crash_dt > 0) :
622 + $crash_ts = time() + $crash_dt;
623 + else :
624 + $crash_ts = NULL;
625 + endif;
626 + endif;
627 +
628 + // Randomize order for load balancing purposes
629 + $feed_set = $this->feeds;
630 + shuffle($feed_set);
631 +
536 632 // Loop through and check for new posts
537 633 $delta = NULL;
538 - foreach ($this->feeds as $feed) :
634 + foreach ($feed_set as $feed) :
635 + if (!is_null($crash_ts) and (time() > $crash_ts)) : // Check whether we've exceeded the time limit
636 + break;
637 + endif;
638 +
539 639 $pinged_that = (is_null($uri) or in_array($uri, array($feed->uri(), $feed->homepage())));
540 640
541 641 if (!is_null($uri)) : // A site-specific ping always updates
542 642 $timely = true;
@@ -549,9 +649,12 @@
549 649 endif;
550 650
551 651 if ($pinged_that and $timely) :
552 652 do_action('feedwordpress_check_feed', $feed->settings);
553 - $added = $feed->poll();
653 + $start_ts = time();
654 + $added = $feed->poll($crash_ts);
655 + do_action('feedwordpress_check_feed_complete', $feed->settings, $added, time() - $start_ts);
656 +
554 657 if (isset($added['new'])) : $delta['new'] += $added['new']; endif;
555 658 if (isset($added['updated'])) : $delta['updated'] += $added['updated']; endif;
556 659 endif;
557 660 endforeach;
@@ -609,9 +712,9 @@
609 712 if (function_exists('wp_insert_link')) { // WordPress 2.x
610 713 $link_id = wp_insert_link(array(
611 714 "link_name" => $name,
612 715 "link_url" => $uri,
613 - "link_category" => array($cat_id),
716 + "link_category" => (fwp_test_wp_version(0, FWP_SCHEMA_21) ? $cat_id : array($cat_id)),
614 717 "link_rss" => $rss
615 718 ));
616 719 } else { // WordPress 1.5.x
617 720 $result = $wpdb->query("
@@ -646,8 +749,33 @@
646 749
647 750 return $ret;
648 751 } // function FeedWordPress::on_unfamiliar()
649 752
753 + function null_email_set () {
754 + $base = get_option('feedwordpress_null_email_set');
755 +
756 + if ($base===false) :
757 + $ret = array('noreply@blogger.com'); // default
758 + else :
759 + $ret = array_map('strtolower',
760 + array_map('trim', explode("\n", $base)));
761 + endif;
762 + $ret = apply_filters('syndicated_item_author_null_email_set', $ret);
763 + return $ret;
764 +
765 + } /* FeedWordPress::null_email_set () */
766 +
767 + function is_null_email ($email) {
768 + $ret = in_array(strtolower(trim($email)), FeedWordPress::null_email_set());
769 + $ret = apply_filters('syndicated_item_author_is_null_email', $ret, $email);
770 + return $ret;
771 + } /* FeedWordPress::is_null_email () */
772 +
773 + function use_aggregator_source_data () {
774 + $ret = get_option('feedwordpress_use_aggregator_source_data');
775 + return apply_filters('syndicated_post_use_aggregator_source_data', ($ret=='yes'));
776 + }
777 +
650 778 function syndicated_links () {
651 779 $contributors = FeedWordPress::link_category_id();
652 780 if (function_exists('get_bookmarks')) :
653 781 $links = get_bookmarks(array("category" => $contributors));
@@ -690,12 +818,12 @@
690 818 if (function_exists('wp_insert_term')) :
691 819 $term = wp_insert_term($cat, 'link_category');
692 820 $cat_id = $term['term_id'];
693 821 // WordPress 2.1, 2.2 category API. By the way, why the fuck is this API function only available in a wp-admin module?
694 - elseif (function_exists('wp_insert_category')) :
822 + elseif (function_exists('wp_insert_category') and !fwp_test_wp_version(FWP_SCHEMA_20, FWP_SCHEMA_21)) :
695 823 $cat_id = wp_insert_category(array('cat_name' => $cat));
696 824 // WordPress 1.5 and 2.0.x
697 - elseif (!isset($wp_db_version) or $wp_db_version < FWP_SCHEMA_21) :
825 + elseif (fwp_test_wp_version(0, FWP_SCHEMA_21)) :
698 826 $result = $wpdb->query("
699 827 INSERT INTO $wpdb->linkcategories
700 828 SET
701 829 cat_id = 0,
@@ -805,8 +933,16 @@
805 933 endswitch;
806 934 echo "<p>Upgrade complete. FeedWordPress is now ready to use again.</p>";
807 935 } /* FeedWordPress::upgrade_database() */
808 936
937 + function create_guid_index () {
938 + global $wpdb;
939 +
940 + $wpdb->query("
941 + CREATE INDEX {$wpdb->posts}_guid_idx ON {$wpdb->posts}(guid)
942 + ");
943 + } /* FeedWordPress::create_guid_index () */
944 +
809 945 # Utility functions for handling text settings
810 946 function negative ($f, $setting) {
811 947 $nego = array ('n', 'no', 'f', 'false');
812 948 return (isset($f[$setting]) and in_array(strtolower($f[$setting]), $nego));
@@ -831,8 +967,14 @@
831 967 echo "\n";
832 968 echo $varname.": "; var_dump($var); echo "\n";
833 969 die;
834 970 }
971 +
972 + function noncritical_bug ($varname, $var, $line) {
973 + if (FEEDWORDPRESS_DEBUG) : // halt only when we are doing debugging
974 + FeedWordPress::critical_bug($varname, $var, $line);
975 + endif;
976 + }
835 977 } // class FeedWordPress
836 978
837 979 class SyndicatedPost {
838 980 var $item = null;
@@ -953,12 +1095,26 @@
953 1095 // In case you want to point back to the blog this was syndicated from
954 1096 if (isset($this->feed->channel['title'])) :
955 1097 $this->post['meta']['syndication_source'] = apply_filters('syndicated_item_source_title', $this->feed->channel['title'], $this);
956 1098 endif;
1099 +
957 1100 if (isset($this->feed->channel['link'])) :
958 1101 $this->post['meta']['syndication_source_uri'] = apply_filters('syndicated_item_source_link', $this->feed->channel['link'], $this);
959 1102 endif;
960 1103
1104 + // Make use of atom:source data, if present in an aggregated feed
1105 + if (isset($this->item['source_title'])) :
1106 + $this->post['meta']['syndication_source_original'] = $this->item['source_title'];
1107 + endif;
1108 +
1109 + if (isset($this->item['source_link'])) :
1110 + $this->post['meta']['syndication_source_uri_original'] = $this->item['source_link'];
1111 + endif;
1112 +
1113 + if (isset($this->item['source_id'])) :
1114 + $this->post['meta']['syndication_source_id_original'] = $this->item['source_id'];
1115 + endif;
1116 +
961 1117 // Store information on human-readable and machine-readable comment URIs
962 1118 if (isset($this->item['comments'])) :
963 1119 $this->post['meta']['rss:comments'] = apply_filters('syndicated_item_comments', $this->item['comments']);
964 1120 endif;
@@ -969,8 +1125,12 @@
969 1125 // Store information to identify the feed that this came from
970 1126 $this->post['meta']['syndication_feed'] = $this->feedmeta['link/uri'];
971 1127 $this->post['meta']['syndication_feed_id'] = $this->feedmeta['link/id'];
972 1128
1129 + if (isset($this->item['source_link_self'])) :
1130 + $this->post['meta']['syndication_feed_original'] = $this->item['source_link_self'];
1131 + endif;
1132 +
973 1133 // In case you want to know the external permalink...
974 1134 $this->post['meta']['syndication_permalink'] = apply_filters('syndicated_item_link', $this->item['link']);
975 1135
976 1136 // Store a hash of the post content for checking whether something needs to be updated
@@ -1011,9 +1171,9 @@
1011 1171
1012 1172 // Tags: start with default tags, if any
1013 1173 $ft = get_option("feedwordpress_syndication_tags");
1014 1174 if ($ft) :
1015 - $this->post['tags_input'] = explode('FEEDWORDPRESS_CAT_SEPARATOR', $ft);
1175 + $this->post['tags_input'] = explode(FEEDWORDPRESS_CAT_SEPARATOR, $ft);
1016 1176 else :
1017 1177 $this->post['tags_input'] = array();
1018 1178 endif;
1019 1179
@@ -1449,9 +1609,9 @@
1449 1609
1450 1610 // SyndicatedPost::author_id (): get the ID for an author name from
1451 1611 // the feed. Create the author if necessary.
1452 1612 function author_id ($unfamiliar_author = 'create') {
1453 - global $wpdb, $wp_db_version; // test for WordPress 2.0 database schema
1613 + global $wpdb;
1454 1614
1455 1615 $a = $this->author();
1456 1616 $author = $a['name'];
1457 1617 $email = $a['email'];
@@ -1456,8 +1616,15 @@
1456 1616 $author = $a['name'];
1457 1617 $email = $a['email'];
1458 1618 $url = $a['uri'];
1459 1619
1620 + $match_author_by_email = !('yes' == get_option("feedwordpress_do_not_match_author_by_email"));
1621 + if ($match_author_by_email and !FeedWordPress::is_null_email($email)) :
1622 + $test_email = $email;
1623 + else :
1624 + $test_email = NULL;
1625 + endif;
1626 +
1460 1627 // Never can be too careful...
1461 1628 $login = sanitize_user($author, /*strict=*/ true);
1462 1629 $login = apply_filters('pre_user_login', $login);
1463 1630
@@ -1466,8 +1633,9 @@
1466 1633
1467 1634 $reg_author = $wpdb->escape(preg_quote($author));
1468 1635 $author = $wpdb->escape($author);
1469 1636 $email = $wpdb->escape($email);
1637 + $test_email = $wpdb->escape($test_email);
1470 1638 $url = $wpdb->escape($url);
1471 1639
1472 1640 // Check for an existing author rule....
1473 1641 if (isset($this->link->settings['map authors']['name'][strtolower(trim($author))])) :
@@ -1486,34 +1654,10 @@
1486 1654
1487 1655 else :
1488 1656 // Check the database for an existing author record that might fit
1489 1657
1490 - #-- WordPress 1.5.x
1491 - if (!isset($wp_db_version)) :
1492 - $id = $wpdb->get_var(
1493 - "SELECT ID from $wpdb->users
1494 - WHERE
1495 - TRIM(LCASE(user_login)) = TRIM(LCASE('$login')) OR
1496 - (
1497 - LENGTH(TRIM(LCASE(user_email))) > 0
1498 - AND TRIM(LCASE(user_email)) = TRIM(LCASE('$email'))
1499 - ) OR
1500 - TRIM(LCASE(user_firstname)) = TRIM(LCASE('$author')) OR
1501 - TRIM(LCASE(user_nickname)) = TRIM(LCASE('$author')) OR
1502 - TRIM(LCASE(user_nicename)) = TRIM(LCASE('$nice_author')) OR
1503 - TRIM(LCASE(user_description)) = TRIM(LCASE('$author')) OR
1504 - (
1505 - LOWER(user_description)
1506 - RLIKE CONCAT(
1507 - '(^|\\n)a\\.?k\\.?a\\.?( |\\t)*:?( |\\t)*',
1508 - LCASE('$reg_author'),
1509 - '( |\\t|\\r)*(\\n|\$)'
1510 - )
1511 - )
1512 - ");
1513 -
1514 1658 #-- WordPress 2.0+
1515 - elseif ($wp_db_version >= 2966) :
1659 + if (fwp_test_wp_version(FWP_SCHEMA_HAS_USERMETA)) :
1516 1660
1517 1661 // First try the user core data table.
1518 1662 $id = $wpdb->get_var(
1519 1663 "SELECT ID FROM $wpdb->users
@@ -1520,9 +1664,9 @@
1520 1664 WHERE
1521 1665 TRIM(LCASE(user_login)) = TRIM(LCASE('$login'))
1522 1666 OR (
1523 1667 LENGTH(TRIM(LCASE(user_email))) > 0
1524 - AND TRIM(LCASE(user_email)) = TRIM(LCASE('$email'))
1668 + AND TRIM(LCASE(user_email)) = TRIM(LCASE('$test_email'))
1525 1669 )
1526 1670 OR TRIM(LCASE(user_nicename)) = TRIM(LCASE('$nice_author'))
1527 1671 ");
1528 1672
@@ -1542,8 +1686,33 @@
1542 1686 )
1543 1687 )
1544 1688 ");
1545 1689 endif;
1690 +
1691 + #-- WordPress 1.5.x
1692 + else :
1693 + $id = $wpdb->get_var(
1694 + "SELECT ID from $wpdb->users
1695 + WHERE
1696 + TRIM(LCASE(user_login)) = TRIM(LCASE('$login')) OR
1697 + (
1698 + LENGTH(TRIM(LCASE(user_email))) > 0
1699 + AND TRIM(LCASE(user_email)) = TRIM(LCASE('$test_email'))
1700 + ) OR
1701 + TRIM(LCASE(user_firstname)) = TRIM(LCASE('$author')) OR
1702 + TRIM(LCASE(user_nickname)) = TRIM(LCASE('$author')) OR
1703 + TRIM(LCASE(user_nicename)) = TRIM(LCASE('$nice_author')) OR
1704 + TRIM(LCASE(user_description)) = TRIM(LCASE('$author')) OR
1705 + (
1706 + LOWER(user_description)
1707 + RLIKE CONCAT(
1708 + '(^|\\n)a\\.?k\\.?a\\.?( |\\t)*:?( |\\t)*',
1709 + LCASE('$reg_author'),
1710 + '( |\\t|\\r)*(\\n|\$)'
1711 + )
1712 + )
1713 + ");
1714 +
1546 1715 endif;
1547 1716
1548 1717 // ... if you don't find one, then do what you need to do
1549 1718 if (is_null($id)) :
@@ -1596,9 +1765,9 @@
1596 1765 $cat_ids[] = $cat_id;
1597 1766 elseif (get_category($cat_id)) :
1598 1767 $cat_ids[] = $cat_id;
1599 1768 endif;
1600 - else :
1769 + elseif (strlen($cat_name) > 0) :
1601 1770 $esc = $wpdb->escape($cat_name);
1602 1771 $resc = $wpdb->escape(preg_quote($cat_name));
1603 1772
1604 1773 // WordPress 2.3+
@@ -1620,9 +1789,13 @@
1620 1789 elseif ('tag'==$unfamiliar_category) :
1621 1790 $tags[] = $cat_name;
1622 1791 elseif ('create'===$unfamiliar_category) :
1623 1792 $term = wp_insert_term($cat_name, 'category');
1624 - $cat_ids[] = $term['term_id'];
1793 + if (is_wp_error($term)) :
1794 + FeedWordPress::noncritical_bug('term insertion problem', array('cat_name' => $cat_name, 'term' => $term, 'this' => $this), __LINE__);
1795 + else :
1796 + $cat_ids[] = $term['term_id'];
1797 + endif;
1625 1798 endif;
1626 1799
1627 1800 // WordPress 1.5.x - 2.2.x
1628 1801 else :
@@ -1999,13 +2172,13 @@
1999 2172 endforeach;
2000 2173 $this->settings['map authors'] = $ma;
2001 2174 endif;
2002 2175 endif;
2003 - } // SyndicatedLink::SyndicatedLink ()
2176 + } /* SyndicatedLink::SyndicatedLink () */
2004 2177
2005 2178 function found () {
2006 2179 return is_object($this->link);
2007 - }
2180 + } /* SyndicatedLink::found () */
2008 2181
2009 2182 function stale () {
2010 2183 $stale = true;
2011 2184 if (isset($this->settings['update/hold']) and ($this->settings['update/hold']=='ping')) :
@@ -2019,16 +2192,25 @@
2019 2192 +((int) $this->settings['update/ttl'] * 60);
2020 2193 $stale = (time() >= $after);
2021 2194 endif;
2022 2195 return $stale;
2023 - }
2196 + } /* SyndicatedLink::stale () */
2024 2197
2025 - function poll () {
2198 + function poll ($crash_ts = NULL) {
2026 2199 global $wpdb;
2027 2200
2028 2201 $this->magpie = fetch_rss($this->link->link_rss);
2029 2202 $new_count = NULL;
2030 2203
2204 + $resume = FeedWordPress::affirmative($this->settings, 'update/unfinished');
2205 + if ($resume) :
2206 + // pick up where we left off
2207 + $processed = array_map('trim', explode("\n", $this->settings['update/processed']));
2208 + else :
2209 + // begin at the beginning
2210 + $processed = array();
2211 + endif;
2212 +
2031 2213 if (is_object($this->magpie)) :
2032 2214 $new_count = array('new' => 0, 'updated' => 0);
2033 2215
2034 2216 # -- Update Link metadata live from feed
@@ -2064,44 +2246,17 @@
2064 2246 else :
2065 2247 $this->settings['update/ttl'] = rand(30, 120); // spread over time interval for staggered updates
2066 2248 $this->settings['update/timed'] = 'automatically';
2067 2249 endif;
2068 -
2250 +
2069 2251 if (!isset($this->settings['update/hold']) or $this->settings['update/hold']!='ping') :
2070 2252 $this->settings['update/hold'] = 'scheduled';
2071 2253 endif;
2072 -
2073 - // Copy back without a few things that we don't want to save in the notes
2074 - $to_notes = $this->settings;
2075 2254
2076 - if (is_array($to_notes['cats'])) :
2077 - $to_notes['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['cats']);
2078 - endif;
2079 - if (is_array($to_notes['tags'])) :
2080 - $to_notes['tags'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['tags']);
2081 - endif;
2255 + $this->settings['update/unfinished'] = 'yes';
2082 2256
2083 - if (isset($to_notes['map authors'])) :
2084 - $ma = array();
2085 - foreach ($to_notes['map authors'] as $rule_type => $author_rules) :
2086 - foreach ($author_rules as $author_name => $author_action) :
2087 - $ma[] = $rule_type."\n".$author_name."\n".$author_action;
2088 - endforeach;
2089 - endforeach;
2090 - $to_notes['map authors'] = implode("\n\n", $ma);
2091 - endif;
2257 + $update[] = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
2092 2258
2093 - unset($to_notes['link/id']); unset($to_notes['link/uri']);
2094 - unset($to_notes['link/name']);
2095 - unset($to_notes['hardcode categories']); // Deprecated
2096 - unset($to_notes['unfamiliar categories']); // Deprecated
2097 -
2098 - $notes = '';
2099 - foreach ($to_notes as $key => $value) :
2100 - $notes .= $key . ": ". addcslashes($value, "\0..\37".'\\') . "\n";
2101 - endforeach;
2102 - $update[] = "link_notes = '".$wpdb->escape($notes)."'";
2103 -
2104 2259 $update_set = implode(',', $update);
2105 2260
2106 2261 // Update the properties of the link from the feed information
2107 2262 $result = $wpdb->query("
@@ -2110,14 +2265,24 @@
2110 2265 WHERE link_id='$this->id'
2111 2266 ");
2112 2267
2113 2268 # -- Add new posts from feed and update any updated posts
2269 + $crashed = false;
2270 +
2114 2271 if (is_array($this->magpie->items)) :
2115 2272 foreach ($this->magpie->items as $item) :
2116 2273 $post =& new SyndicatedPost($item, $this);
2117 - if (!$post->filtered()) :
2118 - $new = $post->store();
2119 - if ( $new !== false ) $new_count[$new]++;
2274 + if (!$resume or !in_array(trim($post->guid()), $processed)) :
2275 + $processed[] = $post->guid();
2276 + if (!$post->filtered()) :
2277 + $new = $post->store();
2278 + if ( $new !== false ) $new_count[$new]++;
2279 + endif;
2280 +
2281 + if (!is_null($crash_ts) and (time() > $crash_ts)) :
2282 + $crashed = true;
2283 + break;
2284 + endif;
2120 2285 endif;
2121 2286 endforeach;
2122 2287 endif;
2123 2288
@@ -2123,53 +2288,102 @@
2123 2288
2124 2289 // Copy back any changes to feed settings made in the course of updating (e.g. new author rules)
2125 2290 $to_notes = $this->settings;
2126 2291
2127 - if (is_array($to_notes['cats'])) :
2128 - $to_notes['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['cats']);
2292 + $this->settings['update/processed'] = $processed;
2293 + if (!$crashed) :
2294 + $this->settings['update/unfinished'] = 'no';
2129 2295 endif;
2130 - if (is_array($to_notes['tags'])) :
2131 - $to_notes['tags'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['tags']);
2132 - endif;
2133 2296
2134 - if (isset($to_notes['map authors'])) :
2135 - $ma = array();
2136 - foreach ($to_notes['map authors'] as $rule_type => $author_rules) :
2137 - foreach ($author_rules as $author_name => $author_action) :
2138 - $ma[] = $rule_type."\n".$author_name."\n".$author_action;
2139 - endforeach;
2140 - endforeach;
2141 - $to_notes['map authors'] = implode("\n\n", $ma);
2142 - endif;
2143 -
2144 - unset($to_notes['link/id']); unset($to_notes['link/uri']);
2145 - unset($to_notes['link/name']);
2146 - unset($to_notes['hardcode categories']); // Deprecated
2147 - unset($to_notes['unfamiliar categories']); // Deprecated
2148 -
2149 - $notes = '';
2150 - foreach ($to_notes as $key => $value) :
2151 - $notes .= $key . ": ". addcslashes($value, "\0..\37".'\\') . "\n";
2152 - endforeach;
2153 -
2154 - $update_set = "link_notes = '".$wpdb->escape($notes)."'";
2297 + $update_set = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
2155 2298
2156 2299 // Update the properties of the link from the feed information
2157 2300 $result = $wpdb->query("
2158 - UPDATE $wpdb->links
2159 - SET $update_set
2160 - WHERE link_id='$this->id'
2301 + UPDATE $wpdb->links
2302 + SET $update_set
2303 + WHERE link_id='$this->id'
2161 2304 ");
2162 2305 endif;
2306 +
2163 2307 return $new_count;
2164 2308 } /* SyndicatedLink::poll() */
2165 -
2309 +
2310 + function map_name_to_new_user ($name, $newuser_name) {
2311 + global $wpdb;
2312 +
2313 + if (strlen($newuser_name) > 0) :
2314 + $userdata = array();
2315 + $userdata['ID'] = NULL;
2316 +
2317 + $userdata['user_login'] = sanitize_user($newuser_name);
2318 + $userdata['user_login'] = apply_filters('pre_user_login', $userdata['user_login']);
2319 +
2320 + $userdata['user_nicename'] = sanitize_title($newuser_name);
2321 + $userdata['user_nicename'] = apply_filters('pre_user_nicename', $userdata['user_nicename']);
2322 +
2323 + $userdata['display_name'] = $wpdb->escape($newuser_name);
2324 +
2325 + $newuser_id = wp_insert_user($userdata);
2326 + if (is_numeric($newuser_id)) :
2327 + if (is_null($name)) : // Unfamiliar author
2328 + $this->settings['unfamiliar author'] = $newuser_id;
2329 + else :
2330 + $this->settings['map authors']['name'][$name] = $newuser_id;
2331 + endif;
2332 + else :
2333 + // TODO: Add some error detection and reporting
2334 + endif;
2335 + else :
2336 + // TODO: Add some error reporting
2337 + endif;
2338 + } /* SyndicatedLink::map_name_to_new_user () */
2339 +
2340 + function settings_to_notes () {
2341 + $to_notes = $this->settings;
2342 +
2343 + unset($to_notes['link/id']); // Magic setting; don't save
2344 + unset($to_notes['link/uri']); // Magic setting; don't save
2345 + unset($to_notes['link/name']); // Magic setting; don't save
2346 + unset($to_notes['hardcode categories']); // Deprecated
2347 + unset($to_notes['unfamiliar categories']); // Deprecated
2348 +
2349 + // Collapse array settings
2350 + if (isset($to_notes['update/processed']) and (is_array($to_notes['update/processed']))) :
2351 + $to_notes['update/processed'] = implode("\n", $to_notes['update/processed']);
2352 + endif;
2353 +
2354 + if (is_array($to_notes['cats'])) :
2355 + $to_notes['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['cats']);
2356 + endif;
2357 + if (is_array($to_notes['tags'])) :
2358 + $to_notes['tags'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['tags']);
2359 + endif;
2360 +
2361 + // Collapse the author mapping rule structure back into a flat string
2362 + if (isset($to_notes['map authors'])) :
2363 + $ma = array();
2364 + foreach ($to_notes['map authors'] as $rule_type => $author_rules) :
2365 + foreach ($author_rules as $author_name => $author_action) :
2366 + $ma[] = $rule_type."\n".$author_name."\n".$author_action;
2367 + endforeach;
2368 + endforeach;
2369 + $to_notes['map authors'] = implode("\n\n", $ma);
2370 + endif;
2371 +
2372 + $notes = '';
2373 + foreach ($to_notes as $key => $value) :
2374 + $notes .= $key . ": ". addcslashes($value, "\0..\37".'\\') . "\n";
2375 + endforeach;
2376 + return $notes;
2377 + } /* SyndicatedLink::settings_to_notes () */
2378 +
2166 2379 function uri () {
2167 2380 return (is_object($this->link) ? $this->link->link_rss : NULL);
2168 - }
2381 + } /* SyndicatedLink::uri () */
2382 +
2169 2383 function homepage () {
2170 2384 return (isset($this->settings['feed/link']) ? $this->settings['feed/link'] : NULL);
2171 - }
2385 + } /* SyndicatedLink::homepage () */
2172 2386
2173 2387 function ttl () {
2174 2388 if (is_object($this->magpie)) :
2175 2389 $channel = $this->magpie->channel;
@@ -2236,9 +2450,9 @@
2236 2450 endif;
2237 2451 endforeach;
2238 2452 endif;
2239 2453 return $ret;
2240 - } // function SyndicatedLink::flatten_array ()
2454 + } /* SyndicatedLink::flatten_array () */
2241 2455
2242 2456 function hardcode ($what) {
2243 2457 $default = get_option("feedwordpress_hardcode_$what");
2244 2458 if ( $default === 'yes' ) :
@@ -2252,9 +2466,9 @@
2252 2466 // setting is explicitly "yes"
2253 2467 $ret = FeedWordPress::affirmative($this->settings, "hardcode $what");
2254 2468 endif;
2255 2469 return $ret;
2256 - } // function SyndicatedLink::hardcode ()
2470 + } /* SyndicatedLink::hardcode () */
2257 2471
2258 2472 function syndicated_status ($what, $default) {
2259 2473 global $wpdb;
2260 2474
@@ -2264,9 +2478,9 @@
2264 2478 elseif (!$ret) :
2265 2479 $ret = $default;
2266 2480 endif;
2267 2481 return $wpdb->escape(trim(strtolower($ret)));
2268 - } // function SyndicatedLink:syndicated_status ()
2482 + } /* SyndicatedLink:syndicated_status () */
2269 2483 } // class SyndicatedLink
2270 2484
2271 2485 ################################################################################
2272 2486 ## XML-RPC HOOKS: accept XML-RPC update pings from Contributors ################
@@ -2301,8 +2515,9 @@
2301 2515
2302 2516 var $verify = FALSE;
2303 2517
2304 2518 var $_data = NULL;
2519 + var $_error = NULL;
2305 2520 var $_head = NULL;
2306 2521
2307 2522 # -- Recognition patterns
2308 2523 var $_feed_types = array(
@@ -2357,8 +2572,12 @@
2357 2572 $this->_get($uri);
2358 2573 return $this->_data;
2359 2574 }
2360 2575
2576 + function error () {
2577 + return $this->_error;
2578 + }
2579 +
2361 2580 function is_feed ($uri = NULL) {
2362 2581 $data = $this->data($uri);
2363 2582
2364 2583 return (
@@ -2377,23 +2596,23 @@
2377 2596 if ($uri) $this->uri = $uri;
2378 2597
2379 2598 // Is the result not yet cached?
2380 2599 if ($this->_cache_uri !== $this->uri) :
2381 - // Snoopy is an HTTP client in PHP
2382 - $client = new Snoopy();
2383 -
2384 - // Prepare headers and internal settings
2385 - $client->rawheaders['Connection'] = 'close';
2386 - $client->accept = 'application/atom+xml application/rdf+xml application/rss+xml application/xml text/html */*';
2387 - $client->agent = 'feedfinder/1.2 (compatible; PHP FeedFinder) +http://projects.radgeek.com/feedwordpress';
2388 - $client->read_timeout = 25;
2389 -
2390 - // Fetch the HTML or feed
2391 - @$client->fetch($this->uri);
2392 - $this->_data = $client->results;
2600 + $headers['Connection'] = 'close';
2601 + $headers['Accept'] = 'application/atom+xml application/rdf+xml application/rss+xml application/xml text/html */*';
2602 + $headers['User-Agent'] = 'feedfinder/1.2 (compatible; PHP FeedFinder) +http://projects.radgeek.com/feedwordpress';
2393 2603
2394 - // Kilroy was here
2395 - $this->_cache_uri = $this->uri;
2604 + // Use function provided by MagpieRSS package
2605 + $client = _fetch_remote_file($this->uri, $headers);
2606 + if (isset($client->error)) :
2607 + $this->_error = $client->error;
2608 + else :
2609 + $this->_error = NULL;
2610 + endif;
2611 + $this->_data = $client->results;
2612 +
2613 + // Kilroy was here
2614 + $this->_cache_uri = $this->uri;
2396 2615 endif;
2397 2616 } /* FeedFinder::_get () */
2398 2617
2399 2618 function _link_rel_feeds () {