Skip to content

Commit 9b26825

Browse files
committed
Copy files from core patch
See WordPress/wordpress-develop#1736
1 parent e629f5b commit 9b26825

15 files changed

+3621
-0
lines changed
Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
<?php
2+
/**
3+
* Webfonts API: Webfonts Controller
4+
*
5+
* @package WordPress
6+
* @subpackage Webfonts
7+
* @since 5.9.0
8+
*/
9+
10+
/**
11+
* Webfonts Controller exposes the public entry point into this API
12+
* and coordinates the interactions between the webfonts registry,
13+
* providers registry, and the Dependencies API.
14+
*
15+
* event
16+
* ↕
17+
* Controller
18+
* ⤢ ⤡
19+
* Webfonts Registry Providers Registry
20+
* ↕ ⤢ ⤡ .. [custom providers]
21+
* Validator Local Google Fonts
22+
* Provider Provider
23+
* ↕ ↕
24+
* Filesystem Remote Font API Service
25+
*
26+
* The Controller receives an event such as a request to register
27+
* a webfont or provider, print `@font-face` styles in the `<head>`
28+
* (e.g. `'wp_enqueue_scripts'`), or print the resource `<link>`
29+
* (`'wp_resource_hints'` ). Then it interacts with the components
30+
* in this API to process the event.
31+
*
32+
* @since 5.9.0
33+
*/
34+
class WP_Webfonts_Controller {
35+
36+
/**
37+
* Instance of the webfont's registry.
38+
*
39+
* @since 5.9.0
40+
*
41+
* @var WP_Webfonts_Registry
42+
*/
43+
private $webfonts_registry;
44+
45+
/**
46+
* Instance of the providers' registry.
47+
*
48+
* @since 5.9.0
49+
*
50+
* @var WP_Webfonts_Provider_Registry
51+
*/
52+
private $providers_registry;
53+
54+
/**
55+
* Stylesheet handle.
56+
*
57+
* @since 5.9.0
58+
*
59+
* @var string
60+
*/
61+
private $stylesheet_handle = '';
62+
63+
/**
64+
* Create the controller.
65+
*
66+
* @since 5.9.0
67+
*
68+
* @param WP_Webfonts_Registry $webfonts_registry Instance of the webfonts' registry.
69+
* @param WP_Webfonts_Provider_Registry $providers_registry Instance of the providers' registry.
70+
*/
71+
public function __construct(
72+
WP_Webfonts_Registry $webfonts_registry,
73+
WP_Webfonts_Provider_Registry $providers_registry
74+
) {
75+
$this->webfonts_registry = $webfonts_registry;
76+
$this->providers_registry = $providers_registry;
77+
}
78+
79+
/**
80+
* Initializes the controller.
81+
*
82+
* @since 5.9.0
83+
*/
84+
public function init() {
85+
$this->providers_registry->init();
86+
87+
// Register callback to generate and enqueue styles.
88+
if ( did_action( 'wp_enqueue_scripts' ) ) {
89+
$this->stylesheet_handle = 'webfonts-footer';
90+
$hook = 'wp_print_footer_scripts';
91+
} else {
92+
$this->stylesheet_handle = 'webfonts';
93+
$hook = 'wp_enqueue_scripts';
94+
}
95+
add_action( $hook, array( $this, 'generate_and_enqueue_styles' ) );
96+
97+
// Enqueue webfonts in the block editor.
98+
add_action( 'admin_init', array( $this, 'generate_and_enqueue_editor_styles' ) );
99+
100+
// Add resources hints.
101+
add_filter( 'wp_resource_hints', array( $this, 'get_resource_hints' ), 10, 2 );
102+
}
103+
104+
/**
105+
* Gets the instance of the webfonts' registry.
106+
*
107+
* The Webfonts Registry handles the registration
108+
* and in-memory storage of webfonts.
109+
*
110+
* @since 5.9.0
111+
*
112+
* @return WP_Webfonts_Registry
113+
*/
114+
public function webfonts() {
115+
return $this->webfonts_registry;
116+
}
117+
118+
/**
119+
* Gets the instance of the providers' registry.
120+
*
121+
* @see WP_Webfonts_Provider_Registry for more information
122+
* on the available methods for use.
123+
*
124+
* @since 5.9.0
125+
*
126+
* @return WP_Webfonts_Provider_Registry
127+
*/
128+
public function providers() {
129+
return $this->providers_registry;
130+
}
131+
132+
/**
133+
* Generate and enqueue webfonts styles.
134+
*
135+
* @since 5.9.0
136+
*/
137+
public function generate_and_enqueue_styles() {
138+
// Generate the styles.
139+
$styles = $this->generate_styles();
140+
141+
// Bail out if there are no styles to enqueue.
142+
if ( '' === $styles ) {
143+
return;
144+
}
145+
146+
// Enqueue the stylesheet.
147+
wp_register_style( $this->stylesheet_handle, '' );
148+
wp_enqueue_style( $this->stylesheet_handle );
149+
150+
// Add the styles to the stylesheet.
151+
wp_add_inline_style( $this->stylesheet_handle, $styles );
152+
}
153+
154+
/**
155+
* Generate and enqueue editor styles.
156+
*
157+
* @since 5.9.0
158+
*/
159+
public function generate_and_enqueue_editor_styles() {
160+
// Generate the styles.
161+
$styles = $this->generate_styles();
162+
163+
// Bail out if there are no styles to enqueue.
164+
if ( '' === $styles ) {
165+
return;
166+
}
167+
168+
wp_add_inline_style( 'wp-block-library', $styles );
169+
}
170+
171+
/**
172+
* Generate styles for webfonts.
173+
*
174+
* By default (due to privacy concerns), this API will not do remote requests to
175+
* external webfont services nor generate `@font-face` styles for these remote
176+
* providers. The filter `'has_remote_webfonts_request_permission'` is provided
177+
* to grant permission to do the remote request.
178+
*
179+
* @since 5.9.0
180+
*
181+
* @return string $styles Generated styles.
182+
*/
183+
private function generate_styles() {
184+
$styles = '';
185+
$providers = $this->providers_registry->get_all_registered();
186+
187+
/*
188+
* Loop through each of the providers to get the CSS for their respective webfonts
189+
* to incrementally generate the collective styles for all of them.
190+
*/
191+
foreach ( $providers as $provider_id => $provider ) {
192+
$registered_webfonts = $this->webfonts_registry->get_by_provider( $provider_id );
193+
194+
// If there are no registered webfonts for this provider, skip it.
195+
if ( empty( $registered_webfonts ) ) {
196+
continue;
197+
}
198+
199+
/*
200+
* Skip fetching from a remote fonts service if the user has not
201+
* consented to the remote request.
202+
*/
203+
if (
204+
'local' !== $provider_id &&
205+
/**
206+
* Allows permission to be set for doing remote requests
207+
* to a webfont service provider.
208+
*
209+
* By default, the Webfonts API will not make remote requests
210+
* due to privacy concerns.
211+
*
212+
* @since 5.9.0
213+
*
214+
* @param bool $has_permission Permission to do the remote request.
215+
* Default false.
216+
* @param string $provider_id Provider's ID, e.g. 'google', to identify
217+
* the remote webfonts service provider.
218+
*/
219+
true !== apply_filters( 'has_remote_webfonts_request_permission', false, $provider_id )
220+
) {
221+
continue;
222+
}
223+
224+
/*
225+
* Process the webfonts by first passing them to the provider via `set_webfonts()`
226+
* and then getting the CSS from the provider.
227+
*/
228+
$provider->set_webfonts( $registered_webfonts );
229+
$styles .= $provider->get_css();
230+
}
231+
232+
return $styles;
233+
}
234+
235+
/**
236+
* Gets the resource hints.
237+
*
238+
* Callback hooked to the filter `'wp_resource_hints'`. Generation
239+
* and rendering of the resource `<link>` is handled where that filter
240+
* fires. This method adds the resource link attributes to pass back
241+
* to that handler.
242+
*
243+
* @since 5.9.0
244+
*
245+
* @param array $urls {
246+
* Array of resources and their attributes, or URLs to print for resource hints.
247+
*
248+
* @type array|string ...$0 {
249+
* Array of resource attributes, or a URL string.
250+
*
251+
* @type string $href URL to include in resource hints. Required.
252+
* @type string $as How the browser should treat the resource
253+
* (`script`, `style`, `image`, `document`, etc).
254+
* @type string $crossorigin Indicates the CORS policy of the specified resource.
255+
* @type float $pr Expected probability that the resource hint will be used.
256+
* @type string $type Type of the resource (`text/html`, `text/css`, etc).
257+
* }
258+
* }
259+
* @param string $relation_type The relation type the URLs are printed for,
260+
* e.g. 'preconnect' or 'prerender'.
261+
* @return array URLs to print for resource hints.
262+
*/
263+
public function get_resource_hints( $urls, $relation_type ) {
264+
foreach ( $this->providers_registry->get_all_registered() as $provider ) {
265+
foreach ( $provider->get_resource_hints() as $relation => $relation_hints ) {
266+
if ( $relation !== $relation_type ) {
267+
continue;
268+
}
269+
// Append this provider's resource hints to the end of the given `$urls` array.
270+
array_push( $urls, ...$relation_hints );
271+
}
272+
}
273+
274+
return $urls;
275+
}
276+
}

0 commit comments

Comments
 (0)