Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sub task/3.18 backend filesystem part#7062 #7083

Draft
wants to merge 10 commits into
base: develop
Choose a base branch
from
217 changes: 217 additions & 0 deletions inc/Engine/Media/Fonts/Controller/Filesystem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
<?php

declare(strict_types=1);

namespace WP_Rocket\Engine\Media\Fonts\Controller;

class Filesystem {
/**
* WP Filesystem instance
*
* @var WP_Filesystem_Direct
*/
private $filesystem;

Check failure on line 13 in inc/Engine/Media/Fonts/Controller/Filesystem.php

View workflow job for this annotation

GitHub Actions / WPRocket lint with PHP Stan. PHP 8.2 on ubuntu-latest.

Property WP_Rocket\Engine\Media\Fonts\Controller\Filesystem::$filesystem has unknown class WP_Rocket\Engine\Media\Fonts\Controller\WP_Filesystem_Direct as its type.

/**
* Path to the fonts storage
*
* @var string
*/
private $path;

/**
* Version of the fonts.
*
* @var int
*/
private $version;

/**
* Instantiate the class
*
* @param string $base_path Base path to the fonts storage.
* @param WP_Filesystem_Direct $filesystem WP Filesystem instance.
*/
public function __construct( $base_path, $filesystem = null ) {

Check failure on line 35 in inc/Engine/Media/Fonts/Controller/Filesystem.php

View workflow job for this annotation

GitHub Actions / WPRocket lint with PHP Stan. PHP 8.2 on ubuntu-latest.

Parameter $filesystem of method WP_Rocket\Engine\Media\Fonts\Controller\Filesystem::__construct() has invalid type WP_Rocket\Engine\Media\Fonts\Controller\WP_Filesystem_Direct.
$this->filesystem = is_null( $filesystem ) ? rocket_direct_filesystem() : $filesystem;
$this->path = $base_path . get_current_blog_id() . '/';
}

/**
* Hash the url
*
* @param string $url Url of the page to hash.
*
* @return string
*/
private function hash_url( string $url ): string {
return md5( $url );
}

/**
* Write font css to path
*
* @param string $font_url The font url to save locally.
* @param string $provider The url of the page.
*
* @return bool
*/
public function write_font_css( string $font_url, string $provider ): bool {
global $wp;
$url = untrailingslashit( home_url( add_query_arg( [], $wp->request ) ) );

$font_provider_path = $this->get_font_provider_path( $provider );
$hash_url = $this->hash_url( $url );
$file = $this->get_fonts_full_path( $font_provider_path, $hash_url );
$css_file_name = $file . $hash_url . '.css';
$relative_path = $this->get_fonts_relative_path( $font_provider_path, $hash_url );

if ( ! rocket_mkdir_p( dirname( $file ) ) ) {
return false;
}

$css_content = $this->download_font( html_entity_decode( $font_url ) );

if ( ! $css_content ) {
return false;
}

preg_match_all( '/url\((https:\/\/[^)]+)\)/', $css_content, $matches );
$font_urls = $matches[1];
$local_css = $css_content;

foreach ( $font_urls as $font_url ) {
$parsed_url = wp_parse_url( $font_url );
$path_parts = explode( '/', trim( $parsed_url['path'], '/' ) );
$local_path = $file . implode( '/', $path_parts );
$local_dir = dirname( $local_path );

rocket_mkdir_p( $local_dir );

if ( ! file_exists( $local_path ) ) {
$font_content = $this->download_font( $font_url );

if ( ! $font_content ) {
continue;
}

$this->filesystem->put_contents( $local_path, $font_content, rocket_get_filesystem_perms( 'file' ) );

Check failure on line 98 in inc/Engine/Media/Fonts/Controller/Filesystem.php

View workflow job for this annotation

GitHub Actions / WPRocket lint with PHP Stan. PHP 8.2 on ubuntu-latest.

Call to method put_contents() on an unknown class WP_Rocket\Engine\Media\Fonts\Controller\WP_Filesystem_Direct.
}

$local_url = content_url( $relative_path . implode( '/', $path_parts ) );
$local_css = str_replace( $font_url, $local_url, $local_css );
}

return $this->filesystem->put_contents( $css_file_name, $local_css, rocket_get_filesystem_perms( 'file' ) );

Check failure on line 105 in inc/Engine/Media/Fonts/Controller/Filesystem.php

View workflow job for this annotation

GitHub Actions / WPRocket lint with PHP Stan. PHP 8.2 on ubuntu-latest.

Call to method put_contents() on an unknown class WP_Rocket\Engine\Media\Fonts\Controller\WP_Filesystem_Direct.
}

/**
* Download font from external url
*
* @param string $url Url of the file to download.
*
* @return bool|string
*/
private function download_font( string $url ): bool|string {
$content = wp_remote_retrieve_body(
wp_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 ( ! $content ) {
return false;
}

return $content;
}

/**
* Get the fonts path for the css file.
*
* @param string $provider Font provider.
* @param string $hash_url Url of the page.
*
* @return string Path for the font file.
*/
private function get_fonts_full_path( string $provider, string $hash_url ): string {
$font_provider_path = $this->get_font_provider_path( $provider );

return $this->path . $font_provider_path . $hash_url . '/' . $this->get_version() . '/';
}


/**
* Get the fonts relative paths
*
* @param string $font_provider_path Font provider path.
* @param string $hash_url Url of the page.
*
* @return string
*/
private function get_fonts_relative_path( string $font_provider_path, string $hash_url, ): string {
$full_path = $this->path . $font_provider_path;
$relative_path = str_replace( WP_CONTENT_DIR, '', $full_path );

return $relative_path . $hash_url . '/' . $this->get_version() . '/';
}

/**
* 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.11.4
*
* @param string $url The url of the page to be deleted.
*
* @return bool
*/
public function delete_font_css( string $url ): bool {
$dir = $this->get_fonts_full_path( $this->get_font_provider_path( $url ), $url );

return $this->filesystem->delete( $dir, true, 'd' );

Check failure on line 188 in inc/Engine/Media/Fonts/Controller/Filesystem.php

View workflow job for this annotation

GitHub Actions / WPRocket lint with PHP Stan. PHP 8.2 on ubuntu-latest.

Call to method delete() on an unknown class WP_Rocket\Engine\Media\Fonts\Controller\WP_Filesystem_Direct.
}

/**
* Deletes all the font CSS files
*/
public function delete_all_font_css() {
// TODO:create method to recursively delete all locally stored fonts.
}

/**
* Set the version of the fonts
*
* @param int $version The version of the font.
*
* @return void
*/
public function set_version( int $version ): void {
$this->version = $version;
}

/**
* Get the font version
*
* @return int
*/
public function get_version(): int {
return $this->version;
}
}
58 changes: 58 additions & 0 deletions inc/Engine/Media/Fonts/Controller/Fonts.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php
declare(strict_types=1);

namespace WP_Rocket\Engine\Media\Fonts\Controller;

use WP_Rocket\Admin\Options_Data;
use WP_Rocket\Engine\Optimization\RegexTrait;

class Fonts {
use RegexTrait;

/**
* Filesystem instance.
*
* @var Filesystem
*/
private $filesystem;

/**
* Instance of options handler.
*
* @var Options_Data
*/
private $options;

/**
* Instantiate the class.
*
* @param Filesystem $filesystem Filesystem Instance.
* @param Options_Data $options Options instance.
*/
public function __construct(
Filesystem $filesystem,
Options_Data $options
) {
$this->filesystem = $filesystem;
$this->options = $options;
}

/**
* Start the process of downloading font locally
*
* @param string $font_url URL of the font to be saved locally.
* @param string $provider Provider of the font.
* @param integer $version Version.
*
* @return void
*/
public function process( string $font_url, string $provider, int $version ): void {
if ( ! $this->options->get( 'host_google_fonts' ) ) {
return;
}

$this->filesystem->set_version( $version );

$this->filesystem->write_font_css( $font_url, $provider );
}
}
51 changes: 51 additions & 0 deletions inc/Engine/Media/Fonts/Frontend/Subscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php
declare(strict_types=1);

namespace WP_Rocket\Engine\Media\Fonts\Frontend;

use WP_Rocket\Engine\Media\Fonts\Controller\Fonts;
use WP_Rocket\Event_Management\Subscriber_Interface;

class Subscriber implements Subscriber_Interface {
/**
* Fonts instance
*
* @var Fonts
*/
private $fonts;

/**
* Instantiate the class
*
* @param Fonts $fonts Fonts instance.
*/
public function __construct( Fonts $fonts ) {
$this->fonts = $fonts;
}

/**
* Return an array of events that this subscriber wants to listen to.
*
* @since 3.18
*
* @return array
*/
public static function get_subscribed_events() {
return [
'rocket_host_google_fonts' => [ 'process', 15, 3 ],
];
}

/**
* Save Fonts locally
*
* @param string $font_url The url of the font.
* @param string $provider The font provider.
* @param integer $version The version of the font.
*
* @return void
*/
public function process( string $font_url, string $provider, int $version ): void {
$this->fonts->process( $font_url, $provider, $version );
}
}
54 changes: 54 additions & 0 deletions inc/Engine/Media/Fonts/ServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace WP_Rocket\Engine\Media\Fonts;

use WP_Rocket\Dependencies\League\Container\ServiceProvider\AbstractServiceProvider;
use WP_Rocket\Engine\Media\Fonts\Frontend\Subscriber as FrontendSubscriber;
use WP_Rocket\Engine\Media\Fonts\Controller\Fonts as FontsController;
use WP_Rocket\Engine\Media\Fonts\Controller\Filesystem;

/**
* Service provider for the WP Rocket Font Optimization
*/
class ServiceProvider extends AbstractServiceProvider {
/**
* Array of services provided by this service provider
*
* @var array
*/
protected $provides = [
'fonts_frontend_subscriber',
'fonts_filesystem',
];

/**
* Check if the service provider provides a specific service.
*
* @param string $id The id of the service.
*
* @return bool
*/
public function provides( string $id ): bool {
return in_array( $id, $this->provides, true );
}

/**
* Registers the option array in the container
*
* @return void
*/
public function register(): void {
$this->getContainer()->add( 'fonts_filesystem', Filesystem::class )
->addArgument( rocket_get_constant( 'WP_ROCKET_FONT_CSS_PATH' ) )
->addArgument( rocket_direct_filesystem() );

$this->getContainer()->add( 'fonts_controller', FontsController::class )
->addArgument( $this->getContainer()->get( 'fonts_filesystem' ) )
->addArgument( $this->getContainer()->get( 'options' ) );

$this->getContainer()->addShared( 'fonts_frontend_subscriber', FrontendSubscriber::class )
->addArgument( $this->getContainer()->get( 'fonts_controller' ) );
}
}
Loading
Loading