Skip to content
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

Font Collections: update registration function signature and add caching #58363

Merged
merged 12 commits into from
Jan 31, 2024

Conversation

creativecoder
Copy link
Contributor

@creativecoder creativecoder commented Jan 29, 2024

What?

  • Updates wp_register_font_collection so that it takes a $slug and optional $arg array, but does not handle JSON
  • Adds wp_register_font_collection_from_json function specifically for registering a collection from a JSON file
  • Adds static caching for accessing all font collections plus transient caching for remote collections
  • Removes WP_Font_Collection::get_content in favor of accessing all properties directly (e.g. $collection->font_families)

Why?

  • Simplifies/standardizes how collection properties are accessed
  • Improves performance for accessing font collections from json with caching
  • Brings PHP function signatures to be more similar to other Core register_ functions

Testing Instructions

  • Ensure the google fonts collection works as expected (with modified json file from this PR ).
  • Try registering a font collection in PHP, and make sure it works as expected

Example PHP font collection for testing:

In a plugin:

wp_register_font_collection_from_json( __DIR__ . '/test-font-collection.json' );

test-font-collection.json

{
	"$schema": "https://schemas.wp.org/trunk/font-collection.json",
	"slug": "test-font-collection",
	"name": "Test Font Collection",
	"description": "A test font collection.",
	"font_families": [
		{
			"font_family_settings": {
				"name": "Open Sans",
				"fontFamily": "Open Sans, sans-serif",
				"slug": "open-sans",
				"fontFace": [
					{
						"src": "https://fonts.gstatic.com/s/opensans/v40/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsiH0C4iY1M2xLER.woff2",
						"fontWeight": "300",
						"fontStyle": "normal",
						"fontFamily": "Open Sans",
						"preview": "https://s.w.org/images/fonts/17.6/previews/open-sans/open-sans-300-normal.svg"
					},
					{
						"src": "https://fonts.gstatic.com/s/opensans/v40/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0C4iY1M2xLER.woff2",
						"fontWeight": "400",
						"fontStyle": "normal",
						"fontFamily": "Open Sans",
						"preview": "https://s.w.org/images/fonts/17.6/previews/open-sans/open-sans-400-normal.svg"
					},
					{
						"src": "https://fonts.gstatic.com/s/opensans/v40/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjr0C4iY1M2xLER.woff2",
						"fontWeight": "500",
						"fontStyle": "normal",
						"fontFamily": "Open Sans",
						"preview": "https://s.w.org/images/fonts/17.6/previews/open-sans/open-sans-500-normal.svg"
					},
					{
						"src": "https://fonts.gstatic.com/s/opensans/v40/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsgH1y4iY1M2xLER.woff2",
						"fontWeight": "600",
						"fontStyle": "normal",
						"fontFamily": "Open Sans",
						"preview": "https://s.w.org/images/fonts/17.6/previews/open-sans/open-sans-600-normal.svg"
					},
					{
						"src": "https://fonts.gstatic.com/s/opensans/v40/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsg-1y4iY1M2xLER.woff2",
						"fontWeight": "700",
						"fontStyle": "normal",
						"fontFamily": "Open Sans",
						"preview": "https://s.w.org/images/fonts/17.6/previews/open-sans/open-sans-700-normal.svg"
					},
					{
						"src": "https://fonts.gstatic.com/s/opensans/v40/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgshZ1y4iY1M2xLER.woff2",
						"fontWeight": "800",
						"fontStyle": "normal",
						"fontFamily": "Open Sans",
						"preview": "https://s.w.org/images/fonts/17.6/previews/open-sans/open-sans-800-normal.svg"
					},
					{
						"src": "https://fonts.gstatic.com/s/opensans/v40/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk5hkaVIUwaERZjA.woff2",
						"fontWeight": "300",
						"fontStyle": "italic",
						"fontFamily": "Open Sans",
						"preview": "https://s.w.org/images/fonts/17.6/previews/open-sans/open-sans-300-italic.svg"
					},
					{
						"src": "https://fonts.gstatic.com/s/opensans/v40/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk8ZkaVIUwaERZjA.woff2",
						"fontWeight": "400",
						"fontStyle": "italic",
						"fontFamily": "Open Sans",
						"preview": "https://s.w.org/images/fonts/17.6/previews/open-sans/open-sans-400-italic.svg"
					},
					{
						"src": "https://fonts.gstatic.com/s/opensans/v40/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk_RkaVIUwaERZjA.woff2",
						"fontWeight": "500",
						"fontStyle": "italic",
						"fontFamily": "Open Sans",
						"preview": "https://s.w.org/images/fonts/17.6/previews/open-sans/open-sans-500-italic.svg"
					},
					{
						"src": "https://fonts.gstatic.com/s/opensans/v40/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0RkxhjaVIUwaERZjA.woff2",
						"fontWeight": "600",
						"fontStyle": "italic",
						"fontFamily": "Open Sans",
						"preview": "https://s.w.org/images/fonts/17.6/previews/open-sans/open-sans-600-italic.svg"
					},
					{
						"src": "https://fonts.gstatic.com/s/opensans/v40/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0RkyFjaVIUwaERZjA.woff2",
						"fontWeight": "700",
						"fontStyle": "italic",
						"fontFamily": "Open Sans",
						"preview": "https://s.w.org/images/fonts/17.6/previews/open-sans/open-sans-700-italic.svg"
					},
					{
						"src": "https://fonts.gstatic.com/s/opensans/v40/memQYaGs126MiZpBA-UFUIcVXSCEkx2cmqvXlWq8tWZ0Pw86hd0Rk0ZjaVIUwaERZjA.woff2",
						"fontWeight": "800",
						"fontStyle": "italic",
						"fontFamily": "Open Sans",
						"preview": "https://s.w.org/images/fonts/17.6/previews/open-sans/open-sans-800-italic.svg"
					}
				],
				"preview": "https://s.w.org/images/fonts/17.6/previews/open-sans/open-sans.svg"
			},
			"categories": ["sans-serif"]
		}
	],
	"categories": [
		{
			"name": "Sans Serif",
			"slug": "sans-serif"
		}
	]
}

@creativecoder creativecoder self-assigned this Jan 29, 2024
@creativecoder creativecoder changed the title Font Collection: update registration signature and add caching Font Collections: update registration function signature and add caching Jan 29, 2024
Copy link

github-actions bot commented Jan 29, 2024

This pull request has changed or added PHP files. Please confirm whether these changes need to be synced to WordPress Core, and therefore featured in the next release of WordPress.

If so, it is recommended to create a new Trac ticket and submit a pull request to the WordPress Core Github repository soon after this pull request is merged.

If you're unsure, you can always ask for help in the #core-editor channel in WordPress Slack.

Thank you! ❤️

View changed files
❔ phpunit/tests/fonts/font-library/wpFontCollection/loadFromJson.php
❔ lib/experimental/fonts/font-library/class-wp-font-collection.php
❔ lib/experimental/fonts/font-library/class-wp-font-library.php
❔ lib/experimental/fonts/font-library/class-wp-rest-font-collections-controller.php
❔ lib/experimental/fonts/font-library/class-wp-rest-font-families-controller.php
❔ lib/experimental/fonts/font-library/font-library.php
❔ phpunit/tests/fonts/font-library/wpFontCollection/__construct.php
❔ phpunit/tests/fonts/font-library/wpFontLibrary/getFontCollection.php
❔ phpunit/tests/fonts/font-library/wpFontLibrary/getFontCollections.php
❔ phpunit/tests/fonts/font-library/wpFontLibrary/registerFontCollection.php
❔ phpunit/tests/fonts/font-library/wpFontLibrary/unregisterFontCollection.php
❔ phpunit/tests/fonts/font-library/wpRestFontCollectionsController.php

Copy link

github-actions bot commented Jan 29, 2024

Flaky tests detected in efce06e19986b9df5a4a6bb61d3aab785b34a69c.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/7703293902
📝 Reported issues:

Comment on lines 128 to 132
if ( is_wp_error( $data ) ) {
return $data;
}

return true;
return $data;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be returning $data anyways. What's the purpose of the if() ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! Will remove the conditional.

Copy link
Contributor

@matiasbenedetto matiasbenedetto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I register a font collection with a wrong URL calling wp_register_font_collection like this:

wp_register_font_collection( 'https://example.com/test.json' );
  • I get a notice which seems correct:
Notice: Function WP_Font_Collection::__construct was called incorrectly. Font collection "https://example.com/test.json" does not contain any font families. Please see Debugging in WordPress for more information. (This message was added in version 6.5.0.) in /var/www/html/wp1/wp-includes/functions.php on line 6031
  • I get the collection with a collection with the url used as slug , which seems unexpected:

image

  • The UI looks like this, the error message does not describe the error accordingly.

image

I think this is caused by the use of $slug_or_file variable used to register a font collection.

public static function register_font_collection( $slug_or_file, $args = array() ) {
if ( file_exists( $slug_or_file ) || wp_http_validate_url( $slug_or_file ) ) {
$args = WP_Font_Collection::load_from_json( $slug_or_file );
if ( is_wp_error( $args ) ) {
return $args;
}
$slug = $args['slug'];
} else {
$slug = $slug_or_file;
}

It seems like it's difficult to differentiate between a wrong url/filepath of a slug.

@creativecoder
Copy link
Contributor Author

I get the collection with a collection with the url used as slug , which seems unexpected:

That seems strange. When I do wp_register_font_collection( 'https://example.com/test.json' ), it returns an error and no collection is registered.

@matiasbenedetto
Copy link
Contributor

Can the problem described here: #58363 (review)

be solved by replacing this

/**
* Register a new font collection.
*
* @since 6.5.0
*
* @param string $slug_or_file Font collection slug or path to a JSON file containing the font collection config.
* @param array $args Font collection config options.
* See {@see wp_register_font_collection()} for the supported fields.
* @return WP_Font_Collection|WP_Error A font collection is it was registered successfully and a WP_Error otherwise.
*/
public static function register_font_collection( $slug_or_file, $args = array() ) {
if ( file_exists( $slug_or_file ) || wp_http_validate_url( $slug_or_file ) ) {
$args = WP_Font_Collection::load_from_json( $slug_or_file );
if ( is_wp_error( $args ) ) {
return $args;
}
$slug = $args['slug'];
} else {
$slug = $slug_or_file;
}

with something like this?

/**
* Register a new font collection.
*
* @since 6.5.0
*
* @param string $slug         Font collection slug or path to a JSON file containing the font collection config.
* @param array  $file_or_args Path to a JSON file containing the font collection config o an array with the font collection config.
*                             See {@see wp_register_font_collection()} for the supported fields.
* @return WP_Font_Collection|WP_Error A font collection is it was registered successfully and a WP_Error otherwise.
*/
public static function register_font_collection( $slug, $file_or_args = array() ) {
if ( is_array( $file_or_args ) ) {
	$args = $file_or_args;
} else {
	$args = WP_Font_Collection::load_from_json( $file_or_args );
}

$new_collection = new WP_Font_Collection( $slug, $args );
		

@creativecoder
Copy link
Contributor Author

I do see a problem when mistyping a url--since it's not a valid url or file path, we have to assume it's a slug, which may not be the case.

Seeing this, I think it's better if we use separate functions for php vs json registration, to make it clear what the intent is. I've updated the PR to include

  • wp_register_font_collection - for registering a collection with PHP properties
  • wp_register_font_collection_from_metadata (inspired by register_block_type_from_metadata) for registering a collection from a json file

@matiasbenedetto
Copy link
Contributor

matiasbenedetto commented Jan 29, 2024

Testing the new function, If I set a non existing file I get no notice about it:

wp_register_font_collection_from_metadata( 'non-existing-file.json' );

I think a _doing_it_wrong kind of notice is expected here, right?

@creativecoder
Copy link
Contributor Author

I think a _doing_it_wrong kind of notice is expected here, right?

Yes, that's a good point--you may not be looking at the output of the function to see the WP_Error, so a notice would aid in debugging. Will add that.

@matiasbenedetto
Copy link
Contributor

matiasbenedetto commented Jan 29, 2024

The name wp_register_font_collection_from_metadata seems to be directly transposed from register_block_type_from_metadata. It makes sense to register blocks, because in that case, the file contains block 'metadata' (data about block description, as opposed to block content). In this case, we are registering the content of a font collection, so the name doesn't fit right.

@creativecoder
Copy link
Contributor Author

@matiasbenedetto What do you think would be better? wp_register_font_collection_from_json ?

@matiasbenedetto
Copy link
Contributor

@matiasbenedetto What do you think would be better? wp_register_font_collection_from_json ?

Yes, it seems more descriptive of the actual functionality.

@creativecoder
Copy link
Contributor Author

I've updated the PR with the following:

  • Rename wp_register_font_collection_from_metadata to wp_register_font_collection_from_json
  • Return error and trigger notice when using invalid url, non-existing file path, or json is missing a slug
  • Adding proper tests for those errors and notices

@matiasbenedetto
Copy link
Contributor

matiasbenedetto commented Jan 30, 2024

I made a mistake and tried to register a collection like this.

wp_register_font_collection( 'https://im-a-fake-url.com/fonts/font-collection.json' );
wp_register_font_collection( 'https://fakeurl.com/fonts/font-collection.json' );

I got this result:

API response:
image

UI:
image

It can be a common mistake among extenders, so the slug should probably be tested to assess if it's a valid slug or not.

@creativecoder
Copy link
Contributor Author

@matiasbenedetto That's a good point. In addition to addressing potential user error, I think the slug should be sanitized since it's used as an identifier in the REST API url.

I've updated this in d8f63b4 to sanitize the slug and emit a notice if the given slug doesn't match the sanitized one. Let me know what you think.

Copy link
Contributor

@matiasbenedetto matiasbenedetto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is testing well on my end. I verified that:

wp_register_font_collection_from_json :

  • Loads properly formatted JSON files as expected.
  • Raise notices when the URL/file provided is existent or doesn't have the right content.

wp_register_font_collection :

  • Loads data as expected.
  • Raises notices when the PHP data provided has missing required arguments like font_families.

@creativecoder creativecoder merged commit 552c76f into trunk Jan 31, 2024
55 checks passed
@creativecoder creativecoder deleted the add/font-collection-caching branch January 31, 2024 18:51
@github-actions github-actions bot added this to the Gutenberg 17.7 milestone Jan 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants