PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 13.0.2
Jetpack – WP Security, Backup, Speed, & Growth v13.0.2
12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 14.4.2 All 500 releases
jetpack / modules / google-fonts / current / class-jetpack-google-font-face.php
class-jetpack-google-font-face.php
224 lines 6.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 class Jetpack_Google_Font_Face {
14 /**
15 * The fonts that are used in global styles or block-level settings.
16 *
17 * @var array
18 */
19 private $fonts_in_use = array();
20
21 /**
22 * The constructor.
23 */
24 public function __construct() {
25 // Turns off hooks to print fonts
26 add_action( 'wp_loaded', array( $this, 'wp_loaded' ) );
27 add_action( 'current_screen', array( $this, 'current_screen' ), 10 );
28
29 // Collect and print fonts in use
30 add_action( 'wp_head', array( $this, 'print_font_faces' ), 50 );
31 add_filter( 'pre_render_block', array( $this, 'collect_block_fonts' ), 10, 2 );
32 }
33
34 /**
35 * Turn off hooks to print fonts on frontend
36 */
37 public function wp_loaded() {
38 remove_action( 'wp_head', 'wp_print_fonts', 50 );
39 remove_action( 'wp_head', 'wp_print_font_faces', 50 );
40 }
41
42 /**
43 * Turn off hooks to print fonts on wp-admin, except for GB editor pages.
44 */
45 public function current_screen() {
46 remove_action( 'admin_print_styles', 'wp_print_fonts', 50 );
47
48 if ( ! $this->is_block_editor() ) {
49 remove_action( 'admin_print_styles', 'wp_print_font_faces', 50 );
50 }
51 }
52
53 /**
54 * Print fonts that are used in global styles or block-level settings.
55 */
56 public function print_font_faces() {
57 $fonts = $this->get_fonts();
58 $fonts_to_print = array();
59
60 $this->collect_global_styles_fonts();
61 $this->fonts_in_use = array_values( array_unique( $this->fonts_in_use, SORT_STRING ) );
62 foreach ( $fonts as $font_family => $font_faces ) {
63 if ( in_array( _wp_to_kebab_case( $font_family ), $this->fonts_in_use, true ) ) {
64 $fonts_to_print[ $font_family ] = $font_faces;
65 }
66 }
67
68 if ( ! empty( $fonts_to_print ) ) {
69 wp_print_font_faces( $fonts_to_print );
70 }
71 }
72
73 /**
74 * Collect fonts used for global styles settings.
75 */
76 public function collect_global_styles_fonts() {
77 $global_styles = wp_get_global_styles();
78
79 $global_styles_font_slug = $this->get_font_slug_from_setting( $global_styles );
80 if ( $global_styles_font_slug ) {
81 $this->add_font( $global_styles_font_slug );
82 }
83
84 if ( isset( $global_styles['blocks'] ) ) {
85 foreach ( $global_styles['blocks'] as $setting ) {
86 $font_slug = $this->get_font_slug_from_setting( $setting );
87
88 if ( $font_slug ) {
89 $this->add_font( $font_slug );
90 }
91 }
92 }
93
94 if ( isset( $global_styles['elements'] ) ) {
95 foreach ( $global_styles['elements'] as $setting ) {
96 $font_slug = $this->get_font_slug_from_setting( $setting );
97
98 if ( $font_slug ) {
99 $this->add_font( $font_slug );
100 }
101 }
102 }
103 }
104
105 /**
106 * Collect fonts used for block-level settings.
107 *
108 * @filter pre_render_block
109 *
110 * @param string|null $content The pre-rendered content. Default null.
111 * @param array $parsed_block The block being rendered.
112 */
113 public function collect_block_fonts( $content, $parsed_block ) {
114 if ( ! is_admin() && isset( $parsed_block['attrs']['fontFamily'] ) ) {
115 $block_font_family = $parsed_block['attrs']['fontFamily'];
116 $this->add_font( $block_font_family );
117 }
118
119 return $content;
120 }
121
122 /**
123 * Add the specify font to the fonts_in_use list.
124 *
125 * @param string $font_slug The font slug.
126 */
127 public function add_font( $font_slug ) {
128 $this->fonts_in_use[] = _wp_to_kebab_case( $font_slug );
129 }
130
131 /**
132 * Get all font definitions from theme json.
133 */
134 public function get_fonts() {
135 $fonts = WP_Font_Face_Resolver::get_fonts_from_theme_json();
136
137 // The font definition might define an alias slug name, so we have to add the map from the slug name to font faces.
138 // See https://github.com/WordPress/twentytwentyfour/blob/df92472089ede6fae5924c124a93c843b84e8cbd/theme.json#L215.
139 $theme_json = WP_Theme_JSON_Resolver::get_theme_data();
140 $raw_data = $theme_json->get_data();
141 if ( ! empty( $raw_data['settings']['typography']['fontFamilies'] ) ) {
142 foreach ( $raw_data['settings']['typography']['fontFamilies'] as $font ) {
143 $font_family_name = $this->get_font_family_name( $font );
144 $font_slug = $font['slug'] ?? '';
145 if ( $font_slug && ! array_key_exists( $font_slug, $fonts ) && array_key_exists( $font_family_name, $fonts ) ) {
146 $fonts[ $font_slug ] = $fonts[ $font_family_name ];
147 }
148 }
149 }
150
151 return $fonts;
152 }
153
154 /**
155 * Get the font family name from a font.
156 *
157 * @param array $font The font definition object.
158 */
159 public static function get_font_family_name( $font ) {
160 $font_family = $font['fontFamily'];
161 if ( str_contains( $font_family, ',' ) ) {
162 $font_family = explode( ',', $font_family )[0];
163 }
164
165 return trim( $font_family, "\"'" );
166 }
167
168 /**
169 * Get the font family slug from a settings array.
170 *
171 * @param array $setting The settings object.
172 *
173 * @return string|null
174 */
175 public function get_font_slug_from_setting( $setting ) {
176 if ( ! isset( $setting['typography']['fontFamily'] ) ) {
177 return null;
178 }
179
180 $font_family = $setting['typography']['fontFamily'];
181
182 // The font family may be a reference to a path to the value stored at that location,
183 // e.g.: { "ref": "styles.elements.heading.typography.fontFamily" }.
184 // Ignore it as we also get the value stored at that location from the setting.
185 if ( ! is_string( $font_family ) ) {
186 return null;
187 }
188
189 // Full string: var(--wp--preset--font-family--slug).
190 // We do not care about the origin of the font, only its slug.
191 preg_match( '/font-family--(?P<slug>.+)\)$/', $font_family, $matches );
192
193 if ( isset( $matches['slug'] ) ) {
194 return $matches['slug'];
195 }
196
197 // Full string: var:preset|font-family|slug
198 // We do not care about the origin of the font, only its slug.
199 preg_match( '/font-family\|(?P<slug>.+)$/', $font_family, $matches );
200
201 if ( isset( $matches['slug'] ) ) {
202 return $matches['slug'];
203 }
204
205 return $font_family;
206 }
207
208 /**
209 * Check if the current screen is the block editor.
210 *
211 * @return bool
212 */
213 public function is_block_editor() {
214 if ( function_exists( 'get_current_screen' ) ) {
215 $current_screen = get_current_screen();
216 if ( ! empty( $current_screen ) && method_exists( $current_screen, 'is_block_editor' ) && $current_screen->is_block_editor() ) {
217 return true;
218 }
219 }
220
221 return false;
222 }
223 }
224