Index: wp-includes/class-simplepie.php =================================================================== --- wp-includes/class-simplepie.php (revision 24806) +++ wp-includes/class-simplepie.php (working copy) @@ -557,6 +557,13 @@ public $cache_duration = 3600; /** + * @var int Error cache duration (in seconds) + * @see SimplePie::set_error_cache_duration() + * @access private + */ + public $error_cache_duration = 3600; + + /** * @var int Auto-discovery cache duration (in seconds) * @see SimplePie::set_autodiscovery_cache_duration() * @access private @@ -877,6 +884,17 @@ } /** + * Set the length of time (in seconds) that the errors for failed feed loads + * will be cached + * + * @param int $seconds The feed error cache duration + */ + public function set_error_cache_duration($seconds = 3600) + { + $this->error_cache_duration = (int) $seconds; + } + + /** * Set the length of time (in seconds) that the autodiscovered feed URL will * be cached * @@ -1470,12 +1488,14 @@ $cache->unlink(); $this->data = array(); } + // If we've hit a collision just rerun it with caching disabled elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url) { $cache = false; $this->data = array(); } + // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL. elseif (isset($this->data['feed_url'])) { @@ -1493,6 +1513,14 @@ $this->data = array(); } } + + // Check if the error cache has been updated + elseif ($cache->mtime() + $this->error_cache_duration < time() && isset($this->data['error'])) + { + $cache->unlink(); + $this->data = array(); + } + // Check if the cache has been updated elseif ($cache->mtime() + $this->cache_duration < time()) { @@ -1527,13 +1555,20 @@ } } } + // If the cache is still valid, just return true else { + // If we're caching an error, pull it back out from the cache payload for persistent error response. + if (!empty($this->data['error'])) + { + $this->error = $this->data['error']; + } $this->raw_data = false; return true; } } + // If the cache is empty, delete it else { @@ -1541,6 +1576,7 @@ $this->data = array(); } } + // If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it. if (!isset($file)) { @@ -1553,6 +1589,7 @@ $headers = array( 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', ); + $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen)); } } @@ -1560,6 +1597,7 @@ if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300))) { $this->error = $file->error; + $this->cache_results( $cache, $this->feed_url ); return !empty($this->data); } @@ -1578,6 +1616,7 @@ { $this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed."; $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__)); + $this->cache_results( $cache, $this->feed_url ); return false; } } @@ -1586,17 +1625,11 @@ // This is usually because DOMDocument doesn't exist $this->error = $e->getMessage(); $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, $e->getFile(), $e->getLine())); + $this->cache_results( $cache, $this->feed_url ); return false; } - if ($cache) - { - $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD); - if (!$cache->save($this)) - { - trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING); - } - $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc')); - } + + $this->cache_results( $cache, $file->url ); $this->feed_url = $file->url; } $locate = null; @@ -1611,7 +1644,39 @@ return array($headers, $sniffed); } + /** + * Cache the results of the feed request. + * + * @param SimplePie_Cache|false $cache Cache handler, or false to not load from the cache + * @param string $feedurl + */ + public function cache_results( &$cache, $feedurl ) + { + if ($cache) + { + $this->data = array('url' => $this->feed_url, 'build' => SIMPLEPIE_BUILD); + + // A weird little hack to ensure that we cache errors. + if (!empty($this->error)) + { + $this->data['error'] = $this->error; + } + // For some reason feed_url in the cache payload should only be set if there are no errors. + else { + $this->data['feed_url'] = $feedurl; + } + + if (!$cache->save($this)) + { + trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING); + } + + $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $feedurl), 'spc')); + } + } + + /** * Get the error message for the occured error * * @return string|array Error message, or array of messages for multifeeds Index: wp-includes/default-widgets.php =================================================================== --- wp-includes/default-widgets.php (revision 24806) +++ wp-includes/default-widgets.php (working copy) @@ -833,7 +833,7 @@ if ( is_wp_error($rss) ) { if ( is_admin() || current_user_can('manage_options') ) - echo '
' . sprintf( __('RSS Error: %s'), $rss->get_error_message() ) . '
'; + echo '' . sprintf( __('RSS Error: %s'), $rss->get_error_message() ) . '
'; return; } Index: wp-includes/feed.php =================================================================== --- wp-includes/feed.php (revision 24806) +++ wp-includes/feed.php (working copy) @@ -541,6 +541,7 @@ $feed->set_feed_url( $url ); $feed->set_cache_duration( apply_filters( 'wp_feed_cache_transient_lifetime', 12 * HOUR_IN_SECONDS, $url ) ); + $feed->set_error_cache_duration( apply_filters( 'wp_feed_error_cache_transient_lifetime', 15 * MINUTE_IN_SECONDS, $url ) ); do_action_ref_array( 'wp_feed_options', array( &$feed, $url ) ); $feed->init(); $feed->handle_content_type();