diff --git a/inc/Engine/Common/AbstractFileSystem.php b/inc/Engine/Common/AbstractFileSystem.php index 0654b64f95..438f75be11 100644 --- a/inc/Engine/Common/AbstractFileSystem.php +++ b/inc/Engine/Common/AbstractFileSystem.php @@ -116,7 +116,7 @@ public function hash_to_path( string $hash ): string { * * @param int $levels Number of levels. */ - $levels = apply_filters( 'rocket_used_css_dir_level', 3 ); + $levels = wpm_apply_filters_typed( 'integer', 'rocket_used_css_dir_level', 3 ); $base = substr( $hash, 0, $levels ); $remain = substr( $hash, $levels ); diff --git a/inc/Engine/Media/Fonts/Filesystem.php b/inc/Engine/Media/Fonts/Filesystem.php index f5917d7eb9..f26c834277 100644 --- a/inc/Engine/Media/Fonts/Filesystem.php +++ b/inc/Engine/Media/Fonts/Filesystem.php @@ -44,6 +44,17 @@ private function hash_url( string $url ): string { return md5( $url ); } + /** + * Checks if the file exists + * + * @param string $file Absolute path to the file. + * + * @return bool + */ + public function exists( string $file ): bool { + return $this->filesystem->exists( $file ); + } + /** * Writes font css to path * @@ -54,12 +65,10 @@ private function hash_url( string $url ): string { */ public function write_font_css( string $font_url, string $provider ): bool { $font_provider_path = $this->get_font_provider_path( $provider ); - $hash_url = $this->hash_url( $font_url ); - $file = $this->get_fonts_full_path( $font_provider_path, $hash_url ); - $css_file_name = $file . '.css'; - $relative_path = $this->get_fonts_relative_path( $font_provider_path, $hash_url ); + $css_filepath = $this->get_absolute_path( $font_provider_path, 'css/' . $this->hash_to_path( $this->hash_url( $font_url ) ) . '.css' ); + $fonts_basepath = $this->get_absolute_path( $font_provider_path, 'fonts' ); - if ( ! rocket_mkdir_p( dirname( $file ) ) ) { + if ( ! rocket_mkdir_p( dirname( $css_filepath ) ) ) { return false; } @@ -71,14 +80,18 @@ public function write_font_css( string $font_url, string $provider ): bool { return false; } - preg_match_all( '/url\((https:\/\/[^)]+)\)/', $css_content, $matches ); + preg_match_all( '/url\((https:\/\/[^)]+)\)/i', $css_content, $matches ); $font_urls = $matches[1]; $local_css = $css_content; foreach ( $font_urls as $font_url ) { - $parsed_url = wp_parse_url( $font_url ); - $font_path = $parsed_url['path']; - $local_path = $file . $font_path; + $font_path = wp_parse_url( $font_url, PHP_URL_PATH ); + + if ( ! $font_path ) { + continue; + } + + $local_path = $fonts_basepath . $font_path; $local_dir = dirname( $local_path ); if ( ! rocket_mkdir_p( $local_dir ) ) { @@ -96,7 +109,7 @@ public function write_font_css( string $font_url, string $provider ): bool { $this->write_file( $local_path, $font_content ); } - $local_url = content_url( $relative_path . $font_path ); + $local_url = content_url( $this->get_fonts_relative_path( $font_provider_path, $font_path ) ); $local_css = str_replace( $font_url, $local_url, $local_css ); } @@ -106,7 +119,7 @@ public function write_font_css( string $font_url, string $provider ): bool { // Add for test purpose. Logger::debug( "Font download and optimization duration in seconds -- $duration", [ 'Host Fonts Locally' ] ); - return $this->write_file( $css_file_name, $local_css ); + return $this->write_file( $css_filepath, $local_css ); } /** @@ -133,31 +146,31 @@ private function get_remote_content( string $url ): string { } /** - * Get the fonts path for the css file. + * Get the absolute path for a file * * @param string $font_provider_path Font provider path. - * @param string $hash Url of the page. + * @param string $path Path to the file. * - * @return string Path for the font file. + * @return string */ - private function get_fonts_full_path( string $font_provider_path, string $hash ): string { - return $this->path . $font_provider_path . $this->hash_to_path( $hash ); + private function get_absolute_path( string $font_provider_path, string $path ): string { + return $this->path . $font_provider_path . $path; } /** * Get the fonts relative paths * * @param string $font_provider_path Font provider path. - * @param string $hash Hash of the font url. + * @param string $path Path to the file. * * @return string */ - private function get_fonts_relative_path( string $font_provider_path, string $hash ): string { - $full_path = $this->path . $font_provider_path; - $wp_content_dir = rocket_get_constant( 'WP_CONTENT_DIR' ); - $relative_path = str_replace( $wp_content_dir, '', $full_path ); + private function get_fonts_relative_path( string $font_provider_path, string $path ): string { + $base_path = $this->path . $font_provider_path . 'fonts'; + $wp_content_dir = rocket_get_constant( 'WP_CONTENT_DIR', '' ); + $relative_path = str_replace( $wp_content_dir, '', $base_path ); - return $relative_path . $this->hash_to_path( $hash ); + return $relative_path . $path; } /** @@ -183,7 +196,7 @@ private function get_font_provider_path( string $provider ): string { * @return bool */ public function delete_font_css( string $url ): bool { - $dir = $this->get_fonts_full_path( $this->get_font_provider_path( $url ), $url ); + $dir = $this->get_absolute_path( $this->get_font_provider_path( $url ), $url ); return $this->delete_file( $dir ); } diff --git a/inc/Engine/Media/Fonts/Frontend/Controller.php b/inc/Engine/Media/Fonts/Frontend/Controller.php index 21d42af562..74da92c1b7 100644 --- a/inc/Engine/Media/Fonts/Frontend/Controller.php +++ b/inc/Engine/Media/Fonts/Frontend/Controller.php @@ -104,14 +104,22 @@ public function rewrite_fonts( $html ): string { * * @return string */ - private function replace_font( array $font, string $html, string $font_provider = 'google-font' ): string { + private function replace_font( array $font, string $html, string $font_provider = 'google-fonts' ): string { + $hash = md5( $font['url'] ); + + if ( $this->filesystem->exists( $this->get_css_path( $hash, $font_provider ) ) ) { + $local = $this->get_optimized_markup( $hash, $font['url'], $font_provider ); + + return str_replace( $font[0], $local, $html ); + } + if ( ! $this->filesystem->write_font_css( $font['url'], $font_provider ) ) { $this->error = true; return $html; } - $local = $this->get_optimized_markup( md5( $font['url'] ), $font['url'], $font_provider ); + $local = $this->get_optimized_markup( $hash, $font['url'], $font_provider ); return str_replace( $font[0], $local, $html ); } @@ -145,7 +153,7 @@ private function get_optimized_markup( * @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'; + $local_css_path = $this->get_css_path( $hash, $font_provider ); $inline_css = $this->get_font_inline_css( $local_css_path, $gf_parameters ); @@ -154,7 +162,7 @@ private function get_optimized_markup( } } - $url = $this->base_url . $font_provider_path . $this->filesystem->hash_to_path( $hash ) . '.css'; + $url = $this->base_url . $font_provider_path . 'css/' . $this->filesystem->hash_to_path( $hash ) . '.css'; return sprintf( '', // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet @@ -163,6 +171,20 @@ private function get_optimized_markup( ); } + /** + * Gets the CSS path for the font. + * + * @param string $hash Font hash. + * @param string $font_provider Font provider. + * + * @return string + */ + private function get_css_path( string $hash, string $font_provider ): string { + $font_provider_path = sprintf( '%s/', $font_provider ); + + return $this->base_path . $font_provider_path . 'css/' . $this->filesystem->hash_to_path( $hash ) . '.css'; + } + /** * Removes preconnect and prefetch links for Google Fonts from the HTML content. diff --git a/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Controller/HTML/expected_v1.php b/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Controller/HTML/expected_v1.php index 8c1fbb7b89..d4174e5c84 100644 --- a/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Controller/HTML/expected_v1.php +++ b/tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Controller/HTML/expected_v1.php @@ -9,8 +9,8 @@