From 0405bc03eff95c61c1049e08bf64e6e7602e57b0 Mon Sep 17 00:00:00 2001 From: Matias Benedetto Date: Wed, 22 May 2024 15:07:05 +0200 Subject: [PATCH 1/4] adds an endpoints that returns a list of font families used by a theme, including their style variants --- admin/create-theme/theme-fonts.php | 60 +++++++++++++++++++++++ includes/class-create-block-theme-api.php | 40 +++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/admin/create-theme/theme-fonts.php b/admin/create-theme/theme-fonts.php index adf30120..e1304bb6 100644 --- a/admin/create-theme/theme-fonts.php +++ b/admin/create-theme/theme-fonts.php @@ -3,6 +3,66 @@ class CBT_Theme_Fonts { + + /** + * Make the font face theme src urls absolute. + * + * It replaces the 'file:./' prefix with the theme directory uri. + * + * Example: 'file:./assets/fonts/my-font.ttf' -> 'http://example.com/wp-content/themes/my-theme/assets/fonts/my-font.ttf' + * Example: [ 'https://example.com/assets/fonts/my-font.ttf' ] -> [ 'https://example.com/assets/fonts/my-font.ttf' ] + * + * @param array|string $src + * @return array|string + */ + public static function make_theme_font_src_absolute( $src ) { + $make_absolute = function ( $url ) { + if ( str_starts_with( $url, 'file:./' ) ) { + return str_replace( 'file:./', get_stylesheet_directory_uri() . '/', $url ); + } + return $url; + }; + + if ( is_array( $src ) ) { + foreach ( $src as &$url ) { + $url = $make_absolute( $url ); + } + } else { + $src = $make_absolute( $src ); + } + + return $src; + } + + /** + * Get all fonts from the theme.json data + all the style variations. + * + * @return array + */ + public static function get_all_fonts() { + $font_families = array(); + $theme = CBT_Theme_JSON_Resolver::get_merged_data(); + $settings = $theme->get_settings(); + + if ( isset( $settings['typography']['fontFamilies']['theme'] ) ) { + $font_families = array_merge( $font_families, $settings['typography']['fontFamilies']['theme'] ); + } + + if ( isset( $settings['typography']['fontFamilies']['custom'] ) ) { + $font_families = array_merge( $font_families, $settings['typography']['fontFamilies']['custom'] ); + } + + $variations = CBT_Theme_JSON_Resolver::get_style_variations(); + + foreach ( $variations as $variation ) { + if ( isset( $variation['settings']['typography']['fontFamilies']['theme'] ) ) { + $font_families = array_merge( $font_families, $variation['settings']['typography']['fontFamilies']['theme'] ); + } + } + + return $font_families; + } + /** * Copy any ACTIVATED fonts from USER configuration to THEME configuration including any font face assets. * Remove any DEACTIVATED fronts from the THEME configuration. diff --git a/includes/class-create-block-theme-api.php b/includes/class-create-block-theme-api.php index b49623a1..626c18d0 100644 --- a/includes/class-create-block-theme-api.php +++ b/includes/class-create-block-theme-api.php @@ -141,6 +141,18 @@ public function register_rest_routes() { }, ), ); + register_rest_route( + 'create-block-theme/v1', + '/font-families', + array( + 'methods' => 'GET', + 'callback' => array( $this, 'rest_get_font_families' ), + 'permission_callback' => function () { + return current_user_can( 'edit_theme_options' ); + }, + 'permission_callback' => '__return_true', + ), + ); } function rest_get_theme_data( $request ) { @@ -481,6 +493,33 @@ function rest_save_theme( $request ) { ); } + /** + * Get a list of all the font families used in the theme. + * + * It includes the font families from the theme.json data (theme.json file + global styles) and the theme style variations. + * The font families with font faces containing src urls relative to the theme folder are converted to absolute urls. + */ + function rest_get_font_families( $request ) { + $font_families = CBT_Theme_Fonts::get_all_fonts(); + + // Iterates through the font families and makes the urls absolute to use in the frontend code. + foreach ( $font_families as &$font_family ) { + if ( isset( $font_family['fontFace'] ) ) { + foreach ( $font_family['fontFace'] as &$font_face ) { + $font_face['src'] = CBT_Theme_Fonts::make_theme_font_src_absolute( $font_face['src'] ); + } + } + } + + return new WP_REST_Response( + array( + 'status' => 'SUCCESS', + 'message' => __( 'Font Families retrieved.', 'create-block-theme' ), + 'data' => $font_families, + ) + ); + } + private function sanitize_theme_data( $theme ) { $sanitized_theme['name'] = sanitize_text_field( $theme['name'] ); $sanitized_theme['description'] = sanitize_text_field( $theme['description'] ?? '' ); @@ -492,6 +531,7 @@ private function sanitize_theme_data( $theme ) { $sanitized_theme['version'] = sanitize_text_field( $theme['version'] ?? '' ); $sanitized_theme['screenshot'] = sanitize_text_field( $theme['screenshot'] ?? '' ); $sanitized_theme['recommended_plugins'] = sanitize_textarea_field( $theme['recommended_plugins'] ?? '' ); + $sanitized_theme['font_credits'] = sanitize_textarea_field( $theme['font_credits'] ?? '' ); $sanitized_theme['template'] = ''; $sanitized_theme['slug'] = sanitize_title( $theme['name'] ); $sanitized_theme['text_domain'] = $sanitized_theme['slug']; From 6b6567989650456c6db75ba78c1603059e9e8905 Mon Sep 17 00:00:00 2001 From: Matias Benedetto Date: Wed, 22 May 2024 15:39:48 +0200 Subject: [PATCH 2/4] remove unwanted line --- includes/class-create-block-theme-api.php | 1 - 1 file changed, 1 deletion(-) diff --git a/includes/class-create-block-theme-api.php b/includes/class-create-block-theme-api.php index 626c18d0..a77bc577 100644 --- a/includes/class-create-block-theme-api.php +++ b/includes/class-create-block-theme-api.php @@ -150,7 +150,6 @@ public function register_rest_routes() { 'permission_callback' => function () { return current_user_can( 'edit_theme_options' ); }, - 'permission_callback' => '__return_true', ), ); } From 55cf62ea5644095da22d73b02dcf8292b9e8dbaf Mon Sep 17 00:00:00 2001 From: Matias Benedetto Date: Thu, 23 May 2024 12:32:57 +0200 Subject: [PATCH 3/4] move some logic into get_all_fonts --- admin/create-theme/theme-fonts.php | 11 ++++++++++- includes/class-create-block-theme-api.php | 9 --------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/admin/create-theme/theme-fonts.php b/admin/create-theme/theme-fonts.php index e1304bb6..e2539c1d 100644 --- a/admin/create-theme/theme-fonts.php +++ b/admin/create-theme/theme-fonts.php @@ -15,7 +15,7 @@ class CBT_Theme_Fonts { * @param array|string $src * @return array|string */ - public static function make_theme_font_src_absolute( $src ) { + private static function make_theme_font_src_absolute( $src ) { $make_absolute = function ( $url ) { if ( str_starts_with( $url, 'file:./' ) ) { return str_replace( 'file:./', get_stylesheet_directory_uri() . '/', $url ); @@ -60,6 +60,15 @@ public static function get_all_fonts() { } } + // Iterates through the font families and makes the urls absolute to use in the frontend code. + foreach ( $font_families as &$font_family ) { + if ( isset( $font_family['fontFace'] ) ) { + foreach ( $font_family['fontFace'] as &$font_face ) { + $font_face['src'] = CBT_Theme_Fonts::make_theme_font_src_absolute( $font_face['src'] ); + } + } + } + return $font_families; } diff --git a/includes/class-create-block-theme-api.php b/includes/class-create-block-theme-api.php index a77bc577..153c82e5 100644 --- a/includes/class-create-block-theme-api.php +++ b/includes/class-create-block-theme-api.php @@ -501,15 +501,6 @@ function rest_save_theme( $request ) { function rest_get_font_families( $request ) { $font_families = CBT_Theme_Fonts::get_all_fonts(); - // Iterates through the font families and makes the urls absolute to use in the frontend code. - foreach ( $font_families as &$font_family ) { - if ( isset( $font_family['fontFace'] ) ) { - foreach ( $font_family['fontFace'] as &$font_face ) { - $font_face['src'] = CBT_Theme_Fonts::make_theme_font_src_absolute( $font_face['src'] ); - } - } - } - return new WP_REST_Response( array( 'status' => 'SUCCESS', From 85001e162ebf1da2e65c56b05a49b9f38bd06466 Mon Sep 17 00:00:00 2001 From: Jason Crist Date: Tue, 28 May 2024 08:45:37 -0400 Subject: [PATCH 4/4] Added get_fonts unit test --- tests/test-theme-fonts.php | 117 +++++++++++++++++++++++++++++++++++-- 1 file changed, 113 insertions(+), 4 deletions(-) diff --git a/tests/test-theme-fonts.php b/tests/test-theme-fonts.php index dee50090..e1a3aeff 100644 --- a/tests/test-theme-fonts.php +++ b/tests/test-theme-fonts.php @@ -101,12 +101,121 @@ public function test_remove_deactivated_fonts_from_theme() { $this->uninstall_theme( $test_theme_slug ); } + public function test_get_all_fonts_just_theme() { + + wp_set_current_user( self::$admin_id ); + + $test_theme_slug = $this->create_blank_theme(); + + $theme_json = CBT_Theme_JSON_Resolver::get_theme_file_contents(); + $theme_json['settings']['typography']['fontFamilies'] = array( + array( + 'slug' => 'open-sans', + 'name' => 'Open Sans', + 'fontFamily' => 'Open Sans', + 'fontFace' => array( + array( + 'fontFamily' => 'Open Sans', + 'fontStyle' => 'normal', + 'fontWeight' => '400', + 'src' => 'file:./assets/fonts/open-sans-normal-400.ttf', + ), + ), + ), + array( + 'slug' => 'closed-sans', + 'name' => 'Closed Sans', + 'fontFamily' => 'Closed Sans', + 'fontFace' => array( + array( + 'fontFamily' => 'Closed Sans', + 'fontStyle' => 'normal', + 'fontWeight' => '400', + 'src' => 'http://example.com/closed-sans-normal-400.ttf', + ), + ), + ), + ); + CBT_Theme_JSON_Resolver::write_theme_file_contents( $theme_json ); + + $fonts = CBT_Theme_Fonts::get_all_fonts(); + + $this->assertCount( 2, $fonts ); + $this->assertEquals( 'open-sans', $fonts[0]['slug'] ); + $this->assertEquals( 'closed-sans', $fonts[1]['slug'] ); + $this->assertStringNotContainsString( 'file:.', $fonts[0]['fontFace'][0]['src'] ); + $this->assertStringNotContainsString( 'file:.', $fonts[1]['fontFace'][0]['src'] ); + + $this->uninstall_theme( $test_theme_slug ); + } + + public function test_get_all_fonts_from_theme_and_variation() { + + wp_set_current_user( self::$admin_id ); + + $test_theme_slug = $this->create_blank_theme(); + + $theme_json = CBT_Theme_JSON_Resolver::get_theme_file_contents(); + $theme_json['settings']['typography']['fontFamilies'] = array( + array( + 'slug' => 'open-sans', + 'name' => 'Open Sans', + 'fontFamily' => 'Open Sans', + 'fontFace' => array( + array( + 'fontFamily' => 'Open Sans', + 'fontStyle' => 'normal', + 'fontWeight' => '400', + 'src' => 'file:./assets/fonts/open-sans-normal-400.ttf', + ), + ), + ), + ); + CBT_Theme_JSON_Resolver::write_theme_file_contents( $theme_json ); + + $variation_json = array( + 'version' => '2', + 'title' => 'Variation', + ); + $variation_json['settings']['typography']['fontFamilies'] = array( + array( + 'slug' => 'closed-sans', + 'name' => 'Closed Sans', + 'fontFamily' => 'Closed Sans', + 'fontFace' => array( + array( + 'fontFamily' => 'Closed Sans', + 'fontStyle' => 'normal', + 'fontWeight' => '400', + 'src' => 'http://example.com/closed-sans-normal-400.ttf', + ), + ), + ), + ); + + // Save the variation + $variation_path = get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'styles' . DIRECTORY_SEPARATOR; + $variation_slug = 'variation'; + wp_mkdir_p( $variation_path ); + file_put_contents( + $variation_path . $variation_slug . '.json', + wp_json_encode( $variation_json, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) + ); + + $fonts = CBT_Theme_Fonts::get_all_fonts(); + + $this->assertCount( 2, $fonts ); + $this->assertEquals( 'open-sans', $fonts[0]['slug'] ); + $this->assertEquals( 'closed-sans', $fonts[1]['slug'] ); + $this->assertStringNotContainsString( 'file:.', $fonts[0]['fontFace'][0]['src'] ); + $this->assertStringNotContainsString( 'file:.', $fonts[1]['fontFace'][0]['src'] ); + + $this->uninstall_theme( $test_theme_slug ); + + } + private function save_theme() { CBT_Theme_Fonts::persist_font_settings(); - // CBT_Theme_Templates::add_templates_to_local( 'all' ); - // CBT_Theme_JSON::add_theme_json_to_local( 'all' ); - // CBT_Theme_Styles::clear_user_styles_customizations(); - // CBT_Theme_Templates::clear_user_templates_customizations(); } private function create_blank_theme() {