function poll ($crash_ts = NULL) {
global $wpdb;
$url = $this->uri(array('add_params' => true));
FeedWordPress::diagnostic('updated_feeds', 'Polling feed ['.$url.']');
$timeout = $this->setting('fetch timeout', 'feedwordpress_fetch_timeout', FEEDWORDPRESS_FETCH_TIMEOUT_DEFAULT);
$this->simplepie = apply_filters(
'syndicated_feed',
FeedWordPress::fetch($this, array('timeout' => $timeout)),
$this
);
// Filter compatibility mode
if (is_wp_error($this->simplepie)) :
$this->magpie = $this->simplepie;
else :
$this->magpie = new MagpieFromSimplePie($this->simplepie, NULL);
endif;
$new_count = NULL;
$resume = ('yes'==$this->setting('update/unfinished'));
if ($resume) :
// pick up where we left off
$processed = array_map('trim', explode("\n", $this->setting('update/processed')));
else :
// begin at the beginning
$processed = array();
endif;
if (is_wp_error($this->simplepie)) :
$new_count = $this->simplepie;
// Error; establish an error setting.
$theError = array();
$theError['ts'] = time();
$theError['since'] = time();
$theError['object'] = $this->simplepie;
$oldError = $this->setting('update/error', NULL, NULL);
if (is_string($oldError)) :
$oldError = unserialize($oldError);
endif;
if (!is_null($oldError)) :
// Copy over the in-error-since timestamp
$theError['since'] = $oldError['since'];
// If this is a repeat error, then we should
// take a step back before we try to fetch it
// again.
$this->update_setting('update/last', time(), NULL);
$ttl = $this->automatic_ttl();
$ttl = apply_filters('syndicated_feed_ttl', $ttl, $this);
$ttl = apply_filters('syndicated_feed_ttl_from_error', $ttl, $this);
$this->update_setting('update/ttl', $ttl, $this);
$this->update_setting('update/timed', 'automatically');
endif;
do_action('syndicated_feed_error', $theError, $oldError, $this);
$this->update_setting('update/error', serialize($theError));
$this->save_settings(/*reload=*/ true);
elseif (is_object($this->simplepie)) :
// Success; clear out error setting, if any.
$this->update_setting('update/error', NULL);
$new_count = array('new' => 0, 'updated' => 0);
# -- Update Link metadata live from feed
$channel = $this->magpie->channel;
if (!isset($channel['id'])) :
$channel['id'] = $this->link->link_rss;
endif;
$update = array();
if (!$this->hardcode('url') and isset($channel['link'])) :
$update[] = "link_url = '".$wpdb->escape($channel['link'])."'";
endif;
if (!$this->hardcode('name') and isset($channel['title'])) :
$update[] = "link_name = '".$wpdb->escape($channel['title'])."'";
endif;
if (!$this->hardcode('description')) :
if (isset($channel['tagline'])) :
$update[] = "link_description = '".$wpdb->escape($channel['tagline'])."'";
elseif (isset($channel['description'])) :
$update[] = "link_description = '".$wpdb->escape($channel['description'])."'";
endif;
endif;
$this->merge_settings($channel, 'feed/');
$this->update_setting('update/last', time());
list($ttl, $xml) = $this->ttl(/*return element=*/ true);
if (!is_null($ttl)) :
$this->update_setting('update/ttl', $ttl);
$this->update_setting('update/xml', $xml);
$this->update_setting('update/timed', 'feed');
else :
$ttl = $this->automatic_ttl();
$this->update_setting('update/ttl', $ttl);
$this->update_setting('update/xml', NULL);
$this->update_setting('update/timed', 'automatically');
endif;
$this->update_setting('update/fudge', rand(0, ($ttl/3))*60);
$this->update_setting('update/ttl', apply_filters(
'syndicated_feed_ttl',
$this->setting('update/ttl'),
$this
));
if (!$this->setting('update/hold') != 'ping') :
$this->update_setting('update/hold', 'scheduled');
endif;
$this->update_setting('update/unfinished', 'yes');
$update[] = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
$update_set = implode(',', $update);
// Update the properties of the link from the feed information
$result = $wpdb->query("
UPDATE $wpdb->links
SET $update_set
WHERE link_id='$this->id'
");
do_action('update_syndicated_feed', $this->id, $this);
# -- Add new posts from feed and update any updated posts
$crashed = false;
$posts = apply_filters(
'syndicated_feed_items',
$this->simplepie->get_items(),
$this
);
$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);
if (!$resume or !in_array(trim($post->guid()), $processed)) :
$processed[] = $post->guid();
if (!$post->filtered()) :
$new = $post->store();
if ( $new !== false ) $new_count[$new]++;
endif;
if (!is_null($crash_ts) and (time() > $crash_ts)) :
$crashed = true;
break;
endif;
endif;
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);
$this->update_setting('update/processed', $processed);
if (!$crashed) :
$this->update_setting('update/unfinished', 'no');
endif;
$this->update_setting('link/item count', count($posts));
// Copy back any changes to feed settings made in the
// course of updating (e.g. new author rules)
$update_set = "link_notes = '".$wpdb->escape($this->settings_to_notes())."'";
// Update the properties of the link from the feed information
$result = $wpdb->query("
UPDATE $wpdb->links
SET $update_set
WHERE link_id='$this->id'
");
do_action("update_syndicated_feed_completed", $this->id, $this);
endif;
// All done; let's clean up.
$this->magpie = NULL;
// Avoid circular-reference memory leak in PHP < 5.3.
// Cf. <http://simplepie.org/wiki/faq/i_m_getting_memory_leaks>
if (method_exists($this->simplepie, '__destruct')) :
$this->simplepie->__destruct();
endif;
$this->simplepie = NULL;
return $new_count;
} /* SyndicatedLink::poll() */