From d16d22603c3dfd6b957ba672a40eed0e0bec25fa Mon Sep 17 00:00:00 2001 From: Anton Vlasenko Date: Fri, 2 Feb 2024 21:07:22 +0100 Subject: [PATCH] Apply fixes. --- .../fonts/class-wp-font-collection.php | 198 +++++++++--------- .../fonts/class-wp-font-library.php | 92 ++++---- .../fonts/class-wp-font-utils.php | 119 ++--------- lib/compat/wordpress-6.5/fonts/fonts-bc.php | 87 ++++++++ lib/compat/wordpress-6.5/fonts/fonts.php | 141 ++++--------- 5 files changed, 297 insertions(+), 340 deletions(-) create mode 100644 lib/compat/wordpress-6.5/fonts/fonts-bc.php diff --git a/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php b/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php index c48d28a6f01fb6..cecfdec1b4a246 100644 --- a/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php +++ b/lib/compat/wordpress-6.5/fonts/class-wp-font-collection.php @@ -2,7 +2,7 @@ /** * Font Collection class. * - * This file contains the Font Collection class definition. + * This class is used to manage a collection of fonts. * * @package WordPress * @subpackage Font Library @@ -12,62 +12,86 @@ if ( ! class_exists( 'WP_Font_Collection' ) ) { /** - * Font Collection class. + * Manages a collection of fonts. + * + * This class provides functionality to manage a group of font families, including loading font data from JSON files. * * @since 6.5.0 */ - final class WP_Font_Collection { + class WP_Font_Collection { /** * The unique slug for the font collection. * * @since 6.5.0 - * * @var string */ public $slug; /** - * Font collection data. + * The name of the font collection. + * + * @since 6.5.0 + * @var string + */ + public $name; + + /** + * Description of the font collection. * * @since 6.5.0 + * @var string + */ + public $description; + + /** + * Array of font families in the collection. * + * @since 6.5.0 * @var array */ - private $data; + public $font_families; /** - * Font collection JSON file path or url. + * Categories associated with the font collection. * * @since 6.5.0 + * @var array + */ + public $categories; + + /** + * Font collection JSON cache. * - * @var string + * Caches the font collection data loaded from JSON to optimize performance. + * + * @since 6.5.0 + * @var array */ - private $src; + private static $collection_json_cache = array(); /** - * WP_Font_Collection constructor. + * Constructor for the WP_Font_Collection class. + * + * Initializes a new instance of the WP_Font_Collection class with the specified slug and configuration options. * * @since 6.5.0 * - * @param string $slug Font collection slug. - * @param array|string $data_or_file { - * Font collection data array or a file path or url to a JSON file containing the font collection. + * @param string $slug Font collection slug. + * @param array $args { + * Optional. Array of configuration options for the font collection. * - * @type string $name Name of the font collection. - * @type string $description Description of the font collection. - * @type array $font_families Array of font family definitions that are in the collection. - * @type array $categories Array of categories for the fonts that are in the collection. + * @type string $name Name of the font collection. + * @type string $description Description of the font collection. + * @type array $font_families Array of font family definitions included in the collection. + * @type array $categories Array of categories associated with the fonts in the collection. * } */ - public function __construct( $slug, $data_or_file ) { - $this->slug = sanitize_title( $slug ); - - // Data or json are lazy loaded and validated in get_data(). - if ( is_array( $data_or_file ) ) { - $this->data = $data_or_file; - } else { - $this->src = $data_or_file; - } + public function __construct( $slug, $args = array() ) { + $this->slug = sanitize_title( $slug ); + $this->name = isset( $args['name'] ) ? $args['name'] : __( 'Unnamed Font Collection', 'gutenberg' ); + $this->description = isset( $args['description'] ) ? $args['description'] : ''; + $this->font_families = isset( $args['font_families'] ) ? $args['font_families'] : array(); + $this->categories = isset( $args['categories'] ) ? $args['categories'] : array(); if ( $this->slug !== $slug ) { _doing_it_wrong( @@ -77,95 +101,83 @@ public function __construct( $slug, $data_or_file ) { '6.5.0' ); } - } - - /** - * Retrieves the font collection data. - * - * @since 6.5.0 - * - * @return array|WP_Error An array containing the font collection data, or a WP_Error on failure. - */ - public function get_data() { - // If we have a JSON config, load it and cache the data if it's valid. - if ( $this->src && empty( $this->data ) ) { - $data = $this->load_from_json( $this->src ); - if ( is_wp_error( $data ) ) { - return $data; - } - - $this->data = $data; - } - // Validate required properties are not empty. - $data = $this->validate_data( $this->data ); - if ( is_wp_error( $data ) ) { - return $data; + if ( empty( $args['font_families'] ) ) { + _doing_it_wrong( + __METHOD__, + /* translators: %s: Font collection slug. */ + sprintf( __( 'Font collection "%s" does not contain any font families.', 'gutenberg' ), $slug ), + '6.5.0' + ); } - - // Set defaults for optional properties. - $data = wp_parse_args( - $data, - array( - 'description' => '', - 'categories' => array(), - ) - ); - - return $data; } /** - * Loads the font collection data from a JSON file path or url. + * Loads the font collection data from a json file path or url. * * @since 6.5.0 * - * @param string $file_or_url File path or url to a JSON file containing the font collection data. + * @param string $file_or_url File path or url to a json file containing the font collection data. * @return array|WP_Error An array containing the font collection data on success, - * else an instance of WP_Error on failure. + * or WP_Error object on failure. */ - private function load_from_json( $file_or_url ) { + public static function load_from_json( $file_or_url ) { $url = wp_http_validate_url( $file_or_url ); $file = file_exists( $file_or_url ) ? wp_normalize_path( realpath( $file_or_url ) ) : false; if ( ! $url && ! $file ) { - // translators: %s: File path or url to font collection JSON file. - $message = __( 'Font collection JSON file is invalid or does not exist.', 'gutenberg' ); + // translators: %s: File path or url to font collection json file. + $message = sprintf( __( 'Font collection JSON file "%s" is invalid or does not exist.', 'gutenberg' ), $file_or_url ); _doing_it_wrong( __METHOD__, $message, '6.5.0' ); return new WP_Error( 'font_collection_json_missing', $message ); } - return $url ? $this->load_from_url( $url ) : $this->load_from_file( $file ); + return $url ? self::load_from_url( $url ) : self::load_from_file( $file ); } /** - * Loads the font collection data from a JSON file path. + * Loads font collection data from a JSON file path. * * @since 6.5.0 * * @param string $file File path to a JSON file containing the font collection data. - * @return array|WP_Error An array containing the font collection data on success, - * else an instance of WP_Error on failure. + * @return array|WP_Error Array containing the font collection data on success, or WP_Error object on failure. */ - private function load_from_file( $file ) { + private static function load_from_file( $file ) { + if ( array_key_exists( $file, static::$collection_json_cache ) ) { + return static::$collection_json_cache[ $file ]; + } + $data = wp_json_file_decode( $file, array( 'associative' => true ) ); if ( empty( $data ) ) { return new WP_Error( 'font_collection_decode_error', __( 'Error decoding the font collection JSON file contents.', 'gutenberg' ) ); } + if ( empty( $data['slug'] ) ) { + // translators: %s: Font collection JSON URL. + $message = sprintf( __( 'Font collection JSON file "%s" requires a slug.', 'gutenberg' ), $file ); + _doing_it_wrong( __METHOD__, $message, '6.5.0' ); + return new WP_Error( 'font_collection_invalid_json', $message ); + } + + static::$collection_json_cache[ $file ] = $data; + return $data; } /** - * Loads the font collection data from a JSON file url. + * Loads font collection data from a JSON file URL. * * @since 6.5.0 * - * @param string $url Url to a JSON file containing the font collection data. - * @return array|WP_Error An array containing the font collection data on success, - * else an instance of WP_Error on failure. + * @param string $url URL to a JSON file containing the font collection data. + * @return array|WP_Error Array containing the font collection data on success, or WP_Error object on failure. */ - private function load_from_url( $url ) { + private static function load_from_url( $url ) { + if ( array_key_exists( $url, static::$collection_json_cache ) ) { + return static::$collection_json_cache[ $url ]; + } + // Limit key to 167 characters to avoid failure in the case of a long url. $transient_key = substr( 'wp_font_collection_url_' . $url, 0, 167 ); $data = get_site_transient( $transient_key ); @@ -182,40 +194,18 @@ private function load_from_url( $url ) { return new WP_Error( 'font_collection_decode_error', __( 'Error decoding the font collection data from the REST response JSON.', 'gutenberg' ) ); } - // Make sure the data is valid before caching it. - $data = $this->validate_data( $data ); - if ( is_wp_error( $data ) ) { - return $data; + if ( empty( $data['slug'] ) ) { + // translators: %s: Font collection JSON URL. + $message = sprintf( __( 'Font collection JSON file "%s" requires a slug.', 'gutenberg' ), $url ); + _doing_it_wrong( __METHOD__, $message, '6.5.0' ); + return new WP_Error( 'font_collection_invalid_json', $message ); } set_site_transient( $transient_key, $data, DAY_IN_SECONDS ); } - return $data; - } + static::$collection_json_cache[ $url ] = $data; - /** - * Validates the font collection configuration. - * - * @since 6.5.0 - * - * @param array $data Font collection configuration. - * @return array|WP_Error Array of data if valid, otherwise a WP_Error instance. - */ - private function validate_data( $data ) { - $required_properties = array( 'name', 'font_families' ); - foreach ( $required_properties as $property ) { - if ( empty( $data[ $property ] ) ) { - $message = sprintf( - // translators: 1: Font collection slug, 2: Missing property name. - __( 'Font collection "%1$s" has missing or empty property: "%2$s."', 'gutenberg' ), - $this->slug, - $property - ); - _doing_it_wrong( __METHOD__, $message, '6.5.0' ); - return new WP_Error( 'font_collection_missing_property', $message ); - } - } return $data; } } diff --git a/lib/compat/wordpress-6.5/fonts/class-wp-font-library.php b/lib/compat/wordpress-6.5/fonts/class-wp-font-library.php index a33aead5571ec0..8797f2dc7a4b9c 100644 --- a/lib/compat/wordpress-6.5/fonts/class-wp-font-library.php +++ b/lib/compat/wordpress-6.5/fonts/class-wp-font-library.php @@ -19,18 +19,27 @@ class WP_Font_Library { /** - * Provide the expected mime-type value for font files per-PHP release. Due to differences in the values returned these values differ between PHP versions. + * Font collections storage. * - * This is necessary until a collection of valid mime-types per-file extension can be provided to 'upload_mimes' filter. + * Holds registered font collections. * * @since 6.5.0 * - * @param array $php_version_id The version of PHP to provide mime types for. The default is the current PHP version. + * @var WP_Font_Collection[] + */ + private static $collections = array(); + + /** + * Gets the expected mime types for font files based on PHP version. * - * @return Array A collection of mime types keyed by file extension. + * Provides the correct mime-type values for font files, which can vary between PHP versions. + * + * @since 6.5.0 + * + * @param int $php_version_id The PHP version ID for which to provide mime types. Defaults to the current PHP version. + * @return array Associative array of mime types keyed by file extension. */ public static function get_expected_font_mime_types_per_php_version( $php_version_id = PHP_VERSION_ID ) { - $php_7_ttf_mime_type = $php_version_id >= 70300 ? 'application/font-sfnt' : 'application/x-font-ttf'; return array( @@ -42,27 +51,17 @@ public static function get_expected_font_mime_types_per_php_version( $php_versio } /** - * Font collections. + * Registers a new font collection. * * @since 6.5.0 * - * @var array - */ - private static $collections = array(); - - /** - * Register a new font collection. - * - * @since 6.5.0 - * - * @param string $slug Font collection slug. - * @param array $data_or_file Font collection data array or a file path or url to a JSON file - * containing the font collection. - * See {@see wp_register_font_collection()} for the supported fields. - * @return WP_Font_Collection|WP_Error A font collection if registration was successful, else WP_Error. + * @param string $slug Font collection slug. + * @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 if registration was successful, or WP_Error object on failure. */ - public static function register_font_collection( $slug, $data_or_file ) { - $new_collection = new WP_Font_Collection( $slug, $data_or_file ); + public static function register_font_collection( $slug, $args = array() ) { + $new_collection = new WP_Font_Collection( $slug, $args ); if ( self::is_collection_registered( $new_collection->slug ) ) { $error_message = sprintf( @@ -81,25 +80,43 @@ public static function register_font_collection( $slug, $data_or_file ) { return $new_collection; } + /** + * Registers a new font collection from a JSON file. + * + * @since 6.5.0 + * + * @param string $file_or_url Path or URL to the JSON file containing the font collection data. + * @return WP_Font_Collection|WP_Error WP_Font_Collection object if successful, or WP_Error object on failure. + */ + public static function register_font_collection_from_json( $file_or_url ) { + $args = WP_Font_Collection::load_from_json( $file_or_url ); + if ( is_wp_error( $args ) ) { + return $args; + } + + return self::register_font_collection( $args['slug'], $args ); + } + /** * Unregisters a previously registered font collection. * * @since 6.5.0 * - * @param string $collection_slug Font collection slug. - * @return bool True if the font collection was unregistered successfully and false otherwise. + * @param string $slug The slug of the font collection to unregister. + * @return bool True on successful unregistration, false otherwise. */ public static function unregister_font_collection( $slug ) { if ( ! self::is_collection_registered( $slug ) ) { _doing_it_wrong( __METHOD__, /* translators: %s: Font collection slug. */ - sprintf( __( 'Font collection "%s" not found.', 'default' ), $slug ), + sprintf( __( 'Font collection "%s" not found.', 'gutenberg' ), $slug ), '6.5.0' ); return false; } unset( self::$collections[ $slug ] ); + return true; } @@ -108,48 +125,49 @@ public static function unregister_font_collection( $slug ) { * * @since 6.5.0 * - * @param string $slug Font collection slug. - * @return bool True if the font collection is registered and false otherwise. + * @param string $slug The slug of the font collection to check. + * @return bool True if registered, false otherwise. */ private static function is_collection_registered( $slug ) { return array_key_exists( $slug, self::$collections ); } /** - * Gets all the font collections available. + * Retrieves all registered font collections. * * @since 6.5.0 * - * @return array List of font collections. + * @return WP_Font_Collection[] Array of WP_Font_Collection objects. */ public static function get_font_collections() { return self::$collections; } /** - * Gets a font collection. + * Retrieves a specific font collection. + * + * Returns a font collection object based on its slug, if registered. * * @since 6.5.0 * - * @param string $slug Font collection slug. - * @return WP_Font_Collection Font collection object. + * @param string $slug The slug of the font collection to retrieve. + * @return WP_Font_Collection|WP_Error WP_Font_Collection object if found, or WP_Error object on failure. */ public static function get_font_collection( $slug ) { if ( array_key_exists( $slug, self::$collections ) ) { return self::$collections[ $slug ]; } + return new WP_Error( 'font_collection_not_found', 'Font collection not found.' ); } - - /** - * Sets the allowed mime types for fonts. + * Sets allowed mime types for font uploads. * * @since 6.5.0 * - * @param array $mime_types List of allowed mime types. - * @return array Modified upload directory. + * @param array $mime_types Current array of allowed mime types. + * @return array Updated array of allowed mime types including font mime types. */ public static function set_allowed_mime_types( $mime_types ) { return array_merge( $mime_types, self::get_expected_font_mime_types_per_php_version() ); diff --git a/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php b/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php index 72a362a3a42a4d..a53eef263117ba 100644 --- a/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php +++ b/lib/compat/wordpress-6.5/fonts/class-wp-font-utils.php @@ -1,8 +1,8 @@ '', - 'fontStyle' => 'normal', - 'fontWeight' => '400', - 'fontStretch' => '100%', - 'unicodeRange' => 'U+0-10FFFF', - ) + $defaults = array( + 'fontFamily' => '', + 'fontStyle' => 'normal', + 'fontWeight' => '400', + 'fontStretch' => '100%', + 'unicodeRange' => 'U+0-10FFFF', ); + $settings = wp_parse_args( $settings, $defaults ); - // Convert all values to lowercase for comparison. - // Font family names may use multibyte characters. $font_family = mb_strtolower( $settings['fontFamily'] ); $font_style = strtolower( $settings['fontStyle'] ); $font_weight = strtolower( $settings['fontWeight'] ); @@ -100,10 +96,8 @@ public static function get_font_face_slug( $settings ) { $unicode_range = strtoupper( $settings['unicodeRange'] ); // Convert weight keywords to numeric strings. - $font_weight = str_replace( 'normal', '400', $font_weight ); - $font_weight = str_replace( 'bold', '700', $font_weight ); + $font_weight = str_replace( array( 'normal', 'bold' ), array( '400', '700' ), $font_weight ); - // Convert stretch keywords to numeric strings. $font_stretch_map = array( 'ultra-condensed' => '50%', 'extra-condensed' => '62.5%', @@ -133,82 +127,7 @@ function ( $elem ) { $slug_elements ); - return join( ';', $slug_elements ); - } - - /** - * Sanitize a tree of data using an schema that defines the sanitization to apply to each key. - * - * It removes the keys not in the schema and applies the sanitizer to the values. - * - * @since 6.5.0 - * - * @access private - * - * @param array $tree The data to sanitize. - * @param array $schema The schema used for sanitization. - * - * @return array The sanitized data. - */ - public static function sanitize_from_schema( $tree, $schema ) { - if ( ! is_array( $tree ) || ! is_array( $schema ) ) { - return array(); - } - - foreach ( $tree as $key => $value ) { - // Remove keys not in the schema or with null/empty values. - if ( ! array_key_exists( $key, $schema ) ) { - unset( $tree[ $key ] ); - continue; - } - - $is_value_array = is_array( $value ); - $is_schema_array = is_array( $schema[ $key ] ); - - if ( $is_value_array && $is_schema_array ) { - if ( wp_is_numeric_array( $value ) ) { - // If indexed, process each item in the array. - foreach ( $value as $item_key => $item_value ) { - $tree[ $key ][ $item_key ] = isset( $schema[ $key ][0] ) && is_array( $schema[ $key ][0] ) - ? self::sanitize_from_schema( $item_value, $schema[ $key ][0] ) - : self::apply_sanitizer( $item_value, $schema[ $key ][0] ); - } - } else { - // If it is an associative or indexed array., process as a single object. - $tree[ $key ] = self::sanitize_from_schema( $value, $schema[ $key ] ); - } - } elseif ( ! $is_value_array && $is_schema_array ) { - // If the value is not an array but the schema is, remove the key. - unset( $tree[ $key ] ); - } elseif ( ! $is_schema_array ) { - // If the schema is not an array, apply the sanitizer to the value. - $tree[ $key ] = self::apply_sanitizer( $value, $schema[ $key ] ); - } - - // Remove keys with null/empty values. - if ( empty( $tree[ $key ] ) ) { - unset( $tree[ $key ] ); - } - } - - return $tree; - } - - /** - * Apply the sanitizer to the value. - * - * @since 6.5.0 - * @param mixed $value The value to sanitize. - * @param mixed $sanitizer The sanitizer to apply. - * - * @return mixed The sanitized value. - */ - private static function apply_sanitizer( $value, $sanitizer ) { - if ( null === $sanitizer ) { - return $value; - - } - return call_user_func( $sanitizer, $value ); + return implode( ';', $slug_elements ); } } } diff --git a/lib/compat/wordpress-6.5/fonts/fonts-bc.php b/lib/compat/wordpress-6.5/fonts/fonts-bc.php new file mode 100644 index 00000000000000..8cb379ac8376fb --- /dev/null +++ b/lib/compat/wordpress-6.5/fonts/fonts-bc.php @@ -0,0 +1,87 @@ + 'wp_font_family', + // Set a maximum, but in reality there will be far less than this. + 'posts_per_page' => 999, + 'update_post_term_cache' => false, + ) + ); + + foreach ( $font_families->get_posts() as $font_family ) { + $already_converted = get_post_meta( $font_family->ID, '_gutenberg_legacy_font_family', true ); + if ( $already_converted ) { + continue; + } + + // Stash the old font family content in a meta field just in case we need it. + update_post_meta( $font_family->ID, '_gutenberg_legacy_font_family', $font_family->post_content ); + + $font_family_json = json_decode( $font_family->post_content, true ); + if ( ! $font_family_json ) { + continue; + } + + $font_faces = isset( $font_family_json['fontFace'] ) ? $font_family_json['fontFace'] : array(); + unset( $font_family_json['fontFace'] ); + + // Save wp_font_face posts within the family. + foreach ( $font_faces as $font_face ) { + $args = array(); + $args['post_type'] = 'wp_font_face'; + $args['post_title'] = WP_Font_Utils::get_font_face_slug( $font_face ); + $args['post_name'] = sanitize_title( $args['post_title'] ); + $args['post_status'] = 'publish'; + $args['post_parent'] = $font_family->ID; + $args['post_content'] = wp_json_encode( $font_face ); + + $font_face_id = wp_insert_post( wp_slash( $args ) ); + + $file_urls = (array) ( isset( $font_face['src'] ) ? $font_face['src'] : array() ); + + foreach ( $file_urls as $file_url ) { + // continue if the file is not local. + if ( false === strpos( $file_url, site_url() ) ) { + continue; + } + + $relative_path = basename( $file_url ); + update_post_meta( $font_face_id, '_wp_font_face_file', $relative_path ); + } + } + + // Update the font family post to remove the font face data. + $args = array(); + $args['ID'] = $font_family->ID; + $args['post_title'] = isset( $font_family_json['name'] ) ? $font_family_json['name'] : ''; + $args['post_name'] = sanitize_title( $font_family_json['slug'] ); + + unset( $font_family_json['name'] ); + unset( $font_family_json['slug'] ); + + $args['post_content'] = wp_json_encode( $font_family_json ); + + wp_update_post( wp_slash( $args ) ); + } + + update_option( 'gutenberg_font_family_format_converted', true ); +} +add_action( 'init', 'gutenberg_convert_legacy_font_family_format' ); diff --git a/lib/compat/wordpress-6.5/fonts/fonts.php b/lib/compat/wordpress-6.5/fonts/fonts.php index 339ab32646d8b4..c5aca599b10694 100644 --- a/lib/compat/wordpress-6.5/fonts/fonts.php +++ b/lib/compat/wordpress-6.5/fonts/fonts.php @@ -19,7 +19,7 @@ * * @since 6.5.0 */ -function gutenberg_init_font_library_routes() { +function gutenberg_create_initial_post_types() { // @core-merge: This code will go into Core's `create_initial_post_types()`. $args = array( 'labels' => array( @@ -82,13 +82,20 @@ function gutenberg_init_font_library_routes() { 'autosave_rest_controller_class' => 'stdClass', ) ); +} +function gutenberg_create_initial_rest_routes() { // @core-merge: This code will go into Core's `create_initial_rest_routes()`. $font_collections_controller = new WP_REST_Font_Collections_Controller(); $font_collections_controller->register_routes(); } -add_action( 'rest_api_init', 'gutenberg_init_font_library_routes' ); +function gutenberg_init_font_library() { + gutenberg_create_initial_post_types(); + gutenberg_create_initial_rest_routes(); +} + +add_action( 'rest_api_init', 'gutenberg_init_font_library' ); if ( ! function_exists( 'wp_register_font_collection' ) ) { @@ -97,10 +104,9 @@ function gutenberg_init_font_library_routes() { * * @since 6.5.0 * - * @param string $slug Font collection slug or path/url to a JSON file defining the font collection. - * @param array|string $data_or_file { - * Font collection associative array of data, or a file path or url to a JSON - * file containing the font collection. + * @param string $slug Font collection slug or path/url to a JSON file defining the font collection. + * @param string[] $args { + * Optional. Font collection associative array of configuration options. * * @type string $name Name of the font collection. * @type string $description Description of the font collection. @@ -108,10 +114,24 @@ function gutenberg_init_font_library_routes() { * @type array $categories Array of categories for the fonts that are in the collection. * } * @return WP_Font_Collection|WP_Error A font collection is it was registered - * successfully, else WP_Error. + * successfully, or WP_Error object on failure. + */ + function wp_register_font_collection( $slug, $args = array() ) { + return WP_Font_Library::register_font_collection( $slug, $args ); + } +} + +if ( ! function_exists( 'wp_register_font_collection_from_json' ) ) { + /** + * Registers a new Font Collection from a json file in the Font Library. + * + * @since 6.5.0 + * + * @param string $file_or_url File path or URL to a JSON file containing the font collection data. + * @return WP_Font_Collection|WP_Error A font collection if registration was successful, or WP_Error object on failure. */ - function wp_register_font_collection( $slug, $data_or_file ) { - return WP_Font_Library::register_font_collection( $slug, $data_or_file ); + function wp_register_font_collection_from_json( $file_or_url ) { + return WP_Font_Library::register_font_collection_from_json( $file_or_url ); } } @@ -122,17 +142,15 @@ function wp_register_font_collection( $slug, $data_or_file ) { * @since 6.5.0 * * @param string $collection_id The font collection ID. + * @return bool True if the font collection was unregistered successfully, else false. */ function wp_unregister_font_collection( $collection_id ) { - WP_Font_Library::unregister_font_collection( $collection_id ); + return WP_Font_Library::unregister_font_collection( $collection_id ); } } -function gutenberg_register_font_collections() { - // TODO: update to production font collection URL. - wp_register_font_collection( 'google-fonts', 'https://raw.githubusercontent.com/WordPress/google-fonts-to-wordpress-collection/01aa57731575bd13f9db8d86ab80a2d74e28a1ac/releases/gutenberg-17.6/collections/google-fonts-with-preview.json' ); -} -add_action( 'init', 'gutenberg_register_font_collections' ); +// TODO: update to production font collection URL. +wp_register_font_collection_from_json( 'https://raw.githubusercontent.com/WordPress/google-fonts-to-wordpress-collection/01aa57731575bd13f9db8d86ab80a2d74e28a1ac/releases/gutenberg-17.6/collections/google-fonts-with-preview.json' ); // @core-merge: This code should probably go into Core's src/wp-includes/functions.php. if ( ! function_exists( 'wp_get_font_dir' ) ) { @@ -151,7 +169,6 @@ function gutenberg_register_font_collections() { * @type string $baseurl URL path without subdir. * @type string|false $error False or error message. * } - * * @return array $defaults { * Array of information about the upload directory. * @@ -178,7 +195,15 @@ function wp_get_font_dir( $defaults = array() ) { $defaults['baseurl'] = untrailingslashit( content_url( 'fonts' ) ) . $site_path; $defaults['error'] = false; - // Filters the fonts directory data. + /** + * Filters the fonts directory data. + * + * This filter allows developers to modify the fonts directory data. + * + * @since 6.5.0 + * + * @param array $defaults The original fonts directory data. + */ return apply_filters( 'font_dir', $defaults ); } } @@ -194,7 +219,6 @@ function wp_get_font_dir( $defaults = array() ) { * * @param int $post_id Post ID. * @param WP_Post $post Post object. - * @return void */ function _wp_after_delete_font_family( $post_id, $post ) { if ( 'wp_font_family' !== $post->post_type ) { @@ -224,7 +248,6 @@ function _wp_after_delete_font_family( $post_id, $post ) { * * @param int $post_id Post ID. * @param WP_Post $post Post object. - * @return void */ function _wp_before_delete_font_face( $post_id, $post ) { if ( 'wp_font_face' !== $post->post_type ) { @@ -239,83 +262,3 @@ function _wp_before_delete_font_face( $post_id, $post ) { } add_action( 'before_delete_post', '_wp_before_delete_font_face', 10, 2 ); } - -// @core-merge: Do not merge this back compat function, it is for supporting a legacy font family format only in Gutenberg. -/** - * Convert legacy font family posts to the new format. - * - * @return void - */ -function gutenberg_convert_legacy_font_family_format() { - if ( get_option( 'gutenberg_font_family_format_converted' ) ) { - return; - } - - $font_families = new WP_Query( - array( - 'post_type' => 'wp_font_family', - // Set a maximum, but in reality there will be far less than this. - 'posts_per_page' => 999, - 'update_post_term_cache' => false, - ) - ); - - foreach ( $font_families->get_posts() as $font_family ) { - $already_converted = get_post_meta( $font_family->ID, '_gutenberg_legacy_font_family', true ); - if ( $already_converted ) { - continue; - } - - // Stash the old font family content in a meta field just in case we need it. - update_post_meta( $font_family->ID, '_gutenberg_legacy_font_family', $font_family->post_content ); - - $font_family_json = json_decode( $font_family->post_content, true ); - if ( ! $font_family_json ) { - continue; - } - - $font_faces = $font_family_json['fontFace'] ?? array(); - unset( $font_family_json['fontFace'] ); - - // Save wp_font_face posts within the family. - foreach ( $font_faces as $font_face ) { - $args = array(); - $args['post_type'] = 'wp_font_face'; - $args['post_title'] = WP_Font_Utils::get_font_face_slug( $font_face ); - $args['post_name'] = sanitize_title( $args['post_title'] ); - $args['post_status'] = 'publish'; - $args['post_parent'] = $font_family->ID; - $args['post_content'] = wp_json_encode( $font_face ); - - $font_face_id = wp_insert_post( wp_slash( $args ) ); - - $file_urls = (array) $font_face['src'] ?? array(); - - foreach ( $file_urls as $file_url ) { - // continue if the file is not local. - if ( false === strpos( $file_url, site_url() ) ) { - continue; - } - - $relative_path = basename( $file_url ); - update_post_meta( $font_face_id, '_wp_font_face_file', $relative_path ); - } - } - - // Update the font family post to remove the font face data. - $args = array(); - $args['ID'] = $font_family->ID; - $args['post_title'] = $font_family_json['name'] ?? ''; - $args['post_name'] = sanitize_title( $font_family_json['slug'] ); - - unset( $font_family_json['name'] ); - unset( $font_family_json['slug'] ); - - $args['post_content'] = wp_json_encode( $font_family_json ); - - wp_update_post( wp_slash( $args ) ); - } - - update_option( 'gutenberg_font_family_format_converted', true ); -} -add_action( 'init', 'gutenberg_convert_legacy_font_family_format' );