diff --git a/src/wp-includes/blocks/rss.php b/src/wp-includes/blocks/rss.php index 85e4e63c9dbf7..6efa547c5fb61 100644 --- a/src/wp-includes/blocks/rss.php +++ b/src/wp-includes/blocks/rss.php @@ -43,15 +43,18 @@ function render_block_core_rss( $attributes ) { } $title = "
{$title}
"; - $date = ''; - if ( $attributes['displayDate'] ) { - $date = $item->get_date( 'U' ); + $date_markup = ''; + if ( ! empty( $attributes['displayDate'] ) ) { + $timestamp = $item->get_date( 'U' ); - if ( $date ) { - $date = sprintf( + if ( $timestamp ) { + $gmt_offset = get_option( 'gmt_offset' ); + $timestamp += (int) ( (float) $gmt_offset * HOUR_IN_SECONDS ); + + $date_markup = sprintf( ' ', - esc_attr( date_i18n( 'c', $date ) ), - esc_attr( date_i18n( get_option( 'date_format' ), $date ) ) + esc_attr( date_i18n( 'c', $timestamp ) ), + esc_html( date_i18n( get_option( 'date_format' ), $timestamp ) ) ); } } @@ -85,7 +88,7 @@ function render_block_core_rss( $attributes ) { $excerpt = '
' . esc_html( $excerpt ) . '
'; } - $list_items .= "
  • {$title}{$date}{$author}{$excerpt}
  • "; + $list_items .= "
  • {$title}{$date_markup}{$author}{$excerpt}
  • "; } $classnames = array(); diff --git a/tests/phpunit/data/feed/feed-with-gmt-offset.xml b/tests/phpunit/data/feed/feed-with-gmt-offset.xml new file mode 100644 index 0000000000000..f3ea0e2aee24e --- /dev/null +++ b/tests/phpunit/data/feed/feed-with-gmt-offset.xml @@ -0,0 +1,31 @@ + + + +Test RSS Feed +https://www.example.com + +This is a test RSS feed for unit testing. +en-us +Wed, 19 Mar 2025 00:00:01 -0700 +Wed, 19 Mar 2025 03:58:04 -0700 +Test + +Test Article 1 +https://www.example.com/article1 +https://www.example.com/article1 +Test Author +This is a test article description. +Thu, 10 Mar 2025 04:00:00 -0700 +Test Source + + +Test Article 2 +https://www.example.com/article2 +https://www.example.com/article2 +Test Author 2 +This is another test article description. +Wed, 18 Mar 2025 10:30:00 -0700 +Test Source + + + \ No newline at end of file diff --git a/tests/phpunit/tests/blocks/renderRssBlock.php b/tests/phpunit/tests/blocks/renderRssBlock.php new file mode 100644 index 0000000000000..fee0ebd29c385 --- /dev/null +++ b/tests/phpunit/tests/blocks/renderRssBlock.php @@ -0,0 +1,111 @@ + array( + 'content-type' => 'application/rss+xml; charset=UTF-8', + ), + // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents + 'body' => file_get_contents( DIR_TESTDATA . '/feed/feed-with-gmt-offset.xml' ), + 'response' => array( + 'code' => 200, + 'message' => 'OK', + ), + 'cookies' => array(), + 'filename' => null, + ); + } + + /** + * Sets up the "core/rss" block context for testing. + * This is needed to avoid null access in WP_Block_Supports::apply_block_supports(). + * + * @ticket 62400 + */ + private function setup_block_context() { + $block = array( + 'blockName' => 'core/rss', + 'attrs' => array(), + ); + + $wp_block_supports = WP_Block_Supports::get_instance(); + $reflection = new ReflectionClass( $wp_block_supports ); + $property = $reflection->getProperty( 'block_to_render' ); + $property->setAccessible( true ); + $property->setValue( $wp_block_supports, $block ); + } + + /** + * Test that the date in the RSS feed is correctly rendered in the HTML. + * + * @ticket 62400 + * + * @covers ::render_block_core_rss + */ + public function test_rss_date_rendering() { + + update_option( 'date_format', 'F j, Y' ); + // We set to UTC+9 to test timezone conversion. + update_option( 'gmt_offset', 9 ); + + $this->setup_block_context(); + + // Mock RSS Attributes. + $attributes = array( + 'feedURL' => 'https://example.com/testrss.xml', + 'itemsToShow' => 2, + 'displayExcerpt' => false, + 'displayAuthor' => false, + 'displayDate' => true, + 'blockLayout' => 'list', + ); + + $rendered_html = render_block_core_rss( $attributes ); + + $this->assertStringContainsString( '