diff --git a/src/wp-includes/admin-bar.php b/src/wp-includes/admin-bar.php index 2ab30a24c27ee..99bb122ec4c36 100644 --- a/src/wp-includes/admin-bar.php +++ b/src/wp-includes/admin-bar.php @@ -385,15 +385,35 @@ function wp_admin_bar_site_menu( $wp_admin_bar ) { } $title = wp_html_excerpt( $blogname, 40, '…' ); + $meta = array( + 'menu_title' => $title, + ); + + if ( ! is_network_admin() && ! is_user_admin() ) { + /** This filter is documented in wp-includes/admin-bar.php */ + $show_site_icons = apply_filters( 'wp_admin_bar_show_site_icons', true ); + + if ( true === $show_site_icons && has_site_icon() ) { + $site_icon_url = get_site_icon_url( 32 ); + $site_icon_url_2x = get_site_icon_url( 64 ); + $srcset = ( $site_icon_url_2x && $site_icon_url !== $site_icon_url_2x ) ? sprintf( ' srcset="%s 2x"', esc_url( $site_icon_url_2x ) ) : ''; + $site_icon = sprintf( + '', + esc_url( $site_icon_url ), + $srcset + ); + + $title = $site_icon . $title; + $meta['class'] = 'has-site-icon'; + } + } $wp_admin_bar->add_node( array( 'id' => 'site-name', 'title' => $title, 'href' => ( is_admin() || ! current_user_can( 'read' ) ) ? home_url( '/' ) : admin_url(), - 'meta' => array( - 'menu_title' => $title, - ), + 'meta' => $meta, ) ); diff --git a/src/wp-includes/css/admin-bar.css b/src/wp-includes/css/admin-bar.css index 7ab855fd919bb..9d16ac41f4ae2 100644 --- a/src/wp-includes/css/admin-bar.css +++ b/src/wp-includes/css/admin-bar.css @@ -539,6 +539,10 @@ html:lang(he-il) .rtl #wpadminbar * { margin: 0 8px 2px -2px; } +#wpadminbar .quicklinks li img.blavatar { + border-radius: 2px; +} + #wpadminbar .quicklinks li div.blavatar:before { content: "\f120"; content: "\f120" / ''; @@ -584,6 +588,23 @@ html:lang(he-il) .rtl #wpadminbar * { content: "\f102" / ''; } +#wpadminbar #wp-admin-bar-site-name.has-site-icon > .ab-item { + display: flex; + align-items: center; + gap: 6px; +} + +#wpadminbar #wp-admin-bar-site-name.has-site-icon > .ab-item:before { + content: none; +} + +#wpadminbar #wp-admin-bar-site-name > .ab-item .site-icon { + width: 20px; + height: 20px; + background: #f0f0f1; /* matching my-account (user avatar) node's background */ + border-radius: 2px; +} + /** @@ -905,7 +926,7 @@ html:lang(he-il) .rtl #wpadminbar * { #wpadminbar #wp-admin-bar-edit > .ab-item:before, #wpadminbar #wp-admin-bar-my-sites > .ab-item:before, - #wpadminbar #wp-admin-bar-site-name > .ab-item:before, + #wpadminbar #wp-admin-bar-site-name:not(.has-site-icon) > .ab-item:before, #wpadminbar #wp-admin-bar-site-editor > .ab-item:before, #wpadminbar #wp-admin-bar-customize > .ab-item:before, #wpadminbar #wp-admin-bar-my-account > .ab-item:before, @@ -920,6 +941,16 @@ html:lang(he-il) .rtl #wpadminbar * { -moz-osx-font-smoothing: grayscale; } + #wpadminbar #wp-admin-bar-site-name > .ab-item .site-icon { + position: absolute; + top: 9px; + left: 12px; + width: 28px; + height: 28px; + margin: 0; + border-radius: 4px; + } + #wpadminbar #wp-admin-bar-appearance { margin-top: 0; } diff --git a/tests/phpunit/tests/adminbar.php b/tests/phpunit/tests/adminbar.php index 27308bd82760e..fb29eaf39af42 100644 --- a/tests/phpunit/tests/adminbar.php +++ b/tests/phpunit/tests/adminbar.php @@ -810,6 +810,100 @@ public function data_my_sites_network_menu_items() { ); } + /** + * @covers ::wp_admin_bar_site_menu + */ + public function test_site_name_menu_has_no_site_icon_when_unset() { + wp_set_current_user( self::$editor_id ); + + $wp_admin_bar = $this->get_standard_admin_bar(); + $node_site_name = $wp_admin_bar->get_node( 'site-name' ); + + $this->assertStringNotContainsString( 'site-icon', $node_site_name->title ); + $this->assertArrayNotHasKey( 'class', $node_site_name->meta ); + } + + /** + * @covers ::wp_admin_bar_site_menu + * @requires function imagejpeg + */ + public function test_site_name_menu_includes_site_icon_when_set() { + wp_set_current_user( self::$editor_id ); + + $attachment_id = self::factory()->attachment->create_upload_object( DIR_TESTDATA . '/images/test-image.jpg' ); + update_option( 'site_icon', $attachment_id ); + + $wp_admin_bar = $this->get_standard_admin_bar(); + $node_site_name = $wp_admin_bar->get_node( 'site-name' ); + + $this->assertStringContainsString( 'title ); + $this->assertStringContainsString( esc_url( get_site_icon_url( 32 ) ), $node_site_name->title ); + $this->assertSame( 'has-site-icon', $node_site_name->meta['class'] ); + } + + /** + * @covers ::wp_admin_bar_site_menu + * @requires function imagejpeg + */ + public function test_site_name_menu_respects_show_site_icons_filter() { + wp_set_current_user( self::$editor_id ); + + $attachment_id = self::factory()->attachment->create_upload_object( DIR_TESTDATA . '/images/test-image.jpg' ); + update_option( 'site_icon', $attachment_id ); + + add_filter( 'wp_admin_bar_show_site_icons', '__return_false' ); + + $wp_admin_bar = $this->get_standard_admin_bar(); + $node_site_name = $wp_admin_bar->get_node( 'site-name' ); + + $this->assertStringNotContainsString( 'site-icon', $node_site_name->title ); + $this->assertArrayNotHasKey( 'class', $node_site_name->meta ); + } + + /** + * @covers ::wp_admin_bar_site_menu + * @group multisite + * @group ms-required + * @requires function imagejpeg + */ + public function test_site_name_menu_has_no_site_icon_in_network_admin() { + wp_set_current_user( self::$admin_id ); + + $attachment_id = self::factory()->attachment->create_upload_object( DIR_TESTDATA . '/images/test-image.jpg' ); + update_option( 'site_icon', $attachment_id ); + + set_current_screen( 'dashboard-network' ); + + $wp_admin_bar = $this->get_standard_admin_bar(); + $node_site_name = $wp_admin_bar->get_node( 'site-name' ); + + $this->assertTrue( is_network_admin() ); + $this->assertStringNotContainsString( 'site-icon', $node_site_name->title ); + $this->assertArrayNotHasKey( 'class', $node_site_name->meta ); + } + + /** + * @covers ::wp_admin_bar_site_menu + * @group multisite + * @group ms-required + * @requires function imagejpeg + */ + public function test_site_name_menu_has_no_site_icon_in_user_admin() { + wp_set_current_user( self::$admin_id ); + + $attachment_id = self::factory()->attachment->create_upload_object( DIR_TESTDATA . '/images/test-image.jpg' ); + update_option( 'site_icon', $attachment_id ); + + set_current_screen( 'dashboard-user' ); + + $wp_admin_bar = $this->get_standard_admin_bar(); + $node_site_name = $wp_admin_bar->get_node( 'site-name' ); + + $this->assertTrue( is_user_admin() ); + $this->assertStringNotContainsString( 'site-icon', $node_site_name->title ); + $this->assertArrayNotHasKey( 'class', $node_site_name->meta ); + } + /** * This test ensures that WP_Admin_Bar::$proto is not defined (including magic methods). *