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

Closes #7063: Google font - Frontend part #7091

Merged
merged 31 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
be9e3b9
Base structure
Miraeld Nov 6, 2024
b33302c
Google font version management
Miraeld Nov 6, 2024
5687237
Change of structure + fixes linters
Miraeld Nov 6, 2024
5fac384
Change use of `home_url` to WPR constant
Miraeld Nov 6, 2024
968eefd
Change use of `home_url` to WPR constant
Miraeld Nov 6, 2024
359f175
Changes the build of the factory
Miraeld Nov 7, 2024
6f044c0
Add unit tests
Miraeld Nov 7, 2024
4882bbf
Fix ServiceProvider
Miraeld Nov 7, 2024
833baaf
Works up to combining URL
Miraeld Nov 8, 2024
98d8fdc
Apply linter
Miraeld Nov 8, 2024
0f2c05b
First working prototype
Miraeld Nov 8, 2024
32fa787
WIP: Integration test
Miraeld Nov 8, 2024
ebbbaf2
revert visibility
remyperona Nov 8, 2024
5160b3d
update context checking
remyperona Nov 8, 2024
e2d59b2
add strict declare
remyperona Nov 8, 2024
02a4c23
rewrite fonts URL
remyperona Nov 8, 2024
03845d4
update instantiation
remyperona Nov 8, 2024
84480aa
update URL
remyperona Nov 8, 2024
44f0891
update tests
remyperona Nov 8, 2024
e4934af
remove group
remyperona Nov 8, 2024
7e7c721
Merge branch 'feature/host-google-fonts' into feature/7063-google-fon…
remyperona Nov 8, 2024
29b218c
update name
remyperona Nov 8, 2024
8ed9d56
update config
remyperona Nov 8, 2024
1322df3
update test
remyperona Nov 8, 2024
32930b5
update instantiation
remyperona Nov 8, 2024
46e6a8b
remove file
remyperona Nov 8, 2024
04dcaed
Change the position of google font combined url process
Khadreal Nov 11, 2024
489c049
Fixed linter error
Khadreal Nov 11, 2024
81eaa9c
update test
Khadreal Nov 11, 2024
cab4e86
refactor duplicate code
remyperona Nov 12, 2024
810538b
Updated namespace
jeawhanlee Nov 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions inc/Engine/Media/Fonts/Context/Context.php
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;
}
}
113 changes: 113 additions & 0 deletions inc/Engine/Media/Fonts/Frontend/Controller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?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
);
}
}
45 changes: 45 additions & 0 deletions inc/Engine/Media/Fonts/Frontend/Subscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?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 ],
];
}

/**
* 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 );
}
}
19 changes: 19 additions & 0 deletions inc/Engine/Media/Fonts/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
use WP_Rocket\Dependencies\League\Container\ServiceProvider\AbstractServiceProvider;
use WP_Rocket\Engine\Media\Fonts\Admin\Settings;
use WP_Rocket\Engine\Media\Fonts\Admin\Subscriber as AdminSubscriber;
use WP_Rocket\Engine\Media\Fonts\Context\Context;
use WP_Rocket\Engine\Media\Fonts\Frontend\Controller as FrontendController;
use WP_Rocket\Engine\Media\Fonts\Frontend\Subscriber as FrontendSubscriber;

class ServiceProvider extends AbstractServiceProvider {
/**
Expand All @@ -20,6 +23,9 @@ class ServiceProvider extends AbstractServiceProvider {
protected $provides = [
'media_fonts_settings',
'media_fonts_admin_subscriber',
'media_fonts_context',
'media_fonts_frontend_controller',
'media_fonts_frontend_subscriber',
];

/**
Expand All @@ -42,5 +48,18 @@ public function register(): void {
$this->getContainer()->add( 'media_fonts_settings', Settings::class );
$this->getContainer()->addShared( 'media_fonts_admin_subscriber', AdminSubscriber::class )
->addArgument( 'media_fonts_settings' );

$this->getContainer()->add( 'media_fonts_context', Context::class )
->addArgument( $this->getContainer()->get( 'options' ) );
$this->getContainer()->add( 'media_fonts_frontend_controller', FrontendController::class )
->addArguments(
[
$this->getContainer()->get( 'media_fonts_context' ),
]
);
$this->getContainer()->add( 'media_fonts_frontend_subscriber', FrontendSubscriber::class )
->addArgument(
$this->getContainer()->get( 'media_fonts_frontend_controller' )
);
}
}
2 changes: 1 addition & 1 deletion inc/Engine/Optimization/GoogleFonts/Subscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public function __construct( AbstractGFOptimization $combine, AbstractGFOptimiza
public static function get_subscribed_events() {
return [
'wp_resource_hints' => [ 'preconnect', 10, 2 ],
'rocket_buffer' => [ 'process', 1001 ],
'rocket_buffer' => [ 'process', 17 ],
];
}

Expand Down
1 change: 1 addition & 0 deletions inc/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ private function init_common_subscribers() {
'performance_hints_admin_subscriber',
'lrc_frontend_subscriber',
'taxonomy_subscriber',
'media_fonts_frontend_subscriber',
'media_fonts_admin_subscriber',
];

Expand Down
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,
],
];
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>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php
/**
* Template Name: Google Font V1 and V2 Template
*/ ?>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Google Font V1 and V2 Template</title>
<link rel="stylesheet" href="http://example.org/wp-content/cache/fonts/1/6/2/4/f2c2b9858423d0688793189f6e6cb.css" data-wpr-hosted-gf-parameters="family=Roboto|Open+Sans"/> <!-- V1 Fonts -->
<link rel="stylesheet" href="http://example.org/wp-content/cache/fonts/1/8/d/4/e42f26da0305c49cd3264956d8329.css" data-wpr-hosted-gf-parameters="family=Lato:wght@400;700&family=Montserrat:wght@400;700&display=swap"/> <!-- V2 Fonts -->
<style>
.v1-font-roboto {
font-family: 'Roboto', sans-serif;
}
.v1-font-open-sans {
font-family: 'Open Sans', sans-serif;
}
.v2-font-lato {
font-family: 'Lato', sans-serif;
}
.v2-font-montserrat {
font-family: 'Montserrat', sans-serif;
}
</style>
</head>
<body>
<div class="wrap">
<div id="primary" class="content-area">
<main id="main" class="site-main">
<h1 class="v1-font-roboto">Hello World</h1>
<p class="v1-font-open-sans">Welcome to the world</p>
<h2 class="v2-font-lato">This is a subtitle</h2>
<p class="v2-font-montserrat">Enjoy your stay</p>
</main><!-- #main -->
</div><!-- #primary -->
</div><!-- .wrap -->
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php
/**
* Template Name: Google Font V2 Template
*/ ?>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Google Font V2 Template</title>
<link rel="stylesheet" href="http://example.org/wp-content/cache/fonts/1/a/b/2/8ffb4f83584e9add1be594dd90dfd.css" data-wpr-hosted-gf-parameters="family=Roboto:wght@400;700&display=swap"/>
<link rel="stylesheet" href="http://example.org/wp-content/cache/fonts/1/b/4/d/9ffca0114d3acb6ab0b068feaf933.css" data-wpr-hosted-gf-parameters="family=Lato:wght@400;700&display=swap"/>
<style>
.roboto-font {
font-family: 'Roboto', sans-serif;
}
.lato-font {
font-family: 'Lato', 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="lato-font">Welcome to the world</p>
</main><!-- #main -->
</div><!-- #primary -->
</div><!-- .wrap -->
</body>
</html>
Loading
Loading