Permalink
Browse files

Framework for processing Atom tombstones and framework for post expir…

…ation. Commissioned by Ellissa Nagle.
  • Loading branch information...
1 parent 69278b5 commit 09684f02acde999561b6e627b825b770c3bad27a Charles Johnson committed Aug 10, 2012
Showing with 260 additions and 51 deletions.
  1. +52 −3 feeds-page.php
  2. +39 −3 feedwordpress.php
  3. +76 −0 syndicatedlink.class.php
  4. +78 −43 syndicatedpost.class.php
  5. +15 −2 syndicationdataqueries.class.php
View
@@ -111,7 +111,7 @@ function display () {
'global_feeds_box' => __('Update Scheduling'),
'updated_posts_box' => __('Updated Posts'),
'custom_settings_box' => __('Custom Feed Settings (for use in templates)'),
- 'fetch_settings_box' => __('Settings for Fetching Feeds (Advanced)'),
+ 'advanced_settings_box' => __('Advanced Settings'),
);
if ($this->for_default_settings()) :
unset($this->boxes_by_methods['custom_settings_box']);
@@ -363,7 +363,13 @@ function fetch_timeout_setting_value ($setting, $defaulted, $params) {
print number_format(intval($setting)) . " " . (($setting==1) ? "second" : "seconds");
}
- function fetch_settings_box ($page, $box = NULL) {
+ function advanced_settings_box ($page, $box = NULL) {
+ ?>
+ <table class="edit-form">
+ <tr>
+ <th>Fetch Timeout:</th>
+ <td>
+ <?php
$this->setting_radio_control(
'fetch timeout', 'fetch_timeout',
array(&$this, 'fetch_timeout_setting'),
@@ -374,7 +380,42 @@ function fetch_settings_box ($page, $box = NULL) {
'labels' => array(&$this, 'fetch_timeout_setting_value'),
)
);
- } /* FeedWordPressFeedsPage::fetch_settings_box () */
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <th>Feed Update Type:</th>
+ <td><?php
+ $this->setting_radio_control('update_incremental', 'update_incremental',
+ /*options=*/ array(
+ 'incremental' => '<strong>Incremental.</strong> When items no longer appear on the feed, keep them in the WordPress posts table.',
+ 'complete' => '<strong>Complete.</strong> When items no longer appear on the feed, they are obsolete; retire them from the WordPress posts table.',
+ ),
+ /*params=*/ array(
+ 'setting-default' => NULL,
+ 'global-setting-default' => 'incremental',
+ 'default-input-value' => 'default',
+ )
+ ); ?></td>
+ </tr>
+ <tr>
+ <th>Allow Feeds to Delete Posts:</th>
+ <td><?php
+ $this->setting_radio_control('tombstones', 'tombstones',
+ /*options=*/ array(
+ 'yes' => 'Yes. If a feed indicates that one of its posts has been deleted, delete the local copy syndicated to this website.',
+ 'no' => 'No. Even if a feed indicates that one of its posts has been deleted, retain the local copy on this website.',
+ ),
+ /*params=*/ array(
+ 'setting-default' => NULL,
+ 'global-setting-default' => 'yes',
+ 'default-input-value' => 'default',
+ )
+ ); ?></td>
+ </tr>
+ </table>
+ <?php
+ } /* FeedWordPressFeedsPage::advanced_settings_box () */
function display_authentication_credentials_box ($params = array()) {
static $count = 0;
@@ -1175,6 +1216,14 @@ function save_settings ($post) {
endif;
$this->update_setting('fetch timeout', $timeout);
endif;
+
+ if (isset($post['update_incremental'])) :
+ $this->update_setting('update_incremental', $post['update_incremental']);
+ endif;
+
+ if (isset($post['tombstones'])) :
+ $this->update_setting('tombstones', $post['tombstones']);
+ endif;
if (isset($post['update_minimum'])) :
$this->update_setting('update/minimum', $post['update_minimum']);
View
@@ -3,15 +3,15 @@
Plugin Name: FeedWordPress
Plugin URI: http://feedwordpress.radgeek.com/
Description: simple and flexible Atom/RSS syndication for WordPress
-Version: 2012.0720
+Version: 2012.0810
Author: Charles Johnson
Author URI: http://radgeek.com/
License: GPL
*/
/**
* @package FeedWordPress
- * @version 2012.0720
+ * @version 2012.0810
*/
# This uses code derived from:
@@ -34,7 +34,7 @@
# -- Don't change these unless you know what you're doing...
-define ('FEEDWORDPRESS_VERSION', '2012.0720');
+define ('FEEDWORDPRESS_VERSION', '2012.0810');
define ('FEEDWORDPRESS_AUTHOR_CONTACT', 'http://radgeek.com/contact');
if (!defined('FEEDWORDPRESS_BLEG')) :
@@ -54,6 +54,8 @@
endif;
endif;
define ('FEEDWORDPRESS_DEBUG', $feedwordpress_debug);
+$feedwordpress_compatibility = true;
+define ('FEEDWORDPRESS_COMPATIBILITY', $feedwordpress_compatibility);
define ('FEEDWORDPRESS_CAT_SEPARATOR_PATTERN', '/[:\n]/');
define ('FEEDWORDPRESS_CAT_SEPARATOR', "\n");
@@ -1213,10 +1215,44 @@ function init () {
endif;*/
endif;
+ // This is a special post status for hiding posts that have expired
+ register_post_status('fwpretired', array(
+ 'label' => _x('Retired', 'post'),
+ 'label_count' => _n_noop('Retired <span class="count">(%s)</span>', 'Retired <span class="count">(%s)</span>'),
+ 'exclude_from_search' => true,
+ 'public' => false,
+ 'publicly_queryable' => false,
+ 'show_in_admin_all_list' => false,
+ 'show_in_admin_status_list' => true,
+ ));
+ add_action(
+ /*hook=*/ 'template_redirect',
+ /*function=*/ array(&$this, 'redirect_retired'),
+ /*priority=*/ -100
+ );
+
$this->clear_cache_magic_url();
$this->update_magic_url();
} /* FeedWordPress::init() */
+ function redirect_retired () {
+ global $wp_query;
+ if (is_singular()) :
+ if ('fwpretired'==$wp_query->post->post_status) :
+ do_action('feedwordpress_redirect_retired', $wp_query->post);
+
+ if (!($template = get_404_template())) :
+ $template = get_index_template();
+ endif;
+ if ($template = apply_filters('template_include', $template)) :
+ header("HTTP/1.1 410 Gone");
+ include($template);
+ endif;
+ exit;
+ endif;
+ endif;
+ }
+
function dashboard_setup () {
$see_it = FeedWordPress::menu_cap();
@@ -57,6 +57,8 @@ function SyndicatedLink ($link) {
if (strlen($this->link->link_rss) > 0) :
$this->get_settings_from_notes();
endif;
+
+ add_filter('feedwordpress_update_complete', array(&$this, 'process_retirements'), 1000, 1);
} /* SyndicatedLink::SyndicatedLink () */
function found () {
@@ -236,6 +238,21 @@ function poll ($crash_ts = NULL) {
$this->magpie->originals = $posts;
+ // If this is a complete feed, rather than an incremental feed, we
+ // need to prepare to mark everything for presumptive retirement.
+ if ($this->is_incremental()) :
+ $q = new WP_Query(array(
+ 'fields' => '_synfrom',
+ 'post_status__not' => 'fwpretired',
+ 'ignore_sticky_posts' => true,
+ 'meta_key' => 'syndication_feed_id',
+ 'meta_value' => $this->id,
+ ));
+ foreach ($q->posts as $p) :
+ update_post_meta($p->ID, '_feedwordpress_retire_me_'.$this->id, '1');
+ endforeach;
+ endif;
+
if (is_array($posts)) :
foreach ($posts as $key => $item) :
$post = new SyndicatedPost($item, $this);
@@ -255,6 +272,39 @@ function poll ($crash_ts = NULL) {
unset($post);
endforeach;
endif;
+
+ if ('yes'==$this->setting('tombstones', 'tombstones', 'yes')) :
+ // Check for use of Atom tombstones. Spec:
+ // <http://tools.ietf.org/html/draft-snell-atompub-tombstones-18>
+ $tombstones = $this->simplepie->get_feed_tags('http://purl.org/atompub/tombstones/1.0', 'deleted-entry');
+ if (count($tombstones) > 0) :
+ foreach ($tombstones as $tombstone) :
+ $ref = NULL;
+ foreach (array('', 'http://purl.org/atompub/tombstones/1.0') as $ns) :
+ if (isset($tombstone['attribs'][$ns])
+ and isset($tombstone['attribs'][$ns]['ref'])) :
+ $ref = $tombstone['attribs'][$ns]['ref'];
+ endif;
+ endforeach;
+
+ $q = new WP_Query(array(
+ 'ignore_sticky_posts' => true,
+ 'guid' => $ref,
+ 'meta_key' => 'syndication_feed_id',
+ 'meta_value' => $this->id, // Only allow a feed to tombstone its own entries.
+ ));
+
+ foreach ($q->posts as $p) :
+ $old_status = $p->post_status;
+ FeedWordPress::diagnostic('syndicated_posts', 'Retiring existing post # '.$p->ID.' "'.$p->post_title.'" due to Atom tombstone element in feed.');
+ set_post_field('post_status', 'fwpretired', $p->ID);
+ wp_transition_post_status('fwpretired', $old_status, $p);
+ endforeach;
+
+ endforeach;
+ endif;
+ endif;
+
$suffix = ($crashed ? 'crashed' : 'completed');
do_action('update_syndicated_feed_items', $this->id, $this);
do_action("update_syndicated_feed_items_${suffix}", $this->id, $this);
@@ -292,6 +342,28 @@ function poll ($crash_ts = NULL) {
return $new_count;
} /* SyndicatedLink::poll() */
+ function process_retirements ($delta) {
+ global $post;
+
+ $q = new WP_Query(array(
+ 'fields' => '_synfrom',
+ 'post_status__not' => 'fwpretired',
+ 'ignore_sticky_posts' => true,
+ 'meta_key' => '_feedwordpress_retire_me_'.$this->id,
+ 'meta_value' => '1',
+ ));
+ if ($q->have_posts()) :
+ foreach ($q->posts as $p) :
+ $old_status = $p->post_status;
+ FeedWordPress::diagnostic('syndicated_posts', 'Retiring existing post # '.$p->ID.' "'.$p->post_title.'" due to absence from a non-incremental feed.');
+ set_post_field('post_status', 'fwpretired', $p->ID);
+ wp_transition_post_status('fwpretired', $old_status, $p);
+ delete_post_meta($p->ID, '_feedwordpress_retire_me_'.$this->id);
+ endforeach;
+ endif;
+ return $delta;
+ }
+
/**
* Updates the URL for the feed syndicated by this link.
*
@@ -616,6 +688,10 @@ function update_setting ($name, $value, $default = 'default') {
endif;
} /* SyndicatedLink::update_setting () */
+ function is_incremental () {
+ return ('complete'==$this->setting('update_incremental', 'update_incremental', 'incremental'));
+ } /* SyndicatedLink::is_incremental () */
+
function uri ($params = array()) {
$params = wp_parse_args($params, array(
'add_params' => false,
Oops, something went wrong.

0 comments on commit 09684f0

Please sign in to comment.