PluginProbe
FeedWordPress / 2008.1105
FeedWordPress v2008.1105
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 +614 -1475 0.9922008.1105 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: 0.992
6 +Version: 2008.1105
7 7 Author: Charles Johnson
8 8 Author URI: http://radgeek.com/
9 9 License: GPL
10 -Last modified: 2008-01-04 18:03 PDT
10 +Last modified: 2008-11-05 4:35pm 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>
@@ -26,9 +26,9 @@
26 26 # <http://www.zyx.com/blog/xmlrpc.php>), or see `update-feeds.php`
27 27
28 28 # -- Don't change these unless you know what you're doing...
29 29
30 -define ('FEEDWORDPRESS_VERSION', '0.992');
30 +define ('FEEDWORDPRESS_VERSION', '2008.1105');
31 31 define ('FEEDWORDPRESS_AUTHOR_CONTACT', 'http://radgeek.com/contact');
32 32 define ('DEFAULT_SYNDICATION_CATEGORY', 'Contributors');
33 33
34 34 define ('FEEDWORDPRESS_DEBUG', false);
@@ -39,11 +39,14 @@
39 39 define ('FEEDVALIDATOR_URI', 'http://feedvalidator.org/check.cgi');
40 40
41 41 define ('FEEDWORDPRESS_FRESHNESS_INTERVAL', 10*60); // Every ten minutes
42 42
43 +define ('FWP_SCHEMA_HAS_USERMETA', 2966);
43 44 define ('FWP_SCHEMA_20', 3308); // Database schema # for WP 2.0
44 45 define ('FWP_SCHEMA_21', 4772); // Database schema # for WP 2.1
45 46 define ('FWP_SCHEMA_23', 5495); // Database schema # for WP 2.3
47 +define ('FWP_SCHEMA_25', 7558); // Database schema # for WP 2.5
48 +define ('FWP_SCHEMA_26', 8201); // Database schema # for WP 2.6
46 49
47 50 if (FEEDWORDPRESS_DEBUG) :
48 51 // Help us to pick out errors, if any.
49 52 ini_set('error_reporting', E_ALL & ~E_NOTICE);
@@ -81,11 +84,9 @@
81 84 require_once (ABSPATH . 'wp-admin/admin-db.php'); // for wp_insert_category
82 85 endif;
83 86 endif;
84 87
85 -if (function_exists('wp_enqueue_script')) :
86 - wp_enqueue_script( 'ajaxcat' ); // Provides the handy-dandy new category text box
87 -endif;
88 +require_once(dirname(__FILE__) . '/compatability.php'); // LEGACY API: Replicate or mock up functions for legacy support purposes
88 89
89 90 // Magic quotes are just about the stupidest thing ever.
90 91 if (is_array($_POST)) :
91 92 $fwp_post = stripslashes_deep($_POST);
@@ -90,9 +91,45 @@
90 91 if (is_array($_POST)) :
91 92 $fwp_post = stripslashes_deep($_POST);
92 93 endif;
93 94
95 +// Get the path relative to the plugins directory in which FWP is stored
96 +preg_match (
97 + '|/wp-content/plugins/(.+)$|',
98 + dirname(__FILE__),
99 + $ref
100 +);
94 101
102 +if (isset($ref[1])) :
103 + $fwp_path = $ref[1];
104 +else : // Something went wrong. Let's just guess.
105 + $fwp_path = 'feedwordpress';
106 +endif;
107 +
108 +// If this is a FeedWordPress admin page, queue up scripts for AJAX functions that FWP uses
109 +// If it is a display page or a non-FeedWordPress admin page, don't.
110 +if (is_admin() and isset($_REQUEST['page']) and preg_match("|^{$fwp_path}/|", $_REQUEST['page'])) :
111 + if (function_exists('wp_enqueue_script')) :
112 + if (isset($wp_db_version) and $wp_db_version >= FWP_SCHEMA_25) :
113 + wp_enqueue_script('post'); // for magic tag and category boxes
114 + wp_enqueue_script('thickbox'); // for fold-up boxes
115 + wp_enqueue_script('admin-forms'); // for checkbox selection
116 + else :
117 + wp_enqueue_script( 'ajaxcat' ); // Provides the handy-dandy new category text box
118 + endif;
119 + endif;
120 + if (function_exists('wp_enqueue_style')) :
121 + if (fwp_test_wp_version(FWP_SCHEMA_25)) :
122 + wp_enqueue_style('dashboard');
123 + endif;
124 + endif;
125 + if (function_exists('wp_admin_css')) :
126 + if (fwp_test_wp_version(FWP_SCHEMA_25)) :
127 + wp_admin_css('css/dashboard');
128 + endif;
129 + endif;
130 +endif;
131 +
95 132 if (!FeedWordPress::needs_upgrade()) : // only work if the conditions are safe!
96 133
97 134 # Syndicated items are generally received in output-ready (X)HTML and
98 135 # should not be folded, crumpled, mutilated, or spindled by WordPress
@@ -109,8 +146,10 @@
109 146
110 147 add_filter('the_content', 'feedwordpress_preserve_syndicated_content', -10000);
111 148 add_filter('the_content', 'feedwordpress_restore_syndicated_content', 10000);
112 149
150 + add_action('atom_entry', 'feedwordpress_item_feed_data');
151 +
113 152 # Filter in original permalinks if the user wants that
114 153 add_filter('post_link', 'syndication_permalink', 1);
115 154
116 155 # WTF? By default, wp_insert_link runs incoming link_url and link_rss
@@ -147,8 +186,12 @@
147 186 endif;
148 187
149 188 # Cron-less auto-update. Hooray!
150 189 add_action('init', 'feedwordpress_auto_update');
190 +
191 + # Default sanitizers
192 + add_filter('syndicated_item_content', array('SyndicatedPost', 'sanitize_content'), 0, 2);
193 +
151 194 else :
152 195 # Hook in the menus, which will just point to the upgrade interface
153 196 add_action('admin_menu', 'fwp_add_pages');
154 197 endif; // if (!FeedWordPress::needs_upgrade())
@@ -201,84 +244,85 @@
201 244 : implode(' and ', $mesg)));
202 245 }
203 246
204 247 ################################################################################
205 -## LEGACY API: Replicate or mock up functions for legacy support purposes ######
248 +## TEMPLATE API: functions to make your templates syndication-aware ############
206 249 ################################################################################
207 250
208 -if (!function_exists('get_option')) {
209 - function get_option ($option) {
210 - return get_settings($option);
211 - }
212 -}
213 -if (!function_exists('current_user_can')) {
214 - $legacy_capability_hack = true;
215 - function current_user_can ($task) {
216 - global $user_level;
251 +function is_syndicated () { return (strlen(get_syndication_feed_id()) > 0); }
217 252
218 - $can = false;
253 +function get_syndication_source_link ($original = NULL) {
254 + if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
255 + endif;
219 256
220 - // This is **not** a full replacement for current_user_can. It
221 - // is only for checking the capabilities we care about via the
222 - // WordPress 1.5 user levels.
223 - switch ($task) {
224 - case 'manage_options':
225 - $can = ($user_level >= 6);
226 - break;
227 - case 'manage_links':
228 - $can = ($user_level >= 5);
229 - break;
230 - } /* switch */
231 - return $can;
232 - }
233 -} else {
234 - $legacy_capability_hack = false;
235 -}
236 -if (!function_exists('sanitize_user')) {
237 - function sanitize_user ($text, $strict) {
238 - return $text; // Don't munge it if it wasn't munged going in...
239 - }
240 -}
241 -if (!function_exists('wp_insert_user')) {
242 - function wp_insert_user ($userdata) {
243 - #-- Help WordPress 1.5.x quack like a duck
244 - $login = $userdata['user_login'];
245 - $author = $userdata['display_name'];
246 - $nice_author = $userdata['user_nicename'];
247 - $email = $userdata['user_email'];
248 - $url = $userdata['user_url'];
257 + if ($original) : $vals = get_post_custom_values('syndication_source_uri_original');
258 + else : $vals = array();
259 + endif;
260 +
261 + if (count($vals) == 0) : $vals = get_post_custom_values('syndication_source_uri');
262 + endif;
263 +
264 + if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
249 265
250 - $wpdb->query (
251 - "INSERT INTO $wpdb->users
252 - SET
253 - ID='0',
254 - user_login='$login',
255 - user_firstname='$author',
256 - user_nickname='$author',
257 - user_nicename='$nice_author',
258 - user_description='$author',
259 - user_email='$email',
260 - user_url='$url'");
261 - $id = $wpdb->insert_id;
262 -
263 - return $id;
264 - }
265 -}
266 -################################################################################
267 -## TEMPLATE API: functions to make your templates syndication-aware ############
268 -################################################################################
266 + return $ret;
267 +} /* function get_syndication_source_link() */
269 268
270 -function is_syndicated () { return (strlen(get_syndication_feed_id()) > 0); }
269 +function the_syndication_source_link ($original = NULL) { echo get_syndication_source_link($original); }
271 270
272 -function the_syndication_source_link () { echo get_syndication_source_link(); }
273 -function get_syndication_source_link () { list($n) = get_post_custom_values('syndication_source_uri'); return $n; }
271 +function get_syndication_source ($original = NULL) {
272 + if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
273 + endif;
274 274
275 -function get_syndication_source () { list($n) = get_post_custom_values('syndication_source'); return $n; }
276 -function the_syndication_source () { echo get_syndication_source(); }
275 + if ($original) : $vals = get_post_custom_values('syndication_source_original');
276 + else : $vals = array();
277 + endif;
278 +
279 + if (count($vals) == 0) : $vals = get_post_custom_values('syndication_source');
280 + endif;
281 +
282 + if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
277 283
278 -function get_syndication_feed () { list($u) = get_post_custom_values('syndication_feed'); return $u; }
279 -function the_syndication_feed () { echo get_syndication_feed (); }
284 + return $ret;
285 +} /* function get_syndication_source() */
280 286
287 +function the_syndication_source ($original = NULL) { echo get_syndication_source($original); }
288 +
289 +function get_syndication_feed ($original = NULL) {
290 + if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
291 + endif;
292 +
293 + if ($original) : $vals = get_post_custom_values('syndication_feed_original');
294 + else : $vals = array();
295 + endif;
296 +
297 + if (count($vals) == 0) : $vals = get_post_custom_values('syndication_feed');
298 + endif;
299 +
300 + if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
301 +
302 + return $ret;
303 +} /* function get_syndication_feed() */
304 +
305 +function the_syndication_feed ($original = NULL) { echo get_syndication_feed ($original); }
306 +
307 +function get_syndication_feed_guid ($original = NULL) {
308 + if (is_null($original)) : $original = FeedWordPress::use_aggregator_source_data();
309 + endif;
310 +
311 + if ($original) : $vals = get_post_custom_values('syndication_source_id_original');
312 + else : $vals = array();
313 + endif;
314 +
315 + if (count($vals) == 0) : $vals = array(get_feed_meta('feed/id'));
316 + endif;
317 +
318 + if (count($vals) > 0) : $ret = $vals[0]; else : $ret = NULL; endif;
319 +
320 + return $ret;
321 +} /* function get_syndication_feed_guid () */
322 +
323 +function the_syndication_feed_guid ($original = NULL) { echo get_syndication_feed_guid($original); }
324 +
281 325 function get_syndication_feed_id () { list($u) = get_post_custom_values('syndication_feed_id'); return $u; }
282 326 function the_syndication_feed_id () { echo get_syndication_feed_id(); }
283 327
284 328 $feedwordpress_linkcache = array (); // only load links from database once
@@ -316,9 +360,9 @@
316 360
317 361 function feedwordpress_preserve_syndicated_content ($text) {
318 362 global $feedwordpress_the_syndicated_content;
319 363
320 - if ( is_syndicated() ) :
364 + if ( is_syndicated() and get_option('feedwordpress_formatting_filters') != 'yes' ) :
321 365 $feedwordpress_the_syndicated_content = $text;
322 366 else :
323 367 $feedwordpress_the_syndicated_content = NULL;
324 368 endif;
@@ -334,1261 +378,57 @@
334 378
335 379 return $text;
336 380 }
337 381
338 -function syndication_permalink ($permalink = '') {
339 - if (get_option('feedwordpress_munge_permalink') != 'no'):
340 - $uri = get_syndication_permalink();
341 - return ((strlen($uri) > 0) ? $uri : $permalink);
342 - else:
343 - return $permalink;
344 - endif;
345 -} // function syndication_permalink ()
346 -
347 -################################################################################
348 -## UPGRADE INTERFACE: Have users upgrade DB from older versions of FWP #########
349 -################################################################################
350 -
351 -function fwp_upgrade_page () {
352 - if (isset($GLOBALS['fwp_post']['action']) and $GLOBALS['fwp_post']['action']=='Upgrade') :
353 - $ver = get_option('feedwordpress_version');
354 - if (get_option('feedwordpress_version') != FEEDWORDPRESS_VERSION) :
355 - echo "<div class=\"wrap\">\n";
356 - echo "<h2>Upgrading FeedWordPress...</h2>";
357 -
358 - $feedwordpress =& new FeedWordPress;
359 - $feedwordpress->upgrade_database();
360 - echo "<p><strong>Done!</strong> Upgraded database to version ".FEEDWORDPRESS_VERSION.".</p>\n";
361 - echo "<form action=\"\" method=\"get\">\n";
362 - echo "<div class=\"submit\"><input type=\"hidden\" name=\"page\" value=\"".basename(__FILE__)."\" />";
363 - echo "<input type=\"submit\" value=\"Continue &raquo;\" /></form></div>\n";
364 - echo "</div>\n";
365 - return;
366 - else :
367 - echo "<div class=\"updated\"><p>Already at version ".FEEDWORDPRESS_VERSION."!</p></div>";
368 - endif;
369 - endif;
382 +function feedwordpress_item_feed_data () {
383 + // In a post context....
384 + if (is_syndicated()) :
370 385 ?>
371 -<div class="wrap">
372 -<h2>Upgrade FeedWordPress</h2>
373 -
374 -<p>It appears that you have installed FeedWordPress
375 -<?php echo FEEDWORDPRESS_VERSION; ?> as an upgrade to an existing installation of
376 -FeedWordPress. That's no problem, but you will need to take a minute out first
377 -to upgrade your database: some necessary changes in how the software keeps
378 -track of posts and feeds will cause problems such as duplicate posts and broken
379 -templates if we were to continue without the upgrade.</p>
380 -
381 -<p>Note that most of FeedWordPress's functionality is temporarily disabled
382 -until we have successfully completed the upgrade. Everything should begin
383 -working as normal again once the upgrade is complete. There's extraordinarily
384 -little chance of any damage as the result of the upgrade, but if you're paranoid
385 -like me you may want to back up your database before you proceed.</p>
386 -
387 -<p>This may take several minutes for a large installation.</p>
388 -
389 -<form action="" method="post">
390 -<div class="submit"><input type="submit" name="action" value="Upgrade" /></div>
391 -</form>
392 -</div>
386 +<source>
387 + <title><?php the_syndication_source(); ?></title>
388 + <link rel="alternate" type="text/html" href="<?php the_syndication_source_link(); ?>" />
389 + <link rel="self" href="<?php the_syndication_feed(); ?>" />
393 390 <?php
394 -} // function fwp_upgrade_page ()
395 -
396 -################################################################################
397 -## ADMIN MENU ADD-ONS: implement Dashboard management pages ####################
398 -################################################################################
399 -
400 -function fwp_add_pages () {
401 - global $legacy_capability_hack;
402 -
403 - if ($legacy_capability_hack) :
404 - // old & busted: numeric user levels
405 - $manage_links = 5;
406 - $manage_options = 6;
407 - else :
408 - // new hotness: named capabilities
409 - $manage_links = 'manage_links';
410 - $manage_options = 'manage_options';
411 - endif;
412 -
413 - //add_submenu_page('plugins.php', 'Akismet Configuration', 'Akismet Configuration', 'manage_options', 'syndication-manage-page', 'fwp_syndication_manage_page');
414 - add_menu_page('Syndicated Sites', 'Syndication', $manage_links, 'feedwordpress/'.basename(__FILE__), 'fwp_syndication_manage_page');
415 - add_submenu_page('feedwordpress/'.basename(__FILE__), 'Syndication Options', 'Options', $manage_options, 'feedwordpress/syndication-options.php');
416 - add_options_page('Syndication Options', 'Syndication', $manage_options, 'feedwordpress/syndication-options.php');
417 -} // function fwp_add_pages () */
418 -
419 -function fwp_category_box ($checked, $object) {
420 - global $wp_db_version;
421 -
422 - if (isset($wp_db_version) and $wp_db_version >= FWP_SCHEMA_20) : // WordPress 2.x
391 + $id = get_syndication_feed_guid();
392 + if (strlen($id) > 0) :
423 393 ?>
424 - <div id="poststuff">
425 -
426 - <div id="moremeta">
427 - <div id="grabit" class="dbx-group">
428 - <fieldset id="categorydiv" class="dbx-box">
429 - <h3 class="dbx-handle"><?php _e('Categories') ?></h3>
430 - <div class="dbx-content">
431 - <p style="font-size:smaller;font-style:bold;margin:0">Place <?php print $object; ?> under...</p>
432 - <p id="jaxcat"></p>
433 - <ul id="categorychecklist"><?php write_nested_categories($checked); ?></ul></div>
434 - </fieldset>
435 - </div>
436 - </div>
437 - </div>
394 + <id><?php print $id; ?></id>
438 395 <?php
439 - else : // WordPress 1.5
440 -?>
441 - <fieldset id="categorydiv" style="width: 20%; margin-right: 2em">
442 - <legend><?php _e('Categories') ?></legend>
443 - <p style="font-size:smaller;font-style:bold;margin:0">Place <?php print $object; ?> under...</p>
444 - <div style="height: 20em"><?php write_nested_categories($checked); ?></div>
445 - </fieldset>
446 -<?php
447 396 endif;
448 -}
449 -
450 -function update_feeds_mention ($feed) {
451 - echo "<li>Updating <cite>".$feed['link/name']."</cite> from &lt;<a href=\""
452 - .$feed['link/uri']."\">".$feed['link/uri']."</a>&gt; ...</li>\n";
453 - flush();
454 -}
455 -
456 -function fwp_syndication_manage_page () {
457 - global $wpdb;
458 -
459 - if (FeedWordPress::needs_upgrade()) :
460 - fwp_upgrade_page();
461 - return;
462 - endif;
463 -
464 -?>
465 -<?php $cont = true;
466 -if (isset($_REQUEST['action'])):
467 - if ($_REQUEST['action'] == 'feedfinder') : $cont = fwp_feedfinder_page();
468 - elseif ($_REQUEST['action'] == 'switchfeed') : $cont = fwp_switchfeed_page();
469 - elseif ($_REQUEST['action'] == 'linkedit') : $cont = fwp_linkedit_page();
470 - elseif ($_REQUEST['action'] == 'Unsubscribe from Checked Links' or $_REQUEST['action'] == 'Unsubscribe') : $cont = fwp_multidelete_page();
471 - endif;
472 -endif;
473 -
474 -if ($cont):
475 -?>
397 + $updated = get_feed_meta('feed/updated');
398 + if (strlen($updated) > 0) : ?>
399 + <updated><?php print $updated; ?></updated>
476 400 <?php
477 - $links = FeedWordPress::syndicated_links();
478 -
479 - if (isset($_POST['update']) or isset($_POST['action']) or isset($_POST['update_uri'])) :
480 - $fwp_update_invoke = 'post';
481 - else :
482 - $fwp_update_invoke = 'get';
483 401 endif;
484 -
485 - $update_set = array();
486 - if (isset($_POST['link_ids']) and is_array($_POST['link_ids']) and ($_POST['action']=='Update Checked Links')) :
487 - $targets = $wpdb->get_results("
488 - SELECT * FROM $wpdb->links
489 - WHERE link_id IN (".implode(",",$_POST['link_ids']).")
490 - ");
491 - if (is_array($targets)) :
492 - foreach ($targets as $target) :
493 - $update_set[] = $target->link_rss;
494 - endforeach;
495 - else : // This should never happen
496 - FeedWordPress::critical_bug('fwp_syndication_manage_page::targets', $targets, __LINE__);
497 - endif;
498 - elseif (isset($_POST['update_uri'])) :
499 - $update_set[] = $_POST['update_uri'];
500 - endif;
501 -
502 - if ($fwp_update_invoke != 'get' and count($update_set) > 0) : // Only do things with side-effects for HTTP POST or command line
503 - $feedwordpress =& new FeedWordPress;
504 - add_action('feedwordpress_check_feed', 'update_feeds_mention');
505 -
506 - echo "<div class=\"updated\">\n";
507 - echo "<ul>\n";
508 - $tdelta = NULL;
509 - foreach ($update_set as $uri) :
510 - if ($uri == '*') : $uri = NULL; endif;
511 - $delta = $feedwordpress->update($uri);
512 - if (!is_null($delta)) :
513 - if (is_null($tdelta)) :
514 - $tdelta = $delta;
515 - else :
516 - $tdelta['new'] += $delta['new'];
517 - $tdelta['updated'] += $delta['updated'];
518 - endif;
519 - else :
520 - echo "<li><p><strong>Error:</strong> There was a problem updating <a href=\"$uri\">$uri</a></p></li>\n";
521 - endif;
522 - endforeach;
523 - echo "</ul>\n";
524 -
525 - if (!is_null($tdelta)) :
526 - $mesg = array();
527 - if (isset($delta['new'])) : $mesg[] = ' '.$tdelta['new'].' new posts were syndicated'; endif;
528 - if (isset($delta['updated'])) : $mesg[] = ' '.$tdelta['updated'].' existing posts were updated'; endif;
529 - echo "<p>Update complete.".implode(' and', $mesg)."</p>";
530 - echo "\n"; flush();
531 - endif;
532 - echo "</div> <!-- class=\"updated\" -->\n";
533 - endif;
534 -
535 - ?>
536 - <div class="wrap">
537 - <form action="" method="POST">
538 - <h2>Update feeds now</h2>
539 - <p>Check currently scheduled feeds for new and updated posts.</p>
540 -
541 -<?php if (!get_option('feedwordpress_automatic_updates')) : ?>
542 - <p><strong>Note:</strong> Automatic updates are currently turned
543 - <strong>off</strong>. New posts from your feeds will not be syndicated
544 - until you manually check for them here. You can turn on automatic
545 - updates under <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication
546 - Options</a>.</p>
547 -<?php endif; ?>
548 -
549 -
550 - <div class="submit"><input type="hidden" name="update_uri" value="*" /><input type="submit" name="update" value="Update" /></div>
551 - </form>
552 - </div> <!-- class="wrap" -->
553 -
554 - <form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
555 - <div class="wrap">
556 - <h2>Syndicated Sites</h2>
557 -<?php $alt_row = true;
558 - if ($links): ?>
559 -
560 -<table width="100%" cellpadding="3" cellspacing="3">
561 -<tr>
562 -<th width="20%"><?php _e('Name'); ?></th>
563 -<th width="40%"><?php _e('Feed'); ?></th>
564 -<th colspan="4"><?php _e('Action'); ?></th>
565 -</tr>
566 -
567 -<?php foreach ($links as $link):
568 - $alt_row = !$alt_row; ?>
569 -<tr<?php echo ($alt_row?' class="alternate"':''); ?>>
570 -<td><a href="<?php echo wp_specialchars($link->link_url, 'both'); ?>"><?php echo wp_specialchars($link->link_name, 'both'); ?></a></td>
571 -<?php
572 - if (strlen($link->link_rss) > 0):
573 - $caption='Switch Feed';
574 - $uri_bits = parse_url($link->link_rss);
575 - $uri_bits['host'] = preg_replace('/^www\./i', '', $uri_bits['host']);
576 - $display_uri =
577 - (isset($uri_bits['user'])?$uri_bits['user'].'@':'')
578 - .(isset($uri_bits['host'])?$uri_bits['host']:'')
579 - .(isset($uri_bits['port'])?':'.$uri_bits['port']:'')
580 - .(isset($uri_bits['path'])?$uri_bits['path']:'')
581 - .(isset($uri_bits['query'])?'?'.$uri_bits['query']:'');
582 - if (strlen($display_uri) > 32) : $display_uri = substr($display_uri, 0, 32).'&#8230;'; endif;
583 402 ?>
584 - <td>
585 - <strong><a href="<?php echo wp_specialchars($link->link_rss, 'both'); ?>"><?php echo wp_specialchars($display_uri, 'both'); ?></a></strong></td>
403 +</source>
586 404 <?php
587 - else:
588 - $caption='Find Feed';
589 -?>
590 - <td style="background-color:#FFFFD0"><p><strong>no
591 - feed assigned</strong></p></td>
592 -<?php
593 - endif;
594 -?>
595 - <td><a href="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>&amp;link_id=<?php echo $link->link_id; ?>&amp;action=linkedit" class="edit"><?php _e('Edit')?></a></td>
596 - <td><a href="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>&amp;link_id=<?php echo $link->link_id; ?>&amp;action=feedfinder" class="edit"><?php echo $caption; ?></a></td>
597 - <td><a href="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>&amp;link_id=<?php echo $link->link_id; ?>&amp;action=Unsubscribe" class="delete"><?php _e('Unsubscribe'); ?></a></td>
598 - <td><input type="checkbox" name="link_ids[]" value="<?php echo $link->link_id; ?>" /></td>
599 -<?php
600 - echo "\n\t</tr>";
601 - endforeach;
602 - else:
603 -?>
604 -
605 -<p>There are no websites currently listed for syndication.</p>
606 -
607 -<?php endif; ?>
608 - </table>
609 -
610 - <br/><hr/>
611 - <div class="submit"><input type="submit" class="delete" name="action" value="Unsubscribe from Checked Links" />
612 - <input type="submit" name="action" value="Update Checked Links" /></div>
613 - </div> <!-- class="wrap" -->
614 - </form>
615 -
616 - <div class="wrap">
617 - <form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
618 - <h2>Add a new syndicated site:</h2>
619 - <div>
620 - <label for="add-uri">Website or newsfeed:</label>
621 - <input type="text" name="lookup" id="add-uri" value="URI" size="64" />
622 - <input type="hidden" name="action" value="feedfinder" />
623 - </div>
624 - <div class="submit"><input type="submit" value="Syndicate &raquo;" /></div>
625 - </form>
626 - </div> <!-- class="wrap" -->
627 -<?php
628 -endif;
629 -}
630 -
631 -function fwp_feedfinder_page () {
632 - global $wpdb;
633 -
634 - $lookup = (isset($_REQUEST['lookup'])?$_REQUEST['lookup']:NULL);
635 -
636 - if (isset($_REQUEST['link_id']) and ($_REQUEST['link_id']!=0)):
637 - $link_id = $_REQUEST['link_id'];
638 - if (!is_numeric($link_id)) : FeedWordPress::critical_bug('fwp_feedfinder_page::link_id', $link_id, __LINE__); endif;
639 -
640 - $link = $wpdb->get_row("SELECT * FROM $wpdb->links WHERE link_id='".$wpdb->escape($link_id)."'");
641 - if (is_object($link)):
642 - if (is_null($lookup)) $lookup = $link->link_url;
643 - $name = wp_specialchars($link->link_name, 'both');
644 - else:
645 - die (__("Cheatin' uh ?"));
646 - endif;
647 - else:
648 - $name = "New Syndicated Feed";
649 - $link_id = 0;
650 405 endif;
651 -?>
652 - <div class="wrap">
653 - <h2>Feed Finder: <?php echo $name; ?></h2>
654 -<?php
655 - $f =& new FeedFinder($lookup);
656 - $feeds = $f->find();
657 - if (count($feeds) > 0):
658 - foreach ($feeds as $key => $f):
659 - $rss = fetch_rss($f);
660 - if ($rss):
661 - $feed_title = isset($rss->channel['title'])?$rss->channel['title']:$rss->channel['link'];
662 - $feed_link = isset($rss->channel['link'])?$rss->channel['link']:'';
663 -?>
664 - <form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
665 - <fieldset style="clear: both">
666 - <legend><?php echo $rss->feed_type; ?> <?php echo $rss->feed_version; ?> feed</legend>
667 -
668 - <?php if ($link_id===0): ?>
669 - <input type="hidden" name="feed_title" value="<?php echo wp_specialchars($feed_title, 'both'); ?>" />
670 - <input type="hidden" name="feed_link" value="<?php echo wp_specialchars($feed_link, 'both'); ?>" />
671 - <?php endif; ?>
672 -
673 - <input type="hidden" name="link_id" value="<?php echo $link_id; ?>" />
674 - <input type="hidden" name="feed" value="<?php echo wp_specialchars($f, 'both'); ?>" />
675 - <input type="hidden" name="action" value="switchfeed" />
676 -
677 - <div>
678 - <div style="float:right; background-color:#D0D0D0; color: black; width:45%; font-size:70%; border-left: 1px dotted #A0A0A0; padding-left: 0.5em; margin-left: 1.0em">
679 -<?php if (count($rss->items) > 0): ?>
680 - <?php $item = $rss->items[0]; ?>
681 - <h3>Sample Item</h3>
682 - <ul>
683 - <li><strong>Title:</strong> <a href="<?php echo $item['link']; ?>"><?php echo $item['title']; ?></a></li>
684 - <li><strong>Date:</strong> <?php echo isset($item['date_timestamp']) ? date('d-M-y g:i:s a', $item['date_timestamp']) : 'unknown'; ?></li>
685 - </ul>
686 - <div class="entry">
687 - <?php echo (isset($item['content']['encoded'])?$item['content']['encoded']:$item['description']); ?>
688 - </div>
689 -<?php else: ?>
690 - <h3>No Items</h3>
691 - <p>FeedWordPress found no posts on this feed.</p>
692 -<?php endif; ?>
693 - </div>
694 -
695 - <div>
696 - <h3>Feed Information</h3>
697 - <ul>
698 - <li><strong>Website:</strong> <a href="<?php echo $feed_link; ?>"><?php echo is_null($feed_title)?'<em>Unknown</em>':$feed_title; ?></a></li>
699 - <li><strong>Feed URI:</strong> <a href="<?php echo wp_specialchars($f, 'both'); ?>"><?php echo wp_specialchars($f, 'both'); ?></a> (<a title="Check feed &lt;<?php echo wp_specialchars($f, 'both'); ?>&gt; for validity" href="http://feedvalidator.org/check.cgi?url=<?php echo urlencode($f); ?>">validate</a>)</li>
700 - <li><strong>Encoding:</strong> <?php echo isset($rss->encoding)?wp_specialchars($rss->encoding, 'both'):"<em>Unknown</em>"; ?></li>
701 - <li><strong>Description:</strong> <?php echo isset($rss->channel['description'])?wp_specialchars($rss->channel['description'], 'both'):"<em>Unknown</em>"; ?></li>
702 - </ul>
703 - <div class="submit"><input type="submit" name="Use" value="&laquo; Use this feed" /></div>
704 - <div class="submit"><input type="submit" name="Cancel" value="&laquo; Cancel" /></div>
705 - </div>
706 - </div>
707 - </fieldset>
708 - </form>
709 -<?php endif;
710 - endforeach;
711 - else:
712 - echo "<p><strong>no feed found</strong></p>";
713 - endif;
714 -?>
715 - </div>
716 -
717 - <form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
718 - <div class="wrap">
719 - <h2>Use another feed</h2>
720 - <div><label>Feed:</label>
721 - <input type="text" name="lookup" value="URI" />
722 - <input type="hidden" name="link_id" value="<?php echo $link_id; ?>" />
723 - <input type="hidden" name="action" value="feedfinder" /></div>
724 - <div class="submit"><input type="submit" value="Use this feed &raquo;" /></div>
725 - </div>
726 - </form>
727 -<?php
728 - return false; // Don't continue
729 406 }
730 407
731 -function fwp_switchfeed_page () {
732 - global $wpdb, $wp_db_version;
733 -
734 - check_admin_referer();
735 - if (!isset($_REQUEST['Cancel'])):
736 - if (!current_user_can('manage_links')):
737 - die (__("Cheatin' uh ?"));
738 - elseif (isset($_REQUEST['link_id']) and ($_REQUEST['link_id']==0)):
739 - $link_id = FeedWordPress::syndicate_link($_REQUEST['feed_title'], $_REQUEST['feed_link'], $_REQUEST['feed']);
740 - if ($link_id): ?>
741 -<div class="updated"><p><a href="<?php echo $_REQUEST['feed_link']; ?>"><?php echo wp_specialchars($_REQUEST['feed_title'], 'both'); ?></a>
742 -has been added as a contributing site, using the newsfeed at &lt;<a href="<?php echo $_REQUEST['feed']; ?>"><?php echo wp_specialchars($_REQUEST['feed'], 'both'); ?></a>&gt;.</p></div>
743 -<?php else: ?>
744 -<div class="updated"><p>There was a problem adding the newsfeed. [SQL: <?php echo wp_specialchars(mysql_error(), 'both'); ?>]</p></div>
745 -<?php endif;
746 - elseif (isset($_REQUEST['link_id'])):
747 - // Update link_rss
748 - $result = $wpdb->query("
749 - UPDATE $wpdb->links
750 - SET
751 - link_rss = '".$wpdb->escape($_REQUEST['feed'])."'
752 - WHERE link_id = '".$wpdb->escape($_REQUEST['link_id'])."'
753 - ");
754 -
755 - if ($result):
756 - $result = $wpdb->get_row("
757 - SELECT link_name, link_url FROM $wpdb->links
758 - WHERE link_id = '".$wpdb->escape($_REQUEST['link_id'])."'
759 - ");
760 - ?>
761 -<div class="updated"><p>Feed for <a href="<?php echo $result->link_url; ?>"><?php echo wp_specialchars($result->link_name, 'both'); ?></a>
762 -updated to &lt;<a href="<?php echo $_REQUEST['feed']; ?>"><?php echo wp_specialchars($_REQUEST['feed'], 'both'); ?></a>&gt;.</p></div>
763 - <?php else: ?>
764 -<div class="updated"><p>Nothing was changed.</p></div>
765 - <?php endif;
766 - endif;
767 - endif;
768 - return true; // Continue
769 -}
770 -
771 -function fwp_linkedit_page () {
772 - global $wpdb;
773 -
774 - check_admin_referer(); // Make sure we arrived here from the Dashboard
775 -
776 - $special_settings = array ( /* Regular expression syntax is OK here */
777 - 'cats',
778 - 'cat_split',
779 - 'hardcode name',
780 - 'hardcode url',
781 - 'hardcode description',
782 - 'hardcode categories', /* Deprecated */
783 - 'post status',
784 - 'comment status',
785 - 'ping status',
786 - 'unfamiliar author',
787 - 'unfamliar categories',
788 - 'map authors',
789 - 'update/.*',
790 - 'feed/.*',
791 - 'link/.*',
792 - );
793 -
794 - if (!current_user_can('manage_links')) :
795 - die (__("Cheatin' uh ?"));
796 - elseif (isset($_REQUEST['feedfinder'])) :
797 - return fwp_feedfinder_page(); // re-route to Feed Finder page
798 - else :
799 - $link_id = (int) $_REQUEST['link_id'];
800 - $link =& new SyndicatedLink($link_id);
801 -
802 - if ($link->found()) :
803 - if (isset($GLOBALS['fwp_post']['save'])) :
804 - $alter = array ();
805 -
806 - $meta = $link->settings;
807 - //if (isset($meta['cats'])):
808 - // $meta['cats'] = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, $meta['cats']);
809 - //endif;
810 -
811 - // custom feed settings first
812 - foreach ($GLOBALS['fwp_post']['notes'] as $mn) :
813 - $mn['key0'] = trim($mn['key0']);
814 - $mn['key1'] = trim($mn['key1']);
815 - if (preg_match("\007^(("
816 - .implode(')|(',$special_settings)
817 - ."))$\007i",
818 - $mn['key1'])) :
819 - $mn['key1'] = 'user/'.$mn['key1'];
820 - endif;
821 -
822 - if (strlen($mn['key0']) > 0) :
823 - unset($meta[$mn['key0']]); // out with the old
824 - endif;
825 -
826 - if (($mn['action']=='update') and (strlen($mn['key1']) > 0)) :
827 - $meta[$mn['key1']] = $mn['value']; // in with the new
828 - endif;
829 - endforeach;
830 -
831 - // now stuff through the web form
832 - // hardcoded feed info
833 - if (isset($GLOBALS['fwp_post']['hardcode_name'])) :
834 - $meta['hardcode name'] = $GLOBALS['fwp_post']['hardcode_name'];
835 - if (FeedWordPress::affirmative($meta, 'hardcode name')) :
836 - $alter[] = "link_name = '".$wpdb->escape($GLOBALS['fwp_post']['name'])."'";
837 - endif;
838 - endif;
839 - if (isset($GLOBALS['fwp_post']['hardcode_description'])) :
840 - $meta['hardcode description'] = $GLOBALS['fwp_post']['hardcode_description'];
841 - if (FeedWordPress::affirmative($meta, 'hardcode description')) :
842 - $alter[] = "link_description = '".$wpdb->escape($GLOBALS['fwp_post']['description'])."'";
843 - endif;
844 - endif;
845 - if (isset($GLOBALS['fwp_post']['hardcode_url'])) :
846 - $meta['hardcode url'] = $GLOBALS['fwp_post']['hardcode_url'];
847 - if (FeedWordPress::affirmative($meta, 'hardcode url')) :
848 - $alter[] = "link_url = '".$wpdb->escape($GLOBALS['fwp_post']['linkurl'])."'";
849 - endif;
850 - endif;
851 -
852 - // Update scheduling
853 - if (isset($GLOBALS['fwp_post']['update_schedule'])) :
854 - $meta['update/hold'] = $GLOBALS['fwp_post']['update_schedule'];
855 - endif;
856 -
857 - // Categories
858 - if (isset($GLOBALS['fwp_post']['post_category'])) :
859 - $meta['cats'] = array();
860 - foreach ($GLOBALS['fwp_post']['post_category'] as $cat_id) :
861 - $meta['cats'][] = '{#'.$cat_id.'}';
862 - endforeach;
863 - else :
864 - unset($meta['cats']);
865 - endif;
866 -
867 - // Post status, comment status, ping status
868 - foreach (array('post', 'comment', 'ping') as $what) :
869 - $sfield = "feed_{$what}_status";
870 - if (isset($GLOBALS['fwp_post'][$sfield])) :
871 - if ($GLOBALS['fwp_post'][$sfield]=='site-default') :
872 - unset($meta["{$what} status"]);
873 - else :
874 - $meta["{$what} status"] = $GLOBALS['fwp_post'][$sfield];
875 - endif;
876 - endif;
877 - endforeach;
878 -
879 - // Unfamiliar author, unfamiliar categories
880 - foreach (array("author", "category") as $what) :
881 - $sfield = "unfamiliar_{$what}";
882 - if (isset($GLOBALS['fwp_post'][$sfield])) :
883 - if ('site-default'==$GLOBALS['fwp_post'][$sfield]) :
884 - unset($meta["unfamiliar {$what}"]);
885 - elseif ('newuser'==$GLOBALS['fwp_post'][$sfield]) :
886 - $newuser_name = trim($GLOBALS['fwp_post']["{$sfield}_newuser"]);
887 - if (strlen($newuser_name) > 0) :
888 - $userdata = array();
889 - $userdata['ID'] = NULL;
890 -
891 - $userdata['user_login'] = sanitize_user($newuser_name);
892 - $userdata['user_login'] = apply_filters('pre_user_login', $userdata['user_login']);
893 -
894 - $userdata['user_nicename'] = sanitize_title($newuser_name);
895 - $userdata['user_nicename'] = apply_filters('pre_user_nicename', $userdata['user_nicename']);
896 -
897 - $userdata['display_name'] = $wpdb->escape($newuser_name);
898 -
899 - $newuser_id = wp_insert_user($userdata);
900 - if (is_numeric($newuser_id)) :
901 - $meta["unfamiliar {$what}"] = $newuser_id;
902 - else :
903 - // TODO: Add some error detection and reporting
904 - endif;
905 - else :
906 - // TODO: Add some error reporting
907 - endif;
908 - else :
909 - $meta["unfamiliar {$what}"] = $GLOBALS['fwp_post'][$sfield];
910 - endif;
911 - endif;
912 - endforeach;
913 -
914 - // Handle author mapping rules
915 - if (isset($GLOBALS['fwp_post']['author_rules_name']) and isset($GLOBALS['fwp_post']['author_rules_action'])) :
916 - unset($meta['map authors']);
917 - foreach ($GLOBALS['fwp_post']['author_rules_name'] as $key => $name) :
918 - // Normalize for case and whitespace
919 - $name = strtolower(trim($name));
920 - $author_action = strtolower(trim($GLOBALS['fwp_post']['author_rules_action'][$key]));
921 -
922 - if (strlen($name) > 0) :
923 - if ('newuser' == $author_action) :
924 - $newuser_name = trim($GLOBALS['fwp_post']['author_rules_newuser'][$key]);
925 - if (strlen($newuser_name) > 0) :
926 - $userdata = array();
927 - $userdata['ID'] = NULL;
928 -
929 - $userdata['user_login'] = sanitize_user($newuser_name);
930 - $userdata['user_login'] = apply_filters('pre_user_login', $userdata['user_login']);
931 -
932 - $userdata['user_nicename'] = sanitize_title($newuser_name);
933 - $userdata['user_nicename'] = apply_filters('pre_user_nicename', $userdata['user_nicename']);
934 -
935 - $userdata['display_name'] = $wpdb->escape($newuser_name);
936 -
937 - $newuser_id = wp_insert_user($userdata);
938 - if (is_numeric($newuser_id)) :
939 - $meta['map authors']['name'][$name] = $newuser_id;
940 - else :
941 - // TODO: Add some error detection and reporting
942 - endif;
943 - else :
944 - // TODO: Add some error reporting
945 - endif;
946 - else :
947 - $meta['map authors']['name'][$name] = $author_action;
948 - endif;
949 - endif;
950 - endforeach;
951 - endif;
952 -
953 - if (isset($GLOBALS['fwp_post']['add_author_rule_name']) and isset($GLOBALS['fwp_post']['add_author_rule_action'])) :
954 - $name = strtolower(trim($GLOBALS['fwp_post']['add_author_rule_name']));
955 - $author_action = strtolower(trim($GLOBALS['fwp_post']['add_author_rule_action']));
956 - if (strlen($name) > 0) :
957 - if ('newuser' == $author_action) :
958 - $newuser_name = trim($GLOBALS['fwp_post']['add_author_rule_newuser']);
959 - if (strlen($newuser_name) > 0) :
960 - $userdata = array();
961 - $userdata['ID'] = NULL;
962 -
963 - $userdata['user_login'] = sanitize_user($newuser_name);
964 - $userdata['user_login'] = apply_filters('pre_user_login', $userdata['user_login']);
965 -
966 - $userdata['user_nicename'] = sanitize_title($newuser_name);
967 - $userdata['user_nicename'] = apply_filters('pre_user_nicename', $userdata['user_nicename']);
968 -
969 - $userdata['display_name'] = $wpdb->escape($newuser_name);
970 -
971 - $newuser_id = wp_insert_user($userdata);
972 - if (is_numeric($newuser_id)) :
973 - $meta['map authors']['name'][$name] = $newuser_id;
974 - else :
975 - // TODO: Add some error detection and reporting
976 - endif;
977 - else :
978 - // TODO: Add some error reporting
979 - endif;
980 - else :
981 - $meta['map authors']['name'][$name] = $author_action;
982 - endif;
983 - endif;
984 - endif;
985 -
986 - if (isset($GLOBALS['fwp_post']['cat_split'])) :
987 - if (strlen(trim($GLOBALS['fwp_post']['cat_split'])) > 0) :
988 - $meta['cat_split'] = trim($GLOBALS['fwp_post']['cat_split']);
989 - else :
990 - unset($meta['cat_split']);
991 - endif;
992 - endif;
993 -
994 - if (is_array($meta['cats'])) :
995 - $meta['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $meta['cats']);
996 - endif;
997 -
998 - // Collapse the author mapping rule structure back into a flat string
999 - if (isset($meta['map authors'])) :
1000 - $ma = array();
1001 - foreach ($meta['map authors'] as $rule_type => $author_rules) :
1002 - foreach ($author_rules as $author_name => $author_action) :
1003 - $ma[] = $rule_type."\n".$author_name."\n".$author_action;
1004 - endforeach;
1005 - endforeach;
1006 - $meta['map authors'] = implode("\n\n", $ma);
1007 - endif;
1008 -
1009 - $notes = '';
1010 - foreach ($meta as $key => $value) :
1011 - $notes .= $key . ": ". addcslashes($value, "\0..\37".'\\') . "\n";
1012 - endforeach;
1013 - $alter[] = "link_notes = '".$wpdb->escape($notes)."'";
1014 -
1015 - $alter_set = implode(", ", $alter);
1016 -
1017 - // issue update query
1018 - $result = $wpdb->query("
1019 - UPDATE $wpdb->links
1020 - SET $alter_set
1021 - WHERE link_id='$link_id'
1022 - ");
1023 - $updated_link = true;
1024 -
1025 - // reload link information from DB
1026 - $link =& new SyndicatedLink($link_id);
1027 - else :
1028 - $updated_link = false;
1029 - endif;
1030 -
1031 - $db_link = $link->link;
1032 - $link_url = wp_specialchars($db_link->link_url, 1);
1033 - $link_name = wp_specialchars($db_link->link_name, 1);
1034 - $link_description = wp_specialchars($db_link->link_description, 'both');
1035 - $link_notes = wp_specialchars($db_link->link_notes, 'both');
1036 - $link_rss_uri = wp_specialchars($db_link->link_rss, 'both');
1037 -
1038 - $meta = $link->settings;
1039 - $post_status_global = get_option('feedwordpress_syndicated_post_status');
1040 - $comment_status_global = get_option('feedwordpress_syndicated_comment_status');
1041 - $ping_status_global = get_option('feedwordpress_syndicated_ping_status');
1042 -
1043 - $status['post'] = array('publish' => '', 'private' => '', 'draft' => '', 'site-default' => '');
1044 - $status['comment'] = array('open' => '', 'closed' => '', 'site-default' => '');
1045 - $status['ping'] = array('open' => '', 'closed' => '', 'site-default' => '');
1046 -
1047 - foreach (array('post', 'comment', 'ping') as $what) :
1048 - if (isset($meta["{$what} status"])) :
1049 - $status[$what][$meta["{$what} status"]] = ' checked="checked"';
1050 - else :
1051 - $status[$what]['site-default'] = ' checked="checked"';
1052 - endif;
1053 - endforeach;
1054 -
1055 - $unfamiliar['author'] = array ('create' => '','default' => '','filter' => '');
1056 - $unfamiliar['category'] = array ('create'=>'','default'=>'','filter'=>'');
1057 -
1058 - foreach (array('author', 'category') as $what) :
1059 - if (is_string($meta["unfamiliar {$what}"]) and
1060 - array_key_exists($meta["unfamiliar {$what}"], $unfamiliar[$what])) :
1061 - $key = $meta["unfamiliar {$what}"];
1062 - else:
1063 - $key = 'site-default';
1064 - endif;
1065 - $unfamiliar[$what][$key] = ' checked="checked"';
1066 - endforeach;
1067 -
1068 - $dogs = get_nested_categories(-1, 0);
1069 - if (is_array($meta['cats'])) :
1070 - $cats = array_map('strtolower',
1071 - array_map('trim',
1072 - $meta['cats']
1073 - ));
1074 - else:
1075 - $cats = array();
1076 - endif;
1077 -
1078 - foreach ($dogs as $tag => $dog) :
1079 - $found_by_name = in_array(strtolower(trim($dog['cat_name'])), $cats);
1080 -
1081 - if (isset($dog['cat_ID'])) : $dog['cat_id'] = $dog['cat_ID']; endif;
1082 - $found_by_id = in_array('{#'.trim($dog['cat_id']).'}', $cats);
1083 -
1084 - if ($found_by_name or $found_by_id) :
1085 - $dogs[$tag]['checked'] = true;
1086 - endif;
1087 - endforeach;
1088 - else :
1089 - die( __('Link not found.') );
1090 - endif;
1091 -
1092 - ?>
1093 -<script type="text/javascript">
1094 - function flip_hardcode (item) {
1095 - ed=document.getElementById('basics-'+item+'-edit');
1096 - view=document.getElementById('basics-'+item+'-view');
1097 -
1098 - o = document.getElementById('basics-hardcode-'+item);
1099 - if (o.value=='yes') { ed.style.display='inline'; view.style.display='none'; }
1100 - else { ed.style.display='none'; view.style.display='inline'; }
1101 - }
1102 - function flip_newuser (item) {
1103 - rollup=document.getElementById(item);
1104 - newuser=document.getElementById(item+'-newuser');
1105 - sitewide=document.getElementById(item+'-default');
1106 - if (rollup) {
1107 - if ('newuser'==rollup.value) {
1108 - if (newuser) newuser.style.display='block';
1109 - if (sitewide) sitewide.style.display='none';
1110 - } else if ('site-default'==rollup.value) {
1111 - if (newuser) newuser.style.display='none';
1112 - if (sitewide) sitewide.style.display='block';
1113 - } else {
1114 - if (newuser) newuser.style.display='none';
1115 - if (sitewide) sitewide.style.display='none';
1116 - }
1117 - }
1118 - }
1119 -</script>
1120 -
1121 -<?php if ($updated_link) : ?>
1122 -<div class="updated"><p>Syndicated feed settings updated.</p></div>
1123 -<?php endif; ?>
1124 -
1125 -<form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
1126 -<div class="wrap">
1127 -<input type="hidden" name="link_id" value="<?php echo $link_id; ?>" />
1128 -<input type="hidden" name="action" value="linkedit" />
1129 -<input type="hidden" name="save" value="link" />
1130 -
1131 -<h2>Edit a syndicated feed:</h2>
1132 -<fieldset class="options"><legend>Basics</legend>
1133 -<table class="editform" width="100%" cellspacing="2" cellpadding="5">
1134 -<tr>
1135 -<th scope="row" width="20%"><?php _e('Feed URI:') ?></th>
1136 -<td width="60%"><a href="<?php echo wp_specialchars($link_rss_uri, 'both'); ?>"><?php echo $link_rss_uri; ?></a>
1137 -(<a href="<?php echo FEEDVALIDATOR_URI; ?>?url=<?php echo urlencode($link_rss_uri); ?>"
1138 -title="Check feed &lt;<?php echo wp_specialchars($link_rss_uri, 'both'); ?>&gt; for validity">validate</a>)
1139 -</td>
1140 -<td width="20%"><input type="submit" name="feedfinder" value="switch &rarr;" style="font-size:smaller" /></td>
1141 -</tr>
1142 -<tr>
1143 -<th scope="row" width="20%"><?php _e('Link Name:') ?></th>
1144 -<td width="60%"><input type="text" id="basics-name-edit" name="name"
1145 -value="<?php echo $link_name; ?>" style="width: 95%" />
1146 -<span id="basics-name-view"><strong><?php echo $link_name; ?></strong></span>
1147 -</td>
1148 -<td>
1149 -<select id="basics-hardcode-name" onchange="flip_hardcode('name')" name="hardcode_name">
1150 -<option value="no" <?php echo $link->hardcode('name')?'':'selected="selected"'; ?>>update automatically</option>
1151 -<option value="yes" <?php echo $link->hardcode('name')?'selected="selected"':''; ?>>edit manually</option>
1152 -</select>
1153 -</td>
1154 -</tr>
1155 -<tr>
1156 -<th scope="row" width="20%"><?php _e('Short description:') ?></th>
1157 -<td width="60%">
1158 -<input id="basics-description-edit" type="text" name="description" value="<?php echo $link_description; ?>" style="width: 95%" />
1159 -<span id="basics-description-view"><strong><?php echo $link_description; ?></strong></span>
1160 -</td>
1161 -<td>
1162 -<select id="basics-hardcode-description" onchange="flip_hardcode('description')"
1163 -name="hardcode_description">
1164 -<option value="no" <?php echo $link->hardcode('description')?'':'selected="selected"'; ?>>update automatically</option>
1165 -<option value="yes" <?php echo $link->hardcode('description')?'selected="selected"':''; ?>>edit manually</option>
1166 -</select></td>
1167 -</tr>
1168 -<tr>
1169 -<th width="20%" scope="row"><?php _e('Homepage:') ?></th>
1170 -<td width="60%">
1171 -<input id="basics-url-edit" type="text" name="linkurl" value="<?php echo $link_url; ?>" style="width: 95%;" />
1172 -<a id="basics-url-view" href="<?php echo $link_url; ?>"><?php echo $link_url; ?></a></td>
1173 -<td>
1174 -<select id="basics-hardcode-url" onchange="flip_hardcode('url')" name="hardcode_url">
1175 -<option value="no"<?php echo $link->hardcode('url')?'':' selected="selected"'; ?>>update automatically</option>
1176 -<option value="yes"<?php echo $link->hardcode('url')?' selected="selected"':''; ?>>edit manually</option>
1177 -</select></td></tr>
1178 -
1179 -<tr>
1180 -<th width="20%"><?php _e('Last update') ?>:</th>
1181 -<td colspan="2"><?php
1182 - if (isset($meta['update/last'])) :
1183 - echo strftime('%x %X', $meta['update/last'])." ";
1184 - else :
1185 - echo " none yet";
1186 - endif;
1187 -?></td></tr>
1188 -<tr><th width="20%">Next update:</th>
1189 -<td colspan="2"><?php
1190 - $holdem = (isset($meta['update/hold']) ? $meta['update/hold'] : 'scheduled');
1191 -?>
1192 -<select name="update_schedule">
1193 -<option value="scheduled"<?php echo ($holdem=='scheduled')?' selected="selected"':''; ?>>update on schedule <?php
1194 - echo " (";
1195 - if (isset($meta['update/ttl']) and is_numeric($meta['update/ttl'])) :
1196 - if (isset($meta['update/timed']) and $meta['update/timed']=='automatically') :
1197 - echo 'next: ';
1198 - $next = $meta['update/last'] + ((int) $meta['update/ttl'] * 60);
1199 - if (strftime('%x', time()) != strftime('%x', $next)) :
1200 - echo strftime('%x', $next)." ";
1201 - endif;
1202 - echo strftime('%X', $meta['update/last']+((int) $meta['update/ttl']*60));
1203 - else :
1204 - echo "every ".$meta['update/ttl']." minute".(($meta['update/ttl']!=1)?"s":"");
1205 - endif;
408 +function syndication_permalink ($permalink = '') {
409 + if (get_option('feedwordpress_munge_permalink') != 'no'):
410 + $uri = get_syndication_permalink();
411 + return ((strlen($uri) > 0) ? $uri : $permalink);
1206 412 else:
1207 - echo "next scheduled update";
413 + return $permalink;
1208 414 endif;
1209 - echo ")";
1210 -?></option>
1211 -<option value="next"<?php echo ($holdem=='next')?' selected="selected"':''; ?>>update ASAP</option>
1212 -<option value="ping"<?php echo ($holdem=='ping')?' selected="selected"':''; ?>>update only when pinged</option>
1213 -</select></tr>
1214 -</table>
1215 -</fieldset>
415 +} // function syndication_permalink ()
1216 416
1217 -<script type="text/javascript">
1218 -flip_hardcode('name');
1219 -flip_hardcode('description');
1220 -flip_hardcode('url');
1221 -</script>
417 +################################################################################
418 +## ADMIN MENU ADD-ONS: register Dashboard management pages #####################
419 +################################################################################
1222 420
1223 -<p class="submit">
1224 -<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1225 -</p>
421 +function fwp_add_pages () {
422 + global $fwp_capability;
423 + global $fwp_path;
1226 424
1227 -<fieldset class="options">
1228 -<legend>Syndicated Posts</legend>
425 + add_menu_page('Syndicated Sites', 'Syndication', $fwp_capability['manage_links'], $fwp_path.'/syndication.php');
426 + add_submenu_page($fwp_path.'/syndication.php', 'Syndicated Authors', 'Authors', $fwp_capability['manage_options'], $fwp_path.'/authors.php');
427 + add_submenu_page($fwp_path.'/syndication.php', 'Syndication Options', 'Options', $fwp_capability['manage_options'], $fwp_path.'/syndication-options.php');
428 + add_options_page('Syndication Options', 'Syndication', $fwp_capability['manage_options'], $fwp_path.'/syndication-options.php');
429 +} // function fwp_add_pages () */
1229 430
1230 -<?php fwp_category_box($dogs, 'all syndicated posts from this feed'); ?>
1231 -
1232 -<table class="editform" width="75%" cellspacing="2" cellpadding="5">
1233 -<tr><th width="27%" scope="row" style="vertical-align:top">Publication:</th>
1234 -<td width="73%" style="vertical-align:top"><ul style="margin:0; list-style:none">
1235 -<li><label><input type="radio" name="feed_post_status" value="site-default"
1236 -<?php echo $status['post']['site-default']; ?> /> Use site-wide setting from <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a>
1237 -(currently: <strong><?php echo ($post_status_global ? $post_status_global : 'publish'); ?></strong>)</label></li>
1238 -<li><label><input type="radio" name="feed_post_status" value="publish"
1239 -<?php echo $status['post']['publish']; ?> /> Publish posts from this feed immediately</label></li>
1240 -<li><label><input type="radio" name="feed_post_status" value="private"
1241 -<?php echo $status['post']['private']; ?> /> Hold posts from this feed as private posts</label></li>
1242 -<li><label><input type="radio" name="feed_post_status" value="draft"
1243 -<?php echo $status['post']['draft']; ?> /> Hold posts from this feed as drafts</label></li>
1244 -</ul></td>
1245 -</tr>
1246 -
1247 -<tr><th width="27%" scope="row" style="vertical-align:top">Comments:</th>
1248 -<td width="73%"><ul style="margin:0; list-style:none">
1249 -<li><label><input type="radio" name="feed_comment_status" value="site-default"
1250 -<?php echo $status['comment']['site-default']; ?> /> Use site-wide setting from <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a>
1251 -(currently: <strong><?php echo ($comment_status_global ? $comment_status_global : 'closed'); ?>)</strong></label></li>
1252 -<li><label><input type="radio" name="feed_comment_status" value="open"
1253 -<?php echo $status['comment']['open']; ?> /> Allow comments on syndicated posts from this feed</label></li>
1254 -<li><label><input type="radio" name="feed_comment_status" value="closed"
1255 -<?php echo $status['comment']['closed']; ?> /> Don't allow comments on syndicated posts from this feed</label></li>
1256 -</ul></td>
1257 -</tr>
1258 -
1259 -<tr><th width="27%" scope="row" style="vertical-align:top">Trackback and Pingback:</th>
1260 -<td width="73%"><ul style="margin:0; list-style:none">
1261 -<li><label><input type="radio" name="feed_ping_status" value="site-default"
1262 -<?php echo $status['ping']['site-default']; ?> /> Use site-wide setting from <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a>
1263 -(currently: <strong><?php echo ($ping_status_global ? $ping_status_global : 'closed'); ?>)</strong></label></li>
1264 -<li><label><input type="radio" name="feed_ping_status" value="open"
1265 -<?php echo $status['ping']['open']; ?> /> Accept pings on syndicated posts from this feed</label></li>
1266 -<li><label><input type="radio" name="feed_ping_status" value="closed"
1267 -<?php echo $status['ping']['closed']; ?> /> Don't accept pings on syndicated posts from this feed</label></li>
1268 -</ul></td>
1269 -</tr>
1270 -</table>
1271 -</fieldset>
1272 -
1273 -<p class="submit">
1274 -<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1275 -</p>
1276 -
1277 -<fieldset class="options">
1278 -<legend>Syndicated Authors</legend>
1279 -<?php $authorlist = fwp_author_list(); ?>
1280 -
1281 -<table>
1282 -<tr><th colspan="3" style="text-align: left; padding-top: 1.0em; border-bottom: 1px dotted black;">For posts by specific authors. Blank out a name to delete the rule.</th></tr>
1283 -
1284 -<?php if (isset($meta['map authors'])) : $i=0; foreach ($meta['map authors'] as $author_rules) : foreach ($author_rules as $author_name => $author_action) : $i++; ?>
1285 -<tr>
1286 - <th style="text-align: left">Posts by <input type="text" name="author_rules_name[]" value="<?php echo htmlspecialchars($author_name); ?>" /></th>
1287 - <td>
1288 - <select id="author-rules-<?php echo $i; ?>" name="author_rules_action[]" onchange="flip_newuser('author-rules-<?php echo $i; ?>');">
1289 - <?php foreach ($authorlist as $local_author_id => $local_author_name) : ?>
1290 - <option value="<?php echo $local_author_id; ?>"<?php if ($local_author_id==$author_action) : echo ' selected="selected"'; endif; ?>>are assigned to <?php echo $local_author_name; ?></option>
1291 - <?php endforeach; ?>
1292 - <option value="newuser">will be assigned to a new user...</option>
1293 - <option value="filter"<?php if ('filter'==$author_action) : echo ' selected="selected"'; endif; ?>>get filtered out</option>
1294 - </select>
1295 - </td>
1296 - <td><div id="author-rules-<?php echo $i; ?>-newuser">named <input type="text" name="author_rules_newuser[]" value="" /></div></td>
1297 -</tr>
1298 -<?php endforeach; endforeach; endif; ?>
1299 -
1300 -<tr><th colspan="3" style="text-align: left; padding-top: 1.0em; border-bottom: 1px dotted black;">Fill in to set up a new rule:</th></tr>
1301 -
1302 -<tr>
1303 - <th style="text-align: left">Posts by <input type="text" name="add_author_rule_name" /></th>
1304 - <td>
1305 - <select id="add-author-rule" name="add_author_rule_action" onchange="flip_newuser('add-author-rule');">
1306 - <?php foreach ($authorlist as $author_id => $author_name) : ?>
1307 - <option value="<?php echo $author_id; ?>">are assigned to <?php echo $author_name; ?></option>
1308 - <?php endforeach; ?>
1309 - <option value="newuser">will be assigned to a new user...</option>
1310 - <option value="filter">get filtered out</option>
1311 - </select>
1312 - </td>
1313 - <td><div id="add-author-rule-newuser">named <input type="text" name="add_author_rule_newuser" value="" /></div></td>
1314 -</tr>
1315 -
1316 -<tr><th colspan="3" style="text-align: left; padding-top: 1.0em; border-bottom: 1px dotted black;">For posts by authors that haven't been syndicated before:</th></tr>
1317 -<tr>
1318 - <th style="text-align: left">Posts by new authors</th>
1319 - <td>
1320 - <select id="unfamiliar-author" name="unfamiliar_author" onchange="flip_newuser('unfamiliar-author');">
1321 - <option value="site-default"<?php if (!isset($meta['unfamiliar author'])) : ?>selected="selected"<?php endif; ?>>are handled using site-wide settings</option>
1322 - <option value="create"<?php if ('create'==$meta['unfamiliar author']) : ?>selected="selected"<?php endif; ?>>create a new author account</option>
1323 - <?php foreach ($authorlist as $author_id => $author_name) : ?>
1324 - <option value="<?php echo $author_id; ?>"<?php if ($author_id==$meta['unfamiliar author']) : ?>selected="selected"<?php endif; ?>>are assigned to <?php echo $author_name; ?></option>
1325 - <?php endforeach; ?>
1326 - <option value="newuser">will be assigned to a new user...</option>
1327 - <option value="filter"<?php if ('filter'==$meta['unfamiliar author']) : ?>selected="selected"<?php endif; ?>>get filtered out</option>
1328 - </select>
1329 - </td>
1330 - <td>
1331 - <div id="unfamiliar-author-default">Site-wide settings can be set in <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a></div>
1332 - <div id="unfamiliar-author-newuser">named <input type="text" name="unfamiliar_author_newuser" value="" /></div>
1333 - </td>
1334 -</tr>
1335 -
1336 -</table>
1337 -</fieldset>
1338 -
1339 -<script>
1340 - flip_newuser('unfamiliar-author');
1341 -<?php for ($j=1; $j<=$i; $j++) : ?>
1342 - flip_newuser('author-rules-<?php echo $j; ?>');
1343 -<?php endfor; ?>
1344 - flip_newuser('add-author-rule');
1345 -</script>
1346 -
1347 -<p class="submit">
1348 -<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1349 -</p>
1350 -
1351 -<fieldset>
1352 -<legend>Advanced Feed Options</legend>
1353 -<table class="editform" width="100%" cellspacing="2" cellpadding="5">
1354 -
1355 -<tr>
1356 -<th width="20%" scope="row" style="vertical-align:top">Unfamiliar categories:</th>
1357 -<td width="80%"><ul style="margin: 0; list-style:none">
1358 -<li><label><input type="radio" name="unfamiliar_category" value="site-default"<?php echo $unfamiliar['category']['site-default']; ?> /> use site-wide setting from <a href="admin.php?page=feedwordpress/syndication-options.php">Syndication Options</a>
1359 -(currently <strong><?php echo FeedWordPress::on_unfamiliar('category'); ?></strong>)</label></li>
1360 -<li><label><input type="radio" name="unfamiliar_category" value="create"<?php echo $unfamiliar['category']['create']; ?> /> create any categories the post is in</label></li>
1361 -<li><label><input type="radio" name="unfamiliar_category" value="default"<?php echo $unfamiliar['category']['default']; ?> /> don't create new categories</label></li>
1362 -<li><label><input type="radio" name="unfamiliar_category" value="filter"<?php echo $unfamiliar['category']['filter']; ?> /> don't create new categories and don't syndicate posts unless they match at least one familiar category</label></li>
1363 -</ul></td>
1364 -</tr>
1365 -
1366 -<tr>
1367 -<th width="20%" scope="row" style="vertical-align:top">Multiple categories:</th>
1368 -<td width="80%">
1369 -<input type="text" size="20" id="cat_split" name="cat_split" value="<?php if (isset($meta['cat_split'])) : echo htmlspecialchars($meta['cat_split']); endif; ?>" /><br/>
1370 -Enter a <a href="http://us.php.net/manual/en/reference.pcre.pattern.syntax.php">Perl-compatible regular expression</a> here if the feed provides multiple
1371 -categories in a single category element. The regular expression should match
1372 -the characters used to separate one category from the next. If the feed uses
1373 -spaces (like <a href="http://del.icio.us/">del.icio.us</a>), use the pattern "\s".
1374 -If the feed does not provide multiple categories in a single element, leave this
1375 -blank.</td>
1376 -</tr>
1377 -</table>
1378 -</fieldset>
1379 -
1380 -<p class="submit">
1381 -<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1382 -</p>
1383 -
1384 -<fieldset id="postcustom">
1385 -<legend>Custom Settings (for use in templates)</legend>
1386 -<div id="postcustomstuff">
1387 -<table id="meta-list" cellpadding="3">
1388 - <tr>
1389 - <th>Key</th>
1390 - <th>Value</th>
1391 - <th>Action</th>
1392 - </tr>
1393 -
1394 -<?php
1395 - $i = 0;
1396 - foreach ($meta as $key => $value) :
1397 - if (!preg_match("\007^((".implode(')|(', $special_settings)."))$\007i", $key)) :
1398 -?>
1399 - <tr style="vertical-align:top">
1400 - <th width="30%" scope="row"><input type="hidden" name="notes[<?php echo $i; ?>][key0]" value="<?php echo wp_specialchars($key, 'both'); ?>" />
1401 - <input id="notes-<?php echo $i; ?>-key" name="notes[<?php echo $i; ?>][key1]" value="<?php echo wp_specialchars($key, 'both'); ?>" /></th>
1402 - <td width="60%"><textarea rows="2" cols="40" id="notes-<?php echo $i; ?>-value" name="notes[<?php echo $i; ?>][value]"><?php echo wp_specialchars($value, 'both'); ?></textarea></td>
1403 - <td width="10%"><select name="notes[<?php echo $i; ?>][action]">
1404 - <option value="update">save changes</option>
1405 - <option value="delete">delete this setting</option>
1406 - </select></td>
1407 - </tr>
1408 -<?php
1409 - $i++;
1410 - endif;
1411 - endforeach;
1412 -?>
1413 - <tr>
1414 - <th scope="row"><input type="text" size="10" name="notes[<?php echo $i; ?>][key1]" value="" /></th>
1415 - <td><textarea name="notes[<?php echo $i; ?>][value]" rows="2" cols="40"></textarea></td>
1416 - <td><em>add new setting...</em><input type="hidden" name="notes[<?php echo $i; ?>][action]" value="update" /></td>
1417 - </tr>
1418 -</table>
1419 -</fieldset>
1420 -
1421 -<p class="submit">
1422 -<input type="submit" name="submit" value="<?php _e('Save Changes &raquo;') ?>" />
1423 -</p>
1424 -
1425 -</div>
1426 - <?php
1427 - endif;
1428 - return false; // Don't continue
1429 -}
1430 -
1431 -function fwp_author_list () {
1432 - global $wpdb;
1433 - $ret = array();
1434 - $users = $wpdb->get_results("SELECT * FROM $wpdb->users ORDER BY display_name");
1435 - if (is_array($users)) :
1436 - foreach ($users as $user) :
1437 - $id = (int) $user->ID;
1438 - $ret[$id] = $user->display_name;
1439 - endforeach;
1440 - endif;
1441 - return $ret;
1442 -}
1443 -
1444 -function fwp_multidelete_page () {
1445 - global $wpdb;
1446 -
1447 - check_admin_referer(); // Make sure the referers are kosher
1448 -
1449 - $link_ids = (isset($_REQUEST['link_ids']) ? $_REQUEST['link_ids'] : array());
1450 - if (isset($_REQUEST['link_id'])) : array_push($link_ids, $_REQUEST['link_id']); endif;
1451 -
1452 - if (!current_user_can('manage_links')):
1453 - die (__("Cheatin' uh ?"));
1454 - elseif (isset($GLOBALS['fwp_post']['confirm']) and $GLOBALS['fwp_post']['confirm']=='Delete'):
1455 - foreach ($GLOBALS['fwp_post']['link_action'] as $link_id => $what) :
1456 - $do_it[$what][] = $link_id;
1457 - endforeach;
1458 -
1459 - $alter = array();
1460 - if (count($do_it['hide']) > 0) :
1461 - $hidem = "(".implode(', ', $do_it['hide']).")";
1462 - $alter[] = "
1463 - UPDATE $wpdb->links
1464 - SET link_visible = 'N'
1465 - WHERE link_id IN {$hidem}
1466 - ";
1467 - endif;
1468 -
1469 - if (count($do_it['nuke']) > 0) :
1470 - $nukem = "(".implode(', ', $do_it['nuke']).")";
1471 -
1472 - // Make a list of the items syndicated from this feed...
1473 - $post_ids = $wpdb->get_col("
1474 - SELECT post_id FROM $wpdb->postmeta
1475 - WHERE meta_key = 'syndication_feed_id'
1476 - AND meta_value IN {$nukem}
1477 - ");
1478 -
1479 - // ... and kill them all
1480 - if (count($post_ids) > 0) :
1481 - foreach ($post_ids as $post_id) :
1482 - wp_delete_post($post_id);
1483 - endforeach;
1484 - endif;
1485 -
1486 - $alter[] = "
1487 - DELETE FROM $wpdb->links
1488 - WHERE link_id IN {$nukem}
1489 - ";
1490 - endif;
1491 -
1492 - if (count($do_it['delete']) > 0) :
1493 - $deletem = "(".implode(', ', $do_it['delete']).")";
1494 -
1495 - // Make the items syndicated from this feed appear to be locally-authored
1496 - $alter[] = "
1497 - DELETE FROM $wpdb->postmeta
1498 - WHERE meta_key = 'syndication_feed_id'
1499 - AND meta_value IN {$deletem}
1500 - ";
1501 -
1502 - // ... and delete the links themselves.
1503 - $alter[] = "
1504 - DELETE FROM $wpdb->links
1505 - WHERE link_id IN {$deletem}
1506 - ";
1507 - endif;
1508 -
1509 - $errs = array(); $success = array ();
1510 - foreach ($alter as $sql) :
1511 - $result = $wpdb->query($sql);
1512 - if (!$result):
1513 - $errs[] = mysql_error();
1514 - endif;
1515 - endforeach;
1516 -
1517 - if (count($alter) > 0) :
1518 - echo "<div class=\"updated\">\n";
1519 - if (count($errs) > 0) :
1520 - echo "There were some problems processing your ";
1521 - echo "unsubscribe request. [SQL: ".implode('; ', $errs)."]";
1522 - else :
1523 - echo "Your unsubscribe request(s) have been processed.";
1524 - endif;
1525 - echo "</div>\n";
1526 - endif;
1527 -
1528 - return true; // Continue on to Syndicated Sites listing
1529 - else :
1530 - $targets = $wpdb->get_results("
1531 - SELECT * FROM $wpdb->links
1532 - WHERE link_id IN (".implode(",",$link_ids).")
1533 - ");
1534 -?>
1535 -<form action="admin.php?page=feedwordpress/<?php echo basename(__FILE__); ?>" method="post">
1536 -<div class="wrap">
1537 -<input type="hidden" name="action" value="Unsubscribe" />
1538 -<input type="hidden" name="confirm" value="Delete" />
1539 -
1540 -<h2>Unsubscribe from Syndicated Links:</h2>
1541 -<?php foreach ($targets as $link) :
1542 - $link_url = wp_specialchars($link->link_url, 1);
1543 - $link_name = wp_specialchars($link->link_name, 1);
1544 - $link_description = wp_specialchars($link->link_description, 'both');
1545 - $link_rss = wp_specialchars($link->link_rss, 'both');
1546 -?>
1547 -<fieldset>
1548 -<legend><?php echo $link_name; ?></legend>
1549 -<table class="editform" width="100%" cellspacing="2" cellpadding="5">
1550 -<tr><th scope="row" width="20%"><?php _e('Feed URI:') ?></th>
1551 -<td width="80%"><a href="<?php echo $link_rss; ?>"><?php echo $link_rss; ?></a></td></tr>
1552 -<tr><th scope="row" width="20%"><?php _e('Short description:') ?></th>
1553 -<td width="80%"><?php echo $link_description; ?></span></td></tr>
1554 -<tr><th width="20%" scope="row"><?php _e('Homepage:') ?></th>
1555 -<td width="80%"><a href="<?php echo $link_url; ?>"><?php echo $link_url; ?></a></td></tr>
1556 -<tr style="vertical-align:top"><th width="20%" scope="row">Subscription <?php _e('Options') ?>:</th>
1557 -<td width="80%"><ul style="margin:0; padding: 0; list-style: none">
1558 -<li><input type="radio" id="hide-<?php echo $link->link_id; ?>"
1559 -name="link_action[<?php echo $link->link_id; ?>]" value="hide" />
1560 -<label for="hide-<?php echo $link->link_id; ?>">Turn off the subscription for this
1561 -syndicated link<br/><span style="font-size:smaller">(Keep the feed information
1562 -and all the posts from this feed in the database, but don't syndicate any
1563 -new posts from the feed.)</span></label></li>
1564 -<li><input type="radio" id="nuke-<?php echo $link->link_id; ?>"
1565 -name="link_action[<?php echo $link->link_id; ?>]" value="nuke" />
1566 -<label for="nuke-<?php echo $link->link_id; ?>">Delete this syndicated link and all the
1567 -posts that were syndicated from it</label></li>
1568 -<li><input type="radio" id="delete-<?php echo $link->link_id; ?>"
1569 -name="link_action[<?php echo $link->link_id; ?>]" value="delete" />
1570 -<label for="delete-<?php echo $link->link_id; ?>">Delete this syndicated link, but
1571 -<em>keep</em> posts that were syndicated from it (as if they were authored
1572 -locally).</label></li>
1573 -<li><input type="radio" id="nothing-<?php echo $link->link_id; ?>"
1574 -name="link_action[<?php echo $link->link_id; ?>]" value="nothing" />
1575 -<label for="nothing-<?php echo $link->link_id; ?>">Keep this feed as it is. I changed
1576 -my mind.</label></li>
1577 -</ul>
1578 -</table>
1579 -</fieldset>
1580 -<?php endforeach; ?>
1581 -
1582 -<div class="submit">
1583 -<input class="delete" type="submit" name="submit" value="<?php _e('Unsubscribe from selected feeds &raquo;') ?>" />
1584 -</div>
1585 -</div>
1586 -<?php
1587 - return false; // Don't continue on to Syndicated Sites listing
1588 - endif;
1589 -}
1590 -
1591 431 ################################################################################
1592 432 ## fwp_hold_pings() and fwp_release_pings(): Outbound XML-RPC ping reform ####
1593 433 ## ... 'coz it's rude to send 500 pings the first time your aggregator runs ####
1594 434 ################################################################################
@@ -1742,9 +582,9 @@
1742 582 #
1743 583 # * Updates to existing posts since the last poll are mirrored in the
1744 584 # WordPress store.
1745 585 #
1746 - function update ($uri = null) {
586 + function update ($uri = null, $crash_ts = null) {
1747 587 global $wpdb;
1748 588
1749 589 if (FeedWordPress::needs_upgrade()) : // Will make duplicate posts if we don't hold off
1750 590 return NULL;
@@ -1757,11 +597,28 @@
1757 597 endif;
1758 598
1759 599 do_action('feedwordpress_update', $uri);
1760 600
601 + if (is_null($crash_ts)) :
602 + $crash_dt = (int) get_option('feedwordpress_update_time_limit');
603 + if ($crash_dt > 0) :
604 + $crash_ts = time() + $crash_dt;
605 + else :
606 + $crash_ts = NULL;
607 + endif;
608 + endif;
609 +
610 + // Randomize order for load balancing purposes
611 + $feed_set = $this->feeds;
612 + shuffle($feed_set);
613 +
1761 614 // Loop through and check for new posts
1762 615 $delta = NULL;
1763 - foreach ($this->feeds as $feed) :
616 + foreach ($feed_set as $feed) :
617 + if (!is_null($crash_ts) and (time() > $crash_ts)) : // Check whether we've exceeded the time limit
618 + break;
619 + endif;
620 +
1764 621 $pinged_that = (is_null($uri) or in_array($uri, array($feed->uri(), $feed->homepage())));
1765 622
1766 623 if (!is_null($uri)) : // A site-specific ping always updates
1767 624 $timely = true;
@@ -1774,9 +631,12 @@
1774 631 endif;
1775 632
1776 633 if ($pinged_that and $timely) :
1777 634 do_action('feedwordpress_check_feed', $feed->settings);
1778 - $added = $feed->poll();
635 + $start_ts = time();
636 + $added = $feed->poll($crash_ts);
637 + do_action('feedwordpress_check_feed_complete', $feed->settings, $added, time() - $start_ts);
638 +
1779 639 if (isset($added['new'])) : $delta['new'] += $added['new']; endif;
1780 640 if (isset($added['updated'])) : $delta['updated'] += $added['updated']; endif;
1781 641 endif;
1782 642 endforeach;
@@ -1852,17 +712,20 @@
1852 712 return $link_id;
1853 713 } // function FeedWordPress::syndicate_link()
1854 714
1855 715 function on_unfamiliar ($what = 'author', $override = NULL) {
1856 - $set = array('create', 'default', 'filter');
1857 -
716 + $set = array(
717 + 'author' => array('create', 'default', 'filter'),
718 + 'category' => array('create', 'tag', 'default', 'filter'),
719 + );
720 +
1858 721 if (is_string($override)) :
1859 722 $ret = strtolower($override);
1860 723 endif;
1861 724
1862 - if (!is_numeric($override) and !in_array($ret, $set)) :
725 + if (!is_numeric($override) and !in_array($ret, $set[$what])) :
1863 726 $ret = get_option('feedwordpress_unfamiliar_'.$what);
1864 - if (!is_numeric($ret) and !in_array($ret, $set)) :
727 + if (!is_numeric($ret) and !in_array($ret, $set[$what])) :
1865 728 $ret = 'create';
1866 729 endif;
1867 730 endif;
1868 731
@@ -1868,8 +731,33 @@
1868 731
1869 732 return $ret;
1870 733 } // function FeedWordPress::on_unfamiliar()
1871 734
735 + function null_email_set () {
736 + $base = get_option('feedwordpress_null_email_set');
737 +
738 + if ($base===false) :
739 + $ret = array('noreply@blogger.com'); // default
740 + else :
741 + $ret = array_map('strtolower',
742 + array_map('trim', explode("\n", $base)));
743 + endif;
744 + $ret = apply_filters('syndicated_item_author_null_email_set', $ret);
745 + return $ret;
746 +
747 + } /* FeedWordPress::null_email_set () */
748 +
749 + function is_null_email ($email) {
750 + $ret = in_array(strtolower(trim($email)), FeedWordPress::null_email_set());
751 + $ret = apply_filters('syndicated_item_author_is_null_email', $ret, $email);
752 + return $ret;
753 + } /* FeedWordPress::is_null_email () */
754 +
755 + function use_aggregator_source_data () {
756 + $ret = get_option('feedwordpress_use_aggregator_source_data');
757 + return apply_filters('syndicated_post_use_aggregator_source_data', ($ret=='yes'));
758 + }
759 +
1872 760 function syndicated_links () {
1873 761 $contributors = FeedWordPress::link_category_id();
1874 762 if (function_exists('get_bookmarks')) :
1875 763 $links = get_bookmarks(array("category" => $contributors));
@@ -2027,8 +915,16 @@
2027 915 endswitch;
2028 916 echo "<p>Upgrade complete. FeedWordPress is now ready to use again.</p>";
2029 917 } /* FeedWordPress::upgrade_database() */
2030 918
919 + function create_guid_index () {
920 + global $wpdb;
921 +
922 + $wpdb->query("
923 + CREATE INDEX {$wpdb->posts}_guid_idx ON {$wpdb->posts}(guid)
924 + ");
925 + } /* FeedWordPress::create_guid_index () */
926 +
2031 927 # Utility functions for handling text settings
2032 928 function negative ($f, $setting) {
2033 929 $nego = array ('n', 'no', 'f', 'false');
2034 930 return (isset($f[$setting]) and in_array(strtolower($f[$setting]), $nego));
@@ -2068,13 +964,8 @@
2068 964
2069 965 var $_freshness = null;
2070 966 var $_wp_id = null;
2071 967
2072 - var $strip_attrs = array (
2073 - array('[a-z]+', 'style'),
2074 - array('[a-z]+', 'target'),
2075 - );
2076 -
2077 968 function SyndicatedPost ($item, $link) {
2078 969 global $wpdb;
2079 970
2080 971 $this->link = $link;
@@ -2105,14 +996,14 @@
2105 996 # That's deliberate. The escaping is done at the point
2106 997 # of insertion, not here, to avoid double-escaping and
2107 998 # to avoid screwing with syndicated_post filters
2108 999
2109 - $this->post['post_title'] = $this->item['title'];
1000 + $this->post['post_title'] = apply_filters('syndicated_item_title', $this->item['title'], $this);
2110 1001
2111 - // This just gives usan alphanumeric representation of
1002 + // This just gives us an alphanumeric representation of
2112 1003 // the author. We will look up (or create) the numeric
2113 1004 // ID for the author in SyndicatedPost::add()
2114 - $this->post['named']['author'] = $this->author();
1005 + $this->post['named']['author'] = apply_filters('syndicated_item_author', $this->author(), $this);
2115 1006
2116 1007 # Identify content and sanitize it.
2117 1008 # ---------------------------------
2118 1009 if (isset($this->item['xhtml']['body'])) :
@@ -2123,24 +1014,9 @@
2123 1014 $content = $this->item['content']['encoded'];
2124 1015 else:
2125 1016 $content = $this->item['description'];
2126 1017 endif;
2127 -
2128 - # FeedWordPress used to resolve URIs relative to the
2129 - # feed URI. It now relies on the xml:base support
2130 - # baked in to the MagpieRSS upgrade. So all we do here
2131 - # now is to sanitize problematic attributes.
2132 - #
2133 - # This kind of sucks. I intend to replace it with
2134 - # lib_filter sometime soon.
2135 - foreach ($this->strip_attrs as $pair):
2136 - list($tag,$attr) = $pair;
2137 - $content = preg_replace (
2138 - ":(<$tag [^>]*)($attr=(\"[^\">]*\"|[^>\\s]+))([^>]*>):i",
2139 - "\\1\\4",
2140 - $content
2141 - );
2142 - endforeach;
1018 + $this->post['post_content'] = apply_filters('syndicated_item_content', $content, $this);
2143 1019
2144 1020 # Identify and sanitize excerpt
2145 1021 $excerpt = NULL;
2146 1022 if ( isset($this->item['description']) and $this->item['description'] ) :
@@ -2150,11 +1026,10 @@
2150 1026 if (strlen($excerpt) > 255) :
2151 1027 $excerpt = substr($excerpt,0,252).'...';
2152 1028 endif;
2153 1029 endif;
1030 + $excerpt = apply_filters('syndicated_item_excerpt', $excerpt, $this);
2154 1031
2155 - $this->post['post_content'] = $content;
2156 -
2157 1032 if (!is_null($excerpt)):
2158 1033 $this->post['post_excerpt'] = $excerpt;
2159 1034 endif;
2160 1035
@@ -2162,11 +1037,11 @@
2162 1037 if (!$this->use_api('wp_insert_post')) :
2163 1038 $this->post['post_name'] = sanitize_title($this->post['post_title']);
2164 1039 endif;
2165 1040
2166 - $this->post['epoch']['issued'] = $this->published();
2167 - $this->post['epoch']['created'] = $this->created();
2168 - $this->post['epoch']['modified'] = $this->updated();
1041 + $this->post['epoch']['issued'] = apply_filters('syndicated_item_published', $this->published(), $this);
1042 + $this->post['epoch']['created'] = apply_filters('syndicated_item_created', $this->created(), $this);
1043 + $this->post['epoch']['modified'] = apply_filters('syndicated_item_updated', $this->updated(), $this);
2169 1044
2170 1045 // Dealing with timestamps in WordPress is so fucking fucked.
2171 1046 $offset = (int) get_option('gmt_offset') * 60 * 60;
2172 1047 $this->post['post_date'] = gmdate('Y-m-d H:i:s', $this->published() + $offset);
@@ -2179,9 +1054,9 @@
2179 1054 $this->post['comment_status'] = $this->link->syndicated_status('comment', 'closed');
2180 1055 $this->post['ping_status'] = $this->link->syndicated_status('ping', 'closed');
2181 1056
2182 1057 // Unique ID (hopefully a unique tag: URI); failing that, the permalink
2183 - $this->post['guid'] = $this->guid();
1058 + $this->post['guid'] = apply_filters('syndicated_item_guid', $this->guid(), $this);
2184 1059
2185 1060 // RSS 2.0 / Atom 1.0 enclosure support
2186 1061 if ( isset($this->item['enclosure#']) ) :
2187 1062 for ($i = 1; $i <= $this->item['enclosure#']; $i++) :
@@ -2186,28 +1061,42 @@
2186 1061 if ( isset($this->item['enclosure#']) ) :
2187 1062 for ($i = 1; $i <= $this->item['enclosure#']; $i++) :
2188 1063 $eid = (($i > 1) ? "#{$id}" : "");
2189 1064 $this->post['meta']['enclosure'][] =
2190 - $this->item["enclosure{$eid}@url"]."\n".
2191 - $this->item["enclosure{$eid}@length"]."\n".
2192 - $this->item["enclosure{$eid}@type"];
1065 + apply_filters('syndicated_item_enclosure_url', $this->item["enclosure{$eid}@url"], $this)."\n".
1066 + apply_filters('syndicated_item_enclosure_length', $this->item["enclosure{$eid}@length"], $this)."\n".
1067 + apply_filters('syndicated_item_enclosure_type', $this->item["enclosure{$eid}@type"], $this);
2193 1068 endfor;
2194 1069 endif;
2195 1070
2196 1071 // In case you want to point back to the blog this was syndicated from
2197 1072 if (isset($this->feed->channel['title'])) :
2198 - $this->post['meta']['syndication_source'] = $this->feed->channel['title'];
1073 + $this->post['meta']['syndication_source'] = apply_filters('syndicated_item_source_title', $this->feed->channel['title'], $this);
2199 1074 endif;
1075 +
2200 1076 if (isset($this->feed->channel['link'])) :
2201 - $this->post['meta']['syndication_source_uri'] = $this->feed->channel['link'];
1077 + $this->post['meta']['syndication_source_uri'] = apply_filters('syndicated_item_source_link', $this->feed->channel['link'], $this);
2202 1078 endif;
2203 1079
1080 + // Make use of atom:source data, if present in an aggregated feed
1081 + if (isset($this->item['source_title'])) :
1082 + $this->post['meta']['syndication_source_original'] = $this->item['source_title'];
1083 + endif;
1084 +
1085 + if (isset($this->item['source_link'])) :
1086 + $this->post['meta']['syndication_source_uri_original'] = $this->item['source_link'];
1087 + endif;
1088 +
1089 + if (isset($this->item['source_id'])) :
1090 + $this->post['meta']['syndication_source_id_original'] = $this->item['source_id'];
1091 + endif;
1092 +
2204 1093 // Store information on human-readable and machine-readable comment URIs
2205 1094 if (isset($this->item['comments'])) :
2206 - $this->post['meta']['rss:comments'] = $this->item['comments'];
1095 + $this->post['meta']['rss:comments'] = apply_filters('syndicated_item_comments', $this->item['comments']);
2207 1096 endif;
2208 1097 if (isset($this->item['wfw']['commentrss'])) :
2209 - $this->post['meta']['wfw:commentRSS'] = $this->item['wfw']['commentrss'];
1098 + $this->post['meta']['wfw:commentRSS'] = apply_filters('syndicated_item_commentrss', $this->item['wfw']['commentrss']);
2210 1099 endif;
2211 1100
2212 1101 // Store information to identify the feed that this came from
2213 1102 $this->post['meta']['syndication_feed'] = $this->feedmeta['link/uri'];
@@ -2212,14 +1101,21 @@
2212 1101 // Store information to identify the feed that this came from
2213 1102 $this->post['meta']['syndication_feed'] = $this->feedmeta['link/uri'];
2214 1103 $this->post['meta']['syndication_feed_id'] = $this->feedmeta['link/id'];
2215 1104
1105 + if (isset($this->item['source_link_self'])) :
1106 + $this->post['meta']['syndication_feed_original'] = $this->item['source_link_self'];
1107 + endif;
1108 +
2216 1109 // In case you want to know the external permalink...
2217 - $this->post['meta']['syndication_permalink'] = $this->item['link'];
1110 + $this->post['meta']['syndication_permalink'] = apply_filters('syndicated_item_link', $this->item['link']);
2218 1111
1112 + // Store a hash of the post content for checking whether something needs to be updated
1113 + $this->post['meta']['syndication_item_hash'] = $this->update_hash();
1114 +
2219 1115 // Feed-by-feed options for author and category creation
2220 1116 $this->post['named']['unfamiliar']['author'] = $this->feedmeta['unfamiliar author'];
2221 - $this->post['named']['unfamiliar']['category'] = $this->feedmeta['unfamiliar categories'];
1117 + $this->post['named']['unfamiliar']['category'] = $this->feedmeta['unfamiliar category'];
2222 1118
2223 1119 // Categories: start with default categories, if any
2224 1120 $fc = get_option("feedwordpress_syndication_cats");
2225 1121 if ($fc) :
@@ -2246,8 +1142,22 @@
2246 1142 $this->post['named']['category'][] = $cat;
2247 1143 endif;
2248 1144 endfor;
2249 1145 endif;
1146 + $this->post['named']['category'] = apply_filters('syndicated_item_categories', $this->post['named']['category'], $this);
1147 +
1148 + // Tags: start with default tags, if any
1149 + $ft = get_option("feedwordpress_syndication_tags");
1150 + if ($ft) :
1151 + $this->post['tags_input'] = explode('FEEDWORDPRESS_CAT_SEPARATOR', $ft);
1152 + else :
1153 + $this->post['tags_input'] = array();
1154 + endif;
1155 +
1156 + if (is_array($this->feedmeta['tags'])) :
1157 + $this->post['tags_input'] = array_merge($this->post['tags_input'], $this->feedmeta['tags']);
1158 + endif;
1159 +
2250 1160 endif;
2251 1161 } // SyndicatedPost::SyndicatedPost()
2252 1162
2253 1163 function filtered () {
@@ -2268,18 +1178,35 @@
2268 1178 SELECT id, guid, post_modified_gmt
2269 1179 FROM $wpdb->posts WHERE guid='$guid'
2270 1180 ");
2271 1181
2272 - preg_match('/([0-9]+)-([0-9]+)-([0-9]+) ([0-9]+):([0-9]+):([0-9]+)/', $result->post_modified_gmt, $backref);
2273 - $updated = gmmktime($backref[4], $backref[5], $backref[6], $backref[2], $backref[3], $backref[1]);
2274 1182 if (!$result) :
2275 1183 $this->_freshness = 2; // New content
2276 - elseif ($this->updated() > $updated) :
2277 - $this->_freshness = 1; // Updated content
2278 - $this->_wp_id = $result->id;
2279 - else :
2280 - $this->_freshness = 0; // Same old, same old
2281 - $this->_wp_id = $result->id;
1184 + else:
1185 + $stored_update_hashes = get_post_custom_values('syndication_item_hash', $result->id);
1186 + if (count($stored_update_hashes) > 0) :
1187 + $stored_update_hash = $stored_update_hashes[0];
1188 + $update_hash_changed = ($stored_update_hash != $this->update_hash());
1189 + else :
1190 + $update_hash_changed = false;
1191 + endif;
1192 +
1193 + preg_match('/([0-9]+)-([0-9]+)-([0-9]+) ([0-9]+):([0-9]+):([0-9]+)/', $result->post_modified_gmt, $backref);
1194 +
1195 + $last_rev_ts = gmmktime($backref[4], $backref[5], $backref[6], $backref[2], $backref[3], $backref[1]);
1196 + $updated_ts = $this->updated(/*fallback=*/ true, /*default=*/ NULL);
1197 + $updated = ((
1198 + !is_null($updated_ts)
1199 + and ($updated_ts > $last_rev_ts)
1200 + ) or $update_hash_changed);
1201 +
1202 + if ($updated) :
1203 + $this->_freshness = 1; // Updated content
1204 + $this->_wp_id = $result->id;
1205 + else :
1206 + $this->_freshness = 0; // Same old, same old
1207 + $this->_wp_id = $result->id;
1208 + endif;
2282 1209 endif;
2283 1210 endif;
2284 1211 return $this->_freshness;
2285 1212 }
@@ -2315,13 +1242,17 @@
2315 1242 endif;
2316 1243
2317 1244 if (!$this->filtered() and $freshness > 0) :
2318 1245 # -- Look up, or create, numeric ID for categories
2319 - $this->post['post_category'] = $this->category_ids (
1246 + list($pcats, $ptags) = $this->category_ids (
2320 1247 $this->post['named']['category'],
2321 - FeedWordPress::on_unfamiliar('category', $this->post['named']['unfamiliar']['category'])
1248 + FeedWordPress::on_unfamiliar('category', $this->post['named']['unfamiliar']['category']),
1249 + /*tags_too=*/ true
2322 1250 );
2323 -
1251 +
1252 + $this->post['post_category'] = $pcats;
1253 + $this->post['tags_input'] = array_merge($this->post['tags_input'], $ptags);
1254 +
2324 1255 if (is_null($this->post['post_category'])) :
2325 1256 // filter mode on, no matching categories; drop the post
2326 1257 $this->post = NULL;
2327 1258 else :
@@ -2377,15 +1308,37 @@
2377 1308 $dbpost[$key] = $value;
2378 1309 endif;
2379 1310 endforeach;
2380 1311
1312 + if (strlen($dbpost['post_title'].$dbpost['post_content'].$dbpost['post_excerpt']) == 0) :
1313 + // FIXME: Option for filtering out empty posts
1314 + endif;
1315 + if (strlen($dbpost['post_title'])==0) :
1316 + $dbpost['post_title'] = $this->post['meta']['syndication_source']
1317 + .' '.gmdate('Y-m-d H:i:s', $this->published() + $offset);
1318 + // FIXME: Option for what to fill a blank title with...
1319 + endif;
1320 +
2381 1321 if ($this->use_api('wp_insert_post')) :
2382 1322 $dbpost['post_pingback'] = false; // Tell WP 2.1 and 2.2 not to process for pingbacks
1323 +
1324 + // This is a ridiculous fucking kludge necessitated by WordPress 2.6 munging authorship meta-data
1325 + add_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1326 +
1327 + // Kludge to prevent kses filters from stripping the
1328 + // content of posts when updating without a logged in
1329 + // user who has `unfiltered_html` capability.
1330 + add_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1331 +
2383 1332 $this->_wp_id = wp_insert_post($dbpost);
2384 -
1333 +
1334 + // Turn off ridiculous fucking kludges #1 and #2
1335 + remove_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1336 + remove_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1337 +
2385 1338 // This should never happen.
2386 1339 if (!is_numeric($this->_wp_id) or ($this->_wp_id == 0)) :
2387 - FeedWordPress::critical_bug('SyndicatedPost (_wp_id problem)', $this, __LINE__);
1340 + FeedWordPress::critical_bug('SyndicatedPost (_wp_id problem)', array("dbpost" => $dbpost, "this" => $this), __LINE__);
2388 1341 endif;
2389 1342
2390 1343 // Unfortunately, as of WordPress 2.3, wp_insert_post()
2391 1344 // *still* offers no way to use a guid of your choice,
@@ -2428,9 +1381,9 @@
2428 1381 $this->_wp_id = $wpdb->insert_id;
2429 1382
2430 1383 // This should never happen.
2431 1384 if (!is_numeric($this->_wp_id) or ($this->_wp_id == 0)) :
2432 - FeedWordPress::critical_bug('SyndicatedPost::_wp_id', $this->_wp_id, __LINE__);
1385 + FeedWordPress::critical_bug('SyndicatedPost (_wp_id problem)', array("dbpost" => $dbpost, "this" => $this), __LINE__);
2433 1386 endif;
2434 1387
2435 1388 // WordPress 1.5.x - 2.0.x
2436 1389 wp_set_post_cats('1', $this->wp_id(), $this->post['post_category']);
@@ -2459,13 +1412,26 @@
2459 1412 endforeach;
2460 1413
2461 1414 if ($this->use_api('wp_insert_post')) :
2462 1415 $dbpost['post_pingback'] = false; // Tell WP 2.1 and 2.2 not to process for pingbacks
1416 +
1417 + // This is a ridiculous fucking kludge necessitated by WordPress 2.6 munging authorship meta-data
1418 + add_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1419 +
1420 + // Kludge to prevent kses filters from stripping the
1421 + // content of posts when updating without a logged in
1422 + // user who has `unfiltered_html` capability.
1423 + add_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1424 +
2463 1425 $this->_wp_id = wp_insert_post($dbpost);
2464 1426
1427 + // Turn off ridiculous fucking kludges #1 and #2
1428 + remove_action('_wp_put_post_revision', array($this, 'fix_revision_meta'));
1429 + remove_filter('content_save_pre', array($this, 'avoid_kses_munge'), 11);
1430 +
2465 1431 // This should never happen.
2466 1432 if (!is_numeric($this->_wp_id) or ($this->_wp_id == 0)) :
2467 - FeedWordPress::critical_bug('SyndicatedPost::_wp_id', $this->_wp_id, __LINE__);
1433 + FeedWordPress::critical_bug('SyndicatedPost (_wp_id problem)', array("dbpost" => $dbpost, "this" => $this), __LINE__);
2468 1434 endif;
2469 1435
2470 1436 // Unfortunately, as of WordPress 2.3, wp_insert_post()
2471 1437 // munges your post modified timestamp.
@@ -2498,9 +1464,9 @@
2498 1464 elseif (function_exists('wp_set_post_cats')) :
2499 1465 wp_set_post_cats('1', $this->wp_id(), $this->post['post_category']);
2500 1466 // This should never happen.
2501 1467 else :
2502 - FeedWordPress::critical_bug('SyndicatedPost::insert_new::wp_version', $GLOBALS['wp_version'], __LINE__);
1468 + FeedWordPress::critical_bug('SyndicatedPost (_wp_id problem)', array("dbpost" => $dbpost, "this" => $this), __LINE__);
2503 1469 endif;
2504 1470
2505 1471 // Since we are not going through official channels, we need to
2506 1472 // manually tell WordPress that we've published a new post.
@@ -2511,8 +1477,63 @@
2511 1477 do_action('edit_post', $this->post['ID']);
2512 1478 endif;
2513 1479 } /* SyndicatedPost::update_existing() */
2514 1480
1481 + /**
1482 + * SyndicatedPost::fix_revision_meta() - Fixes the way WP 2.6+ fucks up
1483 + * meta-data (authorship, etc.) when storing revisions of an updated
1484 + * syndicated post.
1485 + *
1486 + * In their infinite wisdom, the WordPress coders have made it completely
1487 + * impossible for a plugin that uses wp_insert_post() to set certain
1488 + * meta-data (such as the author) when you store an old revision of an
1489 + * updated post. Instead, it uses the WordPress defaults (= currently
1490 + * active user ID if the process is running with a user logged in, or
1491 + * = #0 if there is no user logged in). This results in bogus authorship
1492 + * data for revisions that are syndicated from off the feed, unless we
1493 + * use a ridiculous kludge like this to end-run the munging of meta-data
1494 + * by _wp_put_post_revision.
1495 + *
1496 + * @param int $revision_id The revision ID to fix up meta-data
1497 + */
1498 + function fix_revision_meta ($revision_id) {
1499 + global $wpdb;
1500 +
1501 + $post_author = (int) $this->post['post_author'];
1502 +
1503 + $revision_id = (int) $revision_id;
1504 + $wpdb->query("
1505 + UPDATE $wpdb->posts
1506 + SET post_author={$this->post['post_author']}
1507 + WHERE post_type = 'revision' AND ID='$revision_id'
1508 + ");
1509 + } /* SyndicatedPost::fix_revision_meta () */
1510 +
1511 + /**
1512 + * SyndicatedPost::avoid_kses_munge() -- If FeedWordPress is processing
1513 + * an automatic update, that generally means that wp_insert_post() is
1514 + * being called under the user credentials of whoever is viewing the
1515 + * blog at the time -- usually meaning no user at all. But if WordPress
1516 + * gets a wp_insert_post() when current_user_can('unfiltered_html') is
1517 + * false, it will run the content of the post through a kses function
1518 + * that strips out lots of HTML tags -- notably <object> and some others.
1519 + * This causes problems for syndicating (for example) feeds that contain
1520 + * YouTube videos. It also produces an unexpected asymmetry between
1521 + * automatically-initiated updates and updates initiated manually from
1522 + * the WordPress Dashboard (which are usually initiated under the
1523 + * credentials of a logged-in admin, and so don't get run through the
1524 + * kses function). So, to avoid the whole mess, what we do here is
1525 + * just forcibly disable the kses munging for a single syndicated post,
1526 + * by restoring the contents of the `post_content` field.
1527 + *
1528 + * @param string $content The content of the post, after other filters have gotten to it
1529 + * @return string The original content of the post, before other filters had a chance to munge it.
1530 + */
1531 + function avoid_kses_munge ($content) {
1532 + global $wpdb;
1533 + return $wpdb->escape($this->post['post_content']);
1534 + }
1535 +
2515 1536 // SyndicatedPost::add_rss_meta: adds interesting meta-data to each entry
2516 1537 // using the space for custom keys. The set of keys and values to add is
2517 1538 // specified by the keys and values of $post['meta']. This is used to
2518 1539 // store anything that the WordPress user might want to access from a
@@ -2564,9 +1585,9 @@
2564 1585
2565 1586 // SyndicatedPost::author_id (): get the ID for an author name from
2566 1587 // the feed. Create the author if necessary.
2567 1588 function author_id ($unfamiliar_author = 'create') {
2568 - global $wpdb, $wp_db_version; // test for WordPress 2.0 database schema
1589 + global $wpdb;
2569 1590
2570 1591 $a = $this->author();
2571 1592 $author = $a['name'];
2572 1593 $email = $a['email'];
@@ -2571,8 +1592,15 @@
2571 1592 $author = $a['name'];
2572 1593 $email = $a['email'];
2573 1594 $url = $a['uri'];
2574 1595
1596 + $match_author_by_email = !('yes' == get_option("feedwordpress_do_not_match_author_by_email"));
1597 + if ($match_author_by_email and !FeedWordPress::is_null_email($email)) :
1598 + $test_email = $email;
1599 + else :
1600 + $test_email = NULL;
1601 + endif;
1602 +
2575 1603 // Never can be too careful...
2576 1604 $login = sanitize_user($author, /*strict=*/ true);
2577 1605 $login = apply_filters('pre_user_login', $login);
2578 1606
@@ -2581,8 +1609,9 @@
2581 1609
2582 1610 $reg_author = $wpdb->escape(preg_quote($author));
2583 1611 $author = $wpdb->escape($author);
2584 1612 $email = $wpdb->escape($email);
1613 + $test_email = $wpdb->escape($test_email);
2585 1614 $url = $wpdb->escape($url);
2586 1615
2587 1616 // Check for an existing author rule....
2588 1617 if (isset($this->link->settings['map authors']['name'][strtolower(trim($author))])) :
@@ -2601,34 +1630,10 @@
2601 1630
2602 1631 else :
2603 1632 // Check the database for an existing author record that might fit
2604 1633
2605 - #-- WordPress 1.5.x
2606 - if (!isset($wp_db_version)) :
2607 - $id = $wpdb->get_var(
2608 - "SELECT ID from $wpdb->users
2609 - WHERE
2610 - TRIM(LCASE(user_login)) = TRIM(LCASE('$login')) OR
2611 - (
2612 - LENGTH(TRIM(LCASE(user_email))) > 0
2613 - AND TRIM(LCASE(user_email)) = TRIM(LCASE('$email'))
2614 - ) OR
2615 - TRIM(LCASE(user_firstname)) = TRIM(LCASE('$author')) OR
2616 - TRIM(LCASE(user_nickname)) = TRIM(LCASE('$author')) OR
2617 - TRIM(LCASE(user_nicename)) = TRIM(LCASE('$nice_author')) OR
2618 - TRIM(LCASE(user_description)) = TRIM(LCASE('$author')) OR
2619 - (
2620 - LOWER(user_description)
2621 - RLIKE CONCAT(
2622 - '(^|\\n)a\\.?k\\.?a\\.?( |\\t)*:?( |\\t)*',
2623 - LCASE('$reg_author'),
2624 - '( |\\t|\\r)*(\\n|\$)'
2625 - )
2626 - )
2627 - ");
2628 -
2629 1634 #-- WordPress 2.0+
2630 - elseif ($wp_db_version >= 2966) :
1635 + if (fwp_test_wp_version(FWP_SCHEMA_HAS_USERMETA)) :
2631 1636
2632 1637 // First try the user core data table.
2633 1638 $id = $wpdb->get_var(
2634 1639 "SELECT ID FROM $wpdb->users
@@ -2635,9 +1640,9 @@
2635 1640 WHERE
2636 1641 TRIM(LCASE(user_login)) = TRIM(LCASE('$login'))
2637 1642 OR (
2638 1643 LENGTH(TRIM(LCASE(user_email))) > 0
2639 - AND TRIM(LCASE(user_email)) = TRIM(LCASE('$email'))
1644 + AND TRIM(LCASE(user_email)) = TRIM(LCASE('$test_email'))
2640 1645 )
2641 1646 OR TRIM(LCASE(user_nicename)) = TRIM(LCASE('$nice_author'))
2642 1647 ");
2643 1648
@@ -2657,8 +1662,33 @@
2657 1662 )
2658 1663 )
2659 1664 ");
2660 1665 endif;
1666 +
1667 + #-- WordPress 1.5.x
1668 + else :
1669 + $id = $wpdb->get_var(
1670 + "SELECT ID from $wpdb->users
1671 + WHERE
1672 + TRIM(LCASE(user_login)) = TRIM(LCASE('$login')) OR
1673 + (
1674 + LENGTH(TRIM(LCASE(user_email))) > 0
1675 + AND TRIM(LCASE(user_email)) = TRIM(LCASE('$test_email'))
1676 + ) OR
1677 + TRIM(LCASE(user_firstname)) = TRIM(LCASE('$author')) OR
1678 + TRIM(LCASE(user_nickname)) = TRIM(LCASE('$author')) OR
1679 + TRIM(LCASE(user_nicename)) = TRIM(LCASE('$nice_author')) OR
1680 + TRIM(LCASE(user_description)) = TRIM(LCASE('$author')) OR
1681 + (
1682 + LOWER(user_description)
1683 + RLIKE CONCAT(
1684 + '(^|\\n)a\\.?k\\.?a\\.?( |\\t)*:?( |\\t)*',
1685 + LCASE('$reg_author'),
1686 + '( |\\t|\\r)*(\\n|\$)'
1687 + )
1688 + )
1689 + ");
1690 +
2661 1691 endif;
2662 1692
2663 1693 // ... if you don't find one, then do what you need to do
2664 1694 if (is_null($id)) :
@@ -2689,9 +1719,9 @@
2689 1719 return $id;
2690 1720 } // function SyndicatedPost::author_id ()
2691 1721
2692 1722 // look up (and create) category ids from a list of categories
2693 - function category_ids ($cats, $unfamiliar_category = 'create') {
1723 + function category_ids ($cats, $unfamiliar_category = 'create', $tags_too = false) {
2694 1724 global $wpdb;
2695 1725
2696 1726 // We need to normalize whitespace because (1) trailing
2697 1727 // whitespace can cause PHP and MySQL not to see eye to eye on
@@ -2700,8 +1730,10 @@
2700 1730 // because I doubt most people want to make a semantic
2701 1731 // distinction between 'Computers' and 'Computers '
2702 1732 $cats = array_map('trim', $cats);
2703 1733
1734 + $tags = array();
1735 +
2704 1736 $cat_ids = array ();
2705 1737 foreach ($cats as $cat_name) :
2706 1738 if (preg_match('/^{#([0-9]+)}$/', $cat_name, $backref)) :
2707 1739 $cat_id = (int) $backref[1];
@@ -2729,8 +1761,10 @@
2729 1761 )) :
2730 1762 foreach ($results AS $term) :
2731 1763 $cat_ids[] = (int) $term->term_id;
2732 1764 endforeach;
1765 + elseif ('tag'==$unfamiliar_category) :
1766 + $tags[] = $cat_name;
2733 1767 elseif ('create'===$unfamiliar_category) :
2734 1768 $term = wp_insert_term($cat_name, 'category');
2735 1769 $cat_ids[] = $term['term_id'];
2736 1770 endif;
@@ -2774,18 +1808,28 @@
2774 1808 $cat_ids = NULL; // Drop the post
2775 1809 else :
2776 1810 $cat_ids = array_unique($cat_ids);
2777 1811 endif;
2778 - return $cat_ids;
1812 +
1813 + if ($tags_too) : $ret = array($cat_ids, $tags);
1814 + else : $ret = $cat_ids;
1815 + endif;
1816 +
1817 + return $ret;
2779 1818 } // function SyndicatedPost::category_ids ()
2780 1819
2781 1820 function use_api ($tag) {
2782 1821 global $wp_db_version;
2783 - if ('wp_insert_post'==$tag) :
1822 + switch ($tag) :
1823 + case 'wp_insert_post':
2784 1824 // Before 2.2, wp_insert_post does too much of the wrong stuff to use it
2785 1825 // In 1.5 it was such a resource hog it would make PHP segfault on big updates
2786 1826 $ret = (isset($wp_db_version) and $wp_db_version > FWP_SCHEMA_21);
2787 - endif;
1827 + break;
1828 + case 'post_status_pending':
1829 + $ret = (isset($wp_db_version) and $wp_db_version > FWP_SCHEMA_23);
1830 + break;
1831 + endswitch;
2788 1832 return $ret;
2789 1833 } // function SyndicatedPost::use_api ()
2790 1834
2791 1835 #### EXTRACT DATA FROM FEED ITEM ####
@@ -2823,14 +1867,18 @@
2823 1867 endif;
2824 1868
2825 1869 # If everything failed, then default to the current time.
2826 1870 if (is_null($epoch)) :
2827 - $epoch = time();
1871 + if (-1 == $default) :
1872 + $epoch = time();
1873 + else :
1874 + $epoch = $default;
1875 + endif;
2828 1876 endif;
2829 1877
2830 1878 return $epoch;
2831 1879 }
2832 - function updated ($fallback = true) {
1880 + function updated ($fallback = true, $default = -1) {
2833 1881 $epoch = null;
2834 1882
2835 1883 # As far as I know, only dcterms and Atom have reliable ways to
2836 1884 # specify when something was *modified* last. If neither is
@@ -2843,19 +1891,27 @@
2843 1891 $epoch = @parse_w3cdtf($this->item['modified']);
2844 1892 elseif (isset($this->item['updated'])): // Atom 1.0
2845 1893 $epoch = @parse_w3cdtf($this->item['updated']);
2846 1894 elseif ($fallback) : // Fall back to issued / dc:date
2847 - $epoch = $this->published(/*fallback=*/ false);
1895 + $epoch = $this->published(/*fallback=*/ false, /*default=*/ $default);
2848 1896 endif;
2849 1897
2850 1898 # If everything failed, then default to the current time.
2851 1899 if (is_null($epoch)) :
2852 - $epoch = time();
1900 + if (-1 == $default) :
1901 + $epoch = time();
1902 + else :
1903 + $epoch = $default;
1904 + endif;
2853 1905 endif;
2854 1906
2855 1907 return $epoch;
2856 1908 }
2857 1909
1910 + function update_hash () {
1911 + return md5(serialize($this->item));
1912 + }
1913 +
2858 1914 function guid () {
2859 1915 $guid = null;
2860 1916 if (isset($this->item['id'])): // Atom 0.3 / 1.0
2861 1917 $guid = $this->item['id'];
@@ -2942,8 +1998,31 @@
2942 1998 endif;
2943 1999
2944 2000 return $author;
2945 2001 } // SyndicatedPost::author()
2002 +
2003 + var $strip_attrs = array (
2004 + array('[a-z]+', 'style'),
2005 + array('[a-z]+', 'target'),
2006 + );
2007 + function sanitize_content ($content, $obj) {
2008 + # FeedWordPress used to resolve URIs relative to the
2009 + # feed URI. It now relies on the xml:base support
2010 + # baked in to the MagpieRSS upgrade. So all we do here
2011 + # now is to sanitize problematic attributes.
2012 + #
2013 + # This kind of sucks. I intend to replace it with
2014 + # lib_filter sometime soon.
2015 + foreach ($obj->strip_attrs as $pair):
2016 + list($tag,$attr) = $pair;
2017 + $content = preg_replace (
2018 + ":(<$tag [^>]*)($attr=(\"[^\">]*\"|[^>\\s]+))([^>]*>):i",
2019 + "\\1\\4",
2020 + $content
2021 + );
2022 + endforeach;
2023 + return $content;
2024 + }
2946 2025 } // class SyndicatedPost
2947 2026
2948 2027 # class SyndicatedLink: represents a syndication feed stored within the
2949 2028 # WordPress database
@@ -3021,18 +2100,26 @@
3021 2100 $this->settings['link/uri'] = $this->link->link_rss;
3022 2101 $this->settings['link/name'] = $this->link->link_name;
3023 2102 $this->settings['link/id'] = $this->link->link_id;
3024 2103
3025 - // `hardcode categories` is deprecated in favor of `unfamiliar categories`
2104 + // `hardcode categories` and `unfamiliar categories` are deprecated in favor of `unfamiliar category`
3026 2105 if (
2106 + isset($this->settings['unfamiliar categories'])
2107 + and !isset($this->settings['unfamiliar category'])
2108 + ) :
2109 + $this->settings['unfamiliar category'] = $this->settings['unfamiliar categories'];
2110 + endif;
2111 + if (
3027 2112 FeedWordPress::affirmative($this->settings, 'hardcode categories')
3028 - and !isset($this->settings['unfamiliar categories'])
2113 + and !isset($this->settings['unfamiliar category'])
3029 2114 ) :
3030 - $this->settings['unfamiliar categories'] = 'default';
2115 + $this->settings['unfamiliar category'] = 'default';
3031 2116 endif;
3032 -
2117 +
3033 2118 // Set this up automagically for del.icio.us
3034 - if (!isset($this->settings['cat_split']) and false !== strpos($this->link->link_rss, 'del.icio.us')) :
2119 + $bits = parse_url($this->link->link_rss);
2120 + $tagspacers = array('del.icio.us', 'feeds.delicious.com');
2121 + if (!isset($this->settings['cat_split']) and in_array($bits['host'], $tagspacers)) :
3035 2122 $this->settings['cat_split'] = '\s'; // Whitespace separates multiple tags in del.icio.us RSS feeds
3036 2123 endif;
3037 2124
3038 2125 if (isset($this->settings['cats'])):
@@ -3037,8 +2124,11 @@
3037 2124
3038 2125 if (isset($this->settings['cats'])):
3039 2126 $this->settings['cats'] = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, $this->settings['cats']);
3040 2127 endif;
2128 + if (isset($this->settings['tags'])):
2129 + $this->settings['tags'] = preg_split(FEEDWORDPRESS_CAT_SEPARATOR_PATTERN, $this->settings['tags']);
2130 + endif;
3041 2131
3042 2132 if (isset($this->settings['map authors'])) :
3043 2133 $author_rules = explode("\n\n", $this->settings['map authors']);
3044 2134 $ma = array();
@@ -3054,13 +2144,13 @@
3054 2144 endforeach;
3055 2145 $this->settings['map authors'] = $ma;
3056 2146 endif;
3057 2147 endif;
3058 - } // SyndicatedLink::SyndicatedLink ()
2148 + } /* SyndicatedLink::SyndicatedLink () */
3059 2149
3060 2150 function found () {
3061 2151 return is_object($this->link);
3062 - }
2152 + } /* SyndicatedLink::found () */
3063 2153
3064 2154 function stale () {
3065 2155 $stale = true;
3066 2156 if (isset($this->settings['update/hold']) and ($this->settings['update/hold']=='ping')) :
@@ -3074,16 +2164,25 @@
3074 2164 +((int) $this->settings['update/ttl'] * 60);
3075 2165 $stale = (time() >= $after);
3076 2166 endif;
3077 2167 return $stale;
3078 - }
2168 + } /* SyndicatedLink::stale () */
3079 2169
3080 - function poll () {
2170 + function poll ($crash_ts = NULL) {
3081 2171 global $wpdb;
3082 2172
3083 2173 $this->magpie = fetch_rss($this->link->link_rss);
3084 2174 $new_count = NULL;
3085 2175
2176 + $resume = FeedWordPress::affirmative($this->settings, 'update/unfinished');
2177 + if ($resume) :
2178 + // pick up where we left off
2179 + $processed = array_map('trim', explode("\n", $this->settings['update/processed']));
2180 + else :
2181 + // begin at the beginning
2182 + $processed = array();
2183 + endif;
2184 +
3086 2185 if (is_object($this->magpie)) :
3087 2186 $new_count = array('new' => 0, 'updated' => 0);
3088 2187
3089 2188 # -- Update Link metadata live from feed
@@ -3119,40 +2218,17 @@
3119 2218 else :
3120 2219 $this->settings['update/ttl'] = rand(30, 120); // spread over time interval for staggered updates
3121 2220 $this->settings['update/timed'] = 'automatically';
3122 2221 endif;
3123 -
2222 +
3124 2223 if (!isset($this->settings['update/hold']) or $this->settings['update/hold']!='ping') :
3125 2224 $this->settings['update/hold'] = 'scheduled';
3126 2225 endif;
3127 -
3128 - // Copy back without a few things that we don't want to save in the notes
3129 - $to_notes = $this->settings;
3130 2226
3131 - if (is_array($to_notes['cats'])) :
3132 - $to_notes['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['cats']);
3133 - endif;
2227 + $this->settings['update/unfinished'] = 'yes';
3134 2228
3135 - if (isset($to_notes['map authors'])) :
3136 - $ma = array();
3137 - foreach ($to_notes['map authors'] as $rule_type => $author_rules) :
3138 - foreach ($author_rules as $author_name => $author_action) :
3139 - $ma[] = $rule_type."\n".$author_name."\n".$author_action;
3140 - endforeach;
3141 - endforeach;
3142 - $to_notes['map authors'] = implode("\n\n", $ma);
3143 - endif;
2229 + $update[] = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
3144 2230
3145 - unset($to_notes['link/id']); unset($to_notes['link/uri']);
3146 - unset($to_notes['link/name']);
3147 - unset($to_notes['hardcode categories']); // Deprecated
3148 -
3149 - $notes = '';
3150 - foreach ($to_notes as $key => $value) :
3151 - $notes .= $key . ": ". addcslashes($value, "\0..\37".'\\') . "\n";
3152 - endforeach;
3153 - $update[] = "link_notes = '".$wpdb->escape($notes)."'";
3154 -
3155 2231 $update_set = implode(',', $update);
3156 2232
3157 2233 // Update the properties of the link from the feed information
3158 2234 $result = $wpdb->query("
@@ -3161,14 +2237,24 @@
3161 2237 WHERE link_id='$this->id'
3162 2238 ");
3163 2239
3164 2240 # -- Add new posts from feed and update any updated posts
2241 + $crashed = false;
2242 +
3165 2243 if (is_array($this->magpie->items)) :
3166 2244 foreach ($this->magpie->items as $item) :
3167 2245 $post =& new SyndicatedPost($item, $this);
3168 - if (!$post->filtered()) :
3169 - $new = $post->store();
3170 - if ( $new !== false ) $new_count[$new]++;
2246 + if (!$resume or !in_array(trim($post->guid()), $processed)) :
2247 + $processed[] = $post->guid();
2248 + if (!$post->filtered()) :
2249 + $new = $post->store();
2250 + if ( $new !== false ) $new_count[$new]++;
2251 + endif;
2252 +
2253 + if (!is_null($crash_ts) and (time() > $crash_ts)) :
2254 + $crashed = true;
2255 + break;
2256 + endif;
3171 2257 endif;
3172 2258 endforeach;
3173 2259 endif;
3174 2260
@@ -3174,49 +2260,102 @@
3174 2260
3175 2261 // Copy back any changes to feed settings made in the course of updating (e.g. new author rules)
3176 2262 $to_notes = $this->settings;
3177 2263
3178 - if (is_array($to_notes['cats'])) :
3179 - $to_notes['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['cats']);
2264 + $this->settings['update/processed'] = $processed;
2265 + if (!$crashed) :
2266 + $this->settings['update/unfinished'] = 'no';
3180 2267 endif;
3181 2268
3182 - if (isset($to_notes['map authors'])) :
3183 - $ma = array();
3184 - foreach ($to_notes['map authors'] as $rule_type => $author_rules) :
3185 - foreach ($author_rules as $author_name => $author_action) :
3186 - $ma[] = $rule_type."\n".$author_name."\n".$author_action;
3187 - endforeach;
3188 - endforeach;
3189 - $to_notes['map authors'] = implode("\n\n", $ma);
3190 - endif;
3191 -
3192 - unset($to_notes['link/id']); unset($to_notes['link/uri']);
3193 - unset($to_notes['link/name']);
3194 - unset($to_notes['hardcode categories']); // Deprecated
3195 -
3196 - $notes = '';
3197 - foreach ($to_notes as $key => $value) :
3198 - $notes .= $key . ": ". addcslashes($value, "\0..\37".'\\') . "\n";
3199 - endforeach;
3200 -
3201 - $update_set = "link_notes = '".$wpdb->escape($notes)."'";
2269 + $update_set = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
3202 2270
3203 2271 // Update the properties of the link from the feed information
3204 2272 $result = $wpdb->query("
3205 - UPDATE $wpdb->links
3206 - SET $update_set
3207 - WHERE link_id='$this->id'
2273 + UPDATE $wpdb->links
2274 + SET $update_set
2275 + WHERE link_id='$this->id'
3208 2276 ");
3209 2277 endif;
2278 +
3210 2279 return $new_count;
3211 2280 } /* SyndicatedLink::poll() */
3212 -
2281 +
2282 + function map_name_to_new_user ($name, $newuser_name) {
2283 + global $wpdb;
2284 +
2285 + if (strlen($newuser_name) > 0) :
2286 + $userdata = array();
2287 + $userdata['ID'] = NULL;
2288 +
2289 + $userdata['user_login'] = sanitize_user($newuser_name);
2290 + $userdata['user_login'] = apply_filters('pre_user_login', $userdata['user_login']);
2291 +
2292 + $userdata['user_nicename'] = sanitize_title($newuser_name);
2293 + $userdata['user_nicename'] = apply_filters('pre_user_nicename', $userdata['user_nicename']);
2294 +
2295 + $userdata['display_name'] = $wpdb->escape($newuser_name);
2296 +
2297 + $newuser_id = wp_insert_user($userdata);
2298 + if (is_numeric($newuser_id)) :
2299 + if (is_null($name)) : // Unfamiliar author
2300 + $this->settings['unfamiliar author'] = $newuser_id;
2301 + else :
2302 + $this->settings['map authors']['name'][$name] = $newuser_id;
2303 + endif;
2304 + else :
2305 + // TODO: Add some error detection and reporting
2306 + endif;
2307 + else :
2308 + // TODO: Add some error reporting
2309 + endif;
2310 + } /* SyndicatedLink::map_name_to_new_user () */
2311 +
2312 + function settings_to_notes () {
2313 + $to_notes = $this->settings;
2314 +
2315 + unset($to_notes['link/id']); // Magic setting; don't save
2316 + unset($to_notes['link/uri']); // Magic setting; don't save
2317 + unset($to_notes['link/name']); // Magic setting; don't save
2318 + unset($to_notes['hardcode categories']); // Deprecated
2319 + unset($to_notes['unfamiliar categories']); // Deprecated
2320 +
2321 + // Collapse array settings
2322 + if (isset($to_notes['update/processed']) and (is_array($to_notes['update/processed']))) :
2323 + $to_notes['update/processed'] = implode("\n", $to_notes['update/processed']);
2324 + endif;
2325 +
2326 + if (is_array($to_notes['cats'])) :
2327 + $to_notes['cats'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['cats']);
2328 + endif;
2329 + if (is_array($to_notes['tags'])) :
2330 + $to_notes['tags'] = implode(FEEDWORDPRESS_CAT_SEPARATOR, $to_notes['tags']);
2331 + endif;
2332 +
2333 + // Collapse the author mapping rule structure back into a flat string
2334 + if (isset($to_notes['map authors'])) :
2335 + $ma = array();
2336 + foreach ($to_notes['map authors'] as $rule_type => $author_rules) :
2337 + foreach ($author_rules as $author_name => $author_action) :
2338 + $ma[] = $rule_type."\n".$author_name."\n".$author_action;
2339 + endforeach;
2340 + endforeach;
2341 + $to_notes['map authors'] = implode("\n\n", $ma);
2342 + endif;
2343 +
2344 + $notes = '';
2345 + foreach ($to_notes as $key => $value) :
2346 + $notes .= $key . ": ". addcslashes($value, "\0..\37".'\\') . "\n";
2347 + endforeach;
2348 + return $notes;
2349 + } /* SyndicatedLink::settings_to_notes () */
2350 +
3213 2351 function uri () {
3214 2352 return (is_object($this->link) ? $this->link->link_rss : NULL);
3215 - }
2353 + } /* SyndicatedLink::uri () */
2354 +
3216 2355 function homepage () {
3217 2356 return (isset($this->settings['feed/link']) ? $this->settings['feed/link'] : NULL);
3218 - }
2357 + } /* SyndicatedLink::homepage () */
3219 2358
3220 2359 function ttl () {
3221 2360 if (is_object($this->magpie)) :
3222 2361 $channel = $this->magpie->channel;
@@ -3283,9 +2422,9 @@
3283 2422 endif;
3284 2423 endforeach;
3285 2424 endif;
3286 2425 return $ret;
3287 - } // function SyndicatedLink::flatten_array ()
2426 + } /* SyndicatedLink::flatten_array () */
3288 2427
3289 2428 function hardcode ($what) {
3290 2429 $default = get_option("feedwordpress_hardcode_$what");
3291 2430 if ( $default === 'yes' ) :
@@ -3299,9 +2438,9 @@
3299 2438 // setting is explicitly "yes"
3300 2439 $ret = FeedWordPress::affirmative($this->settings, "hardcode $what");
3301 2440 endif;
3302 2441 return $ret;
3303 - } // function SyndicatedLink::hardcode ()
2442 + } /* SyndicatedLink::hardcode () */
3304 2443
3305 2444 function syndicated_status ($what, $default) {
3306 2445 global $wpdb;
3307 2446
@@ -3311,9 +2450,9 @@
3311 2450 elseif (!$ret) :
3312 2451 $ret = $default;
3313 2452 endif;
3314 2453 return $wpdb->escape(trim(strtolower($ret)));
3315 - } // function SyndicatedLink:syndicated_status ()
2454 + } /* SyndicatedLink:syndicated_status () */
3316 2455 } // class SyndicatedLink
3317 2456
3318 2457 ################################################################################
3319 2458 ## XML-RPC HOOKS: accept XML-RPC update pings from Contributors ################
@@ -3701,5 +2840,5 @@
3701 2840 $ret['name'] = NULL; $ret['email'] = NULL;
3702 2841 endif;
3703 2842 return $ret;
3704 2843 }
3705 -?>
2844 +