File: /var/www/html/wpicare/wp-content/plugins/wp-rocket/inc/Engine/Media/Fonts/Filesystem.php
<?php
declare(strict_types=1);
namespace WP_Rocket\Engine\Media\Fonts;
use WP_Filesystem_Direct;
use WP_Rocket\Engine\Common\AbstractFileSystem;
use WP_Rocket\Logger\Logger;
class Filesystem extends AbstractFileSystem {
/**
* WP Filesystem instance
*
* @var WP_Filesystem_Direct
*/
protected $filesystem;
/**
* Path to the fonts storage
*
* @var string
*/
private $path;
/**
* Instantiate the class
*
* @param WP_Filesystem_Direct $filesystem WP Filesystem instance.
*/
public function __construct( $filesystem = null ) {
parent::__construct( is_null( $filesystem ) ? rocket_direct_filesystem() : $filesystem );
$this->path = rocket_get_constant( 'WP_ROCKET_CACHE_ROOT_PATH', '' ) . 'fonts/' . get_current_blog_id() . '/';
}
/**
* Hashes the url
*
* @param string $url URL to get the hash from.
*
* @return string
*/
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 CSS & fonts locally
*
* @param string $css_url The CSS url to save locally.
* @param string $provider The font provider.
*
* @return bool
*/
public function write_font_css( string $css_url, string $provider ): bool {
$font_provider_path = $this->get_font_provider_path( $provider );
$css_filepath = $this->get_absolute_path( $font_provider_path, 'css/' . $this->hash_to_path( $this->hash_url( $css_url ) ) . '.css' );
$fonts_basepath = $this->get_absolute_path( $font_provider_path, 'fonts' );
if ( ! rocket_mkdir_p( dirname( $css_filepath ) ) ) {
return false;
}
$start_time = microtime( true );
$css_content = $this->get_remote_content( html_entity_decode( $css_url ) );
if ( ! $css_content ) {
return false;
}
preg_match_all( '/url\((https:\/\/[^)]+)\)/i', $css_content, $matches );
$font_urls = $matches[1];
$local_css = $css_content;
$count_fonts = 0;
$download_average = 0;
foreach ( $font_urls as $font_url ) {
$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 ) ) {
continue;
}
if ( ! $this->filesystem->exists( $local_path ) ) {
$download_start = microtime( true );
$font_content = $this->get_remote_content( $font_url );
if ( ! $font_content ) {
Logger::debug( 'Font download was not successful', [ 'Host Fonts Locally' ] );
continue;
}
$this->write_file( $local_path, $font_content );
$download_end = microtime( true );
$download_time = $download_end - $download_start;
$download_average += $download_time;
++$count_fonts;
Logger::debug( "Font $font_url download duration -- $download_time", [ 'Host Fonts Locally' ] );
}
$local_url = content_url( $this->get_fonts_relative_path( $font_provider_path, $font_path ) );
$local_css = str_replace( $font_url, $local_url, $local_css );
}
// This filter is documented in inc/Engine/Optimization/CSSTrait.php.
$local_css = wpm_apply_filters_typed( 'string', 'rocket_css_content', $local_css );
$end_time = microtime( true );
$duration = $end_time - $start_time;
// Add for test purpose.
Logger::debug( "Font download and optimization duration in seconds -- $duration", [ 'Host Fonts Locally' ] );
Logger::debug( "Number of fonts downloaded for $css_url -- $count_fonts", [ 'Host Fonts Locally' ] );
Logger::debug( 'Average download time per font -- ' . ( $count_fonts ? $download_average / $count_fonts : 0 ), [ 'Host Fonts Locally' ] );
return $this->write_file( $css_filepath, $local_css );
}
/**
* Gets the remote content of the URL
*
* @param string $url URL to request content for.
*
* @return string
*/
private function get_remote_content( string $url ): string {
$response = wp_safe_remote_get(
$url,
[
'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'httpversion' => '2.0',
]
);
if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
return '';
}
return wp_remote_retrieve_body( $response );
}
/**
* Get the absolute path for a file
*
* @param string $font_provider_path Font provider path.
* @param string $path Path to the file.
*
* @return string
*/
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 $path Path to the file.
*
* @return string
*/
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 . $path;
}
/**
* Get the fonts provider path
*
* @param string $provider The font provider.
*
* @return string
*/
private function get_font_provider_path( string $provider ): string {
$provider = str_replace( '_', '-', $provider );
return $provider . '/';
}
/**
* Deletes the locally stored fonts for the corresponding url
*
* @since 3.18
*
* @param string $url The url of the page to be deleted.
*
* @return bool
*/
public function delete_font_css( string $url ): bool {
$dir = $this->get_absolute_path( $this->get_font_provider_path( $url ), $url );
return $this->delete_file( $dir );
}
}