Skip to content

Commit

Permalink
Closes #7104: Duplicated tag added to page (#7105)
Browse files Browse the repository at this point in the history
Co-authored-by: Rémy Perona <remperona@gmail.com>
  • Loading branch information
Miraeld and remyperona authored Nov 14, 2024
1 parent 8b7db2e commit dc07f3e
Show file tree
Hide file tree
Showing 24 changed files with 883 additions and 109 deletions.
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;
}
}
128 changes: 128 additions & 0 deletions inc/Engine/Media/Fonts/Frontend/Controller.php
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;
}
}
57 changes: 57 additions & 0 deletions inc/Engine/Media/Fonts/Frontend/Subscriber.php
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 );
}
}
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' )
);
}
}
14 changes: 14 additions & 0 deletions inc/Engine/Optimization/GoogleFonts/AbstractGFOptimization.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,20 @@ protected function get_font_display_value(): string {
* @return string
*/
protected function get_optimized_markup( string $url ): string {
/**
* Filters whether to disable Google Fonts preloading.
*
* @since 3.18
*
* @param bool $disable_google_fonts_preload Whether to disable Google Fonts preloading. Default false.
*/
if ( wpm_apply_filters_typed( 'boolean', 'rocket_disable_google_fonts_preload', false ) ) {
return sprintf(
'<link rel="stylesheet" href="%1$s" />', // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet
$url
);
}

return sprintf(
'<link rel="preload" data-rocket-preload as="style" href="%1$s" /><link rel="stylesheet" href="%1$s" media="print" onload="this.media=\'all\'" /><noscript><link rel="stylesheet" href="%1$s" /></noscript>', // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet
$url
Expand Down
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>
Loading

0 comments on commit dc07f3e

Please sign in to comment.