PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.0-beta
Jetpack – WP Security, Backup, Speed, & Growth v16.0-beta
16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / modules / google-fonts / current / class-jetpack-google-font-face.php
jetpack / modules / google-fonts / current Last commit date
class-jetpack-google-font-face.php 5 months ago load-google-fonts.php 2 weeks ago
class-jetpack-google-font-face.php
261 lines
1 <?php
2 /**
3 * Jetpack_Google_Font_Face class
4 *
5 * @package automattic/jetpack
6 */
7
8 /**
9 * Jetpack Google Font Face disables Font Face hooks in Core that prints **ALL** font faces.
10 * Instead, it collects fonts that are used in global styles or block-level settings and
11 * print those fonts in use.
12 *
13 * @phan-constructor-used-for-side-effects
14 */
15 class Jetpack_Google_Font_Face {
16 /**
17 * The fonts that are used in global styles or block-level settings.
18 *
19 * @var array
20 */
21 private $fonts_in_use = array();
22
23 /**
24 * The constructor.
25 */
26 public function __construct() {
27 // Turns off hooks to print fonts
28 add_action( 'wp_loaded', array( $this, 'wp_loaded' ) );
29 add_action( 'current_screen', array( $this, 'current_screen' ), 10 );
30
31 // Collect and print fonts in use
32 if ( wp_is_block_theme() ) {
33 add_action( 'wp_head', array( $this, 'print_font_faces' ), 50 );
34 } else {
35 // In classic themes wp_head runs before the blocks are processed to collect the block fonts.
36 add_action( 'wp_footer', array( $this, 'print_font_faces' ), 50 );
37 }
38 add_filter( 'pre_render_block', array( $this, 'collect_block_fonts' ), 10, 2 );
39 }
40
41 /**
42 * Turn off hooks to print fonts on frontend
43 */
44 public function wp_loaded() {
45 remove_action( 'wp_head', 'wp_print_fonts', 50 );
46 remove_action( 'wp_head', 'wp_print_font_faces', 50 );
47 // Gutenberg 22.4+ overrides Core's font printing with its own function
48 // for classic theme support. Remove it so we can print only fonts in use.
49 remove_action( 'wp_head', 'gutenberg_print_font_faces', 50 );
50 }
51
52 /**
53 * Turn off hooks to print fonts on wp-admin, except for GB editor pages.
54 */
55 public function current_screen() {
56 remove_action( 'admin_print_styles', 'wp_print_fonts', 50 );
57
58 if ( ! $this->is_block_editor() ) {
59 remove_action( 'admin_print_styles', 'wp_print_font_faces', 50 );
60 }
61 }
62
63 /**
64 * Print fonts that are used in global styles or block-level settings.
65 */
66 public function print_font_faces() {
67 $fonts = WP_Font_Face_Resolver::get_fonts_from_theme_json();
68 $font_slug_aliases = $this->get_font_slug_aliases();
69 $fonts_to_print = array();
70
71 $this->collect_global_styles_fonts();
72 $fonts_in_use = array_values( array_unique( $this->fonts_in_use, SORT_STRING ) );
73 $fonts_in_use = array_map(
74 function ( $font_slug ) use ( $font_slug_aliases ) {
75 return $font_slug_aliases[ $font_slug ] ?? $font_slug;
76 },
77 $this->fonts_in_use
78 );
79
80 foreach ( $fonts as $font_faces ) {
81 $font_family = $font_faces[0]['font-family'] ?? '';
82 if ( in_array( $this->format_font( $font_family ), $fonts_in_use, true ) ) {
83 $fonts_to_print[] = $font_faces;
84 }
85 }
86
87 if ( ! empty( $fonts_to_print ) ) {
88 wp_print_font_faces( $fonts_to_print );
89 }
90 }
91
92 /**
93 * Collect fonts used for global styles settings.
94 */
95 public function collect_global_styles_fonts() {
96 $global_styles = wp_get_global_styles();
97
98 $global_styles_font_slug = $this->get_font_slug_from_setting( $global_styles );
99 if ( $global_styles_font_slug ) {
100 $this->add_font( $global_styles_font_slug );
101 }
102
103 if ( isset( $global_styles['blocks'] ) ) {
104 foreach ( $global_styles['blocks'] as $setting ) {
105 $font_slug = $this->get_font_slug_from_setting( $setting );
106
107 if ( $font_slug ) {
108 $this->add_font( $font_slug );
109 }
110 }
111 }
112
113 if ( isset( $global_styles['elements'] ) ) {
114 foreach ( $global_styles['elements'] as $setting ) {
115 $font_slug = $this->get_font_slug_from_setting( $setting );
116
117 if ( $font_slug ) {
118 $this->add_font( $font_slug );
119 }
120 }
121 }
122 }
123
124 /**
125 * Collect fonts used for block-level settings.
126 *
127 * @filter pre_render_block
128 *
129 * @param string|null $content The pre-rendered content. Default null.
130 * @param array $parsed_block The block being rendered.
131 */
132 public function collect_block_fonts( $content, $parsed_block ) {
133 if ( ! is_admin() && isset( $parsed_block['attrs']['fontFamily'] ) ) {
134 $block_font_family = $parsed_block['attrs']['fontFamily'];
135 $this->add_font( $block_font_family );
136 }
137
138 return $content;
139 }
140
141 /**
142 * Add the specify font to the fonts_in_use list.
143 *
144 * @param string $font_slug The font slug.
145 */
146 public function add_font( $font_slug ) {
147 if ( is_string( $font_slug ) ) {
148 $this->fonts_in_use[] = $this->format_font( $font_slug );
149 }
150 }
151
152 /**
153 * Format the given font slug.
154 *
155 * @example "ABeeZee" formats to "abeezee"
156 * @example "ADLaM Display" formats to "adlam-display"
157 * @param string $font_slug The font slug.
158 * @return string The formatted font slug.
159 */
160 public function format_font( $font_slug ) {
161 return _wp_to_kebab_case( strtolower( $font_slug ) );
162 }
163
164 /**
165 * Get the font slug aliases that maps the font slug to the font family if they are different.
166 *
167 * The font definition may define an alias slug name, so we have to add the map from the slug name to the font family.
168 * See https://github.com/WordPress/twentytwentyfour/blob/df92472089ede6fae5924c124a93c843b84e8cbd/theme.json#L215.
169 */
170 public function get_font_slug_aliases() {
171 $font_slug_aliases = array();
172
173 $theme_json = WP_Theme_JSON_Resolver::get_theme_data();
174 $raw_data = $theme_json->get_data();
175 if ( ! empty( $raw_data['settings']['typography']['fontFamilies'] ) ) {
176 foreach ( $raw_data['settings']['typography']['fontFamilies'] as $font ) {
177 if ( ! isset( $font['fontFamily'] ) ) {
178 continue;
179 }
180 $font_family_name = $this->format_font( $this->get_font_family_name( $font ) );
181 $font_slug = $font['slug'] ?? '';
182 if ( $font_slug && $font_slug !== $font_family_name && ! array_key_exists( $font_slug, $font_slug_aliases ) ) {
183 $font_slug_aliases[ $font_slug ] = $font_family_name;
184 }
185 }
186 }
187
188 return $font_slug_aliases;
189 }
190
191 /**
192 * Get the font family name from a font.
193 *
194 * @param array $font The font definition object.
195 */
196 public static function get_font_family_name( $font ) {
197 $font_family = $font['fontFamily'];
198 if ( str_contains( $font_family, ',' ) ) {
199 $font_family = explode( ',', $font_family )[0];
200 }
201
202 return trim( $font_family, "\"'" );
203 }
204
205 /**
206 * Get the font family slug from a settings array.
207 *
208 * @param array $setting The settings object.
209 *
210 * @return string|null
211 */
212 public function get_font_slug_from_setting( $setting ) {
213 if ( ! isset( $setting['typography']['fontFamily'] ) ) {
214 return null;
215 }
216
217 $font_family = $setting['typography']['fontFamily'];
218
219 // The font family may be a reference to a path to the value stored at that location,
220 // e.g.: { "ref": "styles.elements.heading.typography.fontFamily" }.
221 // Ignore it as we also get the value stored at that location from the setting.
222 if ( ! is_string( $font_family ) ) {
223 return null;
224 }
225
226 // Full string: var(--wp--preset--font-family--slug).
227 // We do not care about the origin of the font, only its slug.
228 preg_match( '/font-family--(?P<slug>.+)\)$/', $font_family, $matches );
229
230 if ( isset( $matches['slug'] ) ) {
231 return $matches['slug'];
232 }
233
234 // Full string: var:preset|font-family|slug
235 // We do not care about the origin of the font, only its slug.
236 preg_match( '/font-family\|(?P<slug>.+)$/', $font_family, $matches );
237
238 if ( isset( $matches['slug'] ) ) {
239 return $matches['slug'];
240 }
241
242 return $font_family;
243 }
244
245 /**
246 * Check if the current screen is the block editor.
247 *
248 * @return bool
249 */
250 public function is_block_editor() {
251 if ( function_exists( 'get_current_screen' ) ) {
252 $current_screen = get_current_screen();
253 if ( ! empty( $current_screen ) && method_exists( $current_screen, 'is_block_editor' ) && $current_screen->is_block_editor() ) {
254 return true;
255 }
256 }
257
258 return false;
259 }
260 }
261