PluginProbe
EasyFonts – Host Google Fonts Locally, Fast & Auto-Optimize, GDPR Compliant / 2.0.4
EasyFonts – Host Google Fonts Locally, Fast & Auto-Optimize, GDPR Compliant v2.0.4
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.4, at src/Frontend/Beacon.php

131 lines 3.4 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 'token' => Settings::beacon_token(),
55 );
56
57 $src = EASYFONTS_DIR . 'assets/frontend/async-blocker.min.js';
58
59 if ( ! is_readable( $src ) ) {
60 return;
61 }
62
63 $js = file_get_contents( $src ); // phpcs:ignore WordPress.WP.AlternativeFunctions -- reading a bundled plugin asset.
64
65 if ( false === $js || '' === $js ) {
66 return;
67 }
68
69 // Config first, then the blocker. Printed via core's helper so the tag
70 // is generated and escaped by WordPress (no manual echo of markup), and
71 // runs early in <head> so it beats any font-injecting script.
72 $inline = 'window.EasyFontsAsync=' . wp_json_encode( $cfg ) . ';' . $js;
73
74 wp_print_inline_script_tag( $inline, array( 'id' => 'easyfonts-async-blocker' ) );
75 }
76
77 /**
78 * Enqueue scripts.
79 */
80 public function enqueue(): void {
81 if ( is_admin() ) {
82 return;
83 }
84
85 // Master kill switch: when Easy Fonts is disabled, add nothing to the
86 // front end — no beacon, no X-ray, no inline config.
87 if ( ! Settings::get( 'enabled', 1 ) ) {
88 return;
89 }
90
91 $route = (string) wp_parse_url( home_url( add_query_arg( array() ) ), PHP_URL_PATH );
92 $device = wp_is_mobile() ? 'mobile' : 'desktop';
93
94 if ( Settings::get( 'beacon', 1 ) ) {
95 wp_enqueue_script(
96 'easyfonts-beacon',
97 EASYFONTS_URL . 'assets/frontend/beacon.min.js',
98 array(),
99 EASYFONTS_VERSION,
100 array(
101 'strategy' => 'defer',
102 'in_footer' => true,
103 )
104 );
105
106 wp_localize_script(
107 'easyfonts-beacon',
108 'EasyFontsBeacon',
109 array(
110 'endpoint' => esc_url_raw( rest_url( 'easyfonts/v1/beacon' ) ),
111 'nonce' => wp_create_nonce( 'wp_rest' ),
112 'token' => Settings::beacon_token(),
113 'route' => '' === $route ? '/' : $route,
114 'device' => $device,
115 )
116 );
117 }
118
119 // X-ray overlay: admins only, on demand.
120 if ( current_user_can( 'manage_options' ) && isset( $_GET['easyfonts_xray'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
121 wp_enqueue_script(
122 'easyfonts-xray',
123 EASYFONTS_URL . 'assets/frontend/xray.min.js',
124 array(),
125 EASYFONTS_VERSION,
126 array( 'in_footer' => true )
127 );
128 }
129 }
130 }
131