From 00dc4a7950c39f6ddc156c949394baebfe81c1dd Mon Sep 17 00:00:00 2001 From: Tonya Mork Date: Tue, 9 May 2023 14:47:18 -0500 Subject: [PATCH] [Fonts API] Automatically enqueue user-selected fonts (#50297) * Adds user-select fonts enqueuer * Auto queue before printing * Always set $handles to false when empty --- .../fonts-api/class-wp-fonts-resolver.php | 102 +++++++ lib/experimental/fonts-api/fonts-api.php | 24 +- lib/load.php | 2 + .../enqueueUserSelectedFonts-test.php | 256 ++++++++++++++++++ 4 files changed, 371 insertions(+), 13 deletions(-) create mode 100644 lib/experimental/fonts-api/class-wp-fonts-resolver.php create mode 100644 phpunit/fonts-api/wpFontsResolver/enqueueUserSelectedFonts-test.php diff --git a/lib/experimental/fonts-api/class-wp-fonts-resolver.php b/lib/experimental/fonts-api/class-wp-fonts-resolver.php new file mode 100644 index 00000000000000..5b8314129726b5 --- /dev/null +++ b/lib/experimental/fonts-api/class-wp-fonts-resolver.php @@ -0,0 +1,102 @@ +queue; - $done = $wp_fonts->done; - $wp_fonts->done = array(); - $wp_fonts->queue = $registered; - $handles = false; - } elseif ( empty( $handles ) ) { - // When falsey, assign `false` to print enqueued fonts. - $handles = false; - } + if ( empty( $handles ) ) { + // Automatically enqueue all user-selected fonts. + WP_Fonts_Resolver::enqueue_user_selected_fonts(); + $handles = false; + } elseif ( $in_iframed_editor ) { + // Print all registered fonts for the iframed editor. + $queue = $wp_fonts->queue; + $done = $wp_fonts->done; + $wp_fonts->done = array(); + $wp_fonts->queue = $registered; + $handles = false; } _wp_scripts_maybe_doing_it_wrong( __FUNCTION__ ); diff --git a/lib/load.php b/lib/load.php index ac4941cb0e96a5..5b571cb4021592 100644 --- a/lib/load.php +++ b/lib/load.php @@ -112,7 +112,9 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/experimental/fonts-api/register-fonts-from-theme-json.php'; require __DIR__ . '/experimental/fonts-api/class-wp-fonts.php'; require __DIR__ . '/experimental/fonts-api/class-wp-fonts-provider-local.php'; + require __DIR__ . '/experimental/fonts-api/class-wp-fonts-resolver.php'; require __DIR__ . '/experimental/fonts-api/fonts-api.php'; + // BC Layer files, which will not be backported to WP Core. require __DIR__ . '/experimental/fonts-api/bc-layer/class-gutenberg-fonts-api-bc-layer.php'; require __DIR__ . '/experimental/fonts-api/bc-layer/webfonts-deprecations.php'; diff --git a/phpunit/fonts-api/wpFontsResolver/enqueueUserSelectedFonts-test.php b/phpunit/fonts-api/wpFontsResolver/enqueueUserSelectedFonts-test.php new file mode 100644 index 00000000000000..437c95b698d350 --- /dev/null +++ b/phpunit/fonts-api/wpFontsResolver/enqueueUserSelectedFonts-test.php @@ -0,0 +1,256 @@ +user->create( + array( + 'role' => 'administrator', + 'user_email' => 'administrator@example.com', + ) + ); + } + + /** + * @dataProvider data_should_not_enqueue_when_no_user_selected_fonts + * + * @param array $styles Optional. Test styles. Default empty array. + */ + public function test_should_not_enqueue_when_no_user_selected_fonts( $styles = array() ) { + $this->set_up_global_styles( $styles ); + + $mock = $this->set_up_mock( 'enqueue' ); + $mock->expects( $this->never() ) + ->method( 'enqueue' ); + + $expected = array(); + $this->assertSame( $expected, WP_Fonts_Resolver::enqueue_user_selected_fonts() ); + } + + /** + * Data provider. + * + * @return array + */ + public function data_should_not_enqueue_when_no_user_selected_fonts() { + return array( + 'no user-selected styles' => array(), + 'invalid element' => array( + array( + 'elements' => array( + 'invalid' => array( + 'typography' => array( + 'fontFamily' => 'var:preset|font-family|font1', + 'fontStyle' => 'normal', + 'fontWeight' => '400', + ), + ), + ), + ), + ), + ); + } + + /** + * @dataProvider data_should_enqueue_when_user_selected_fonts + * + * @param array $styles Test styles. + * @param array $expected Expected results. + */ + public function test_should_enqueue_when_user_selected_fonts( $styles, $expected ) { + $mock = $this->set_up_mock( 'enqueue' ); + $mock->expects( $this->once() ) + ->method( 'enqueue' ) + ->with( + $this->identicalTo( $expected ) + ); + + $this->set_up_global_styles( $styles ); + + $this->assertSameSets( $expected, WP_Fonts_Resolver::enqueue_user_selected_fonts() ); + } + + /** + * Data provider. + * + * @return array + */ + public function data_should_enqueue_when_user_selected_fonts() { + $fonts = array( + 'font1-400-normal' => array( + 'fontFamily' => 'var:preset|font-family|font1', + 'fontStyle' => 'normal', + 'fontWeight' => '400', + ), + 'font1-400-italic' => array( + 'fontFamily' => 'var:preset|font-family|font1', + 'fontStyle' => 'italic', + 'fontWeight' => '400', + ), + 'font2-600-normal' => array( + 'fontFamily' => 'var:preset|font-family|font2', + 'fontStyle' => 'normal', + 'fontWeight' => '600', + ), + 'font2-600-italic' => array( + 'fontFamily' => 'var:preset|font-family|font2', + 'fontStyle' => 'italic', + 'fontWeight' => '600', + ), + 'font3-900-normal' => array( + 'fontFamily' => 'var:preset|font-family|font3', + 'fontStyle' => 'normal', + 'fontWeight' => '900', + ), + ); + + return array( + 'link' => array( + 'styles' => array( + 'elements' => array( + 'link' => array( + 'typography' => $fonts['font1-400-italic'], + ), + ), + ), + 'expected' => array( 'font1' ), + ), + 'heading' => array( + 'styles' => array( + 'elements' => array( + 'heading' => array( + 'typography' => $fonts['font2-600-italic'], + ), + ), + ), + 'expected' => array( 'font2' ), + ), + 'caption' => array( + 'styles' => array( + 'elements' => array( + 'caption' => array( + 'typography' => $fonts['font2-600-normal'], + ), + ), + ), + 'expected' => array( 'font2' ), + ), + 'button' => array( + 'styles' => array( + 'elements' => array( + 'button' => array( + 'typography' => $fonts['font1-400-normal'], + ), + ), + ), + 'expected' => array( 'font1' ), + ), + 'text' => array( + 'styles' => array( + 'typography' => $fonts['font1-400-normal'], + ), + 'expected' => array( 'font1' ), + ), + 'all elements' => array( + 'styles' => array( + 'elements' => array( + 'link' => array( + 'typography' => $fonts['font1-400-italic'], + ), + 'heading' => array( + 'typography' => $fonts['font2-600-italic'], + ), + 'caption' => array( + 'typography' => $fonts['font2-600-normal'], + ), + 'button' => array( + 'typography' => $fonts['font1-400-normal'], + ), + ), + ), + 'expected' => array( 'font1', 'font2' ), + ), + 'all elements and text' => array( + 'styles' => array( + 'elements' => array( + 'link' => array( + 'typography' => $fonts['font1-400-italic'], + ), + 'heading' => array( + 'typography' => $fonts['font2-600-italic'], + ), + 'caption' => array( + 'typography' => $fonts['font3-900-normal'], + ), + 'button' => array( + 'typography' => $fonts['font1-400-normal'], + ), + ), + 'typography' => $fonts['font1-400-normal'], + ), + 'expected' => array( 'font1', 'font2', 'font3' ), + ), + 'with invalid element' => array( + 'styles' => array( + 'elements' => array( + 'button' => array( + 'typography' => $fonts['font1-400-normal'], + ), + 'invalid' => array( + 'typography' => $fonts['font3-900-normal'], + ), + ), + ), + 'expected' => array( 'font1' ), + ), + ); + } + + /** + * Sets up the global styles. + * + * @param array $styles User-selected styles structure. + */ + private function set_up_global_styles( array $styles ) { + switch_theme( static::FONTS_THEME ); + + if ( empty( $styles ) ) { + return; + } + + // Make sure there is data from the user origin. + wp_set_current_user( self::$administrator_id ); + $user_cpt = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( wp_get_theme(), true ); + $config = json_decode( $user_cpt['post_content'], true ); + + // Add the test styles. + $config['styles'] = $styles; + + // Update the global styles and settings post. + $user_cpt['post_content'] = wp_json_encode( $config ); + wp_update_post( $user_cpt, true, false ); + } +}