From c6284a0475fe2ae71cafb45dc3e66a004adc2805 Mon Sep 17 00:00:00 2001 From: asadister <77143123+asadister@users.noreply.github.com> Date: Tue, 4 Nov 2025 12:56:21 +0330 Subject: [PATCH 1/6] Update class-wp-styles.php ### Summary Adds support for loading `ltr.css` in RTL-based multilingual WordPress sites, mirroring the existing `rtl.css` behavior. ### Details - Introduces `wp_style_add_data( $handle, 'ltr', 'replace' )` and `'suffix'` modes - Uses `extra['ltr']` and `_css_href()` for consistent file resolution - Applies `style_loader_tag` filter for extensibility - Ensures compatibility with single-file enqueue behavior in WordPress Core ### Trac Ticket See: https://core.trac.wordpress.org/ticket/64193 --- src/wp-includes/class-wp-styles.php | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/wp-includes/class-wp-styles.php b/src/wp-includes/class-wp-styles.php index 9d6d5b5dd2460..4b7199554e5dd 100644 --- a/src/wp-includes/class-wp-styles.php +++ b/src/wp-includes/class-wp-styles.php @@ -271,6 +271,34 @@ public function do_item( $handle, $group = false ) { $tag .= $rtl_tag; } } + + if ( 'rtl' !== $this->text_direction && isset( $obj->extra['ltr'] ) && $obj->extra['ltr'] ) { + if ( is_bool( $obj->extra['ltr'] ) || 'replace' === $obj->extra['ltr'] ) { + $suffix = isset( $obj->extra['suffix'] ) ? $obj->extra['suffix'] : ''; + $ltr_href = str_replace( "{$suffix}.css", "-ltr{$suffix}.css", $this->_css_href( $src, $ver, "$handle-ltr" ) ); + } else { + $ltr_href = $this->_css_href( $obj->extra['ltr'], $ver, "$handle-ltr" ); + } + + $ltr_tag = sprintf( + "\n", + $rel, + esc_attr( $handle ), + $title ? sprintf( " title='%s'", esc_attr( $title ) ) : '', + $ltr_href, + $this->type_attr, + esc_attr( $media ) + ); + + /** This filter is documented in wp-includes/class-wp-styles.php */ + $ltr_tag = apply_filters( 'style_loader_tag', $ltr_tag, $handle, $ltr_href, $media ); + + if ( 'replace' === $obj->extra['ltr'] ) { + $tag = $ltr_tag; + } else { + $tag .= $ltr_tag; + } + } if ( $this->do_concat ) { $this->print_html .= $tag; From 23d1a5d106155e51f2347a48472168a9f31d7f21 Mon Sep 17 00:00:00 2001 From: asadister <77143123+asadister@users.noreply.github.com> Date: Tue, 4 Nov 2025 13:41:09 +0330 Subject: [PATCH 2/6] Fix coding standards remove trailing whitespace on line 274 --- src/wp-includes/class-wp-styles.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/class-wp-styles.php b/src/wp-includes/class-wp-styles.php index 4b7199554e5dd..fc839ca8e433e 100644 --- a/src/wp-includes/class-wp-styles.php +++ b/src/wp-includes/class-wp-styles.php @@ -271,7 +271,7 @@ public function do_item( $handle, $group = false ) { $tag .= $rtl_tag; } } - + if ( 'rtl' !== $this->text_direction && isset( $obj->extra['ltr'] ) && $obj->extra['ltr'] ) { if ( is_bool( $obj->extra['ltr'] ) || 'replace' === $obj->extra['ltr'] ) { $suffix = isset( $obj->extra['suffix'] ) ? $obj->extra['suffix'] : ''; From 34f68ab31a06cc6adfe550dfe141f073d5d5eed4 Mon Sep 17 00:00:00 2001 From: Asadister Date: Thu, 6 Nov 2025 16:19:22 +0330 Subject: [PATCH 3/6] Add unit tests for LTR CSS support including metadata and output rendering. Props @asadister. See #64193 --- .../tests/dependencies/stylesLTRSupport.php | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 tests/phpunit/tests/dependencies/stylesLTRSupport.php diff --git a/tests/phpunit/tests/dependencies/stylesLTRSupport.php b/tests/phpunit/tests/dependencies/stylesLTRSupport.php new file mode 100644 index 0000000000000..43cf0c0e39b6c --- /dev/null +++ b/tests/phpunit/tests/dependencies/stylesLTRSupport.php @@ -0,0 +1,51 @@ +registered = []; + } + + public function tear_down(): void { + restore_previous_locale(); + parent::tear_down(); + } + + public function test_ltr_css_replace_data_is_set() { + $handle = 'sample-style'; + wp_register_style( $handle, 'https://example.com/style.css' ); + wp_style_add_data( $handle, 'ltr', 'replace' ); + + $styles = wp_styles(); + $this->assertArrayHasKey( 'ltr', $styles->registered[ $handle ]->extra ); + $this->assertSame( 'replace', $styles->registered[ $handle ]->extra['ltr'] ); + } + + public function test_ltr_css_suffix_data_is_set() { + $handle = 'sample-style-suffix'; + wp_register_style( $handle, 'https://example.com/style.min.css' ); + wp_style_add_data( $handle, 'ltr', 'suffix' ); + + $styles = wp_styles(); + $this->assertArrayHasKey( 'ltr', $styles->registered[ $handle ]->extra ); + $this->assertSame( 'suffix', $styles->registered[ $handle ]->extra['ltr'] ); + } + + public function test_no_ltr_data_for_ltr_locale() { + restore_previous_locale(); + switch_to_locale( 'en_US' ); // LTR language + + $handle = 'sample-style-ltr'; + wp_register_style( $handle, 'https://example.com/style.css' ); + wp_style_add_data( $handle, 'ltr', 'replace' ); + + $styles = wp_styles(); + $this->assertArrayHasKey( 'ltr', $styles->registered[ $handle ]->extra ); + $this->assertSame( 'replace', $styles->registered[ $handle ]->extra['ltr'] ); + } +} From 70a36511fc2deb22ac0f112c0bc5b471d915cbf1 Mon Sep 17 00:00:00 2001 From: asadister <77143123+asadister@users.noreply.github.com> Date: Thu, 6 Nov 2025 16:56:46 +0330 Subject: [PATCH 4/6] Fix: use long array syntax for WPCS compliance Replaced short array syntax `[]` with `array()` to meet WordPress Coding Standards. --- tests/phpunit/tests/dependencies/stylesLTRSupport.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/phpunit/tests/dependencies/stylesLTRSupport.php b/tests/phpunit/tests/dependencies/stylesLTRSupport.php index 43cf0c0e39b6c..8359f56858072 100644 --- a/tests/phpunit/tests/dependencies/stylesLTRSupport.php +++ b/tests/phpunit/tests/dependencies/stylesLTRSupport.php @@ -8,7 +8,7 @@ class Tests_Dependencies_StylesLtrSupport extends WP_UnitTestCase { public function set_up(): void { parent::set_up(); switch_to_locale( 'fa_IR' ); // RTL language - wp_styles()->registered = []; + wp_styles()->registered = array(); } public function tear_down(): void { From 86bd3588466de9f37c5057089b659203189566c7 Mon Sep 17 00:00:00 2001 From: asadister <77143123+asadister@users.noreply.github.com> Date: Thu, 6 Nov 2025 19:21:35 +0330 Subject: [PATCH 5/6] Implement tests for LTR stylesheet handling Adds unit tests verifying LTR stylesheet support in wp_register_style() and wp_print_styles(). - Confirms that `wp_style_add_data()` correctly stores 'ltr' data (replace/suffix modes). - Ensures LTR stylesheets are printed after their main styles in HTML output. - Covers both RTL and LTR locale cases. - Marks `print_emoji_styles` as expected deprecated to prevent false failures. Props asadister. See [#64193](https://core.trac.wordpress.org/ticket/64193). --- .../tests/dependencies/stylesLTRSupport.php | 57 ++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/tests/phpunit/tests/dependencies/stylesLTRSupport.php b/tests/phpunit/tests/dependencies/stylesLTRSupport.php index 8359f56858072..e1c3cc343a12c 100644 --- a/tests/phpunit/tests/dependencies/stylesLTRSupport.php +++ b/tests/phpunit/tests/dependencies/stylesLTRSupport.php @@ -1,13 +1,21 @@ registered = array(); } @@ -16,6 +24,9 @@ public function tear_down(): void { parent::tear_down(); } + /** + * @ticket 64193 + */ public function test_ltr_css_replace_data_is_set() { $handle = 'sample-style'; wp_register_style( $handle, 'https://example.com/style.css' ); @@ -26,6 +37,9 @@ public function test_ltr_css_replace_data_is_set() { $this->assertSame( 'replace', $styles->registered[ $handle ]->extra['ltr'] ); } + /** + * @ticket 64193 + */ public function test_ltr_css_suffix_data_is_set() { $handle = 'sample-style-suffix'; wp_register_style( $handle, 'https://example.com/style.min.css' ); @@ -36,6 +50,9 @@ public function test_ltr_css_suffix_data_is_set() { $this->assertSame( 'suffix', $styles->registered[ $handle ]->extra['ltr'] ); } + /** + * @ticket 64193 + */ public function test_no_ltr_data_for_ltr_locale() { restore_previous_locale(); switch_to_locale( 'en_US' ); // LTR language @@ -48,4 +65,42 @@ public function test_no_ltr_data_for_ltr_locale() { $this->assertArrayHasKey( 'ltr', $styles->registered[ $handle ]->extra ); $this->assertSame( 'replace', $styles->registered[ $handle ]->extra['ltr'] ); } + + /** + * Verify that an LTR stylesheet is printed after its main stylesheet in the HTML output. + * + * @group output + * @ticket 64193 + * @expectedDeprecated print_emoji_styles + */ + public function test_ltr_stylesheet_is_printed_in_output() { + global $wp_styles; + + // Reset styles registry to ensure a clean environment. + $wp_styles = null; + wp_styles(); + + // Register main style. + wp_register_style( 'ltr-test-style', 'http://example.com/css/style.css', array(), '1.0' ); + + // Mark this style as having an LTR variant. + wp_style_add_data( 'ltr-test-style', 'ltr', true ); + + // Enqueue the style. + wp_enqueue_style( 'ltr-test-style' ); + + // Capture printed output. + ob_start(); + wp_print_styles(); + $output = ob_get_clean(); + + // Assertions. + $this->assertStringContainsString( 'style.css', $output, 'Main stylesheet was not printed in output.' ); + $this->assertStringContainsString( 'ltr.css', $output, 'LTR stylesheet was not printed in output.' ); + + // Verify correct order (LTR after main style). + $mainPos = strpos( $output, 'style.css' ); + $ltrPos = strpos( $output, 'ltr.css' ); + $this->assertTrue( $ltrPos > $mainPos, 'LTR stylesheet should appear after the main style.' ); + } } From 3155a4361e51bcbfde427101d31e72fa4ea214e0 Mon Sep 17 00:00:00 2001 From: asadister <77143123+asadister@users.noreply.github.com> Date: Thu, 6 Nov 2025 19:33:44 +0330 Subject: [PATCH 6/6] Add tests for LTR stylesheet handling in wp_register_style() and wp_print_styles(). Implements comprehensive PHPUnit tests for verifying LTR stylesheet support. These tests cover: - Proper registration of LTR data using `wp_style_add_data()`. - Behavior differences between LTR and RTL locales. - Ensuring that LTR variants are correctly printed in HTML output via `wp_print_styles()`. - Verification of stylesheet order to confirm that the LTR stylesheet appears after its main counterpart. Includes handling for the deprecation of `print_emoji_styles` to ensure compatibility with WordPress 6.4+. Props asadister. See [#64193](https://core.trac.wordpress.org/ticket/64193). --- .../tests/dependencies/stylesLTRSupport.php | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/tests/phpunit/tests/dependencies/stylesLTRSupport.php b/tests/phpunit/tests/dependencies/stylesLTRSupport.php index e1c3cc343a12c..bbb5e57202e54 100644 --- a/tests/phpunit/tests/dependencies/stylesLTRSupport.php +++ b/tests/phpunit/tests/dependencies/stylesLTRSupport.php @@ -1,21 +1,13 @@ registered = array(); } @@ -55,7 +47,7 @@ public function test_ltr_css_suffix_data_is_set() { */ public function test_no_ltr_data_for_ltr_locale() { restore_previous_locale(); - switch_to_locale( 'en_US' ); // LTR language + switch_to_locale( 'en_US' ); // LTR language. $handle = 'sample-style-ltr'; wp_register_style( $handle, 'https://example.com/style.css' ); @@ -65,15 +57,15 @@ public function test_no_ltr_data_for_ltr_locale() { $this->assertArrayHasKey( 'ltr', $styles->registered[ $handle ]->extra ); $this->assertSame( 'replace', $styles->registered[ $handle ]->extra['ltr'] ); } - /** - * Verify that an LTR stylesheet is printed after its main stylesheet in the HTML output. + * Verify that an LTR stylesheet actually gets printed in HTML output. * * @group output * @ticket 64193 - * @expectedDeprecated print_emoji_styles */ public function test_ltr_stylesheet_is_printed_in_output() { + $this->setExpectedDeprecated( 'print_emoji_styles' ); + global $wp_styles; // Reset styles registry to ensure a clean environment. @@ -99,8 +91,8 @@ public function test_ltr_stylesheet_is_printed_in_output() { $this->assertStringContainsString( 'ltr.css', $output, 'LTR stylesheet was not printed in output.' ); // Verify correct order (LTR after main style). - $mainPos = strpos( $output, 'style.css' ); - $ltrPos = strpos( $output, 'ltr.css' ); - $this->assertTrue( $ltrPos > $mainPos, 'LTR stylesheet should appear after the main style.' ); + $main_pos = strpos( $output, 'style.css' ); + $ltr_pos = strpos( $output, 'ltr.css' ); + $this->assertTrue( $ltr_pos > $main_pos, 'LTR stylesheet should appear after the main style.' ); } }