Skip to content

Commit

Permalink
Add GB specific resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
hellofromtonya authored and matiasbenedetto committed Nov 17, 2023
1 parent bb8adcd commit 27c0f6f
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
<?php
/**
* Gutenberg_Font_Face_Resolver_6_4 class.
*
* @package Gutenberg
* @subpackage Fonts
*/

/**
* The Font Face Resolver abstracts the processing of different data sources
* (such as theme.json) for processing within the Font Face.
*
* This class is for internal core usage and is not supposed to be used by
* extenders (plugins and/or themes).
*
* @access private
*/
class Gutenberg_Font_Face_Resolver_6_4 {

/**
* Gets fonts defined in theme.json.
*
* @since 6.4.0
*
* @return array Returns the font-families, each with their font-face variations.
*/
public static function get_fonts_from_theme_json() {
$settings = gutenberg_get_global_settings();

// Bail out early if there are no font settings.
if ( empty( $settings['typography']['fontFamilies'] ) ) {
return array();
}

return static::parse_settings( $settings );
}

/**
* Parse theme.json settings to extract font definitions with variations grouped by font-family.
*
* @since 6.4.0
*
* @param array $settings Font settings to parse.
* @return array Returns an array of fonts, grouped by font-family.
*/
private static function parse_settings( array $settings ) {
$fonts = array();

foreach ( $settings['typography']['fontFamilies'] as $font_families ) {
foreach ( $font_families as $definition ) {

// Skip if "fontFace" is not defined, meaning there are no variations.
if ( empty( $definition['fontFace'] ) ) {
continue;
}

// Skip if "fontFamily" is not defined.
if ( empty( $definition['fontFamily'] ) ) {
continue;
}

$font_family_name = static::maybe_parse_name_from_comma_separated_list( $definition['fontFamily'] );

// Skip if no font family is defined.
if ( empty( $font_family_name ) ) {
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 );
}
}

return $fonts;
}

/**
* Parse font-family name from comma-separated lists.
*
* If the given `fontFamily` is a comma-separated lists (example: "Inter, sans-serif" ),
* parse and return the fist font from the list.
*
* @since 6.4.0
*
* @param string $font_family Font family `fontFamily' to parse.
* @return string Font-family name.
*/
private static function maybe_parse_name_from_comma_separated_list( $font_family ) {
if ( str_contains( $font_family, ',' ) ) {
$font_family = explode( ',', $font_family )[0];
}

return trim( $font_family, "\"'" );
}

/**
* Converts font-face properties from theme.json format.
*
* @since 6.4.0
*
* @param array $font_face_definition The font-face definitions to convert.
* @param string $font_family_property The value to store in the font-face font-family property.
* @return array Converted font-face properties.
*/
private static function convert_font_face_properties( array $font_face_definition, $font_family_property ) {
$converted_font_faces = array();

foreach ( $font_face_definition as $font_face ) {
// Add the font-family property to the font-face.
$font_face['font-family'] = $font_family_property;

// Converts the "file:./" src placeholder into a theme font file URI.
if ( ! empty( $font_face['src'] ) ) {
$font_face['src'] = static::to_theme_file_uri( (array) $font_face['src'] );
}

// Convert camelCase properties into kebab-case.
$font_face = static::to_kebab_case( $font_face );

$converted_font_faces[] = $font_face;
}

return $converted_font_faces;
}

/**
* Converts each 'file:./' placeholder into a URI to the font file in the theme.
*
* The 'file:./' is specified in the theme's `theme.json` as a placeholder to be
* replaced with the URI to the font file's location in the theme. When a "src"
* beings with this placeholder, it is replaced, converting the src into a URI.
*
* @since 6.4.0
*
* @param array $src An array of font file sources to process.
* @return array An array of font file src URI(s).
*/
private static function to_theme_file_uri( array $src ) {
$placeholder = 'file:./';

foreach ( $src as $src_key => $src_url ) {
// Skip if the src doesn't start with the placeholder, as there's nothing to replace.
if ( ! str_starts_with( $src_url, $placeholder ) ) {
continue;
}

$src_file = str_replace( $placeholder, '', $src_url );
$src[ $src_key ] = get_theme_file_uri( $src_file );
}

return $src;
}

/**
* Converts all first dimension keys into kebab-case.
*
* @since 6.4.0
*
* @param array $data The array to process.
* @return array Data with first dimension keys converted into kebab-case.
*/
private static function to_kebab_case( array $data ) {
foreach ( $data as $key => $value ) {
$kebab_case = _wp_to_kebab_case( $key );
$data[ $kebab_case ] = $value;
if ( $kebab_case !== $key ) {
unset( $data[ $key ] );
}
}

return $data;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public static function get_fonts_from_theme_json() {
* @param array $settings Font settings to parse.
* @return array Returns an array of fonts, grouped by font-family.
*/
private static function parse_settings( array $settings ) {
protected static function parse_settings( array $settings ) {
$fonts = array();

foreach ( $settings['typography']['fontFamilies'] as $font_families ) {
Expand Down
25 changes: 25 additions & 0 deletions lib/compat/wordpress-6.4/fonts/fonts.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,31 @@ function wp_print_font_faces( $fonts = array() ) {
$wp_font_face = new WP_Font_Face();
$wp_font_face->generate_and_print( $fonts );
}
} else {
// @core-merge: do not merge this code into Core.

// Remove Core's hooked callback to replace with the plugin's callback.
remove_action( 'wp_head', 'wp_print_font_faces', 50 );
remove_action( 'admin_print_styles', 'wp_print_font_faces', 50 );
add_action( 'wp_head', '_gutenberg_print_font_faces', 50 );
add_action( 'admin_print_styles', '_gutenberg_print_font_faces', 50 );

/**
* Generates and prints font-face styles for given fonts or theme.json fonts.
*
* @access private
*/
function _gutenberg_print_font_faces() {
// Uses the plugin's resolver, i.e. that includes changes not yet merged
// that may not yet be merged into WP Core.
$fonts = Gutenberg_Font_Face_Resolver_6_4::get_fonts_from_theme_json();

if ( empty( $fonts ) ) {
return;
}

wp_print_font_faces( $fonts );
}
}

// @core-merge: do not merge this code into Core.
Expand Down
1 change: 1 addition & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/compat/wordpress-6.4/fonts/font-face/class-wp-font-face.php';
require __DIR__ . '/compat/wordpress-6.4/fonts/font-face/class-wp-font-face-resolver.php';
}
require __DIR__ . '/compat/wordpress-6.4/fonts/font-face/class-gutenberg-font-face-resolver-6-4.php';

/*
* As _gutenberg_get_iframed_editor_assets_6_4() overrides Core's _wp_get_iframed_editor_assets(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ public static function set_up_before_class() {
public function test_should_return_empty_array_when_no_fonts_defined_in_theme() {
switch_theme( 'block-theme' );

$fonts = WP_Font_Face_Resolver::get_fonts_from_theme_json();
$fonts = Gutenberg_Font_Face_Resolver_6_4::get_fonts_from_theme_json();
$this->assertIsArray( $fonts, 'Should return an array data type' );
$this->assertEmpty( $fonts, 'Should return an empty array' );
}

public function test_should_return_all_fonts_from_theme() {
switch_theme( static::FONTS_THEME );

$actual = WP_Font_Face_Resolver::get_fonts_from_theme_json();
$actual = Gutenberg_Font_Face_Resolver_6_4::get_fonts_from_theme_json();
$expected = $this->get_expected_fonts_for_fonts_block_theme( 'fonts' );
$this->assertSame( $expected, $actual );
}
Expand All @@ -52,7 +52,7 @@ public function test_should_return_all_fonts_from_theme() {
public function test_should_replace_src_file_placeholder( $font_name, $font_index, $expected ) {
switch_theme( static::FONTS_THEME );

$fonts = WP_Font_Face_Resolver::get_fonts_from_theme_json();
$fonts = Gutenberg_Font_Face_Resolver_6_4::get_fonts_from_theme_json();

$actual = $fonts[ $font_name ][ $font_index ]['src'][0];
$expected = get_stylesheet_directory_uri() . $expected;
Expand Down

0 comments on commit 27c0f6f

Please sign in to comment.