url_to_path( $local_url ) ) ) { return str_replace( $href, $local_url, $tag ); } // Download the Google Fonts CSS. $response = wp_remote_get( $href, array( 'timeout' => 10, 'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', ) ); if ( is_wp_error( $response ) ) { return $tag; // Serve original on failure. } $css = wp_remote_retrieve_body( $response ); if ( empty( $css ) ) { return $tag; } // Download font files and rewrite URLs. $font_dir = wpsco_get_cache_dir( 'fonts/' ); if ( ! is_dir( $font_dir ) ) { wp_mkdir_p( $font_dir ); } $css = preg_replace_callback( '/url\s*\(\s*([\'"]?)(https?:\/\/fonts\.gstatic\.com\/[^)\'"]+)\1\s*\)/i', function ( $matches ) use ( $font_dir ) { $font_url = $matches[2]; $font_file = md5( $font_url ) . '.' . pathinfo( wp_parse_url( $font_url, PHP_URL_PATH ), PATHINFO_EXTENSION ); $local_path = $font_dir . $font_file; if ( ! file_exists( $local_path ) ) { $font_response = wp_remote_get( $font_url, array( 'timeout' => 10 ) ); if ( ! is_wp_error( $font_response ) ) { wpsco_write_file( $local_path, wp_remote_retrieve_body( $font_response ) ); } else { return $matches[0]; // Keep original URL on failure. } } $local_url = wpsco_get_cache_url( 'fonts/' . $font_file ); return 'url(' . $matches[1] . $local_url . $matches[1] . ')'; }, $css ); // Add font-display: swap if not present. if ( strpos( $css, 'font-display' ) === false ) { $css = preg_replace( '/(@font-face\s*\{)/', '$1font-display:swap;', $css ); } // Save CSS. $css_hash = md5( $href ); $css_file = $font_dir . 'google-fonts-' . substr( $css_hash, 0, 8 ) . '.css'; $css_url = wpsco_get_cache_url( 'fonts/google-fonts-' . substr( $css_hash, 0, 8 ) . '.css' ); wpsco_write_file( $css_file, $css ); // Cache for 30 days. set_transient( $cache_key, $css_url, 30 * DAY_IN_SECONDS ); return str_replace( $href, $css_url, $tag ); } /** * Preload critical fonts. */ public function preload_fonts() { if ( is_admin() ) { return; } $font_urls = wpsco_get_setting( 'preload_font_urls', array() ); if ( empty( $font_urls ) ) { return; } foreach ( $font_urls as $url ) { $url = trim( $url ); if ( empty( $url ) ) { continue; } // Determine type from extension. $ext = strtolower( pathinfo( wp_parse_url( $url, PHP_URL_PATH ), PATHINFO_EXTENSION ) ); $type = 'font/woff2'; switch ( $ext ) { case 'woff': $type = 'font/woff'; break; case 'woff2': $type = 'font/woff2'; break; case 'ttf': $type = 'font/ttf'; break; case 'otf': $type = 'font/otf'; break; } printf( '' . "\n", esc_url( $url ), esc_attr( $type ) ); } } /** * Convert URL to path. * * @param string $url URL. * @return string|false */ private function url_to_path( $url ) { return wpsco_url_to_path( $url ); } }