PluginProbe
EasyFonts – Host Google Fonts Locally, Fast & Auto-Optimize, GDPR Compliant / 2.0.0
EasyFonts – Host Google Fonts Locally, Fast & Auto-Optimize, GDPR Compliant v2.0.0
2.0.4 2.0.3 2.0.2 2.0.1 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2 1.3 2.0.0
easyfonts / src / Frontend / Beacon.php

Beacon.php in EasyFonts – Host Google Fonts Locally, Fast & Auto-Optimize, GDPR Compliant 2.0.0, at src/Frontend/Beacon.php

123 lines 3.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Frontend script loader: usage beacon + X-ray overlay.
4 *
5 * @package EasyFonts
6 */
7
8 namespace EasyFonts\Frontend;
9
10 use EasyFonts\Settings;
11
12 defined( 'ABSPATH' ) || exit;
13
14 /**
15 * Enqueues the runtime beacon and (for admins) the X-ray overlay.
16 */
17 class Beacon {
18
19 /**
20 * Register hooks.
21 */
22 public function boot(): void {
23 add_action( 'wp_enqueue_scripts', array( $this, 'enqueue' ) );
24
25 // The async blocker must run before any theme/plugin script can inject a
26 // provider <link>, so it loads as early as possible in <head>.
27 add_action( 'wp_head', array( $this, 'print_async_blocker' ), 1 );
28 }
29
30 /**
31 * Print the async-injection blocker inline, very early in <head>.
32 *
33 * It intercepts runtime-injected Google/Bunny stylesheet links (which the
34 * server buffer can't see), neutralises the remote request, and reports the
35 * URLs so the next render self-hosts them. Front-end only; respects the
36 * master + async toggles and skips admins' builder/preview screens.
37 */
38 public function print_async_blocker(): void {
39 if ( is_admin() ) {
40 return;
41 }
42
43 if ( ! Settings::get( 'enabled', 1 ) || ! Settings::get( 'async_blocker', 0 ) ) {
44 return;
45 }
46
47 if ( ( defined( 'REST_REQUEST' ) && REST_REQUEST ) || wp_doing_ajax() || is_feed() ) {
48 return;
49 }
50
51 $cfg = array(
52 'endpoint' => esc_url_raw( rest_url( 'easyfonts/v1/async-fonts' ) ),
53 'nonce' => wp_create_nonce( 'wp_rest' ),
54 );
55
56 $src = EASYFONTS_DIR . 'assets/frontend/async-blocker.js';
57
58 if ( ! is_readable( $src ) ) {
59 return;
60 }
61
62 $js = file_get_contents( $src ); // phpcs:ignore WordPress.WP.AlternativeFunctions -- reading a bundled plugin asset.
63
64 if ( false === $js || '' === $js ) {
65 return;
66 }
67
68 // Config first, then the blocker. Printed via core's helper so the tag
69 // is generated and escaped by WordPress (no manual echo of markup), and
70 // runs early in <head> so it beats any font-injecting script.
71 $inline = 'window.EasyFontsAsync=' . wp_json_encode( $cfg ) . ';' . $js;
72
73 wp_print_inline_script_tag( $inline, array( 'id' => 'easyfonts-async-blocker' ) );
74 }
75
76 /**
77 * Enqueue scripts.
78 */
79 public function enqueue(): void {
80 if ( is_admin() ) {
81 return;
82 }
83
84 $route = (string) wp_parse_url( home_url( add_query_arg( array() ) ), PHP_URL_PATH );
85 $device = wp_is_mobile() ? 'mobile' : 'desktop';
86
87 if ( Settings::get( 'beacon', 1 ) ) {
88 wp_enqueue_script(
89 'easyfonts-beacon',
90 EASYFONTS_URL . 'assets/frontend/beacon.js',
91 array(),
92 EASYFONTS_VERSION,
93 array(
94 'strategy' => 'defer',
95 'in_footer' => true,
96 )
97 );
98
99 wp_localize_script(
100 'easyfonts-beacon',
101 'EasyFontsBeacon',
102 array(
103 'endpoint' => esc_url_raw( rest_url( 'easyfonts/v1/beacon' ) ),
104 'nonce' => wp_create_nonce( 'wp_rest' ),
105 'route' => '' === $route ? '/' : $route,
106 'device' => $device,
107 )
108 );
109 }
110
111 // X-ray overlay: admins only, on demand.
112 if ( current_user_can( 'manage_options' ) && isset( $_GET['easyfonts_xray'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
113 wp_enqueue_script(
114 'easyfonts-xray',
115 EASYFONTS_URL . 'assets/frontend/xray.js',
116 array(),
117 EASYFONTS_VERSION,
118 array( 'in_footer' => true )
119 );
120 }
121 }
122 }
123