-
Notifications
You must be signed in to change notification settings - Fork 219
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Co-authored-by: Rémy Perona <remperona@gmail.com>
- Loading branch information
1 parent
8b7db2e
commit dc07f3e
Showing
24 changed files
with
883 additions
and
109 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<?php | ||
declare(strict_types=1); | ||
|
||
namespace WP_Rocket\Engine\Media\Fonts\Context; | ||
|
||
use WP_Rocket\Engine\Common\Context\AbstractContext; | ||
|
||
class Context extends AbstractContext { | ||
/** | ||
* Checks if the feature is allowed. | ||
* | ||
* @param array $data Optional. Data to check against. | ||
* | ||
* @return bool | ||
*/ | ||
public function is_allowed( array $data = [] ): bool { | ||
$is_allowed = $this->run_common_checks( | ||
[ | ||
'do_not_optimize' => false, | ||
'bypass' => false, | ||
'option' => 'host_fonts_locally', | ||
] | ||
); | ||
|
||
return $is_allowed; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
<?php | ||
declare(strict_types=1); | ||
|
||
namespace WP_Rocket\Engine\Media\Fonts\Frontend; | ||
|
||
use WP_Rocket\Engine\Media\Fonts\Context\Context; | ||
use WP_Rocket\Engine\Optimization\RegexTrait; | ||
use WP_Rocket\Logger\Logger; | ||
|
||
class Controller { | ||
use RegexTrait; | ||
|
||
/** | ||
* Context instance. | ||
* | ||
* @var Context | ||
*/ | ||
private $context; | ||
|
||
/** | ||
* Base url. | ||
* | ||
* @var string | ||
*/ | ||
private $base_url; | ||
|
||
/** | ||
* Constructor. | ||
* | ||
* @param Context $context Context instance. | ||
*/ | ||
public function __construct( Context $context ) { | ||
$this->context = $context; | ||
$this->base_url = rocket_get_constant( 'WP_ROCKET_CACHE_ROOT_URL', '' ) . 'fonts/' . get_current_blog_id() . '/'; | ||
} | ||
|
||
/** | ||
* Rewrites the Google Fonts paths to local ones. | ||
* | ||
* @param string $html HTML content. | ||
* @return string | ||
*/ | ||
public function rewrite_fonts( string $html ): string { | ||
if ( ! $this->context->is_allowed() ) { | ||
return $html; | ||
} | ||
|
||
$html_nocomments = $this->hide_comments( $html ); | ||
|
||
$v1_fonts = $this->find( '<link(?:\s+(?:(?!href\s*=\s*)[^>])+)?(?:\s+href\s*=\s*([\'"])(?<url>(?:https?:)?\/\/fonts\.googleapis\.com\/css[^\d](?:(?!\1).)+)\1)(?:\s+[^>]*)?>', $html_nocomments ); | ||
$v2_fonts = $this->find( '<link(?:\s+(?:(?!href\s*=\s*)[^>])+)?(?:\s+href\s*=\s*([\'"])(?<url>(?:https?:)?\/\/fonts\.googleapis\.com\/css2(?:(?!\1).)+)\1)(?:\s+[^>]*)?>', $html_nocomments ); | ||
|
||
if ( ! $v1_fonts && ! $v2_fonts ) { | ||
Logger::debug( 'No Google Fonts found.', [ 'Host Fonts Locally' ] ); | ||
return $html; | ||
} | ||
|
||
foreach ( $v1_fonts as $font ) { | ||
$html = $this->replace_font( $font, $html ); | ||
} | ||
|
||
foreach ( $v2_fonts as $font ) { | ||
$html = $this->replace_font( $font, $html ); | ||
} | ||
|
||
return $html; | ||
} | ||
|
||
/** | ||
* Replaces the Google Fonts URL with the local one. | ||
* | ||
* @param array $font Font data. | ||
* @param string $html HTML content. | ||
* | ||
* @return string | ||
*/ | ||
private function replace_font( $font, $html ): string { | ||
$hash = md5( $font['url'] ); | ||
$local = $this->get_optimized_markup( $hash, $font['url'] ); | ||
|
||
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. | ||
* | ||
* @return string | ||
*/ | ||
protected function get_optimized_markup( string $hash, string $original_url ): string { | ||
$levels = 3; | ||
$base = substr( $hash, 0, $levels ); | ||
$remain = substr( $hash, $levels ); | ||
|
||
$path_array = str_split( $base ); | ||
$path_array[] = $remain; | ||
|
||
$path = implode( '/', $path_array ); | ||
$url = $this->base_url . $path . '.css'; | ||
|
||
$gf_parameters = wp_parse_url( $original_url, PHP_URL_QUERY ); | ||
|
||
return sprintf( | ||
'<link rel="stylesheet" href="%1$s" data-wpr-hosted-gf-parameters="%2$s"/>', // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet | ||
$url, | ||
$gf_parameters | ||
); | ||
} | ||
|
||
/** | ||
* 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->context->is_allowed() ) { | ||
return $disable; | ||
} | ||
|
||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
<?php | ||
declare(strict_types=1); | ||
|
||
namespace WP_Rocket\Engine\Media\Fonts\Frontend; | ||
|
||
use WP_Rocket\Event_Management\Subscriber_Interface; | ||
|
||
class Subscriber implements Subscriber_Interface { | ||
/** | ||
* Frontend Controller instance. | ||
* | ||
* @var Controller | ||
*/ | ||
private $frontend_controller; | ||
|
||
/** | ||
* Constructor. | ||
* | ||
* @param Controller $frontend_controller Frontend Controller instance. | ||
*/ | ||
public function __construct( Controller $frontend_controller ) { | ||
$this->frontend_controller = $frontend_controller; | ||
} | ||
|
||
/** | ||
* Returns an array of events that this subscriber wants to listen to. | ||
* | ||
* @return array | ||
*/ | ||
public static function get_subscribed_events(): array { | ||
return [ | ||
'rocket_buffer' => [ 'rewrite_fonts', 18 ], | ||
'rocket_disable_google_fonts_preload' => 'disable_google_fonts_preload', | ||
]; | ||
} | ||
|
||
/** | ||
* Rewrites the Google Fonts paths to local ones. | ||
* | ||
* @param string $html HTML content. | ||
* @return string | ||
*/ | ||
public function rewrite_fonts( string $html ): string { | ||
return $this->frontend_controller->rewrite_fonts( $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 { | ||
return $this->frontend_controller->disable_google_fonts_preload( $disable ); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
tests/Fixtures/inc/Engine/Media/Fonts/Context/Context/isAllowed.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<?php | ||
|
||
return [ | ||
'testShouldReturnFalseWhenBypass' => [ | ||
'config' => [ | ||
'bypass' => true, | ||
'do_not_optimize' => false, | ||
'option' => true, | ||
], | ||
'expected' => false, | ||
], | ||
'testShouldReturnFalseWhenDoNotOptimize' => [ | ||
'config' => [ | ||
'bypass' => false, | ||
'do_not_optimize' => true, | ||
'option' => true, | ||
], | ||
'expected' => false, | ||
], | ||
'testShouldReturnFalseWhenOptionDisabled' => [ | ||
'config' => [ | ||
'bypass' => false, | ||
'do_not_optimize' => true, | ||
'option' => false, | ||
], | ||
'expected' => false, | ||
], | ||
'testShouldReturnTrueWhenOptionEnabled' => [ | ||
'config' => [ | ||
'bypass' => false, | ||
'do_not_optimize' => false, | ||
'option' => true, | ||
], | ||
'expected' => true, | ||
], | ||
]; |
33 changes: 33 additions & 0 deletions
33
tests/Fixtures/inc/Engine/Media/Fonts/Frontend/Controller/HTML/expected_v1.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<?php | ||
/** | ||
* Template Name: Google Font V1 Template | ||
*/ ?> | ||
|
||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Google Font V1 Template</title> | ||
<link rel="stylesheet" href="http://example.org/wp-content/cache/fonts/1/e/b/c/173c0fc97eef86a6e51ada56c5a9a.css" data-wpr-hosted-gf-parameters="family=Roboto"/> | ||
<link rel="stylesheet" href="http://example.org/wp-content/cache/fonts/1/5/9/5/cb6ccb56826a802ed411cef875f0e.css" data-wpr-hosted-gf-parameters="family=Open+Sans"/> | ||
<style> | ||
.roboto-font { | ||
font-family: 'Roboto', sans-serif; | ||
} | ||
.open-sans-font { | ||
font-family: 'Open Sans', sans-serif; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div class="wrap"> | ||
<div id="primary" class="content-area"> | ||
<main id="main" class="site-main"> | ||
<h1 class="roboto-font">Hello World</h1> | ||
<p class="open-sans-font">Welcome to the world</p> | ||
</main><!-- #main --> | ||
</div><!-- #primary --> | ||
</div><!-- .wrap --> | ||
</body> | ||
</html> |
Oops, something went wrong.