Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
19 changes: 16 additions & 3 deletions src/wp-includes/embed.php
Original file line number Diff line number Diff line change
Expand Up @@ -1233,11 +1233,24 @@ function print_embed_sharing_dialog() {
* @since 4.5.0
*/
function the_embed_site_title() {
$fallback_icon_url = includes_url( 'images/w-logo-blue.png' );
$site_icon_url = get_site_icon_url( 32, $fallback_icon_url );

$icon_img = '';
if ( $site_icon_url ) {
$site_icon_url_2x = get_site_icon_url( 64, $fallback_icon_url );
$srcset = ( $site_icon_url_2x && $site_icon_url !== $site_icon_url_2x ) ? sprintf( ' srcset="%s 2x"', esc_url( $site_icon_url_2x ) ) : '';
$icon_img = sprintf(
'<img src="%s"%s width="32" height="32" alt="" class="wp-embed-site-icon" />',
esc_url( $site_icon_url ),
$srcset
);
}

$site_title = sprintf(
'<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>',
'<a href="%s" target="_top">%s<span>%s</span></a>',
esc_url( home_url() ),
esc_url( get_site_icon_url( 32, includes_url( 'images/w-logo-blue.png' ) ) ),
esc_url( get_site_icon_url( 64, includes_url( 'images/w-logo-blue.png' ) ) ),
$icon_img,
esc_html( get_bloginfo( 'name' ) )
);

Expand Down
5 changes: 4 additions & 1 deletion src/wp-includes/general-template.php
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,10 @@ function get_site_icon_url( $size = 512, $url = '', $blog_id = 0 ) {
} else {
$size_data = array( $size, $size );
}
$url = wp_get_attachment_image_url( $site_icon_id, $size_data );
$attachment_url = wp_get_attachment_image_url( $site_icon_id, $size_data );
if ( $attachment_url ) {
$url = $attachment_url;
}
}

if ( $switched_blog ) {
Expand Down
13 changes: 11 additions & 2 deletions tests/phpunit/includes/utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -432,10 +432,19 @@ function dmp_filter( $a ) {
return $a;
}

function get_echo( $callback, $args = array() ) {
/**
* Gets the output of a given callback via output buffering.
*
* The return value of the callback is disregarded.
*
* @param callable $callback Callback to capture the output from.
* @param array<int, mixed> $args The positional params to pass to the callback.
* @return string Output buffer.
*/
function get_echo( callable $callback, array $args = array() ): string {
ob_start();
call_user_func_array( $callback, $args );
return ob_get_clean();
return (string) ob_get_clean();
}

// Recursively generate some quick assertEquals() tests based on an array.
Expand Down
115 changes: 115 additions & 0 deletions tests/phpunit/tests/general/template.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,22 @@ public function test_get_site_icon_url() {
$this->assertEmpty( get_site_icon_url(), 'Site icon URL should not be set after removal.' );
}

/**
* @ticket 65098
* @group site_icon
* @covers ::get_site_icon_url
* @requires function imagejpeg
*/
public function test_get_site_icon_url_returns_fallback_when_attachment_url_fails(): void {
$this->set_site_icon();

$fallback = 'https://example.com/fallback-icon.png';
add_filter( 'wp_get_attachment_image_src', '__return_false' );
$url = get_site_icon_url( 32, $fallback );

$this->assertSame( $fallback, $url, 'Fallback URL should be returned when attachment URL lookup fails.' );
}

/**
* @group site_icon
* @covers ::site_icon_url
Expand Down Expand Up @@ -807,4 +823,103 @@ public function test_get_the_archive_title_is_correct_for_author_queries() {
$this->assertSame( $user_with_posts->display_name, $title_when_posts );
$this->assertSame( $user_with_no_posts->display_name, $title_when_no_posts );
}

/**
* @ticket 65098
* @group site_icon
* @covers ::the_embed_site_title
* @requires function imagejpeg
*/
public function test_the_embed_site_title_contains_site_icon_when_set(): void {
$this->set_site_icon();

$url_32 = get_site_icon_url( 32 );
$url_64 = get_site_icon_url( 64 );

$output = get_echo( 'the_embed_site_title' );
$processor = new WP_HTML_Tag_Processor( $output );

$this->assertTrue( $processor->next_tag( 'IMG' ), 'Expected IMG tag.' );
$this->assertTrue( $processor->has_class( 'wp-embed-site-icon' ), 'Expected IMG to have wp-embed-site-icon class.' );
$this->assertSame( $url_32, $processor->get_attribute( 'src' ), 'Output should contain 32px site icon URL in src.' );
$srcset = $processor->get_attribute( 'srcset' );
$this->assertIsString( $srcset, 'Expected srcset to be present.' );
$this->assertStringContainsString( $url_64, $srcset, 'Output should contain 64px site icon URL in srcset.' );
}

/**
* @ticket 65098
* @group site_icon
* @covers ::the_embed_site_title
* @requires function imagejpeg
*/
public function test_the_embed_site_title_uses_fallback_when_attachment_url_fails(): void {
$this->set_site_icon();

// Simulate wp_get_attachment_image_url() failing.
add_filter( 'wp_get_attachment_image_src', '__return_false' );
$output = get_echo( 'the_embed_site_title' );

$fallback = includes_url( 'images/w-logo-blue.png' );
$processor = new WP_HTML_Tag_Processor( $output );

$this->assertTrue( $processor->next_tag( 'IMG' ), 'Expected IMG tag with fallback.' );
$this->assertTrue( $processor->has_class( 'wp-embed-site-icon' ), 'Expected IMG to have wp-embed-site-icon class.' );
$this->assertSame( $fallback, $processor->get_attribute( 'src' ), 'Output should contain fallback URL in src when attachment URL fails.' );
}

/**
* @ticket 65098
* @group site_icon
* @covers ::the_embed_site_title
*/
public function test_the_embed_site_title_omits_img_when_url_is_empty(): void {
// Force get_site_icon_url() to return empty string via filter.
add_filter( 'get_site_icon_url', '__return_empty_string' );
$output = get_echo( 'the_embed_site_title' );

$processor = new WP_HTML_Tag_Processor( $output );

$this->assertFalse( $processor->next_tag( 'IMG' ), 'IMG tag should be omitted when URL is empty.' );
$this->assertStringContainsString( get_bloginfo( 'name' ), $output, 'Site name should still be present.' );
}

/**
* @ticket 65098
* @group site_icon
* @covers ::the_embed_site_title
*/
public function test_the_embed_site_title_omits_srcset_when_1x_and_2x_urls_are_identical(): void {
// Force both sizes to return the same URL.
$svg_url = 'https://example.com/icon.svg';
$filter = static function () use ( $svg_url ) {
return $svg_url;
};

add_filter( 'get_site_icon_url', $filter );
$output = get_echo( 'the_embed_site_title' );

$processor = new WP_HTML_Tag_Processor( $output );

$this->assertTrue( $processor->next_tag( 'IMG' ), 'Expected IMG tag.' );
$this->assertSame( $svg_url, $processor->get_attribute( 'src' ), '1x URL should be present in src.' );
Comment on lines +904 to +905
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$this->assertTrue( $processor->next_tag( 'IMG' ), 'Expected IMG tag.' );
$this->assertSame( $svg_url, $processor->get_attribute( 'src' ), '1x URL should be present in src.' );
$this->assertTrue( $processor->next_tag( 'IMG' ), 'Expected IMG tag.' );
$this->assertTrue( $processor->has_class( 'wp-embed-site-icon' ), 'Expected IMG to have wp-embed-site-icon class.' );
$this->assertSame( $svg_url, $processor->get_attribute( 'src' ), '1x URL should be present in src.' );

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker ☝️

$this->assertNull( $processor->get_attribute( 'srcset' ), 'srcset should be omitted when 1x and 2x URLs are identical.' );
}

/**
* @ticket 65098
* @group site_icon
* @covers ::the_embed_site_title
*/
public function test_the_embed_site_title_uses_fallback_without_srcset_when_no_site_icon_set(): void {
$output = get_echo( 'the_embed_site_title' );
$fallback = includes_url( 'images/w-logo-blue.png' );

$processor = new WP_HTML_Tag_Processor( $output );

$this->assertTrue( $processor->next_tag( 'IMG' ), 'Expected IMG tag with fallback.' );
$this->assertTrue( $processor->has_class( 'wp-embed-site-icon' ), 'Expected IMG to have wp-embed-site-icon class.' );
$this->assertSame( $fallback, $processor->get_attribute( 'src' ), 'Output should contain fallback icon URL in src.' );
$this->assertNull( $processor->get_attribute( 'srcset' ), 'srcset should be omitted when 1x and 2x fallback URLs are identical.' );
}
}
Loading