From f5e428b13e3918533d6cc3eb2083c03833cb282d Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Mon, 15 Dec 2025 14:25:16 +1100 Subject: [PATCH 1/5] Accept and merge multiple URLs for SimplePie requests. --- src/wp-includes/feed.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/wp-includes/feed.php b/src/wp-includes/feed.php index 421bee71730d1..923ac436140e8 100644 --- a/src/wp-includes/feed.php +++ b/src/wp-includes/feed.php @@ -806,6 +806,21 @@ function fetch_feed( $url ) { require_once ABSPATH . WPINC . '/class-simplepie.php'; } + if ( is_array( $url ) && count( $url ) <= 1 ) { + $url = array_shift( $url ); + } elseif ( is_array( $url ) ) { + $feeds = array(); + foreach ( (array) $url as $feed_url ) { + $feeds[] = fetch_feed( $feed_url ); + } + $items = SimplePie\SimplePie::merge_items( $feeds ); + + $feed = new SimplePie\SimplePie(); + $feed->init(); + $feed->data['items'] = $items; + return $feed; + } + require_once ABSPATH . WPINC . '/class-wp-feed-cache-transient.php'; require_once ABSPATH . WPINC . '/class-wp-simplepie-file.php'; require_once ABSPATH . WPINC . '/class-wp-simplepie-sanitize-kses.php'; From e0f01b93c7161180a2f2a44b118a2fbfe1c070ec Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Mon, 15 Dec 2025 14:27:36 +1100 Subject: [PATCH 2/5] Test fetch and merge of multiple feeds. --- tests/phpunit/tests/feed/fetchFeed.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/phpunit/tests/feed/fetchFeed.php b/tests/phpunit/tests/feed/fetchFeed.php index 71ed1650e717a..4f6e3cee7008a 100644 --- a/tests/phpunit/tests/feed/fetchFeed.php +++ b/tests/phpunit/tests/feed/fetchFeed.php @@ -33,6 +33,28 @@ public function test_empty_charset_does_not_trigger_fatal_error() { $this->assertStringContainsString( 'Learn WordPress is a learning resource providing workshops, quizzes, courses, lesson plans, and discussion groups so that anyone, from beginners to advanced users, can learn to do more with WordPress.', $content ); } + /** + * Ensure fetch_feed() accepts multiple feeds. + * + * The main purpose of this test is to ensure that the SimplePie deprecation warning + * is not thrown when requesting multiple feeds. + * + * Secondly it confirms that the markup of the first two items match as they will + * both be from the same feed URL as the array contains the WordPress News feed twice. + * + * @ticket 64136 + */ + public function test_fetch_feed_supports_multiple_feeds() { + $feed = fetch_feed( array( 'https://wordpress.org/news/feed/', 'https://wordpress.org/news/feed/' ) ); + $content = array(); + + foreach ( $feed->get_items( 0, 2 ) as $item ) { + $content[] = $item->get_content(); + } + + $this->assertEqualHTML( $content[0], $content[1], null, 'The contents of both items should be identical.' ); + } + /** * Ensure that fetch_feed() is cached on second and subsequent calls. * From a737ed61f25d625e986e11bd090b50226e1ff317 Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Mon, 15 Dec 2025 14:31:07 +1100 Subject: [PATCH 3/5] Ensure SimplePie is initialized fully. --- src/wp-includes/feed.php | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/wp-includes/feed.php b/src/wp-includes/feed.php index 923ac436140e8..31d4f22624b2a 100644 --- a/src/wp-includes/feed.php +++ b/src/wp-includes/feed.php @@ -805,6 +805,9 @@ function fetch_feed( $url ) { if ( ! class_exists( 'SimplePie\SimplePie', false ) ) { require_once ABSPATH . WPINC . '/class-simplepie.php'; } + require_once ABSPATH . WPINC . '/class-wp-feed-cache-transient.php'; + require_once ABSPATH . WPINC . '/class-wp-simplepie-file.php'; + require_once ABSPATH . WPINC . '/class-wp-simplepie-sanitize-kses.php'; if ( is_array( $url ) && count( $url ) <= 1 ) { $url = array_shift( $url ); @@ -816,15 +819,22 @@ function fetch_feed( $url ) { $items = SimplePie\SimplePie::merge_items( $feeds ); $feed = new SimplePie\SimplePie(); + $feed->get_registry()->register( SimplePie\Sanitize::class, 'WP_SimplePie_Sanitize_KSES', true ); + $feed->sanitize = new WP_SimplePie_Sanitize_KSES(); + if ( method_exists( 'SimplePie_Cache', 'register' ) ) { + SimplePie_Cache::register( 'wp_transient', 'WP_Feed_Cache_Transient' ); + $feed->set_cache_location( 'wp_transient' ); + } else { + // Back-compat for SimplePie 1.2.x. + require_once ABSPATH . WPINC . '/class-wp-feed-cache.php'; + $feed->set_cache_class( 'WP_Feed_Cache' ); + } + $feed->get_registry()->register( SimplePie\File::class, 'WP_SimplePie_File', true ); $feed->init(); $feed->data['items'] = $items; return $feed; } - require_once ABSPATH . WPINC . '/class-wp-feed-cache-transient.php'; - require_once ABSPATH . WPINC . '/class-wp-simplepie-file.php'; - require_once ABSPATH . WPINC . '/class-wp-simplepie-sanitize-kses.php'; - $feed = new SimplePie\SimplePie(); $feed->get_registry()->register( SimplePie\Sanitize::class, 'WP_SimplePie_Sanitize_KSES', true ); From 1e227d2b9b71daf7021517c4de8dccd01d44911a Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Tue, 16 Dec 2025 10:06:12 +1100 Subject: [PATCH 4/5] De-duplicate initial set up of SimplePie. --- src/wp-includes/feed.php | 40 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/src/wp-includes/feed.php b/src/wp-includes/feed.php index 31d4f22624b2a..b796843d43e86 100644 --- a/src/wp-includes/feed.php +++ b/src/wp-includes/feed.php @@ -805,36 +805,11 @@ function fetch_feed( $url ) { if ( ! class_exists( 'SimplePie\SimplePie', false ) ) { require_once ABSPATH . WPINC . '/class-simplepie.php'; } + require_once ABSPATH . WPINC . '/class-wp-feed-cache-transient.php'; require_once ABSPATH . WPINC . '/class-wp-simplepie-file.php'; require_once ABSPATH . WPINC . '/class-wp-simplepie-sanitize-kses.php'; - if ( is_array( $url ) && count( $url ) <= 1 ) { - $url = array_shift( $url ); - } elseif ( is_array( $url ) ) { - $feeds = array(); - foreach ( (array) $url as $feed_url ) { - $feeds[] = fetch_feed( $feed_url ); - } - $items = SimplePie\SimplePie::merge_items( $feeds ); - - $feed = new SimplePie\SimplePie(); - $feed->get_registry()->register( SimplePie\Sanitize::class, 'WP_SimplePie_Sanitize_KSES', true ); - $feed->sanitize = new WP_SimplePie_Sanitize_KSES(); - if ( method_exists( 'SimplePie_Cache', 'register' ) ) { - SimplePie_Cache::register( 'wp_transient', 'WP_Feed_Cache_Transient' ); - $feed->set_cache_location( 'wp_transient' ); - } else { - // Back-compat for SimplePie 1.2.x. - require_once ABSPATH . WPINC . '/class-wp-feed-cache.php'; - $feed->set_cache_class( 'WP_Feed_Cache' ); - } - $feed->get_registry()->register( SimplePie\File::class, 'WP_SimplePie_File', true ); - $feed->init(); - $feed->data['items'] = $items; - return $feed; - } - $feed = new SimplePie\SimplePie(); $feed->get_registry()->register( SimplePie\Sanitize::class, 'WP_SimplePie_Sanitize_KSES', true ); @@ -857,6 +832,19 @@ function fetch_feed( $url ) { $feed->get_registry()->register( SimplePie\File::class, 'WP_SimplePie_File', true ); + if ( is_array( $url ) && count( $url ) <= 1 ) { + $url = array_shift( $url ); + } elseif ( is_array( $url ) ) { + $feeds = array(); + foreach ( (array) $url as $feed_url ) { + $feeds[] = fetch_feed( $feed_url ); + } + $items = SimplePie\SimplePie::merge_items( $feeds ); + $feed->init(); + $feed->data['items'] = $items; + return $feed; + } + $feed->set_feed_url( $url ); /** This filter is documented in wp-includes/class-wp-feed-cache-transient.php */ $feed->set_cache_duration( apply_filters( 'wp_feed_cache_transient_lifetime', 12 * HOUR_IN_SECONDS, $url ) ); From 33002559d355f726191fedc0175398ca2c38df31 Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Tue, 16 Dec 2025 10:08:43 +1100 Subject: [PATCH 5/5] Improve test error message. --- tests/phpunit/tests/feed/fetchFeed.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/phpunit/tests/feed/fetchFeed.php b/tests/phpunit/tests/feed/fetchFeed.php index 4f6e3cee7008a..9b191747d3e2f 100644 --- a/tests/phpunit/tests/feed/fetchFeed.php +++ b/tests/phpunit/tests/feed/fetchFeed.php @@ -52,7 +52,7 @@ public function test_fetch_feed_supports_multiple_feeds() { $content[] = $item->get_content(); } - $this->assertEqualHTML( $content[0], $content[1], null, 'The contents of both items should be identical.' ); + $this->assertEqualHTML( $content[0], $content[1], null, 'The contents of the first two items should be identical.' ); } /**