Skip to content

Commit 68cbdc9

Browse files
committed
Embeds: Preserve the site icon fallback URL.
Previously, `get_site_icon_url()` overwrote a caller-supplied fallback URL with the return value of `wp_get_attachment_image_url()` even when that lookup returned `false`, so a defined fallback (such as the bundled WordPress logo) was silently discarded whenever the assigned site icon attachment could not be resolved. Only update the URL when a non-empty attachment URL is returned. Additionally, `the_embed_site_title()` now renders the site icon `<img>` only when a URL is available, and omits the `srcset` attribute when the 2x URL is missing or identical to the 1x URL. This avoids the malformed markup (an empty `src` and a bare ` 2x` `srcset`) that produced a broken image and spurious requests in oEmbed cards. Developed in WordPress#11601. Follow-up to r35571, r36693, r47832. Props sukhendu2002, sabernhardt, mukesh27, westonruter, pontocinza, mohamedahamed, abcd95, manhar, rollybueno. Fixes #65098. git-svn-id: https://develop.svn.wordpress.org/trunk@62502 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 73ed971 commit 68cbdc9

3 files changed

Lines changed: 137 additions & 5 deletions

File tree

src/wp-includes/embed.php

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,12 +1232,25 @@ function print_embed_sharing_dialog() {
12321232
*
12331233
* @since 4.5.0
12341234
*/
1235-
function the_embed_site_title() {
1235+
function the_embed_site_title(): void {
1236+
$fallback_icon_url = includes_url( 'images/w-logo-blue.png' );
1237+
$site_icon_url = get_site_icon_url( 32, $fallback_icon_url );
1238+
1239+
$icon_img = '';
1240+
if ( $site_icon_url ) {
1241+
$site_icon_url_2x = get_site_icon_url( 64, $fallback_icon_url );
1242+
$srcset = ( $site_icon_url_2x && $site_icon_url !== $site_icon_url_2x ) ? sprintf( ' srcset="%s 2x"', esc_url( $site_icon_url_2x ) ) : '';
1243+
$icon_img = sprintf(
1244+
'<img src="%s"%s width="32" height="32" alt="" class="wp-embed-site-icon" />',
1245+
esc_url( $site_icon_url ),
1246+
$srcset
1247+
);
1248+
}
1249+
12361250
$site_title = sprintf(
1237-
'<a href="%s" target="_top"><img src="%s" srcset="%s 2x" width="32" height="32" alt="" class="wp-embed-site-icon" /><span>%s</span></a>',
1251+
'<a href="%s" target="_top">%s<span>%s</span></a>',
12381252
esc_url( home_url() ),
1239-
esc_url( get_site_icon_url( 32, includes_url( 'images/w-logo-blue.png' ) ) ),
1240-
esc_url( get_site_icon_url( 64, includes_url( 'images/w-logo-blue.png' ) ) ),
1253+
$icon_img,
12411254
esc_html( get_bloginfo( 'name' ) )
12421255
);
12431256

src/wp-includes/general-template.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -978,7 +978,10 @@ function get_site_icon_url( $size = 512, $url = '', $blog_id = 0 ) {
978978
} else {
979979
$size_data = array( $size, $size );
980980
}
981-
$url = wp_get_attachment_image_url( $site_icon_id, $size_data );
981+
$attachment_url = wp_get_attachment_image_url( $site_icon_id, $size_data );
982+
if ( $attachment_url ) {
983+
$url = $attachment_url;
984+
}
982985
}
983986

984987
if ( $switched_blog ) {

tests/phpunit/tests/general/template.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,22 @@ public function test_get_site_icon_url() {
122122
$this->assertEmpty( get_site_icon_url(), 'Site icon URL should not be set after removal.' );
123123
}
124124

125+
/**
126+
* @ticket 65098
127+
* @group site_icon
128+
* @covers ::get_site_icon_url
129+
* @requires function imagejpeg
130+
*/
131+
public function test_get_site_icon_url_returns_fallback_when_attachment_url_fails(): void {
132+
$this->set_site_icon();
133+
134+
$fallback = 'https://example.com/fallback-icon.png';
135+
add_filter( 'wp_get_attachment_image_src', '__return_false' );
136+
$url = get_site_icon_url( 32, $fallback );
137+
138+
$this->assertSame( $fallback, $url, 'Fallback URL should be returned when attachment URL lookup fails.' );
139+
}
140+
125141
/**
126142
* @group site_icon
127143
* @covers ::site_icon_url
@@ -807,4 +823,104 @@ public function test_get_the_archive_title_is_correct_for_author_queries() {
807823
$this->assertSame( $user_with_posts->display_name, $title_when_posts );
808824
$this->assertSame( $user_with_no_posts->display_name, $title_when_no_posts );
809825
}
826+
827+
/**
828+
* @ticket 65098
829+
* @group site_icon
830+
* @covers ::the_embed_site_title
831+
* @requires function imagejpeg
832+
*/
833+
public function test_the_embed_site_title_contains_site_icon_when_set(): void {
834+
$this->set_site_icon();
835+
836+
$url_32 = get_site_icon_url( 32 );
837+
$url_64 = get_site_icon_url( 64 );
838+
839+
$output = get_echo( 'the_embed_site_title' );
840+
$processor = new WP_HTML_Tag_Processor( $output );
841+
842+
$this->assertTrue( $processor->next_tag( 'IMG' ), 'Expected IMG tag.' );
843+
$this->assertTrue( $processor->has_class( 'wp-embed-site-icon' ), 'Expected IMG to have wp-embed-site-icon class.' );
844+
$this->assertSame( $url_32, $processor->get_attribute( 'src' ), 'Output should contain 32px site icon URL in src.' );
845+
$srcset = $processor->get_attribute( 'srcset' );
846+
$this->assertIsString( $srcset, 'Expected srcset to be present.' );
847+
$this->assertStringContainsString( $url_64, $srcset, 'Output should contain 64px site icon URL in srcset.' );
848+
}
849+
850+
/**
851+
* @ticket 65098
852+
* @group site_icon
853+
* @covers ::the_embed_site_title
854+
* @requires function imagejpeg
855+
*/
856+
public function test_the_embed_site_title_uses_fallback_when_attachment_url_fails(): void {
857+
$this->set_site_icon();
858+
859+
// Simulate wp_get_attachment_image_url() failing.
860+
add_filter( 'wp_get_attachment_image_src', '__return_false' );
861+
$output = get_echo( 'the_embed_site_title' );
862+
863+
$fallback = includes_url( 'images/w-logo-blue.png' );
864+
$processor = new WP_HTML_Tag_Processor( $output );
865+
866+
$this->assertTrue( $processor->next_tag( 'IMG' ), 'Expected IMG tag with fallback.' );
867+
$this->assertTrue( $processor->has_class( 'wp-embed-site-icon' ), 'Expected IMG to have wp-embed-site-icon class.' );
868+
$this->assertSame( $fallback, $processor->get_attribute( 'src' ), 'Output should contain fallback URL in src when attachment URL fails.' );
869+
}
870+
871+
/**
872+
* @ticket 65098
873+
* @group site_icon
874+
* @covers ::the_embed_site_title
875+
*/
876+
public function test_the_embed_site_title_omits_img_when_url_is_empty(): void {
877+
// Force get_site_icon_url() to return empty string via filter.
878+
add_filter( 'get_site_icon_url', '__return_empty_string' );
879+
$output = get_echo( 'the_embed_site_title' );
880+
881+
$processor = new WP_HTML_Tag_Processor( $output );
882+
883+
$this->assertFalse( $processor->next_tag( 'IMG' ), 'IMG tag should be omitted when URL is empty.' );
884+
$this->assertStringContainsString( get_bloginfo( 'name' ), $output, 'Site name should still be present.' );
885+
}
886+
887+
/**
888+
* @ticket 65098
889+
* @group site_icon
890+
* @covers ::the_embed_site_title
891+
*/
892+
public function test_the_embed_site_title_omits_srcset_when_1x_and_2x_urls_are_identical(): void {
893+
// Force both sizes to return the same URL.
894+
$svg_url = 'https://example.com/icon.svg';
895+
$filter = static function () use ( $svg_url ) {
896+
return $svg_url;
897+
};
898+
899+
add_filter( 'get_site_icon_url', $filter );
900+
$output = get_echo( 'the_embed_site_title' );
901+
902+
$processor = new WP_HTML_Tag_Processor( $output );
903+
904+
$this->assertTrue( $processor->next_tag( 'IMG' ), 'Expected IMG tag.' );
905+
$this->assertTrue( $processor->has_class( 'wp-embed-site-icon' ), 'Expected IMG to have wp-embed-site-icon class.' );
906+
$this->assertSame( $svg_url, $processor->get_attribute( 'src' ), '1x URL should be present in src.' );
907+
$this->assertNull( $processor->get_attribute( 'srcset' ), 'srcset should be omitted when 1x and 2x URLs are identical.' );
908+
}
909+
910+
/**
911+
* @ticket 65098
912+
* @group site_icon
913+
* @covers ::the_embed_site_title
914+
*/
915+
public function test_the_embed_site_title_uses_fallback_without_srcset_when_no_site_icon_set(): void {
916+
$output = get_echo( 'the_embed_site_title' );
917+
$fallback = includes_url( 'images/w-logo-blue.png' );
918+
919+
$processor = new WP_HTML_Tag_Processor( $output );
920+
921+
$this->assertTrue( $processor->next_tag( 'IMG' ), 'Expected IMG tag with fallback.' );
922+
$this->assertTrue( $processor->has_class( 'wp-embed-site-icon' ), 'Expected IMG to have wp-embed-site-icon class.' );
923+
$this->assertSame( $fallback, $processor->get_attribute( 'src' ), 'Output should contain fallback icon URL in src.' );
924+
$this->assertNull( $processor->get_attribute( 'srcset' ), 'srcset should be omitted when 1x and 2x fallback URLs are identical.' );
925+
}
810926
}

0 commit comments

Comments
 (0)