Commit 9fa0650492 for wordpress.org
commit 9fa06504926524d2aeb454e27995d71544ad9a3d
Author: westonruter <westonruter@git.wordpress.org>
Date: Fri Oct 9 03:01:53 2026 +0000
Feeds: Fix feed build date for ID-only and partial queries.
When the main query used `fields => 'ids'`, `get_feed_build_date()` passed the integer IDs to `wp_list_pluck()`, which could not read `post_modified_gmt` from them and returned an empty array, so `max()` threw a `ValueError` on PHP 8 and broke the feed. With `fields => 'id=>parent'`, the partial objects lack `post_modified_gmt`, producing a bogus build date. Post IDs and partial objects are now resolved to posts after priming the post cache in a single query, while `WP_Post` objects are read as-is so that virtual posts and in-memory changes are respected. An empty list of modified times now falls back to the last modified time of any post instead of reaching `max()`.
The `have_posts()` check is also removed, since it has side effects: for an empty query it fires the `loop_no_results` action from the feed header before the template's own loop runs, and after a completed loop it fires `loop_end` and rewinds the posts. Comments that a `get_comment` filter returned null for are skipped. These changes also resolve the PHPStan errors that were reported in the function.
Developed in https://github.com/WordPress/wordpress-develop/pull/11387.
Follow-up to r44948, r46974.
Props extrachill, westonruter, janareddy, hellofromtonya, wildworks.
See #65817.
Fixes #59956.
Built from https://develop.svn.wordpress.org/trunk@64247
git-svn-id: http://core.svn.wordpress.org/trunk@63398 1a063a9b-81f0-0310-95a4-ce76da25c4cd
diff --git a/wp-includes/feed.php b/wp-includes/feed.php
index 7f9b977656..952194c1bc 100644
--- a/wp-includes/feed.php
+++ b/wp-includes/feed.php
@@ -854,21 +854,56 @@ function get_feed_build_date( $format ) {
$max_modified_time = false;
$utc = new DateTimeZone( 'UTC' );
- if ( ! empty( $wp_query ) && $wp_query->have_posts() ) {
- // Extract the post modified times from the posts.
- $modified_times = wp_list_pluck( $wp_query->posts, 'post_modified_gmt' );
+ if ( $wp_query instanceof WP_Query && is_array( $wp_query->posts ) ) {
+ /*
+ * Collect the post modified times. WP_Post objects are read as-is, since
+ * passing them through get_post() would look them up again by ID, which
+ * drops virtual posts and discards in-memory changes. Queries using
+ * fields => 'ids' (or 'id=>parent') yield post IDs instead, which are
+ * looked up after priming the post cache to avoid a query per post.
+ */
+ $modified_times = array();
+ $post_ids = array();
+ foreach ( $wp_query->posts as $post ) {
+ if ( $post instanceof WP_Post ) {
+ $modified_times[] = $post->post_modified_gmt;
+ } elseif ( is_int( $post ) ) {
+ // A post ID, from a query with fields => 'ids'.
+ $post_ids[] = $post;
+ } elseif ( is_object( $post ) && isset( $post->ID ) && is_int( $post->ID ) ) {
+ /*
+ * A partial post object of shape object{ ID: int, post_parent: int },
+ * from a query with fields => 'id=>parent'. It lacks post_modified_gmt,
+ * so the post is looked up by its ID.
+ */
+ $post_ids[] = $post->ID;
+ }
+ }
- // If this is a comment feed, check those objects too.
- if ( $wp_query->is_comment_feed() && $wp_query->comment_count ) {
- // Extract the comment modified times from the comments.
- $comment_times = wp_list_pluck( $wp_query->comments, 'comment_date_gmt' );
+ if ( $post_ids ) {
+ _prime_post_caches( $post_ids, false, false );
+ foreach ( $post_ids as $post_id ) {
+ $post = get_post( $post_id );
+ if ( $post instanceof WP_Post ) {
+ $modified_times[] = $post->post_modified_gmt;
+ }
+ }
+ }
- // Add the comment times to the post times for comparison.
- $modified_times = array_merge( $modified_times, $comment_times );
+ // If this is a comment feed, check those objects too.
+ if ( $wp_query->is_comment_feed() && is_array( $wp_query->comments ) ) {
+ foreach ( $wp_query->comments as $comment ) {
+ // A 'get_comment' filter may have returned null for a comment.
+ if ( $comment instanceof WP_Comment ) {
+ $modified_times[] = $comment->comment_date_gmt;
+ }
+ }
}
// Determine the maximum modified time.
- $datetime = date_create_immutable_from_format( 'Y-m-d H:i:s', max( $modified_times ), $utc );
+ if ( $modified_times ) {
+ $datetime = date_create_immutable_from_format( 'Y-m-d H:i:s', max( $modified_times ), $utc );
+ }
}
if ( false === $datetime ) {
diff --git a/wp-includes/version.php b/wp-includes/version.php
index 028cec25f1..201169a775 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
-$wp_version = '7.2-alpha-64246';
+$wp_version = '7.2-alpha-64247';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.