diff --git a/src/wp-includes/fonts.php b/src/wp-includes/fonts.php index 9940761e738dd..953898136300e 100644 --- a/src/wp-includes/fonts.php +++ b/src/wp-includes/fonts.php @@ -13,13 +13,13 @@ * @since 6.4.0 * * @param array[][] $fonts { - * Optional. The font-families and their font variations. Default empty array. + * Optional. The font-families and their font faces. Default empty array. * - * @type string $font-family => array[] $variations { - * Optional. An associated array of font variations for this font-family. - * Each variation has the following structure. + * @type array { + * An indexed or associative (keyed by font-family) array of font variations for this font-family. + * Each font face has the following structure. * - * @type array $font_variation { + * @type array { * @type string $font-family The font-family property. * @type string|string[] $src The URL(s) to each resource containing the font data. * @type string $font-style Optional. The font-style property. Default 'normal'. diff --git a/src/wp-includes/fonts/class-wp-font-face-resolver.php b/src/wp-includes/fonts/class-wp-font-face-resolver.php index 125ff6a227705..12245af556b58 100644 --- a/src/wp-includes/fonts/class-wp-font-face-resolver.php +++ b/src/wp-includes/fonts/class-wp-font-face-resolver.php @@ -67,12 +67,7 @@ private static function parse_settings( array $settings ) { continue; } - // Prepare the fonts array structure for this font-family. - if ( ! array_key_exists( $font_family_name, $fonts ) ) { - $fonts[ $font_family_name ] = array(); - } - - $fonts[ $font_family_name ] = static::convert_font_face_properties( $definition['fontFace'], $font_family_name ); + $fonts[] = static::convert_font_face_properties( $definition['fontFace'], $font_family_name ); } } diff --git a/tests/phpunit/tests/fonts/font-face/wp-font-face-tests-dataset.php b/tests/phpunit/tests/fonts/font-face/wp-font-face-tests-dataset.php index 00ae66e865a89..1432c8589f5cc 100644 --- a/tests/phpunit/tests/fonts/font-face/wp-font-face-tests-dataset.php +++ b/tests/phpunit/tests/fonts/font-face/wp-font-face-tests-dataset.php @@ -92,7 +92,7 @@ public function data_should_print_given_fonts() { , ), 'multiple woff2 format fonts' => array( - 'fonts' => array( + 'fonts' => array( 'DM Sans' => array( array( @@ -184,7 +184,7 @@ public function data_should_print_given_fonts() { ), ), ), - 'expected' => << << array( + 'fonts' => array( + array( + array( + 'font-family' => 'Piazzolla', + 'src' => array( 'https://example.org/fonts/piazzolla400.ttf' ), + 'font-style' => 'normal', + 'font-weight' => '400', + 'font-stretch' => 'normal', + ), + array( + 'font-family' => 'Piazzolla', + 'src' => array( 'https://example.org/fonts/piazzolla500.ttf' ), + 'font-style' => 'normal', + 'font-weight' => '400', + 'font-stretch' => 'normal', + ), + ), + array( + array( + 'font-family' => 'Lobster', + 'src' => array( 'https://example.org/fonts/lobster400.ttf' ), + 'font-style' => 'normal', + 'font-weight' => '400', + 'font-stretch' => 'normal', + ), + array( + 'font-family' => 'Lobster', + 'src' => array( 'https://example.org/fonts/lobster500.ttf' ), + 'font-style' => 'normal', + 'font-weight' => '500', + 'font-stretch' => 'normal', + ), + ), + ), + 'expected' => << array( - 'DM Sans' => array( + array( array( 'src' => array( $uri . 'dm-sans/DMSans-Regular.woff2' ), 'font-family' => 'DM Sans', @@ -236,7 +279,7 @@ public function get_expected_fonts_for_fonts_block_theme( $key = '' ) { 'font-weight' => '700', ), ), - 'Source Serif Pro' => array( + array( array( 'src' => array( $uri . 'source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2' ), 'font-family' => 'Source Serif Pro', @@ -271,4 +314,93 @@ public function get_expected_fonts_for_fonts_block_theme( $key = '' ) { return $data; } + + public static function get_custom_font_families( $key = '' ) { + static $data = null; + + $custom_theme_json_fonts = array( + array( + 'fontFamily' => 'Piazzolla, serif', + 'name' => 'Piazzolla', + 'slug' => 'piazzolla', + 'fontFace' => array( + array( + 'fontFamily' => 'Piazzolla', + 'src' => array( 'https://example.org/fonts/piazzolla400.ttf' ), + 'fontStyle' => 'normal', + 'fontWeight' => '400', + ), + array( + 'fontFamily' => 'Piazzolla', + 'src' => array( 'https://example.org/fonts/piazzolla500.ttf' ), + 'fontStyle' => 'normal', + 'fontWeight' => '400', + ), + ), + ), + array( + 'fontFamily' => 'Lobster, sans-serif', + 'name' => 'Lobster', + 'slug' => 'lobster', + 'fontFace' => array( + array( + 'fontFamily' => 'Lobster', + 'src' => array( 'https://example.org/fonts/lobster400.ttf' ), + 'fontStyle' => 'normal', + 'fontWeight' => '400', + ), + array( + 'fontFamily' => 'Lobster', + 'src' => array( 'https://example.org/fonts/lobster500.ttf' ), + 'fontStyle' => 'normal', + 'fontWeight' => '500', + ), + ), + ), + ); + + $expected_font_faces = array( + array( + array( + 'src' => array( 'https://example.org/fonts/piazzolla400.ttf' ), + 'font-family' => 'Piazzolla', + 'font-style' => 'normal', + 'font-weight' => '400', + ), + array( + 'src' => array( 'https://example.org/fonts/piazzolla500.ttf' ), + 'font-family' => 'Piazzolla', + 'font-style' => 'normal', + 'font-weight' => '400', + ), + ), + array( + array( + 'src' => array( 'https://example.org/fonts/lobster400.ttf' ), + 'font-family' => 'Lobster', + 'font-style' => 'normal', + 'font-weight' => '400', + ), + array( + 'src' => array( 'https://example.org/fonts/lobster500.ttf' ), + 'font-family' => 'Lobster', + 'font-style' => 'normal', + 'font-weight' => '500', + ), + ), + ); + + if ( null === $data ) { + $data = array( + 'input' => $custom_theme_json_fonts, + 'expected' => $expected_font_faces, + ); + } + + if ( isset( $data[ $key ] ) ) { + return $data[ $key ]; + } + + return $data; + } } diff --git a/tests/phpunit/tests/fonts/font-face/wpFontFaceResolver/getFontsFromThemeJson.php b/tests/phpunit/tests/fonts/font-face/wpFontFaceResolver/getFontsFromThemeJson.php index 654601363f2e4..1e48c5ae7dd59 100644 --- a/tests/phpunit/tests/fonts/font-face/wpFontFaceResolver/getFontsFromThemeJson.php +++ b/tests/phpunit/tests/fonts/font-face/wpFontFaceResolver/getFontsFromThemeJson.php @@ -37,20 +37,58 @@ public function test_should_return_all_fonts_from_theme() { $this->assertSame( $expected, $actual ); } + /** + * @ticket 60605 + */ + public function test_should_return_all_fonts_from_all_theme_origins() { + switch_theme( static::FONTS_THEME ); + + $add_custom_fonts = static function ( $theme_json_data ) { + $data = $theme_json_data->get_data(); + // Add font families to the custom origin of theme json. + $data['settings']['typography']['fontFamilies']['custom'] = self::get_custom_font_families( 'input' ); + return new WP_Theme_JSON_Data( $data ); + }; + + add_filter( 'wp_theme_json_data_theme', $add_custom_fonts ); + $actual = WP_Font_Face_Resolver::get_fonts_from_theme_json(); + remove_filter( 'wp_theme_json_data_theme', $add_custom_fonts ); + + $expected = array_merge( + $this->get_expected_fonts_for_fonts_block_theme( 'fonts' ), + $this->get_custom_font_families( 'expected' ) + ); + + $this->assertSame( $expected, $actual, 'Both the fonts from the theme and the custom origin should be returned.' ); + } + /** * @dataProvider data_should_replace_src_file_placeholder * * @param string $font_name Font's name. - * @param string $font_index Font's index in the $fonts array. + * @param string $font_weight Font's weight. + * @param string $font_style Font's style. * @param string $expected Expected src. */ - public function test_should_replace_src_file_placeholder( $font_name, $font_index, $expected ) { + public function test_should_replace_src_file_placeholder( $font_name, $font_weight, $font_style, $expected ) { switch_theme( static::FONTS_THEME ); $fonts = WP_Font_Face_Resolver::get_fonts_from_theme_json(); + $fonts = array_merge( array(), ...array_map( 'array_values', $fonts ) ); + + $font = array_filter( + $fonts, + static function ( $font ) use ( $font_name, $font_weight, $font_style ) { + return $font['font-family'] === $font_name + && $font['font-weight'] === $font_weight + && $font['font-style'] === $font_style; + } + ); + + $font = reset( $font ); - $actual = $fonts[ $font_name ][ $font_index ]['src'][0]; $expected = get_stylesheet_directory_uri() . $expected; + $actual = $font['src'][0]; $this->assertStringNotContainsString( 'file:./', $actual, 'Font src should not contain the "file:./" placeholder' ); $this->assertSame( $expected, $actual, 'Font src should be an URL to its file' ); @@ -65,34 +103,40 @@ public function data_should_replace_src_file_placeholder() { return array( // Theme's theme.json. 'DM Sans: 400 normal' => array( - 'font_name' => 'DM Sans', - 'font_index' => 0, - 'expected' => '/assets/fonts/dm-sans/DMSans-Regular.woff2', + 'font_name' => 'DM Sans', + 'font_weight' => '400', + 'font_style' => 'normal', + 'expected' => '/assets/fonts/dm-sans/DMSans-Regular.woff2', ), 'DM Sans: 400 italic' => array( - 'font_name' => 'DM Sans', - 'font_index' => 1, - 'expected' => '/assets/fonts/dm-sans/DMSans-Regular-Italic.woff2', + 'font_name' => 'DM Sans', + 'font_weight' => '400', + 'font_style' => 'italic', + 'expected' => '/assets/fonts/dm-sans/DMSans-Regular-Italic.woff2', ), 'DM Sans: 700 normal' => array( - 'font_name' => 'DM Sans', - 'font_index' => 2, - 'expected' => '/assets/fonts/dm-sans/DMSans-Bold.woff2', + 'font_name' => 'DM Sans', + 'font_weight' => '700', + 'font_style' => 'normal', + 'expected' => '/assets/fonts/dm-sans/DMSans-Bold.woff2', ), 'DM Sans: 700 italic' => array( - 'font_name' => 'DM Sans', - 'font_index' => 3, - 'expected' => '/assets/fonts/dm-sans/DMSans-Bold-Italic.woff2', + 'font_name' => 'DM Sans', + 'font_weight' => '700', + 'font_style' => 'italic', + 'expected' => '/assets/fonts/dm-sans/DMSans-Bold-Italic.woff2', ), 'Source Serif Pro: 200-900 normal' => array( - 'font_name' => 'Source Serif Pro', - 'font_index' => 0, - 'expected' => '/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2', + 'font_name' => 'Source Serif Pro', + 'font_weight' => '200 900', + 'font_style' => 'normal', + 'expected' => '/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2', ), 'Source Serif Pro: 200-900 italic' => array( - 'font_name' => 'Source Serif Pro', - 'font_index' => 1, - 'expected' => '/assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2', + 'font_name' => 'Source Serif Pro', + 'font_weight' => '200 900', + 'font_style' => 'italic', + 'expected' => '/assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2', ), ); } @@ -118,7 +162,17 @@ public function test_should_get_font_family_name( $fonts, $expected_name ) { $fonts = WP_Font_Face_Resolver::get_fonts_from_theme_json(); remove_filter( 'wp_theme_json_data_theme', $replace_fonts ); - $this->assertArrayHasKey( $expected_name, $fonts ); + // flatten the array to make it easier to test. + $fonts = array_merge( array(), ...array_map( 'array_values', $fonts ) ); + + $fonts_found = array_filter( + $fonts, + function ( $font ) use ( $expected_name ) { + return $font['font-family'] === $expected_name; + } + ); + + $this->assertNotEmpty( $fonts_found, 'Expected font-family name not found in the array' ); } /**