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 / class-wp-fonts-provider-local.php

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

237 lines 5.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Webfonts API: Provider for locally-hosted fonts.
4 *
5 * @package WordPress
6 * @subpackage Fonts API
7 * @since X.X.X
8 */
9
10 if ( class_exists( 'WP_Fonts_Provider_Local' ) ) {
11 return;
12 }
13
14 /**
15 * A core bundled provider for generating `@font-face` styles
16 * from locally-hosted font files.
17 *
18 * This provider builds an optimized `src` (for browser support)
19 * and then generates the `@font-face` styles.
20 *
21 * All know-how (business logic) for how to interact with and
22 * generate styles from locally-hosted font files is contained
23 * in this provider.
24 *
25 * @since X.X.X
26 */
27 class WP_Fonts_Provider_Local extends WP_Fonts_Provider {
28
29 /**
30 * The provider's unique ID.
31 *
32 * @since X.X.X
33 *
34 * @var string
35 */
36 protected $id = 'local';
37
38 /**
39 * Constructor.
40 *
41 * @since 6.1.0
42 */
43 public function __construct() {
44 if (
45 function_exists( 'is_admin' ) && ! is_admin()
46 &&
47 function_exists( 'current_theme_supports' ) && ! current_theme_supports( 'html5', 'style' )
48 ) {
49 $this->style_tag_atts = array( 'type' => 'text/css' );
50 }
51 }
52
53 /**
54 * Gets the `@font-face` CSS styles for locally-hosted font files.
55 *
56 * This method does the following processing tasks:
57 * 1. Orchestrates an optimized `src` (with format) for browser support.
58 * 2. Generates the `@font-face` for all its fonts.
59 *
60 * @since X.X.X
61 *
62 * @return string The `@font-face` CSS.
63 */
64 public function get_css() {
65 $css = '';
66
67 foreach ( $this->fonts as $font ) {
68 // Order the font's `src` items to optimize for browser support.
69 $font = $this->order_src( $font );
70
71 // Build the @font-face CSS for this font.
72 $css .= '@font-face{' . $this->build_font_face_css( $font ) . '}';
73 }
74
75 return $css;
76 }
77
78 /**
79 * Order `src` items to optimize for browser support.
80 *
81 * @since X.X.X
82 *
83 * @param array $font Font to process.
84 * @return array
85 */
86 private function order_src( array $font ) {
87 if ( ! is_array( $font['src'] ) ) {
88 $font['src'] = (array) $font['src'];
89 }
90
91 $src = array();
92 $src_ordered = array();
93
94 foreach ( $font['src'] as $url ) {
95 // Add data URIs first.
96 if ( str_starts_with( trim( $url ), 'data:' ) ) {
97 $src_ordered[] = array(
98 'url' => $url,
99 'format' => 'data',
100 );
101 continue;
102 }
103 $format = pathinfo( $url, PATHINFO_EXTENSION );
104 $src[ $format ] = $url;
105 }
106
107 // Add woff2.
108 if ( ! empty( $src['woff2'] ) ) {
109 $src_ordered[] = array(
110 'url' => $src['woff2'],
111 'format' => 'woff2',
112 );
113 }
114
115 // Add woff.
116 if ( ! empty( $src['woff'] ) ) {
117 $src_ordered[] = array(
118 'url' => $src['woff'],
119 'format' => 'woff',
120 );
121 }
122
123 // Add ttf.
124 if ( ! empty( $src['ttf'] ) ) {
125 $src_ordered[] = array(
126 'url' => $src['ttf'],
127 'format' => 'truetype',
128 );
129 }
130
131 // Add eot.
132 if ( ! empty( $src['eot'] ) ) {
133 $src_ordered[] = array(
134 'url' => $src['eot'],
135 'format' => 'embedded-opentype',
136 );
137 }
138
139 // Add otf.
140 if ( ! empty( $src['otf'] ) ) {
141 $src_ordered[] = array(
142 'url' => $src['otf'],
143 'format' => 'opentype',
144 );
145 }
146 $font['src'] = $src_ordered;
147
148 return $font;
149 }
150
151 /**
152 * Builds the font-family's CSS.
153 *
154 * @since X.X.X
155 *
156 * @param array $font Font to process.
157 * @return string This font-family's CSS.
158 */
159 private function build_font_face_css( array $font ) {
160 $css = '';
161
162 // Wrap font-family in quotes if it contains spaces
163 // and is not already wrapped in quotes.
164 if (
165 str_contains( $font['font-family'], ' ' ) &&
166 ! str_contains( $font['font-family'], '"' ) &&
167 ! str_contains( $font['font-family'], "'" )
168 ) {
169 $font['font-family'] = '"' . $font['font-family'] . '"';
170 }
171
172 foreach ( $font as $key => $value ) {
173
174 // Skip "provider", since it's for internal API use,
175 // and not a valid CSS property.
176 if ( 'provider' === $key ) {
177 continue;
178 }
179
180 // Compile the "src" parameter.
181 if ( 'src' === $key ) {
182 $value = $this->compile_src( $value );
183 }
184
185 // If font-variation-settings is an array, convert it to a string.
186 if ( 'font-variation-settings' === $key && is_array( $value ) ) {
187 $value = $this->compile_variations( $value );
188 }
189
190 if ( ! empty( $value ) ) {
191 $css .= "$key:$value;";
192 }
193 }
194
195 return $css;
196 }
197
198 /**
199 * Compiles the `src` into valid CSS.
200 *
201 * @since X.X.X
202 *
203 * @param array $value Value to process.
204 * @return string The CSS.
205 */
206 private function compile_src( array $value ) {
207 $src = '';
208
209 foreach ( $value as $item ) {
210 $src .= ( 'data' === $item['format'] )
211 ? ", url({$item['url']})"
212 : ", url('{$item['url']}') format('{$item['format']}')";
213 }
214
215 $src = ltrim( $src, ', ' );
216 return $src;
217 }
218
219 /**
220 * Compiles the font variation settings.
221 *
222 * @since X.X.X
223 *
224 * @param array $font_variation_settings Array of font variation settings.
225 * @return string The CSS.
226 */
227 private function compile_variations( array $font_variation_settings ) {
228 $variations = '';
229
230 foreach ( $font_variation_settings as $key => $value ) {
231 $variations .= "$key $value";
232 }
233
234 return $variations;
235 }
236 }
237