PluginProbe
Gutenberg / 17.2.1
Gutenberg v17.2.1
24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 All 403 releases
gutenberg / lib / experimental / fonts-api / bc-layer / class-wp-webfonts-provider-local.php

class-wp-webfonts-provider-local.php in Gutenberg 17.2.1, at lib/experimental/fonts-api/bc-layer/class-wp-webfonts-provider-local.php

285 lines 7.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Fonts API: Provider for locally-hosted fonts.
4 *
5 * Part of the backwards-compatibility (BC) layer for all
6 * deprecated publicly exposed methods and functionality.
7 *
8 * This class/file will NOT be backported to Core. Rather for sites
9 * using the previous API, it exists to prevent breakages, giving
10 * developers time to upgrade their code.
11 *
12 * @package WordPress
13 * @subpackage Fonts
14 * @since X.X.X
15 */
16
17 if ( class_exists( 'WP_Webfonts_Provider_Local' ) ) {
18 return;
19 }
20
21 /**
22 * A deprecated core bundled provider for generating `@font-face` styles
23 * from locally-hosted font files.
24 *
25 * BACKPORT NOTE: Do not backport this file to Core.
26 *
27 * @since X.X.X
28 * @deprecated GB 15.1 Use `WP_Fonts_Provider_Local` instead.
29 */
30 class WP_Webfonts_Provider_Local extends WP_Webfonts_Provider {
31
32 /**
33 * The provider's unique ID.
34 *
35 * @since 6.0.0
36 *
37 * @var string
38 */
39 protected $id = 'local';
40
41 /**
42 * Constructor.
43 *
44 * @since 6.1.0
45 */
46 public function __construct() {
47 _deprecated_function( __METHOD__, 'GB 15.1', 'WP_Fonts_Provider_Local' );
48
49 if (
50 function_exists( 'is_admin' ) && ! is_admin()
51 &&
52 function_exists( 'current_theme_supports' ) && ! current_theme_supports( 'html5', 'style' )
53 ) {
54 $this->style_tag_atts = array( 'type' => 'text/css' );
55 }
56 }
57
58 /**
59 * Gets the `@font-face` CSS styles for locally-hosted font files.
60 *
61 * This method does the following processing tasks:
62 * 1. Orchestrates an optimized `src` (with format) for browser support.
63 * 2. Generates the `@font-face` for all its webfonts.
64 *
65 * For example, when given these webfonts:
66 * <code>
67 * array(
68 * 'source-serif-pro.normal.200 900' => array(
69 * 'provider' => 'local',
70 * 'font_family' => 'Source Serif Pro',
71 * 'font_weight' => '200 900',
72 * 'font_style' => 'normal',
73 * 'src' => 'https://example.com/wp-content/themes/twentytwentytwo/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2' ),
74 * ),
75 * 'source-serif-pro.italic.400 900' => array(
76 * 'provider' => 'local',
77 * 'font_family' => 'Source Serif Pro',
78 * 'font_weight' => '200 900',
79 * 'font_style' => 'italic',
80 * 'src' => 'https://example.com/wp-content/themes/twentytwentytwo/assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2' ),
81 * ),
82 * )
83 * </code>
84 *
85 * the following `@font-face` styles are generated and returned:
86 * <code>
87 *
88 * @font-face{
89 * font-family:"Source Serif Pro";
90 * font-style:normal;
91 * font-weight:200 900;
92 * font-stretch:normal;
93 * src:local("Source Serif Pro"), url('/assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2') format('woff2');
94 * }
95 * @font-face{
96 * font-family:"Source Serif Pro";
97 * font-style:italic;
98 * font-weight:200 900;
99 * font-stretch:normal;
100 * src:local("Source Serif Pro"), url('/assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2') format('woff2');
101 * }
102 * </code>
103 *
104 * @since X.X.X
105 *
106 * @return string The `@font-face` CSS.
107 */
108 public function get_css() {
109 $css = '';
110
111 foreach ( $this->webfonts as $webfont ) {
112 // Order the webfont's `src` items to optimize for browser support.
113 $webfont = $this->order_src( $webfont );
114
115 // Build the @font-face CSS for this webfont.
116 $css .= '@font-face{' . $this->build_font_face_css( $webfont ) . '}';
117 }
118
119 return $css;
120 }
121
122 /**
123 * Order `src` items to optimize for browser support.
124 *
125 * @since 6.0.0
126 *
127 * @param array $webfont Webfont to process.
128 * @return array
129 */
130 private function order_src( array $webfont ) {
131 if ( ! is_array( $webfont['src'] ) ) {
132 $webfont['src'] = (array) $webfont['src'];
133 }
134
135 $src = array();
136 $src_ordered = array();
137
138 foreach ( $webfont['src'] as $url ) {
139 // Add data URIs first.
140 if ( str_starts_with( trim( $url ), 'data:' ) ) {
141 $src_ordered[] = array(
142 'url' => $url,
143 'format' => 'data',
144 );
145 continue;
146 }
147 $format = pathinfo( $url, PATHINFO_EXTENSION );
148 $src[ $format ] = $url;
149 }
150
151 // Add woff2.
152 if ( ! empty( $src['woff2'] ) ) {
153 $src_ordered[] = array(
154 'url' => $src['woff2'],
155 'format' => 'woff2',
156 );
157 }
158
159 // Add woff.
160 if ( ! empty( $src['woff'] ) ) {
161 $src_ordered[] = array(
162 'url' => $src['woff'],
163 'format' => 'woff',
164 );
165 }
166
167 // Add ttf.
168 if ( ! empty( $src['ttf'] ) ) {
169 $src_ordered[] = array(
170 'url' => $src['ttf'],
171 'format' => 'truetype',
172 );
173 }
174
175 // Add eot.
176 if ( ! empty( $src['eot'] ) ) {
177 $src_ordered[] = array(
178 'url' => $src['eot'],
179 'format' => 'embedded-opentype',
180 );
181 }
182
183 // Add otf.
184 if ( ! empty( $src['otf'] ) ) {
185 $src_ordered[] = array(
186 'url' => $src['otf'],
187 'format' => 'opentype',
188 );
189 }
190 $webfont['src'] = $src_ordered;
191
192 return $webfont;
193 }
194
195 /**
196 * Builds the font-family's CSS.
197 *
198 * @since 6.0.0
199 *
200 * @param array $webfont Webfont to process.
201 * @return string This font-family's CSS.
202 */
203 private function build_font_face_css( array $webfont ) {
204 $css = '';
205
206 // Wrap font-family in quotes if it contains spaces
207 // and is not already wrapped in quotes.
208 if (
209 str_contains( $webfont['font-family'], ' ' ) &&
210 ! str_contains( $webfont['font-family'], '"' ) &&
211 ! str_contains( $webfont['font-family'], "'" )
212 ) {
213 $webfont['font-family'] = '"' . $webfont['font-family'] . '"';
214 }
215
216 foreach ( $webfont as $key => $value ) {
217
218 // Skip "provider", since it's for internal API use,
219 // and not a valid CSS property.
220 if ( 'provider' === $key ) {
221 continue;
222 }
223
224 // Compile the "src" parameter.
225 if ( 'src' === $key ) {
226 $value = $this->compile_src( $webfont['font-family'], $value );
227 }
228
229 // If font-variation-settings is an array, convert it to a string.
230 if ( 'font-variation-settings' === $key && is_array( $value ) ) {
231 $value = $this->compile_variations( $value );
232 }
233
234 if ( ! empty( $value ) ) {
235 $css .= "$key:$value;";
236 }
237 }
238
239 return $css;
240 }
241
242 /**
243 * Compiles the `src` into valid CSS.
244 *
245 * @since 6.0.0
246 *
247 * @param string $font_family Font family.
248 * @param array $value Value to process.
249 * @return string The CSS.
250 */
251 private function compile_src( $font_family, array $value ) {
252 $src = "local($font_family)";
253
254 foreach ( $value as $item ) {
255
256 if ( str_starts_with( $item['url'], get_site_url() ) ) {
257 $item['url'] = wp_make_link_relative( $item['url'] );
258 }
259
260 $src .= ( 'data' === $item['format'] )
261 ? ", url({$item['url']})"
262 : ", url('{$item['url']}') format('{$item['format']}')";
263 }
264 return $src;
265 }
266
267 /**
268 * Compiles the font variation settings.
269 *
270 * @since 6.0.0
271 *
272 * @param array $font_variation_settings Array of font variation settings.
273 * @return string The CSS.
274 */
275 private function compile_variations( array $font_variation_settings ) {
276 $variations = '';
277
278 foreach ( $font_variation_settings as $key => $value ) {
279 $variations .= "$key $value";
280 }
281
282 return $variations;
283 }
284 }
285