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($url, 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); } $new_count = NULL; $resume = FeedWordPress::affirmative($this->settings, 'update/unfinished'); if ($resume) { // pick up where we left off $processed = array_map('trim', explode("\n", $this->settings['update/processed'])); } else { // begin at the beginning $processed = array(); } 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); } 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->settings['update/last'] = time(); $this->settings['update/ttl'] = $this->automatic_ttl(); $this->settings['update/ttl'] = apply_filters('syndicated_feed_ttl', $this->settings['update/ttl'], $this); $this->settings['update/ttl'] = apply_filters('syndicated_feed_ttl_from_error', $this->settings['update/ttl'], $this); $this->settings['update/timed'] = 'automatically'; } do_action('syndicated_feed_error', $theError, $oldError, $this); $this->settings['update/error'] = serialize($theError); $this->save_settings(true); } elseif (is_object($this->simplepie)) { // Success; clear out error setting, if any. if (isset($this->settings['update/error'])) { unset($this->settings['update/error']); } $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; } $update = array(); if (!$this->hardcode('url') and isset($channel['link'])) { $update[] = "link_url = '" . $wpdb->escape($channel['link']) . "'"; } if (!$this->hardcode('name') and isset($channel['title'])) { $update[] = "link_name = '" . $wpdb->escape($channel['title']) . "'"; } 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']) . "'"; } } $this->settings = array_merge($this->settings, $this->flatten_array($channel)); $this->settings['update/last'] = time(); list($ttl, $xml) = $this->ttl(true); if (!is_null($ttl)) { $this->settings['update/ttl'] = $ttl; $this->settings['update/xml'] = $xml; $this->settings['update/timed'] = 'feed'; } else { $ttl = $this->automatic_ttl(); $this->settings['update/ttl'] = $ttl; $this->settings['update/xml'] = NULL; $this->settings['update/timed'] = 'automatically'; } $this->settings['update/fudge'] = rand(0, $ttl / 3) * 60; $this->settings['update/ttl'] = apply_filters('syndicated_feed_ttl', $this->setting('update/ttl'), $this); if (!$this->setting('update/hold') != 'ping') { $this->settings['update/hold'] = 'scheduled'; } $this->settings['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("\n\t\t\t\tUPDATE {$wpdb->links}\n\t\t\t\tSET {$update_set}\n\t\t\t\tWHERE link_id='{$this->id}'\n\t\t\t"); 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 (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]++; } } if (!is_null($crash_ts) and time() > $crash_ts) { $crashed = true; break; } } unset($post); } } $suffix = $crashed ? 'crashed' : 'completed'; do_action('update_syndicated_feed_items', $this->id, $this); do_action("update_syndicated_feed_items_{$suffix}", $this->id, $this); // Copy back any changes to feed settings made in the course of updating (e.g. new author rules) $to_notes = $this->settings; $this->settings['update/processed'] = $processed; if (!$crashed) { $this->settings['update/unfinished'] = 'no'; } $update_set = "link_notes = '" . $wpdb->escape($this->settings_to_notes()) . "'"; // Update the properties of the link from the feed information $result = $wpdb->query("\n\t\t\tUPDATE {$wpdb->links}\n\t\t\tSET {$update_set}\n\t\t\tWHERE link_id='{$this->id}'\n\t\t\t"); do_action("update_syndicated_feed_completed", $this->id, $this); } // 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(); } $this->simplepie = NULL; return $new_count; }
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() */
function poll($crash_ts = NULL) { FeedWordPress::diagnostic('updated_feeds', 'Polling feed <' . $this->link->link_rss . '>'); $this->simplepie = apply_filters('syndicated_feed', FeedWordPress::fetch($this->link->link_rss), $this); // Filter compatibility mode if (is_wp_error($this->simplepie)) { $this->magpie = $this->simplepie; } else { $this->magpie = new MagpieFromSimplePie($this->simplepie); } $new_count = NULL; $resume = FeedWordPress::affirmative($this->settings, 'update/unfinished'); if ($resume) { // pick up where we left off $processed = array_map('trim', explode("\n", $this->settings['update/processed'])); } else { // begin at the beginning $processed = array(); } 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); } 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->settings['update/last'] = time(); $this->settings['update/ttl'] = $this->automatic_ttl(); $this->settings['update/ttl'] = apply_filters('syndicated_feed_ttl', $this->settings['update/ttl'], $this); $this->settings['update/ttl'] = apply_filters('syndicated_feed_ttl_from_error', $this->settings['update/ttl'], $this); $this->settings['update/timed'] = 'automatically'; } $this->settings['update/error'] = serialize($theError); $this->save_settings(true); } elseif (is_object($this->simplepie)) { // Grab our bookmark we're going to be updating $link = get_bookmark($this->id, ARRAY_A); if (is_array($link) && !empty($link)) { // Success; clear out error setting, if any. if (isset($this->settings['update/error'])) { unset($this->settings['update/error']); } $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; } if (!$this->hardcode('url') and isset($channel['link'])) { $link['link_url'] = $channel['link']; } if (!$this->hardcode('name') and isset($channel['title'])) { $link['link_name'] = $channel['title']; } if (!$this->hardcode('description')) { if (isset($channel['tagline'])) { $link['link_description'] = $channel['tagline']; } elseif (isset($channel['description'])) { $link['link_description'] = $channel['description']; } } $this->settings = array_merge($this->settings, $this->flatten_array($channel)); $this->settings['update/last'] = time(); $ttl = $this->ttl(); if (!is_null($ttl)) { $this->settings['update/ttl'] = $ttl; $this->settings['update/timed'] = 'feed'; } else { $this->settings['update/ttl'] = $this->automatic_ttl(); $this->settings['update/timed'] = 'automatically'; } $this->settings['update/ttl'] = apply_filters('syndicated_feed_ttl', $this->settings['update/ttl'], $this); if (!isset($this->settings['update/hold']) or $this->settings['update/hold'] != 'ping') { $this->settings['update/hold'] = 'scheduled'; } $this->settings['update/unfinished'] = 'yes'; $link['link_notes'] = $this->settings_to_notes(); // Update the properties of the link from the feed information $result = wp_update_link($link); 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->magpie->originals, $this); if (is_array($posts)) { foreach ($posts as $key => $original) { $item = $this->magpie->items[$key]; $post = new SyndicatedPost(array('simplepie' => $original, 'magpie' => $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]++; } } if (!is_null($crash_ts) and time() > $crash_ts) { $crashed = true; break; } } unset($post); } } $suffix = $crashed ? 'crashed' : 'completed'; do_action('update_syndicated_feed_items', $this->id, $this); do_action("update_syndicated_feed_items_{$suffix}", $this->id, $this); // Copy back any changes to feed settings made in the course of updating (e.g. new author rules) $to_notes = $this->settings; $this->settings['update/processed'] = $processed; if (!$crashed) { $this->settings['update/unfinished'] = 'no'; } $link['link_notes'] = $this->settings_to_notes(); // Update the properties of the link from the feed information $result = wp_update_link($link); do_action("update_syndicated_feed_completed", $this->id, $this); } } return $new_count; }