diff --git a/inc/Engine/Common/AbstractFileSystem.php b/inc/Engine/Common/AbstractFileSystem.php index e5147c1d28..0654b64f95 100644 --- a/inc/Engine/Common/AbstractFileSystem.php +++ b/inc/Engine/Common/AbstractFileSystem.php @@ -44,7 +44,11 @@ protected function write_file( string $file_path, string $content ): bool { * * @return string */ - protected function get_file_content( string $file ): string { + public function get_file_content( string $file ): string { + if ( ! $this->filesystem->exists( $file ) ) { + return ''; + } + return $this->filesystem->get_contents( $file ); } diff --git a/inc/Engine/Media/Fonts/Frontend/Controller.php b/inc/Engine/Media/Fonts/Frontend/Controller.php index 460ed28719..7f9c488c24 100644 --- a/inc/Engine/Media/Fonts/Frontend/Controller.php +++ b/inc/Engine/Media/Fonts/Frontend/Controller.php @@ -32,6 +32,13 @@ class Controller { */ private $base_url; + /** + * Base path. + * + * @var string + */ + private $base_path; + /** * Error flag. * @@ -47,6 +54,7 @@ class Controller { */ public function __construct( Context $context, Filesystem $filesystem ) { $this->context = $context; + $this->base_path = rocket_get_constant( 'WP_ROCKET_CACHE_ROOT_PATH', '' ) . 'fonts/' . get_current_blog_id() . '/'; $this->base_url = rocket_get_constant( 'WP_ROCKET_CACHE_ROOT_URL', '' ) . 'fonts/' . get_current_blog_id() . '/'; $this->filesystem = $filesystem; } @@ -125,10 +133,26 @@ private function get_optimized_markup( string $font_provider ): string { $font_provider_path = sprintf( '%s/', $font_provider ); + $gf_parameters = wp_parse_url( $original_url, PHP_URL_QUERY ); - $url = $this->base_url . $font_provider_path . $this->filesystem->hash_to_path( $hash ) . '.css'; + /** + * Filters to enable the inline css output. + * + * @since 3.18 + * + * @param bool $enable Tells if we are enabling or not the inline css output. + */ + if ( wpm_apply_filters_typed( 'boolean', 'rocket_host_fonts_locally_inline_css', false ) ) { + $local_css_path = $this->base_path . $font_provider_path . $this->filesystem->hash_to_path( $hash ) . '.css'; - $gf_parameters = wp_parse_url( $original_url, PHP_URL_QUERY ); + $inline_css = $this->get_font_inline_css( $local_css_path, $gf_parameters ); + + if ( ! empty( $inline_css ) ) { + return $inline_css; + } + } + + $url = $this->base_url . $font_provider_path . $this->filesystem->hash_to_path( $hash ) . '.css'; return sprintf( '', // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet @@ -180,4 +204,26 @@ public function disable_google_fonts_preload( $disable ): bool { return true; } + + /** + * Gets the font inline css. + * + * @param string $local_css_path CSS file path. + * @param string $gf_parameters Google Fonts parameters. + * + * @return string + */ + private function get_font_inline_css( string $local_css_path, string $gf_parameters ): string { + $content = $this->filesystem->get_file_content( $local_css_path ); + + if ( empty( $content ) ) { + return ''; + } + + return sprintf( + '', + $gf_parameters, + $content + ); + } } diff --git a/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/expected_v1.php b/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/expected_v1.php new file mode 100644 index 0000000000..8c1fbb7b89 --- /dev/null +++ b/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/expected_v1.php @@ -0,0 +1,33 @@ + + + + + + + + Google Font V1 Template + + + + + +
+
+
+

Hello World

+

Welcome to the world

+
+
+
+ + diff --git a/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/expected_v1_style_tag.php b/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/expected_v1_style_tag.php new file mode 100644 index 0000000000..bcbcee1f97 --- /dev/null +++ b/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/expected_v1_style_tag.php @@ -0,0 +1,33 @@ + + + + + + + + Google Font V1 Template + + + + + +
+
+
+

Hello World

+

Welcome to the world

+
+
+
+ + diff --git a/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/expected_v1_v2.php b/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/expected_v1_v2.php new file mode 100644 index 0000000000..ff49829e42 --- /dev/null +++ b/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/expected_v1_v2.php @@ -0,0 +1,41 @@ + + + + + + + + Google Font V1 and V2 Template + + + + + +
+
+
+

Hello World

+

Welcome to the world

+

This is a subtitle

+

Enjoy your stay

+
+
+
+ + diff --git a/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/expected_v2.php b/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/expected_v2.php new file mode 100644 index 0000000000..c5ff58d682 --- /dev/null +++ b/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/expected_v2.php @@ -0,0 +1,33 @@ + + + + + + + + Google Font V2 Template + + + + + +
+
+
+

Hello World

+

Welcome to the world

+
+
+
+ + diff --git a/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/input_v1.php b/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/input_v1.php new file mode 100644 index 0000000000..e49961654e --- /dev/null +++ b/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/input_v1.php @@ -0,0 +1,33 @@ + + + + + + + + Google Font V1 Template + + + + + +
+
+
+

Hello World

+

Welcome to the world

+
+
+
+ + diff --git a/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/input_v1_v2.php b/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/input_v1_v2.php new file mode 100644 index 0000000000..34be74bed6 --- /dev/null +++ b/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/input_v1_v2.php @@ -0,0 +1,41 @@ + + + + + + + + Google Font V1 and V2 Template + + + + + +
+
+
+

Hello World

+

Welcome to the world

+

This is a subtitle

+

Enjoy your stay

+
+
+
+ + diff --git a/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/input_v2.php b/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/input_v2.php new file mode 100644 index 0000000000..2abf18db1b --- /dev/null +++ b/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/HTML/input_v2.php @@ -0,0 +1,33 @@ + + + + + + + + Google Font V2 Template + + + + + +
+
+
+

Hello World

+

Welcome to the world

+
+
+
+ + diff --git a/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/rewriteFonts.php b/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/rewriteFonts.php new file mode 100644 index 0000000000..4a9ab856a2 --- /dev/null +++ b/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Subscriber/rewriteFonts.php @@ -0,0 +1,96 @@ + [ + 'testShouldReturnOriginalWhenNoGoogleFonts' => [ + 'config' => [ + 'html' => '', + 'host_fonts_locally' => true, + 'locally_inline_css' => false, + ], + 'expected' => [ + 'html' => '' + ], + ], + 'testShouldRewriteV1Font' => [ + 'config' => [ + 'html' => file_get_contents( __DIR__ . '/HTML/input_v1.php' ), + 'host_fonts_locally' => true, + 'locally_inline_css' => false, + 'http' => [ + 'https://fonts.googleapis.com/css?family=Roboto' => [ + 'body' => 'body { font-family: "Roboto"; }', + 'response' => ['code' => 200 ] + ], + 'https://fonts.googleapis.com/css?family=Open+Sans' => [ + 'body' => 'body { font-family: "Open-San"; }', + 'response' => ['code' => 200 ] + ], + ], + ], + 'expected' => [ + 'html' => file_get_contents( __DIR__ . '/HTML/expected_v1.php' ), + ], + ], + 'testShouldRewriteV2Font' => [ + 'config' => [ + 'html' => file_get_contents( __DIR__ . '/HTML/input_v2.php' ), + 'host_fonts_locally' => true, + 'locally_inline_css' => false, + 'http' => [ + 'https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap' => [ + 'body' => 'body { font-family: "Roboto"; }', + 'response' => ['code' => 200 ] + ], + 'https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap' => [ + 'body' => 'body { font-family: "Lato"; }', + 'response' => ['code' => 200 ] + ], + ], + ], + 'expected' => [ + 'html' => file_get_contents( __DIR__ . '/HTML/expected_v2.php' ), + ], + ], + 'testShouldRewriteV1AndV2Fonts' => [ + 'config' => [ + 'html' => file_get_contents( __DIR__ . '/HTML/input_v1_v2.php' ), + 'host_fonts_locally' => true, + 'locally_inline_css' => false, + 'http' => [ + 'https://fonts.googleapis.com/css?family=Roboto|Open+Sans' => [ + 'body' => '.roboto { font-family: "Roboto"; } .open-san { font-family: "Open-San"; }', + 'response' => ['code' => 200 ] + ], + 'https://fonts.googleapis.com/css2?family=Lato:wght@400;700&family=Montserrat:wght@400;700&display=swap' => [ + 'body' => '.lato { font-family: "Lato"; } .montserrat { font-family: "Montserrat"; }', + 'response' => ['code' => 200 ] + ], + ], + ], + 'expected' => [ + 'html' => file_get_contents( __DIR__ . '/HTML/expected_v1_v2.php' ), + ], + ], + 'testShouldRewriteFontV1PathInStyleTag' => [ + 'config' => [ + 'html' => file_get_contents( __DIR__ . '/HTML/input_v1.php' ), + 'host_fonts_locally' => true, + 'http' => [ + 'https://fonts.googleapis.com/css?family=Roboto' => [ + 'body' => 'body { font-family: "Roboto"; }', + 'response' => ['code' => 200 ] + ], + 'https://fonts.googleapis.com/css?family=Open+Sans' => [ + 'body' => 'body { font-family: "Open-San"; }', + 'response' => ['code' => 200 ] + ], + ], + 'locally_inline_css' => true, + ], + 'expected' => [ + 'html' => file_get_contents( __DIR__ . '/HTML/expected_v1_style_tag.php' ), + ], + ] + ] +]; diff --git a/tests/Integration/inc/Engine/Media/Fonts/Frontend/Subscriber/rewriteFonts.php b/tests/Integration/inc/Engine/Media/Fonts/Frontend/Subscriber/rewriteFonts.php new file mode 100644 index 0000000000..c071ead144 --- /dev/null +++ b/tests/Integration/inc/Engine/Media/Fonts/Frontend/Subscriber/rewriteFonts.php @@ -0,0 +1,59 @@ +unregisterAllCallbacksExcept('rocket_buffer', 'rewrite_fonts', 18); + add_filter( 'pre_get_rocket_option_host_fonts_locally', [ $this, 'host_fonts_locally' ] ); + add_filter( 'rocket_host_fonts_locally_inline_css', [ $this, 'locally_inline_css' ] ); + $this->setup_http(); + + } + + public function tear_down() { + remove_filter('pre_get_rocket_option_host_fonts_locally', [$this, 'host_fonts_locally']); + remove_filter('rocket_host_fonts_locally_inline_css', [$this, 'locally_inline_css']); + $this->restoreWpHook('rocket_buffer'); + $this->tear_down_http(); + + + parent::tear_down(); + } + + /** + * @dataProvider providerTestData + */ + public function testShouldReturnAsExpected( $config, $expected ) { + $this->config = $config; + + $this->assertSame( + $expected['html'], + apply_filters('rocket_buffer', $config['html']) + ); + } + + public function host_fonts_locally() { + return $this->config['host_fonts_locally']; + } + + public function locally_inline_css() { + return $this->config['locally_inline_css']; + } +}