** * Replaces the Google Fonts URL with the local one. * * @param array $font Font data. * @param string $html HTML content. * @param string $font_provider Font provider. * * @return 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( $hash, $font['url'], $font_provider ); return str_replace( $font[0], $local, $html ); } /** * Returns the optimized markup for Google Fonts * * @since 3.18 * * @param string $hash Font Url has. * @param string $original_url Fonts Url. * @param string $font_provider Fonts provider. * * @return string */ private function get_optimized_markup( string $hash, string $original_url, string $font_provider ): string { $font_provider_path = sprintf( '%s/', $font_provider ); $original_url = html_entity_decode( $original_url, ENT_QUOTES ); $gf_parameters = wp_parse_url( $original_url, PHP_URL_QUERY ); /** * 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->get_css_path( $hash, $font_provider ); $inline_css = $this->get_font_inline_css( $local_css_path, $gf_parameters ); if ( ! empty( $inline_css ) ) { return $inline_css; } } // This filter is documented in inc/classes/optimization/css/class-abstract-css-optimization.php. $url = wpm_apply_filters_typed( 'string', 'rocket_css_url', $this->base_url . $font_provider_path . 'css/' . $this->filesystem->hash_to_path( $hash ) . '.css' ); return sprintf( '', // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet $url, $gf_parameters ); } /** * 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. * * @param string $html HTML content. * * @return string Modified HTML content without preconnect and prefetch links. */ private function remove_preconnect_and_prefetch( string $html ) { /** * Filters the removal of Google preconnect/prefetch links. * * @since 3.18 * * @param bool $enable_removal Enable or disable removal of Google preconnect/prefetch links. */ $remove_links = wpm_apply_filters_typed( 'boolean', 'rocket_remove_font_pre_links', true ); if ( ! $remove_links ) { return $html; } $pattern = '/]*\b(rel\s*=\s*[\'"](?:preconnect|dns-prefetch)[\'"]|href\s*=\s*[\'"](?:https?:)?\/\/(?:fonts\.(?:googleapis|gstatic)\.com)[\'"])[^>]*\b(rel\s*=\s*[\'"](?:preconnect|dns-prefetch)[\'"]|href\s*=\s*[\'"](?:https?:)?\/\/(?:fonts\.(?:googleapis|gstatic)\.com)[\'"])[^>]*>/i'; $html = preg_replace( $pattern, '', $html ); return $html; } /** * Disables the preload of Google Fonts. * * @param bool $disable Whether to disable the preload of Google Fonts. * * @return bool */ public function disable_google_fonts_preload( $disable ): bool { if ( ! $this->optimization_context->is_allowed() ) { return $disable; } 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 ); } }