mirrored from git://develop.git.wordpress.org/
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Webfonts API - webfonts collection implementation #1736
Closed
Closed
Changes from all commits
Commits
Show all changes
94 commits
Select commit
Hold shift + click to select a range
cef117a
1st Webfonts API implementation - to change.
aristath 9facf39
Register collections instead of individual fonts
aristath 85e0fb9
New architecture scaffolding.
hellofromtonya 5ee49bb
Add get_validated_params method
aristath a1f34f0
Tweak validation for local fonts
aristath d5ac8df
fix paths
aristath 6531b66
typo
aristath f99faf4
Adds tests and fixes for WP_Webfonts_Registry.
hellofromtonya 42bc934
Adds tests amd fixes for WP_Webfonts_Provider_Registry.
hellofromtonya 1804d67
Adds tests and fixes for WP_Webfonts_Controller.
hellofromtonya a2331ae
Moved schema validator to separate class.
hellofromtonya ee9ea3b
Made font weight and style optional.
hellofromtonya 0ad4f54
Fix method name
aristath 566fea7
validation: should use kebab since it's 1 step before the CSS output
aristath ecfa1da
Fix styles generation
aristath 45c6f21
remove blank line (CS)
aristath 78812dd
Add editor styles for webfonts
aristath 75c0bf9
Make function public. We'll need it for the theme.json implementation
aristath 228508d
Revert "Make function public. We'll need it for the theme.json implem…
aristath 880178d
Account for "file:./" URLs defined in a theme.json file.
aristath 780cda6
Update docblocks and remove final for testing.
hellofromtonya da9ebcf
Replaces _doing_it_wrong() with trigger_error().
hellofromtonya a73bc1d
Moves validation from providers to Validator.
hellofromtonya 9966b19
Adds src validation to Validator.
hellofromtonya 56ebaa7
Remove invalid_parameters & related method
aristath 0c0354b
Improves readability, usability, and performance.
hellofromtonya 2e541a1
Remove file:./ implementation
aristath 1d92844
update tests
aristath e5ca831
CS
aristath 33872b8
more tests fixes
aristath 551adee
Make links relative if URL is on-site
aristath 846e860
Update tests for local URLs CSS generation
aristath dab75cc
Add check to verify the provider is registered.
aristath d14aa9e
This was already done
aristath d87a3b8
test unregistered provider
aristath 646c9c0
cs
aristath fe29ea7
Trigger error when provider is not registered
aristath 01fd844
CS fix
aristath 27116bc
Fix some failing tests
aristath 4be94a3
meh, copy/pasta typo-error
aristath d2f1474
Fix failing test for unregistered provider
aristath dc5ed3f
minor improvements to the validator
aristath 291e4a8
fix docs & typos
aristath 4b7b099
another typo fix
aristath 88fb4af
Don't check if provider is registered
aristath 699f96c
This is not necessary, the browser won't get a request for this URL.
aristath e22ed3e
CS
aristath 4757065
simplify configuration params
aristath d2b2c91
Add docs to the register method
aristath 09742ca
This was removed
aristath 571c40d
Check if provider is a subclass of WP_Webfonts_Provider
aristath 022467a
more docs
aristath 68f439a
more docs
aristath b2aef24
rename the webfonts file.
aristath cf6ac7c
Remove get_by_font_family and related tests
aristath 46c87d5
Move font-family quoting to css-generation method
aristath 5bf5f66
Simplify the controller
aristath e31dee5
Move require_once to script_loader.php
aristath 9ae7f9a
add missing "since" to classes
aristath 0883e97
Simplify the preconnect-URLs implementation
aristath 2d0274b
minify styles if not debugging scripts
aristath 28445b3
Removes store by font-family during register.
hellofromtonya aff4233
Abstracts generating resources hints.
aristath 1ec9d69
Fix method parameter name typo.
hellofromtonya 6b08c0a
Fix variable name typo.
hellofromtonya a9c62fc
Remove unused key variable from `foreach`.
hellofromtonya b0e0296
Fixes to tests from code review.
hellofromtonya febc81b
Skip "provider" in CSS generation in the local provider.
aristath de65387
Update src/wp-includes/webfonts-api/class-wp-webfonts-registry.php
aristath 00c54aa
Allow using a range of font-weights for google-fonts
aristath 0e75bcf
provider no longer printed in the CSS
aristath ec7c787
Require 'is-external' => true to load external API webfonts
aristath 2139913
fix some (not all) test failures
aristath 4ea1f34
bugfix
aristath 864b5d1
typecast to array
aristath 9dd78c0
Improves the WP_Webfonts_Controller::generate_styles().
hellofromtonya 0f89538
Require valid CSS properties for webfont schema.
hellofromtonya 9a9f91c
Document classname needs for provider registration.
hellofromtonya d035860
Removes WP_Webfonts_Provider::prepare().
hellofromtonya 3929bf9
Require CSS properties in snake_case for registration.
hellofromtonya 125c29c
Shortens the Controller's getter names.
hellofromtonya 1380de5
Use MINUTE_IN_SECONDS constant instead of hard coded 60.
hellofromtonya acde215
Type cast font weights to int for range().
hellofromtonya f88500c
Remove unnecessary empty line.
hellofromtonya 6a0c723
Micro-optimizations, fixes, and comments.
hellofromtonya 14efc74
Removes unnecessary guard clauses.
hellofromtonya c8ea408
Makes reflection get_webfonts_property() consistent in tests.
hellofromtonya d898462
Simplify wp_register_webfonts by removing the unnecessary guard clause.
hellofromtonya cb0c9bc
Adds tests for Google Fonts provider `get_css()`.
hellofromtonya 81bba48
Changes the remote privacy permission logic.
hellofromtonya 81326fd
Code review: comments, typos, micro-optimizations.
hellofromtonya 6024894
Adds remaining class DocBlock comments.
hellofromtonya aa08030
typo fix
aristath 0ce34f6
should be an instance of WP_Webfonts_Controller, not WP_Webfonts
aristath File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
276 changes: 276 additions & 0 deletions
276
src/wp-includes/webfonts-api/class-wp-webfonts-controller.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,276 @@ | ||
<?php | ||
/** | ||
* Webfonts API: Webfonts Controller | ||
* | ||
* @package WordPress | ||
* @subpackage Webfonts | ||
* @since 5.9.0 | ||
*/ | ||
|
||
/** | ||
* Webfonts Controller exposes the public entry point into this API | ||
* and coordinates the interactions between the webfonts registry, | ||
* providers registry, and the Dependencies API. | ||
* | ||
* event | ||
* ↕ | ||
* Controller | ||
* ⤢ ⤡ | ||
* Webfonts Registry Providers Registry | ||
* ↕ ⤢ ⤡ .. [custom providers] | ||
* Validator Local Google Fonts | ||
* Provider Provider | ||
* ↕ ↕ | ||
* Filesystem Remote Font API Service | ||
* | ||
* The Controller receives an event such as a request to register | ||
* a webfont or provider, print `@font-face` styles in the `<head>` | ||
* (e.g. `'wp_enqueue_scripts'`), or print the resource `<link>` | ||
* (`'wp_resource_hints'` ). Then it interacts with the components | ||
* in this API to process the event. | ||
* | ||
* @since 5.9.0 | ||
*/ | ||
class WP_Webfonts_Controller { | ||
|
||
/** | ||
* Instance of the webfont's registry. | ||
* | ||
* @since 5.9.0 | ||
* | ||
* @var WP_Webfonts_Registry | ||
*/ | ||
private $webfonts_registry; | ||
|
||
/** | ||
* Instance of the providers' registry. | ||
* | ||
* @since 5.9.0 | ||
* | ||
* @var WP_Webfonts_Provider_Registry | ||
*/ | ||
private $providers_registry; | ||
|
||
/** | ||
* Stylesheet handle. | ||
* | ||
* @since 5.9.0 | ||
* | ||
* @var string | ||
*/ | ||
private $stylesheet_handle = ''; | ||
|
||
/** | ||
* Create the controller. | ||
* | ||
* @since 5.9.0 | ||
* | ||
* @param WP_Webfonts_Registry $webfonts_registry Instance of the webfonts' registry. | ||
* @param WP_Webfonts_Provider_Registry $providers_registry Instance of the providers' registry. | ||
*/ | ||
public function __construct( | ||
WP_Webfonts_Registry $webfonts_registry, | ||
WP_Webfonts_Provider_Registry $providers_registry | ||
) { | ||
$this->webfonts_registry = $webfonts_registry; | ||
$this->providers_registry = $providers_registry; | ||
} | ||
|
||
/** | ||
* Initializes the controller. | ||
* | ||
* @since 5.9.0 | ||
*/ | ||
public function init() { | ||
$this->providers_registry->init(); | ||
|
||
// Register callback to generate and enqueue styles. | ||
if ( did_action( 'wp_enqueue_scripts' ) ) { | ||
$this->stylesheet_handle = 'webfonts-footer'; | ||
$hook = 'wp_print_footer_scripts'; | ||
} else { | ||
$this->stylesheet_handle = 'webfonts'; | ||
$hook = 'wp_enqueue_scripts'; | ||
} | ||
add_action( $hook, array( $this, 'generate_and_enqueue_styles' ) ); | ||
|
||
// Enqueue webfonts in the block editor. | ||
add_action( 'admin_init', array( $this, 'generate_and_enqueue_editor_styles' ) ); | ||
|
||
// Add resources hints. | ||
add_filter( 'wp_resource_hints', array( $this, 'get_resource_hints' ), 10, 2 ); | ||
} | ||
|
||
/** | ||
* Gets the instance of the webfonts' registry. | ||
* | ||
* The Webfonts Registry handles the registration | ||
* and in-memory storage of webfonts. | ||
* | ||
* @since 5.9.0 | ||
* | ||
* @return WP_Webfonts_Registry | ||
*/ | ||
public function webfonts() { | ||
return $this->webfonts_registry; | ||
} | ||
|
||
/** | ||
* Gets the instance of the providers' registry. | ||
* | ||
* @see WP_Webfonts_Provider_Registry for more information | ||
* on the available methods for use. | ||
* | ||
* @since 5.9.0 | ||
* | ||
* @return WP_Webfonts_Provider_Registry | ||
*/ | ||
public function providers() { | ||
return $this->providers_registry; | ||
} | ||
|
||
/** | ||
* Generate and enqueue webfonts styles. | ||
* | ||
* @since 5.9.0 | ||
*/ | ||
public function generate_and_enqueue_styles() { | ||
// Generate the styles. | ||
$styles = $this->generate_styles(); | ||
|
||
// Bail out if there are no styles to enqueue. | ||
if ( '' === $styles ) { | ||
return; | ||
} | ||
|
||
// Enqueue the stylesheet. | ||
wp_register_style( $this->stylesheet_handle, '' ); | ||
wp_enqueue_style( $this->stylesheet_handle ); | ||
|
||
// Add the styles to the stylesheet. | ||
wp_add_inline_style( $this->stylesheet_handle, $styles ); | ||
} | ||
|
||
/** | ||
* Generate and enqueue editor styles. | ||
* | ||
* @since 5.9.0 | ||
*/ | ||
public function generate_and_enqueue_editor_styles() { | ||
// Generate the styles. | ||
$styles = $this->generate_styles(); | ||
|
||
// Bail out if there are no styles to enqueue. | ||
if ( '' === $styles ) { | ||
return; | ||
} | ||
|
||
wp_add_inline_style( 'wp-block-library', $styles ); | ||
} | ||
|
||
/** | ||
* Generate styles for webfonts. | ||
* | ||
* By default (due to privacy concerns), this API will not do remote requests to | ||
* external webfont services nor generate `@font-face` styles for these remote | ||
* providers. The filter `'has_remote_webfonts_request_permission'` is provided | ||
* to grant permission to do the remote request. | ||
* | ||
* @since 5.9.0 | ||
* | ||
* @return string $styles Generated styles. | ||
*/ | ||
private function generate_styles() { | ||
$styles = ''; | ||
$providers = $this->providers_registry->get_all_registered(); | ||
|
||
/* | ||
* Loop through each of the providers to get the CSS for their respective webfonts | ||
* to incrementally generate the collective styles for all of them. | ||
*/ | ||
foreach ( $providers as $provider_id => $provider ) { | ||
$registered_webfonts = $this->webfonts_registry->get_by_provider( $provider_id ); | ||
|
||
// If there are no registered webfonts for this provider, skip it. | ||
if ( empty( $registered_webfonts ) ) { | ||
continue; | ||
} | ||
|
||
/* | ||
* Skip fetching from a remote fonts service if the user has not | ||
* consented to the remote request. | ||
*/ | ||
if ( | ||
'local' !== $provider_id && | ||
/** | ||
* Allows permission to be set for doing remote requests | ||
* to a webfont service provider. | ||
* | ||
* By default, the Webfonts API will not make remote requests | ||
* due to privacy concerns. | ||
* | ||
* @since 5.9.0 | ||
* | ||
* @param bool $has_permission Permission to do the remote request. | ||
* Default false. | ||
* @param string $provider_id Provider's ID, e.g. 'google', to identify | ||
* the remote webfonts service provider. | ||
*/ | ||
true !== apply_filters( 'has_remote_webfonts_request_permission', false, $provider_id ) | ||
) { | ||
continue; | ||
} | ||
|
||
/* | ||
* Process the webfonts by first passing them to the provider via `set_webfonts()` | ||
* and then getting the CSS from the provider. | ||
*/ | ||
$provider->set_webfonts( $registered_webfonts ); | ||
$styles .= $provider->get_css(); | ||
} | ||
|
||
return $styles; | ||
} | ||
|
||
/** | ||
* Gets the resource hints. | ||
* | ||
* Callback hooked to the filter `'wp_resource_hints'`. Generation | ||
* and rendering of the resource `<link>` is handled where that filter | ||
* fires. This method adds the resource link attributes to pass back | ||
* to that handler. | ||
* | ||
* @since 5.9.0 | ||
* | ||
* @param array $urls { | ||
* Array of resources and their attributes, or URLs to print for resource hints. | ||
* | ||
* @type array|string ...$0 { | ||
* Array of resource attributes, or a URL string. | ||
* | ||
* @type string $href URL to include in resource hints. Required. | ||
* @type string $as How the browser should treat the resource | ||
* (`script`, `style`, `image`, `document`, etc). | ||
* @type string $crossorigin Indicates the CORS policy of the specified resource. | ||
* @type float $pr Expected probability that the resource hint will be used. | ||
* @type string $type Type of the resource (`text/html`, `text/css`, etc). | ||
* } | ||
* } | ||
* @param string $relation_type The relation type the URLs are printed for, | ||
* e.g. 'preconnect' or 'prerender'. | ||
* @return array URLs to print for resource hints. | ||
*/ | ||
public function get_resource_hints( $urls, $relation_type ) { | ||
hellofromtonya marked this conversation as resolved.
Show resolved
Hide resolved
|
||
foreach ( $this->providers_registry->get_all_registered() as $provider ) { | ||
foreach ( $provider->get_resource_hints() as $relation => $relation_hints ) { | ||
if ( $relation !== $relation_type ) { | ||
continue; | ||
} | ||
// Append this provider's resource hints to the end of the given `$urls` array. | ||
array_push( $urls, ...$relation_hints ); | ||
} | ||
} | ||
|
||
return $urls; | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @azaozz, here's the new filter we discussed for granting permission to do a remote request to an external webfonts service provider, such as Google Fonts. By default, it's set to
false
meaning the API will not do remote requests. What do you think?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huzzah