diff --git a/src/wp-includes/icons.php b/src/wp-includes/icons.php new file mode 100644 index 0000000000000..33f6498d50f23 --- /dev/null +++ b/src/wp-includes/icons.php @@ -0,0 +1,68 @@ +get_registered_icon( $name ); + if ( is_null( $icon ) ) { + return ''; + } + + $svg = $icon['content']; + if ( empty( $svg ) ) { + return ''; + } + + $args = wp_parse_args( + $args, + array( + 'size' => 24, + 'class' => '', + 'label' => '', + ) + ); + + $processor = new WP_HTML_Tag_Processor( $svg ); + if ( ! $processor->next_tag( 'svg' ) ) { + return ''; + } + + $processor->set_attribute( 'width', (string) $args['size'] ); + $processor->set_attribute( 'height', (string) $args['size'] ); + $processor->add_class( 'wp-icon' ); + + if ( ! empty( $args['class'] ) ) { + $processor->add_class( $args['class'] ); + } + + if ( ! empty( $args['label'] ) ) { + $processor->set_attribute( 'role', 'img' ); + $processor->set_attribute( 'aria-label', $args['label'] ); + } else { + $processor->set_attribute( 'aria-hidden', 'true' ); + } + + return $processor->get_updated_html(); +} diff --git a/src/wp-settings.php b/src/wp-settings.php index b2736bddadc3c..ac831c864c285 100644 --- a/src/wp-settings.php +++ b/src/wp-settings.php @@ -297,6 +297,7 @@ require ABSPATH . WPINC . '/class-wp-connector-registry.php'; require ABSPATH . WPINC . '/connectors.php'; require ABSPATH . WPINC . '/class-wp-icons-registry.php'; +require ABSPATH . WPINC . '/icons.php'; require ABSPATH . WPINC . '/widgets.php'; require ABSPATH . WPINC . '/class-wp-widget.php'; require ABSPATH . WPINC . '/class-wp-widget-factory.php'; diff --git a/tests/phpunit/tests/icons/wpGetIcon.php b/tests/phpunit/tests/icons/wpGetIcon.php new file mode 100644 index 0000000000000..33911b1b38faf --- /dev/null +++ b/tests/phpunit/tests/icons/wpGetIcon.php @@ -0,0 +1,97 @@ +assertStringStartsWith( 'assertStringContainsString( '', $output ); + } + + /** + * @ticket 64847 + */ + public function test_wp_get_icon_returns_empty_string_for_unknown_icon() { + $output = wp_get_icon( 'this-icon-does-not-exist' ); + $this->assertSame( '', $output ); + } + + /** + * @ticket 64847 + */ + public function test_wp_get_icon_default_attributes() { + $output = wp_get_icon( 'core/plus' ); + // WP_HTML_Tag_Processor lowercases attribute names. + $this->assertStringContainsString( 'viewbox="0 0 24 24"', $output ); + $this->assertStringContainsString( 'width="24"', $output ); + $this->assertStringContainsString( 'height="24"', $output ); + $this->assertStringContainsString( 'class="wp-icon"', $output ); + $this->assertStringContainsString( 'aria-hidden="true"', $output ); + } + + /** + * @ticket 64847 + */ + public function test_wp_get_icon_custom_size() { + $output = wp_get_icon( 'core/plus', array( 'size' => 32 ) ); + $this->assertStringContainsString( 'width="32"', $output ); + $this->assertStringContainsString( 'height="32"', $output ); + } + + /** + * @ticket 64847 + */ + public function test_wp_get_icon_custom_class() { + $output = wp_get_icon( 'core/plus', array( 'class' => 'my-button-icon' ) ); + $this->assertStringContainsString( 'class="wp-icon my-button-icon"', $output ); + } + + /** + * @ticket 64847 + */ + public function test_wp_get_icon_with_label() { + $output = wp_get_icon( 'core/plus', array( 'label' => 'Add item' ) ); + $this->assertStringContainsString( 'role="img"', $output ); + $this->assertStringContainsString( 'aria-label="Add item"', $output ); + $this->assertStringNotContainsString( 'aria-hidden', $output ); + } + + /** + * @ticket 64847 + */ + public function test_wp_get_icon_without_label_is_hidden() { + $output = wp_get_icon( 'core/plus' ); + $this->assertStringContainsString( 'aria-hidden="true"', $output ); + $this->assertStringNotContainsString( 'role="img"', $output ); + $this->assertStringNotContainsString( 'aria-label', $output ); + } + + /** + * @ticket 64847 + */ + public function test_wp_get_icon_contains_svg_content() { + $output = wp_get_icon( 'core/plus' ); + $this->assertStringContainsString( ' '">' ) ); + $this->assertStringNotContainsString( '