Feeds: Always return a valid timestamp for the Last-Modified header of comment or post feeds.
Fixes bug where an invalid Last-Modified value would be returned in feed requests for sites that had 0 items to return. Comment or post feeds will now return the current timestamp as the Last-Modified header value. Example: a request for the comments feed for a site without any comments. Replaced use of the local static variable `$cache_lastcommentmodified` to store the modified date in `get_lastcommentmodified()` with the Object Cache API. The `get_lastcommentmodified()` function returns early if there is a cached value and returns `false` if there where no comments found. Introduced `_clear_modified_cache_on_transition_comment_status()` to flush the `lastcommentmodified` cache key when a comment enters or leaves approval status. In `get_lastpostmodified()` return early if there is a cached value and return `false` if there are no posts found. Props swissspidy, rachelbaker, dllh, leobaiano. Fixes #38027. Built from https://develop.svn.wordpress.org/trunk@38925 git-svn-id: http://core.svn.wordpress.org/trunk@38868 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
92dfd29aee
commit
2f263fce99
|
@ -422,22 +422,30 @@ class WP {
|
||||||
}
|
}
|
||||||
$headers['Content-Type'] = feed_content_type( $type ) . '; charset=' . get_option( 'blog_charset' );
|
$headers['Content-Type'] = feed_content_type( $type ) . '; charset=' . get_option( 'blog_charset' );
|
||||||
|
|
||||||
// We're showing a feed, so WP is indeed the only thing that last changed
|
// We're showing a feed, so WP is indeed the only thing that last changed.
|
||||||
if ( !empty($this->query_vars['withcomments'])
|
if ( ! empty( $this->query_vars['withcomments'] )
|
||||||
|| false !== strpos( $this->query_vars['feed'], 'comments-' )
|
|| false !== strpos( $this->query_vars['feed'], 'comments-' )
|
||||||
|| ( empty($this->query_vars['withoutcomments'])
|
|| ( empty( $this->query_vars['withoutcomments'] )
|
||||||
&& ( !empty($this->query_vars['p'])
|
&& ( ! empty( $this->query_vars['p'] )
|
||||||
|| !empty($this->query_vars['name'])
|
|| ! empty( $this->query_vars['name'] )
|
||||||
|| !empty($this->query_vars['page_id'])
|
|| ! empty( $this->query_vars['page_id'] )
|
||||||
|| !empty($this->query_vars['pagename'])
|
|| ! empty( $this->query_vars['pagename'] )
|
||||||
|| !empty($this->query_vars['attachment'])
|
|| ! empty( $this->query_vars['attachment'] )
|
||||||
|| !empty($this->query_vars['attachment_id'])
|
|| ! empty( $this->query_vars['attachment_id'] )
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
) {
|
||||||
$wp_last_modified = mysql2date('D, d M Y H:i:s', get_lastcommentmodified('GMT'), 0).' GMT';
|
$wp_last_modified = mysql2date( 'D, d M Y H:i:s', get_lastcommentmodified( 'GMT' ), false );
|
||||||
else
|
} else {
|
||||||
$wp_last_modified = mysql2date('D, d M Y H:i:s', get_lastpostmodified('GMT'), 0).' GMT';
|
$wp_last_modified = mysql2date( 'D, d M Y H:i:s', get_lastpostmodified( 'GMT' ), false );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! $wp_last_modified ) {
|
||||||
|
$wp_last_modified = date( 'D, d M Y H:i:s' );
|
||||||
|
}
|
||||||
|
|
||||||
|
$wp_last_modified .= ' GMT';
|
||||||
|
|
||||||
$wp_etag = '"' . md5($wp_last_modified) . '"';
|
$wp_etag = '"' . md5($wp_last_modified) . '"';
|
||||||
$headers['Last-Modified'] = $wp_last_modified;
|
$headers['Last-Modified'] = $wp_last_modified;
|
||||||
$headers['ETag'] = $wp_etag;
|
$headers['ETag'] = $wp_etag;
|
||||||
|
|
|
@ -293,38 +293,46 @@ function get_default_comment_status( $post_type = 'post', $comment_type = 'comme
|
||||||
* The date the last comment was modified.
|
* The date the last comment was modified.
|
||||||
*
|
*
|
||||||
* @since 1.5.0
|
* @since 1.5.0
|
||||||
|
* @since 4.7.0 Replaced caching the modified date in a local static variable
|
||||||
|
* with the Object Cache API.
|
||||||
*
|
*
|
||||||
* @global wpdb $wpdb WordPress database abstraction object.
|
* @global wpdb $wpdb WordPress database abstraction object.
|
||||||
* @staticvar array $cache_lastcommentmodified
|
|
||||||
*
|
*
|
||||||
* @param string $timezone Which timezone to use in reference to 'gmt', 'blog',
|
* @param string $timezone Which timezone to use in reference to 'gmt', 'blog', or 'server' locations.
|
||||||
* or 'server' locations.
|
* @return string|false Last comment modified date on success, false on failure.
|
||||||
* @return string Last comment modified date.
|
|
||||||
*/
|
*/
|
||||||
function get_lastcommentmodified($timezone = 'server') {
|
function get_lastcommentmodified( $timezone = 'server' ) {
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
static $cache_lastcommentmodified = array();
|
|
||||||
|
|
||||||
if ( isset($cache_lastcommentmodified[$timezone]) )
|
$timezone = strtolower( $timezone );
|
||||||
return $cache_lastcommentmodified[$timezone];
|
$key = "lastcommentmodified:$timezone";
|
||||||
|
|
||||||
$add_seconds_server = date('Z');
|
$comment_modified_date = wp_cache_get( $key, 'timeinfo' );
|
||||||
|
if ( false !== $comment_modified_date ) {
|
||||||
|
return $comment_modified_date;
|
||||||
|
}
|
||||||
|
|
||||||
switch ( strtolower($timezone)) {
|
switch ( $timezone ) {
|
||||||
case 'gmt':
|
case 'gmt':
|
||||||
$lastcommentmodified = $wpdb->get_var("SELECT comment_date_gmt FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1");
|
$comment_modified_date = $wpdb->get_var( "SELECT comment_date_gmt FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1" );
|
||||||
break;
|
break;
|
||||||
case 'blog':
|
case 'blog':
|
||||||
$lastcommentmodified = $wpdb->get_var("SELECT comment_date FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1");
|
$comment_modified_date = $wpdb->get_var( "SELECT comment_date FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1" );
|
||||||
break;
|
break;
|
||||||
case 'server':
|
case 'server':
|
||||||
$lastcommentmodified = $wpdb->get_var($wpdb->prepare("SELECT DATE_ADD(comment_date_gmt, INTERVAL %s SECOND) FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1", $add_seconds_server));
|
$add_seconds_server = date( 'Z' );
|
||||||
|
|
||||||
|
$comment_modified_date = $wpdb->get_var( $wpdb->prepare( "SELECT DATE_ADD(comment_date_gmt, INTERVAL %s SECOND) FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1", $add_seconds_server ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$cache_lastcommentmodified[$timezone] = $lastcommentmodified;
|
if ( $comment_modified_date ) {
|
||||||
|
wp_cache_set( $key, $comment_modified_date, 'timeinfo' );
|
||||||
|
|
||||||
return $lastcommentmodified;
|
return $comment_modified_date;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1572,6 +1580,26 @@ function wp_transition_comment_status($new_status, $old_status, $comment) {
|
||||||
do_action( "comment_{$new_status}_{$comment->comment_type}", $comment->comment_ID, $comment );
|
do_action( "comment_{$new_status}_{$comment->comment_type}", $comment->comment_ID, $comment );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the lastcommentmodified cached value when a comment status is changed.
|
||||||
|
*
|
||||||
|
* Deletes the lastcommentmodified cache key when a comment enters or leaves
|
||||||
|
* 'approved' status.
|
||||||
|
*
|
||||||
|
* @since 4.7.0
|
||||||
|
* @access private
|
||||||
|
*
|
||||||
|
* @param string $new_status The new comment status.
|
||||||
|
* @param string $old_status The old comment status.
|
||||||
|
*/
|
||||||
|
function _clear_modified_cache_on_transition_comment_status( $new_status, $old_status ) {
|
||||||
|
if ( 'approved' === $new_status || 'approved' === $old_status ) {
|
||||||
|
foreach ( array( 'server', 'gmt', 'blog' ) as $timezone ) {
|
||||||
|
wp_cache_delete( "lastcommentmodified:$timezone", 'timeinfo' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get current commenter's name, email, and URL.
|
* Get current commenter's name, email, and URL.
|
||||||
*
|
*
|
||||||
|
@ -1681,6 +1709,10 @@ function wp_insert_comment( $commentdata ) {
|
||||||
|
|
||||||
if ( $comment_approved == 1 ) {
|
if ( $comment_approved == 1 ) {
|
||||||
wp_update_comment_count( $comment_post_ID );
|
wp_update_comment_count( $comment_post_ID );
|
||||||
|
|
||||||
|
foreach ( array( 'server', 'gmt', 'blog' ) as $timezone ) {
|
||||||
|
wp_cache_delete( "lastcommentmodified:$timezone", 'timeinfo' );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clean_comment_cache( $id );
|
clean_comment_cache( $id );
|
||||||
|
|
|
@ -214,6 +214,8 @@ add_filter( 'pingback_ping_source_uri', 'pingback_ping_source_uri' );
|
||||||
add_filter( 'xmlrpc_pingback_error', 'xmlrpc_pingback_error' );
|
add_filter( 'xmlrpc_pingback_error', 'xmlrpc_pingback_error' );
|
||||||
add_filter( 'title_save_pre', 'trim' );
|
add_filter( 'title_save_pre', 'trim' );
|
||||||
|
|
||||||
|
add_action( 'transition_comment_status', '_clear_modified_cache_on_transition_comment_status', 10, 2 );
|
||||||
|
|
||||||
add_filter( 'http_request_host_is_external', 'allowed_http_request_hosts', 10, 2 );
|
add_filter( 'http_request_host_is_external', 'allowed_http_request_hosts', 10, 2 );
|
||||||
|
|
||||||
// REST API filters.
|
// REST API filters.
|
||||||
|
|
|
@ -37,7 +37,10 @@ do_action( 'rss_tag_pre', 'atom-comments' );
|
||||||
?></title>
|
?></title>
|
||||||
<subtitle type="text"><?php bloginfo_rss('description'); ?></subtitle>
|
<subtitle type="text"><?php bloginfo_rss('description'); ?></subtitle>
|
||||||
|
|
||||||
<updated><?php echo mysql2date('Y-m-d\TH:i:s\Z', get_lastcommentmodified('GMT'), false); ?></updated>
|
<updated><?php
|
||||||
|
$date = get_lastcommentmodified( 'GMT' );
|
||||||
|
echo $date ? mysql2date( 'Y-m-d\TH:i:s\Z', $date ) : date( 'Y-m-d\TH:i:s\Z' );
|
||||||
|
?></updated>
|
||||||
|
|
||||||
<?php if ( is_singular() ) { ?>
|
<?php if ( is_singular() ) { ?>
|
||||||
<link rel="alternate" type="<?php bloginfo_rss('html_type'); ?>" href="<?php comments_link_feed(); ?>" />
|
<link rel="alternate" type="<?php bloginfo_rss('html_type'); ?>" href="<?php comments_link_feed(); ?>" />
|
||||||
|
|
|
@ -30,7 +30,10 @@ do_action( 'rss_tag_pre', 'atom' );
|
||||||
<title type="text"><?php wp_title_rss(); ?></title>
|
<title type="text"><?php wp_title_rss(); ?></title>
|
||||||
<subtitle type="text"><?php bloginfo_rss("description") ?></subtitle>
|
<subtitle type="text"><?php bloginfo_rss("description") ?></subtitle>
|
||||||
|
|
||||||
<updated><?php echo mysql2date('Y-m-d\TH:i:s\Z', get_lastpostmodified('GMT'), false); ?></updated>
|
<updated><?php
|
||||||
|
$date = get_lastpostmodified( 'GMT' );
|
||||||
|
echo $date ? mysql2date( 'Y-m-d\TH:i:s\Z', $date ) : date( 'Y-m-d\TH:i:s\Z' );
|
||||||
|
?></updated>
|
||||||
|
|
||||||
<link rel="alternate" type="<?php bloginfo_rss('html_type'); ?>" href="<?php bloginfo_rss('url') ?>" />
|
<link rel="alternate" type="<?php bloginfo_rss('html_type'); ?>" href="<?php bloginfo_rss('url') ?>" />
|
||||||
<id><?php bloginfo('atom_url'); ?></id>
|
<id><?php bloginfo('atom_url'); ?></id>
|
||||||
|
|
|
@ -33,7 +33,10 @@ do_action( 'rss_tag_pre', 'rdf' );
|
||||||
<title><?php wp_title_rss(); ?></title>
|
<title><?php wp_title_rss(); ?></title>
|
||||||
<link><?php bloginfo_rss('url') ?></link>
|
<link><?php bloginfo_rss('url') ?></link>
|
||||||
<description><?php bloginfo_rss('description') ?></description>
|
<description><?php bloginfo_rss('description') ?></description>
|
||||||
<dc:date><?php echo mysql2date('Y-m-d\TH:i:s\Z', get_lastpostmodified('GMT'), false); ?></dc:date>
|
<dc:date><?php
|
||||||
|
$date = get_lastpostmodified( 'GMT' );
|
||||||
|
echo $date ? mysql2date( 'Y-m-d\TH:i:s\Z', $date ) : date( 'Y-m-d\TH:i:s\Z' );
|
||||||
|
?></dc:date>
|
||||||
<sy:updatePeriod><?php
|
<sy:updatePeriod><?php
|
||||||
/** This filter is documented in wp-includes/feed-rss2.php */
|
/** This filter is documented in wp-includes/feed-rss2.php */
|
||||||
echo apply_filters( 'rss_update_period', 'hourly' );
|
echo apply_filters( 'rss_update_period', 'hourly' );
|
||||||
|
|
|
@ -14,7 +14,10 @@ echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>'; ?>
|
||||||
<title><?php wp_title_rss(); ?></title>
|
<title><?php wp_title_rss(); ?></title>
|
||||||
<link><?php bloginfo_rss('url') ?></link>
|
<link><?php bloginfo_rss('url') ?></link>
|
||||||
<description><?php bloginfo_rss('description') ?></description>
|
<description><?php bloginfo_rss('description') ?></description>
|
||||||
<lastBuildDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_lastpostmodified('GMT'), false); ?></lastBuildDate>
|
<lastBuildDate><?php
|
||||||
|
$date = get_lastpostmodified( 'GMT' );
|
||||||
|
echo $date ? mysql2date( 'D, d M Y H:i:s +0000', $date ) : date( 'D, d M Y H:i:s +0000' );
|
||||||
|
?></lastBuildDate>
|
||||||
<docs>http://backend.userland.com/rss092</docs>
|
<docs>http://backend.userland.com/rss092</docs>
|
||||||
<language><?php bloginfo_rss( 'language' ); ?></language>
|
<language><?php bloginfo_rss( 'language' ); ?></language>
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,10 @@ do_action( 'rss_tag_pre', 'rss2-comments' );
|
||||||
<atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
|
<atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
|
||||||
<link><?php (is_single()) ? the_permalink_rss() : bloginfo_rss("url") ?></link>
|
<link><?php (is_single()) ? the_permalink_rss() : bloginfo_rss("url") ?></link>
|
||||||
<description><?php bloginfo_rss("description") ?></description>
|
<description><?php bloginfo_rss("description") ?></description>
|
||||||
<lastBuildDate><?php echo mysql2date('r', get_lastcommentmodified('GMT')); ?></lastBuildDate>
|
<lastBuildDate><?php
|
||||||
|
$date = get_lastcommentmodified( 'GMT' );
|
||||||
|
echo $date ? mysql2date( 'r', $date ) : date( 'r' );
|
||||||
|
?></lastBuildDate>
|
||||||
<sy:updatePeriod><?php
|
<sy:updatePeriod><?php
|
||||||
/** This filter is documented in wp-includes/feed-rss2.php */
|
/** This filter is documented in wp-includes/feed-rss2.php */
|
||||||
echo apply_filters( 'rss_update_period', 'hourly' );
|
echo apply_filters( 'rss_update_period', 'hourly' );
|
||||||
|
|
|
@ -42,7 +42,10 @@ do_action( 'rss_tag_pre', 'rss2' );
|
||||||
<atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
|
<atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
|
||||||
<link><?php bloginfo_rss('url') ?></link>
|
<link><?php bloginfo_rss('url') ?></link>
|
||||||
<description><?php bloginfo_rss("description") ?></description>
|
<description><?php bloginfo_rss("description") ?></description>
|
||||||
<lastBuildDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_lastpostmodified('GMT'), false); ?></lastBuildDate>
|
<lastBuildDate><?php
|
||||||
|
$date = get_lastpostmodified( 'GMT' );
|
||||||
|
echo $date ? mysql2date( 'D, d M Y H:i:s +0000', $date ) : date( 'D, d M Y H:i:s +0000' );
|
||||||
|
?></lastBuildDate>
|
||||||
<language><?php bloginfo_rss( 'language' ); ?></language>
|
<language><?php bloginfo_rss( 'language' ); ?></language>
|
||||||
<sy:updatePeriod><?php
|
<sy:updatePeriod><?php
|
||||||
$duration = 'hourly';
|
$duration = 'hourly';
|
||||||
|
|
|
@ -5612,35 +5612,38 @@ function _get_last_post_time( $timezone, $field, $post_type = 'any' ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
$date = wp_cache_get( $key, 'timeinfo' );
|
$date = wp_cache_get( $key, 'timeinfo' );
|
||||||
|
if ( false !== $date ) {
|
||||||
if ( ! $date ) {
|
return $date;
|
||||||
if ( 'any' === $post_type ) {
|
|
||||||
$post_types = get_post_types( array( 'public' => true ) );
|
|
||||||
array_walk( $post_types, array( $wpdb, 'escape_by_ref' ) );
|
|
||||||
$post_types = "'" . implode( "', '", $post_types ) . "'";
|
|
||||||
} else {
|
|
||||||
$post_types = "'" . sanitize_key( $post_type ) . "'";
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ( $timezone ) {
|
|
||||||
case 'gmt':
|
|
||||||
$date = $wpdb->get_var("SELECT post_{$field}_gmt FROM $wpdb->posts WHERE post_status = 'publish' AND post_type IN ({$post_types}) ORDER BY post_{$field}_gmt DESC LIMIT 1");
|
|
||||||
break;
|
|
||||||
case 'blog':
|
|
||||||
$date = $wpdb->get_var("SELECT post_{$field} FROM $wpdb->posts WHERE post_status = 'publish' AND post_type IN ({$post_types}) ORDER BY post_{$field}_gmt DESC LIMIT 1");
|
|
||||||
break;
|
|
||||||
case 'server':
|
|
||||||
$add_seconds_server = date( 'Z' );
|
|
||||||
$date = $wpdb->get_var("SELECT DATE_ADD(post_{$field}_gmt, INTERVAL '$add_seconds_server' SECOND) FROM $wpdb->posts WHERE post_status = 'publish' AND post_type IN ({$post_types}) ORDER BY post_{$field}_gmt DESC LIMIT 1");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $date ) {
|
|
||||||
wp_cache_set( $key, $date, 'timeinfo' );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $date;
|
if ( 'any' === $post_type ) {
|
||||||
|
$post_types = get_post_types( array( 'public' => true ) );
|
||||||
|
array_walk( $post_types, array( $wpdb, 'escape_by_ref' ) );
|
||||||
|
$post_types = "'" . implode( "', '", $post_types ) . "'";
|
||||||
|
} else {
|
||||||
|
$post_types = "'" . sanitize_key( $post_type ) . "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( $timezone ) {
|
||||||
|
case 'gmt':
|
||||||
|
$date = $wpdb->get_var("SELECT post_{$field}_gmt FROM $wpdb->posts WHERE post_status = 'publish' AND post_type IN ({$post_types}) ORDER BY post_{$field}_gmt DESC LIMIT 1");
|
||||||
|
break;
|
||||||
|
case 'blog':
|
||||||
|
$date = $wpdb->get_var("SELECT post_{$field} FROM $wpdb->posts WHERE post_status = 'publish' AND post_type IN ({$post_types}) ORDER BY post_{$field}_gmt DESC LIMIT 1");
|
||||||
|
break;
|
||||||
|
case 'server':
|
||||||
|
$add_seconds_server = date( 'Z' );
|
||||||
|
$date = $wpdb->get_var("SELECT DATE_ADD(post_{$field}_gmt, INTERVAL '$add_seconds_server' SECOND) FROM $wpdb->posts WHERE post_status = 'publish' AND post_type IN ({$post_types}) ORDER BY post_{$field}_gmt DESC LIMIT 1");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $date ) {
|
||||||
|
wp_cache_set( $key, $date, 'timeinfo' );
|
||||||
|
|
||||||
|
return $date;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*
|
*
|
||||||
* @global string $wp_version
|
* @global string $wp_version
|
||||||
*/
|
*/
|
||||||
$wp_version = '4.7-alpha-38924';
|
$wp_version = '4.7-alpha-38925';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||||
|
|
Loading…
Reference in New Issue