Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/block-library/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
### Bug Fixes

- Accordion Heading: Anchor notes to the selected title text instead of the whole block ([#84497](https://github.com/WordPress/gutenberg/pull/84497)).
- Cover: Decode the oEmbed iframe source before parsing it, so an embedded background video keeps the parameters the provider sent ([#83770](https://github.com/WordPress/gutenberg/pull/83770)).

## 11.2.0 (2026-10-07)

Expand Down
12 changes: 7 additions & 5 deletions packages/block-library/src/cover/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@ function render_block_core_cover( $attributes, $content ) {
$oembed_html = wp_oembed_get( $url );

if ( $oembed_html ) {
// Extract iframe src from the oEmbed HTML.
preg_match( '/src=["\']([^"\']+)["\']/', $oembed_html, $src_matches );
if ( ! empty( $src_matches[1] ) ) {
$iframe_src = $src_matches[1];

// Read the iframe src with the HTML API, which returns the attribute
// value decoded, so `&` in the query string becomes `&`.
$oembed_processor = new WP_HTML_Tag_Processor( $oembed_html );
$iframe_src = $oembed_processor->next_tag( 'IFRAME' )
? $oembed_processor->get_attribute( 'src' )
: null;
if ( is_string( $iframe_src ) && '' !== $iframe_src ) {
// Detect provider from iframe src URL.
$lower_src = strtolower( $iframe_src );
$provider = null;
Expand Down
34 changes: 34 additions & 0 deletions phpunit/blocks/render-block-cover-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,38 @@ public function test_gutenberg_render_block_core_cover_fixed_or_repeated_backgro
$this->assertStringNotContainsString( 'background-image', $rendered );
$this->assertStringNotContainsString( 'min-height', $rendered );
}

/**
* Tests that an embed background reads the iframe src, decoded, from the
* oEmbed HTML.
*
* @covers ::gutenberg_render_block_core_cover
*/
public function test_gutenberg_render_block_core_cover_embed_background_reads_decoded_iframe_src() {
$oembed_html = '<iframe data-src="https://example.com/placeholder" src="https://www.youtube.com/embed/abc123?feature=oembed&amp;si=xyz" title="Video"></iframe>';
$filter = static function () use ( $oembed_html ) {
return $oembed_html;
};
add_filter( 'pre_oembed_result', $filter );

$attributes = array(
'backgroundType' => 'embed-video',
'url' => 'https://www.youtube.com/watch?v=abc123',
);
$content = '<div class="wp-block-cover"><figure class="wp-block-embed"><div class="wp-block-embed__wrapper">https://www.youtube.com/watch?v=abc123</div></figure></div>';
$rendered = gutenberg_render_block_core_cover( $attributes, $content );

remove_filter( 'pre_oembed_result', $filter );

$processor = new WP_HTML_Tag_Processor( $rendered );
$this->assertTrue( $processor->next_tag( 'IFRAME' ), 'The rendered cover should contain an iframe.' );

$src = $processor->get_attribute( 'src' );
$this->assertSame( 'www.youtube.com', wp_parse_url( $src, PHP_URL_HOST ), 'The src should come from the src attribute, not data-src.' );

parse_str( wp_parse_url( $src, PHP_URL_QUERY ), $query_params );
$this->assertSame( 'oembed', $query_params['feature'] ?? null );
$this->assertSame( 'xyz', $query_params['si'] ?? null, 'Parameters after the first one should keep their names.' );
$this->assertArrayNotHasKey( 'amp;si', $query_params );
}
}
Loading