<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[38925] trunk: Feeds: Always return a valid timestamp for the Last-Modified header of comment or post feeds.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/38925">38925</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/38925","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>rachelbaker</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2016-10-25 20:47:06 +0000 (Tue, 25 Oct 2016)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>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 <a href="https://core.trac.wordpress.org/ticket/38027">#38027</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesclasswpphp">trunk/src/wp-includes/class-wp.php</a></li>
<li><a href="#trunksrcwpincludescommentphp">trunk/src/wp-includes/comment.php</a></li>
<li><a href="#trunksrcwpincludesdefaultfiltersphp">trunk/src/wp-includes/default-filters.php</a></li>
<li><a href="#trunksrcwpincludesfeedatomcommentsphp">trunk/src/wp-includes/feed-atom-comments.php</a></li>
<li><a href="#trunksrcwpincludesfeedatomphp">trunk/src/wp-includes/feed-atom.php</a></li>
<li><a href="#trunksrcwpincludesfeedrdfphp">trunk/src/wp-includes/feed-rdf.php</a></li>
<li><a href="#trunksrcwpincludesfeedrssphp">trunk/src/wp-includes/feed-rss.php</a></li>
<li><a href="#trunksrcwpincludesfeedrss2commentsphp">trunk/src/wp-includes/feed-rss2-comments.php</a></li>
<li><a href="#trunksrcwpincludesfeedrss2php">trunk/src/wp-includes/feed-rss2.php</a></li>
<li><a href="#trunksrcwpincludespostphp">trunk/src/wp-includes/post.php</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunktestsphpunittestscommentlastCommentModifiedphp">trunk/tests/phpunit/tests/comment/lastCommentModified.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesclasswpphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp.php        2016-10-25 20:16:58 UTC (rev 38924)
+++ trunk/src/wp-includes/class-wp.php  2016-10-25 20:47:06 UTC (rev 38925)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -422,22 +422,30 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                        $headers['Content-Type'] = feed_content_type( $type ) . '; charset=' . get_option( 'blog_charset' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        // We're showing a feed, so WP is indeed the only thing that last changed
-                       if ( !empty($this->query_vars['withcomments'])
-                               || false !== strpos( $this->query_vars['feed'], 'comments-' )
-                               || ( empty($this->query_vars['withoutcomments'])
-                                       && ( !empty($this->query_vars['p'])
-                                               || !empty($this->query_vars['name'])
-                                               || !empty($this->query_vars['page_id'])
-                                               || !empty($this->query_vars['pagename'])
-                                               || !empty($this->query_vars['attachment'])
-                                               || !empty($this->query_vars['attachment_id'])
-                                       )
-                               )
-                       )
-                               $wp_last_modified = mysql2date('D, d M Y H:i:s', get_lastcommentmodified('GMT'), 0).' GMT';
-                       else
-                               $wp_last_modified = mysql2date('D, d M Y H:i:s', get_lastpostmodified('GMT'), 0).' GMT';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // We're showing a feed, so WP is indeed the only thing that last changed.
+                       if ( ! empty( $this->query_vars['withcomments'] )
+                            || false !== strpos( $this->query_vars['feed'], 'comments-' )
+                            || ( empty( $this->query_vars['withoutcomments'] )
+                                 && ( ! empty( $this->query_vars['p'] )
+                                      || ! empty( $this->query_vars['name'] )
+                                      || ! empty( $this->query_vars['page_id'] )
+                                      || ! empty( $this->query_vars['pagename'] )
+                                      || ! empty( $this->query_vars['attachment'] )
+                                      || ! empty( $this->query_vars['attachment_id'] )
+                                 )
+                            )
+                       ) {
+                               $wp_last_modified = mysql2date( 'D, d M Y H:i:s', get_lastcommentmodified( 'GMT' ), false );
+                       } else {
+                               $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';
+
</ins><span class="cx" style="display: block; padding: 0 10px">                         $wp_etag = '"' . md5($wp_last_modified) . '"';
</span><span class="cx" style="display: block; padding: 0 10px">                        $headers['Last-Modified'] = $wp_last_modified;
</span><span class="cx" style="display: block; padding: 0 10px">                        $headers['ETag'] = $wp_etag;
</span></span></pre></div>
<a id="trunksrcwpincludescommentphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/comment.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/comment.php 2016-10-25 20:16:58 UTC (rev 38924)
+++ trunk/src/wp-includes/comment.php   2016-10-25 20:47:06 UTC (rev 38925)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -293,38 +293,46 @@
</span><span class="cx" style="display: block; padding: 0 10px">  * The date the last comment was modified.
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @since 1.5.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 4.7.0 Replaced caching the modified date in a local static variable
+ *              with the Object Cache API.
</ins><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @global wpdb $wpdb WordPress database abstraction object.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @staticvar array $cache_lastcommentmodified
</del><span class="cx" style="display: block; padding: 0 10px">  *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @param string $timezone Which timezone to use in reference to 'gmt', 'blog',
- *             or 'server' locations.
- * @return string Last comment modified date.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param string $timezone Which timezone to use in reference to 'gmt', 'blog', or 'server' locations.
+ * @return string|false Last comment modified date on success, false on failure.
</ins><span class="cx" style="display: block; padding: 0 10px">  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function get_lastcommentmodified($timezone = 'server') {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function get_lastcommentmodified( $timezone = 'server' ) {
</ins><span class="cx" style="display: block; padding: 0 10px">         global $wpdb;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        static $cache_lastcommentmodified = array();
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( isset($cache_lastcommentmodified[$timezone]) )
-               return $cache_lastcommentmodified[$timezone];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $timezone = strtolower( $timezone );
+       $key = "lastcommentmodified:$timezone";
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        $add_seconds_server = date('Z');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $comment_modified_date = wp_cache_get( $key, 'timeinfo' );
+       if ( false !== $comment_modified_date ) {
+               return $comment_modified_date;
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        switch ( strtolower($timezone)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ switch ( $timezone ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                 case 'gmt':
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $lastcommentmodified = $wpdb->get_var("SELECT comment_date_gmt FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $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" );
</ins><span class="cx" style="display: block; padding: 0 10px">                         break;
</span><span class="cx" style="display: block; padding: 0 10px">                case 'blog':
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $lastcommentmodified = $wpdb->get_var("SELECT comment_date FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $comment_modified_date = $wpdb->get_var( "SELECT comment_date FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1" );
</ins><span class="cx" style="display: block; padding: 0 10px">                         break;
</span><span class="cx" style="display: block; padding: 0 10px">                case 'server':
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $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));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $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 ) );
</ins><span class="cx" style="display: block; padding: 0 10px">                         break;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        $cache_lastcommentmodified[$timezone] = $lastcommentmodified;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $comment_modified_date ) {
+               wp_cache_set( $key, $comment_modified_date, 'timeinfo' );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        return $lastcommentmodified;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         return $comment_modified_date;
+       }
+
+       return false;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1573,6 +1581,26 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * 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' );
+               }
+       }
+}
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px">  * Get current commenter's name, email, and URL.
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * Expects cookies content to already be sanitized. User of this function might
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1681,6 +1709,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        if ( $comment_approved == 1 ) {
</span><span class="cx" style="display: block; padding: 0 10px">                wp_update_comment_count( $comment_post_ID );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+               foreach ( array( 'server', 'gmt', 'blog' ) as $timezone ) {
+                       wp_cache_delete( "lastcommentmodified:$timezone", 'timeinfo' );
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        clean_comment_cache( $id );
</span></span></pre></div>
<a id="trunksrcwpincludesdefaultfiltersphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/default-filters.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/default-filters.php 2016-10-25 20:16:58 UTC (rev 38924)
+++ trunk/src/wp-includes/default-filters.php   2016-10-25 20:47:06 UTC (rev 38925)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -214,6 +214,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> add_filter( 'xmlrpc_pingback_error',    'xmlrpc_pingback_error'               );
</span><span class="cx" style="display: block; padding: 0 10px"> add_filter( 'title_save_pre',           'trim'                                );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+add_action( 'transition_comment_status', '_clear_modified_cache_on_transition_comment_status', 10, 2 );
+
</ins><span class="cx" style="display: block; padding: 0 10px"> add_filter( 'http_request_host_is_external',    'allowed_http_request_hosts', 10, 2 );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> // REST API filters.
</span></span></pre></div>
<a id="trunksrcwpincludesfeedatomcommentsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/feed-atom-comments.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/feed-atom-comments.php      2016-10-25 20:16:58 UTC (rev 38924)
+++ trunk/src/wp-includes/feed-atom-comments.php        2016-10-25 20:47:06 UTC (rev 38925)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -37,7 +37,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">        ?></title>
</span><span class="cx" style="display: block; padding: 0 10px">        <subtitle type="text"><?php bloginfo_rss('description'); ?></subtitle>
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        <updated><?php echo mysql2date('Y-m-d\TH:i:s\Z', get_lastcommentmodified('GMT'), false); ?></updated>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <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>
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> <?php if ( is_singular() ) { ?>
</span><span class="cx" style="display: block; padding: 0 10px">        <link rel="alternate" type="<?php bloginfo_rss('html_type'); ?>" href="<?php comments_link_feed(); ?>" />
</span></span></pre></div>
<a id="trunksrcwpincludesfeedatomphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/feed-atom.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/feed-atom.php       2016-10-25 20:16:58 UTC (rev 38924)
+++ trunk/src/wp-includes/feed-atom.php 2016-10-25 20:47:06 UTC (rev 38925)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -30,7 +30,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">        <title type="text"><?php wp_title_rss(); ?></title>
</span><span class="cx" style="display: block; padding: 0 10px">        <subtitle type="text"><?php bloginfo_rss("description") ?></subtitle>
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        <updated><?php echo mysql2date('Y-m-d\TH:i:s\Z', get_lastpostmodified('GMT'), false); ?></updated>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <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>
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        <link rel="alternate" type="<?php bloginfo_rss('html_type'); ?>" href="<?php bloginfo_rss('url') ?>" />
</span><span class="cx" style="display: block; padding: 0 10px">        <id><?php bloginfo('atom_url'); ?></id>
</span></span></pre></div>
<a id="trunksrcwpincludesfeedrdfphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/feed-rdf.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/feed-rdf.php        2016-10-25 20:16:58 UTC (rev 38924)
+++ trunk/src/wp-includes/feed-rdf.php  2016-10-25 20:47:06 UTC (rev 38925)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -33,7 +33,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">        <title><?php wp_title_rss(); ?></title>
</span><span class="cx" style="display: block; padding: 0 10px">        <link><?php bloginfo_rss('url') ?></link>
</span><span class="cx" style="display: block; padding: 0 10px">        <description><?php bloginfo_rss('description') ?></description>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        <dc:date><?php echo mysql2date('Y-m-d\TH:i:s\Z', get_lastpostmodified('GMT'), false); ?></dc:date>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <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>
</ins><span class="cx" style="display: block; padding: 0 10px">         <sy:updatePeriod><?php
</span><span class="cx" style="display: block; padding: 0 10px">                /** This filter is documented in wp-includes/feed-rss2.php */
</span><span class="cx" style="display: block; padding: 0 10px">                echo apply_filters( 'rss_update_period', 'hourly' );
</span></span></pre></div>
<a id="trunksrcwpincludesfeedrssphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/feed-rss.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/feed-rss.php        2016-10-25 20:16:58 UTC (rev 38924)
+++ trunk/src/wp-includes/feed-rss.php  2016-10-25 20:47:06 UTC (rev 38925)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -14,7 +14,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">        <title><?php wp_title_rss(); ?></title>
</span><span class="cx" style="display: block; padding: 0 10px">        <link><?php bloginfo_rss('url') ?></link>
</span><span class="cx" style="display: block; padding: 0 10px">        <description><?php bloginfo_rss('description') ?></description>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        <lastBuildDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_lastpostmodified('GMT'), false); ?></lastBuildDate>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <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>
</ins><span class="cx" style="display: block; padding: 0 10px">         <docs>http://backend.userland.com/rss092</docs>
</span><span class="cx" style="display: block; padding: 0 10px">        <language><?php bloginfo_rss( 'language' ); ?></language>
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre></div>
<a id="trunksrcwpincludesfeedrss2commentsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/feed-rss2-comments.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/feed-rss2-comments.php      2016-10-25 20:16:58 UTC (rev 38924)
+++ trunk/src/wp-includes/feed-rss2-comments.php        2016-10-25 20:47:06 UTC (rev 38925)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -43,7 +43,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">        <atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
</span><span class="cx" style="display: block; padding: 0 10px">        <link><?php (is_single()) ? the_permalink_rss() : bloginfo_rss("url") ?></link>
</span><span class="cx" style="display: block; padding: 0 10px">        <description><?php bloginfo_rss("description") ?></description>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        <lastBuildDate><?php echo mysql2date('r', get_lastcommentmodified('GMT')); ?></lastBuildDate>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <lastBuildDate><?php
+               $date = get_lastcommentmodified( 'GMT' );
+               echo $date ? mysql2date( 'r', $date ) : date( 'r' );
+       ?></lastBuildDate>
</ins><span class="cx" style="display: block; padding: 0 10px">         <sy:updatePeriod><?php
</span><span class="cx" style="display: block; padding: 0 10px">                /** This filter is documented in wp-includes/feed-rss2.php */
</span><span class="cx" style="display: block; padding: 0 10px">                echo apply_filters( 'rss_update_period', 'hourly' );
</span></span></pre></div>
<a id="trunksrcwpincludesfeedrss2php"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/feed-rss2.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/feed-rss2.php       2016-10-25 20:16:58 UTC (rev 38924)
+++ trunk/src/wp-includes/feed-rss2.php 2016-10-25 20:47:06 UTC (rev 38925)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -42,7 +42,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">        <atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
</span><span class="cx" style="display: block; padding: 0 10px">        <link><?php bloginfo_rss('url') ?></link>
</span><span class="cx" style="display: block; padding: 0 10px">        <description><?php bloginfo_rss("description") ?></description>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        <lastBuildDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_lastpostmodified('GMT'), false); ?></lastBuildDate>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <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>
</ins><span class="cx" style="display: block; padding: 0 10px">         <language><?php bloginfo_rss( 'language' ); ?></language>
</span><span class="cx" style="display: block; padding: 0 10px">        <sy:updatePeriod><?php
</span><span class="cx" style="display: block; padding: 0 10px">                $duration = 'hourly';
</span></span></pre></div>
<a id="trunksrcwpincludespostphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/post.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/post.php    2016-10-25 20:16:58 UTC (rev 38924)
+++ trunk/src/wp-includes/post.php      2016-10-25 20:47:06 UTC (rev 38925)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5612,35 +5612,38 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        $date = wp_cache_get( $key, 'timeinfo' );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        if ( false !== $date ) {
+               return $date;
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( ! $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 ) . "'";
-               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 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 ) . "'";
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                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;
-               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 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;
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( $date ) {
-                       wp_cache_set( $key, $date, 'timeinfo' );
-               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $date ) {
+               wp_cache_set( $key, $date, 'timeinfo' );
+
+               return $date;
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        return $date;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return false;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span></span></pre></div>
<a id="trunktestsphpunittestscommentlastCommentModifiedphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/comment/lastCommentModified.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/comment/lastCommentModified.php                         (rev 0)
+++ trunk/tests/phpunit/tests/comment/lastCommentModified.php   2016-10-25 20:47:06 UTC (rev 38925)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,118 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * @group comment
+ * @group 38027
+ */
+class Tests_Comment_Last_Modified extends WP_UnitTestCase {
+       public function test_no_comments() {
+               $this->assertFalse( get_lastcommentmodified() );
+       }
+
+       public function test_default_timezone() {
+               self::factory()->comment->create_and_get( array(
+                       'comment_status'   => 1,
+                       'comment_date'     => '2000-01-01 11:00:00',
+                       'comment_date_gmt' => '2000-01-01 10:00:00',
+               ) );
+
+               $this->assertSame( strtotime( '2000-01-01 10:00:00' ), strtotime( get_lastcommentmodified() ) );
+       }
+
+       public function test_server_timezone() {
+               self::factory()->comment->create_and_get( array(
+                       'comment_status'   => 1,
+                       'comment_date'     => '2000-01-01 11:00:00',
+                       'comment_date_gmt' => '2000-01-01 10:00:00',
+               ) );
+
+               $this->assertSame( strtotime( '2000-01-01 10:00:00' ), strtotime( get_lastcommentmodified() ) );
+       }
+
+       public function test_blog_timezone() {
+               self::factory()->comment->create_and_get( array(
+                       'comment_status'   => 1,
+                       'comment_date'     => '2000-01-01 11:00:00',
+                       'comment_date_gmt' => '2000-01-01 10:00:00',
+               ) );
+
+               $this->assertSame( '2000-01-01 11:00:00', get_lastcommentmodified( 'blog' ) );
+       }
+
+       public function test_gmt_timezone() {
+               self::factory()->comment->create_and_get( array(
+                       'comment_status'   => 1,
+                       'comment_date'     => '2000-01-01 11:00:00',
+                       'comment_date_gmt' => '2000-01-01 10:00:00',
+               ) );
+
+               $this->assertSame( strtotime( '2000-01-01 10:00:00' ), strtotime( get_lastcommentmodified( 'GMT' ) ) );
+       }
+
+       public function test_unknown_timezone() {
+               self::factory()->comment->create_and_get( array(
+                       'comment_status'   => 1,
+                       'comment_date'     => '2000-01-01 11:00:00',
+                       'comment_date_gmt' => '2000-01-01 10:00:00',
+               ) );
+
+               $this->assertFalse( get_lastcommentmodified( 'foo' ) );
+       }
+
+       public function test_data_is_cached() {
+               self::factory()->comment->create_and_get( array(
+                       'comment_status'   => 1,
+                       'comment_date'     => '2015-04-01 11:00:00',
+                       'comment_date_gmt' => '2015-04-01 10:00:00',
+               ) );
+
+               get_lastcommentmodified();
+               $this->assertSame( strtotime( '2015-04-01 10:00:00' ), strtotime( wp_cache_get( 'lastcommentmodified:server', 'timeinfo' ) ) );
+       }
+
+       public function test_cache_is_cleared() {
+               self::factory()->comment->create_and_get( array(
+                       'comment_status'   => 1,
+                       'comment_date'     => '2000-01-01 11:00:00',
+                       'comment_date_gmt' => '2000-01-01 10:00:00',
+               ) );
+
+               get_lastcommentmodified();
+
+               $this->assertSame( strtotime( '2000-01-01 10:00:00' ), strtotime( wp_cache_get( 'lastcommentmodified:server', 'timeinfo' ) ) );
+
+               self::factory()->comment->create_and_get( array(
+                       'comment_status'   => 1,
+                       'comment_date'     => '2000-01-02 11:00:00',
+                       'comment_date_gmt' => '2000-01-02 10:00:00',
+               ) );
+
+               $this->assertFalse( wp_cache_get( 'lastcommentmodified:server', 'timeinfo' ) );
+               $this->assertSame( strtotime( '2000-01-02 10:00:00' ), strtotime( get_lastcommentmodified() ) );
+                $this->assertSame( strtotime( '2000-01-02 10:00:00' ), strtotime( wp_cache_get( 'lastcommentmodified:server', 'timeinfo' ) ) );
+       }
+
+       public function test_cache_is_cleared_when_comment_is_trashed() {
+               $comment_1 = self::factory()->comment->create_and_get( array(
+                       'comment_status'   => 1,
+                       'comment_date'     => '1998-01-01 11:00:00',
+                       'comment_date_gmt' => '1998-01-01 10:00:00',
+               ) );
+
+               $comment_2 = self::factory()->comment->create_and_get( array(
+                       'comment_status'   => 1,
+                       'comment_date'     => '2000-01-02 11:00:00',
+                       'comment_date_gmt' => '2000-01-02 10:00:00',
+               ) );
+
+               get_lastcommentmodified();
+
+               $this->assertSame( strtotime( '2000-01-02 10:00:00' ), strtotime( wp_cache_get( 'lastcommentmodified:server', 'timeinfo' ) ) );
+
+               wp_trash_comment( $comment_2->comment_ID );
+
+               $this->assertFalse( wp_cache_get( 'lastcommentmodified:server', 'timeinfo' ) );
+               $this->assertSame( strtotime( '1998-01-01 10:00:00' ), strtotime( get_lastcommentmodified() ) );
+               $this->assertSame( strtotime( '1998-01-01 10:00:00' ), strtotime( wp_cache_get( 'lastcommentmodified:server', 'timeinfo' ) ) );
+       }
+}
</ins></span></pre>
</div>
</div>

</body>
</html>