summaryrefslogtreecommitdiffstats
path: root/wp-includes/fonts
diff options
context:
space:
mode:
Diffstat (limited to 'wp-includes/fonts')
-rw-r--r--wp-includes/fonts/class-wp-font-collection.php295
-rw-r--r--wp-includes/fonts/class-wp-font-face-resolver.php7
-rw-r--r--wp-includes/fonts/class-wp-font-library.php142
-rw-r--r--wp-includes/fonts/class-wp-font-utils.php259
4 files changed, 697 insertions, 6 deletions
diff --git a/wp-includes/fonts/class-wp-font-collection.php b/wp-includes/fonts/class-wp-font-collection.php
new file mode 100644
index 0000000..b915e3e
--- /dev/null
+++ b/wp-includes/fonts/class-wp-font-collection.php
@@ -0,0 +1,295 @@
+<?php
+/**
+ * Font Collection class.
+ *
+ * This file contains the Font Collection class definition.
+ *
+ * @package WordPress
+ * @subpackage Fonts
+ * @since 6.5.0
+ */
+
+/**
+ * Font Collection class.
+ *
+ * @since 6.5.0
+ *
+ * @see wp_register_font_collection()
+ */
+final class WP_Font_Collection {
+ /**
+ * The unique slug for the font collection.
+ *
+ * @since 6.5.0
+ * @var string
+ */
+ public $slug;
+
+ /**
+ * Font collection data.
+ *
+ * @since 6.5.0
+ * @var array|WP_Error|null
+ */
+ private $data;
+
+ /**
+ * Font collection JSON file path or URL.
+ *
+ * @since 6.5.0
+ * @var string|null
+ */
+ private $src;
+
+ /**
+ * WP_Font_Collection constructor.
+ *
+ * @since 6.5.0
+ *
+ * @param string $slug Font collection slug. May only contain alphanumeric characters, dashes,
+ * and underscores. See sanitize_title().
+ * @param array $args Font collection data. See wp_register_font_collection() for information on accepted arguments.
+ */
+ public function __construct( string $slug, array $args ) {
+ $this->slug = sanitize_title( $slug );
+ if ( $this->slug !== $slug ) {
+ _doing_it_wrong(
+ __METHOD__,
+ /* translators: %s: Font collection slug. */
+ sprintf( __( 'Font collection slug "%s" is not valid. Slugs must use only alphanumeric characters, dashes, and underscores.' ), $slug ),
+ '6.5.0'
+ );
+ }
+
+ $required_properties = array( 'name', 'font_families' );
+
+ if ( isset( $args['font_families'] ) && is_string( $args['font_families'] ) ) {
+ // JSON data is lazy loaded by ::get_data().
+ $this->src = $args['font_families'];
+ unset( $args['font_families'] );
+
+ $required_properties = array( 'name' );
+ }
+
+ $this->data = $this->sanitize_and_validate_data( $args, $required_properties );
+ }
+
+ /**
+ * 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 ( is_wp_error( $this->data ) ) {
+ return $this->data;
+ }
+
+ // If the collection uses JSON data, load it and cache the data/error.
+ if ( isset( $this->src ) ) {
+ $this->data = $this->load_from_json( $this->src );
+ }
+
+ if ( is_wp_error( $this->data ) ) {
+ return $this->data;
+ }
+
+ // Set defaults for optional properties.
+ $defaults = array(
+ 'description' => '',
+ 'categories' => array(),
+ );
+
+ return wp_parse_args( $this->data, $defaults );
+ }
+
+ /**
+ * Loads font collection data from a JSON file or URL.
+ *
+ * @since 6.5.0
+ *
+ * @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.
+ */
+ private 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.' );
+ _doing_it_wrong( __METHOD__, $message, '6.5.0' );
+ return new WP_Error( 'font_collection_json_missing', $message );
+ }
+
+ $data = $url ? $this->load_from_url( $url ) : $this->load_from_file( $file );
+
+ if ( is_wp_error( $data ) ) {
+ return $data;
+ }
+
+ $data = array(
+ 'name' => $this->data['name'],
+ 'font_families' => $data['font_families'],
+ );
+
+ if ( isset( $this->data['description'] ) ) {
+ $data['description'] = $this->data['description'];
+ }
+
+ if ( isset( $this->data['categories'] ) ) {
+ $data['categories'] = $this->data['categories'];
+ }
+
+ return $data;
+ }
+
+ /**
+ * Loads the 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.
+ */
+ private function load_from_file( $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.' ) );
+ }
+
+ return $this->sanitize_and_validate_data( $data, array( 'font_families' ) );
+ }
+
+ /**
+ * Loads the 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.
+ */
+ private function load_from_url( $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 );
+
+ if ( false === $data ) {
+ $response = wp_safe_remote_get( $url );
+ if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
+ return new WP_Error(
+ 'font_collection_request_error',
+ sprintf(
+ // translators: %s: Font collection URL.
+ __( 'Error fetching the font collection data from "%s".' ),
+ $url
+ )
+ );
+ }
+
+ $data = json_decode( wp_remote_retrieve_body( $response ), true );
+ if ( empty( $data ) ) {
+ return new WP_Error( 'font_collection_decode_error', __( 'Error decoding the font collection data from the HTTP response JSON.' ) );
+ }
+
+ // Make sure the data is valid before storing it in a transient.
+ $data = $this->sanitize_and_validate_data( $data, array( 'font_families' ) );
+ if ( is_wp_error( $data ) ) {
+ return $data;
+ }
+
+ set_site_transient( $transient_key, $data, DAY_IN_SECONDS );
+ }
+
+ return $data;
+ }
+
+ /**
+ * Sanitizes and validates the font collection data.
+ *
+ * @since 6.5.0
+ *
+ * @param array $data Font collection data to sanitize and validate.
+ * @param array $required_properties Required properties that must exist in the passed data.
+ * @return array|WP_Error Sanitized data if valid, otherwise a WP_Error instance.
+ */
+ private function sanitize_and_validate_data( $data, $required_properties = array() ) {
+ $schema = self::get_sanitization_schema();
+ $data = WP_Font_Utils::sanitize_from_schema( $data, $schema );
+
+ foreach ( $required_properties as $property ) {
+ if ( empty( $data[ $property ] ) ) {
+ $message = sprintf(
+ // translators: 1: Font collection slug, 2: Missing property name, e.g. "font_families".
+ __( 'Font collection "%1$s" has missing or empty property: "%2$s".' ),
+ $this->slug,
+ $property
+ );
+ _doing_it_wrong( __METHOD__, $message, '6.5.0' );
+ return new WP_Error( 'font_collection_missing_property', $message );
+ }
+ }
+
+ return $data;
+ }
+
+ /**
+ * Retrieves the font collection sanitization schema.
+ *
+ * @since 6.5.0
+ *
+ * @return array Font collection sanitization schema.
+ */
+ private static function get_sanitization_schema() {
+ return array(
+ 'name' => 'sanitize_text_field',
+ 'description' => 'sanitize_text_field',
+ 'font_families' => array(
+ array(
+ 'font_family_settings' => array(
+ 'name' => 'sanitize_text_field',
+ 'slug' => static function ( $value ) {
+ return _wp_to_kebab_case( sanitize_title( $value ) );
+ },
+ 'fontFamily' => 'WP_Font_Utils::sanitize_font_family',
+ 'preview' => 'sanitize_url',
+ 'fontFace' => array(
+ array(
+ 'fontFamily' => 'sanitize_text_field',
+ 'fontStyle' => 'sanitize_text_field',
+ 'fontWeight' => 'sanitize_text_field',
+ 'src' => static function ( $value ) {
+ return is_array( $value )
+ ? array_map( 'sanitize_text_field', $value )
+ : sanitize_text_field( $value );
+ },
+ 'preview' => 'sanitize_url',
+ 'fontDisplay' => 'sanitize_text_field',
+ 'fontStretch' => 'sanitize_text_field',
+ 'ascentOverride' => 'sanitize_text_field',
+ 'descentOverride' => 'sanitize_text_field',
+ 'fontVariant' => 'sanitize_text_field',
+ 'fontFeatureSettings' => 'sanitize_text_field',
+ 'fontVariationSettings' => 'sanitize_text_field',
+ 'lineGapOverride' => 'sanitize_text_field',
+ 'sizeAdjust' => 'sanitize_text_field',
+ 'unicodeRange' => 'sanitize_text_field',
+ ),
+ ),
+ ),
+ 'categories' => array( 'sanitize_title' ),
+ ),
+ ),
+ 'categories' => array(
+ array(
+ 'name' => 'sanitize_text_field',
+ 'slug' => 'sanitize_title',
+ ),
+ ),
+ );
+ }
+}
diff --git a/wp-includes/fonts/class-wp-font-face-resolver.php b/wp-includes/fonts/class-wp-font-face-resolver.php
index 125ff6a..12245af 100644
--- a/wp-includes/fonts/class-wp-font-face-resolver.php
+++ b/wp-includes/fonts/class-wp-font-face-resolver.php
@@ -67,12 +67,7 @@ class WP_Font_Face_Resolver {
continue;
}
- // Prepare the fonts array structure for this font-family.
- if ( ! array_key_exists( $font_family_name, $fonts ) ) {
- $fonts[ $font_family_name ] = array();
- }
-
- $fonts[ $font_family_name ] = static::convert_font_face_properties( $definition['fontFace'], $font_family_name );
+ $fonts[] = static::convert_font_face_properties( $definition['fontFace'], $font_family_name );
}
}
diff --git a/wp-includes/fonts/class-wp-font-library.php b/wp-includes/fonts/class-wp-font-library.php
new file mode 100644
index 0000000..3069ecb
--- /dev/null
+++ b/wp-includes/fonts/class-wp-font-library.php
@@ -0,0 +1,142 @@
+<?php
+/**
+ * Font Library class.
+ *
+ * This file contains the Font Library class definition.
+ *
+ * @package WordPress
+ * @subpackage Fonts
+ * @since 6.5.0
+ */
+
+/**
+ * Font Library class.
+ *
+ * @since 6.5.0
+ */
+class WP_Font_Library {
+
+ /**
+ * Font collections.
+ *
+ * @since 6.5.0
+ * @var array
+ */
+ private $collections = array();
+
+ /**
+ * Container for the main instance of the class.
+ *
+ * @since 6.5.0
+ * @var WP_Font_Library|null
+ */
+ private static $instance = null;
+
+ /**
+ * Register a new font collection.
+ *
+ * @since 6.5.0
+ *
+ * @param string $slug Font collection slug. May only contain alphanumeric characters, dashes,
+ * and underscores. See sanitize_title().
+ * @param array $args Font collection data. See wp_register_font_collection() for information on accepted arguments.
+ * @return WP_Font_Collection|WP_Error A font collection if it was registered successfully,
+ * or WP_Error object on failure.
+ */
+ public function register_font_collection( string $slug, array $args ) {
+ $new_collection = new WP_Font_Collection( $slug, $args );
+
+ if ( $this->is_collection_registered( $new_collection->slug ) ) {
+ $error_message = sprintf(
+ /* translators: %s: Font collection slug. */
+ __( 'Font collection with slug: "%s" is already registered.' ),
+ $new_collection->slug
+ );
+ _doing_it_wrong(
+ __METHOD__,
+ $error_message,
+ '6.5.0'
+ );
+ return new WP_Error( 'font_collection_registration_error', $error_message );
+ }
+ $this->collections[ $new_collection->slug ] = $new_collection;
+ return $new_collection;
+ }
+
+ /**
+ * Unregisters a previously registered font collection.
+ *
+ * @since 6.5.0
+ *
+ * @param string $slug Font collection slug.
+ * @return bool True if the font collection was unregistered successfully and false otherwise.
+ */
+ public function unregister_font_collection( string $slug ) {
+ if ( ! $this->is_collection_registered( $slug ) ) {
+ _doing_it_wrong(
+ __METHOD__,
+ /* translators: %s: Font collection slug. */
+ sprintf( __( 'Font collection "%s" not found.' ), $slug ),
+ '6.5.0'
+ );
+ return false;
+ }
+ unset( $this->collections[ $slug ] );
+ return true;
+ }
+
+ /**
+ * Checks if a font collection is registered.
+ *
+ * @since 6.5.0
+ *
+ * @param string $slug Font collection slug.
+ * @return bool True if the font collection is registered and false otherwise.
+ */
+ private function is_collection_registered( string $slug ) {
+ return array_key_exists( $slug, $this->collections );
+ }
+
+ /**
+ * Gets all the font collections available.
+ *
+ * @since 6.5.0
+ *
+ * @return array List of font collections.
+ */
+ public function get_font_collections() {
+ return $this->collections;
+ }
+
+ /**
+ * Gets a font collection.
+ *
+ * @since 6.5.0
+ *
+ * @param string $slug Font collection slug.
+ * @return WP_Font_Collection|null Font collection object, or null if the font collection doesn't exist.
+ */
+ public function get_font_collection( string $slug ) {
+ if ( $this->is_collection_registered( $slug ) ) {
+ return $this->collections[ $slug ];
+ }
+ return null;
+ }
+
+ /**
+ * Utility method to retrieve the main instance of the class.
+ *
+ * The instance will be created if it does not exist yet.
+ *
+ * @since 6.5.0
+ *
+ * @return WP_Font_Library The main instance.
+ */
+ public static function get_instance() {
+ if ( null === self::$instance ) {
+ self::$instance = new self();
+ }
+
+ return self::$instance;
+ }
+}
diff --git a/wp-includes/fonts/class-wp-font-utils.php b/wp-includes/fonts/class-wp-font-utils.php
new file mode 100644
index 0000000..6e91440
--- /dev/null
+++ b/wp-includes/fonts/class-wp-font-utils.php
@@ -0,0 +1,259 @@
+<?php
+/**
+ * Font Utils class.
+ *
+ * Provides utility functions for working with font families.
+ *
+ * @package WordPress
+ * @subpackage Fonts
+ * @since 6.5.0
+ */
+
+/**
+ * A class of utilities for working with the Font Library.
+ *
+ * These utilities may change or be removed in the future and are intended for internal use only.
+ *
+ * @since 6.5.0
+ * @access private
+ */
+class WP_Font_Utils {
+ /**
+ * Adds surrounding quotes to font family names that contain special characters.
+ *
+ * It follows the recommendations from the CSS Fonts Module Level 4.
+ * @link https://www.w3.org/TR/css-fonts-4/#font-family-prop
+ *
+ * @since 6.5.0
+ *
+ * @param string $item A font family name.
+ * @return string The font family name with surrounding quotes, if necessary.
+ */
+ private static function maybe_add_quotes( $item ) {
+ // Matches strings that are not exclusively alphabetic characters or hyphens, and do not exactly follow the pattern generic(alphabetic characters or hyphens).
+ $regex = '/^(?!generic\([a-zA-Z\-]+\)$)(?!^[a-zA-Z\-]+$).+/';
+ $item = trim( $item );
+ if ( preg_match( $regex, $item ) ) {
+ $item = trim( $item, "\"'" );
+ return '"' . $item . '"';
+ }
+ return $item;
+ }
+
+ /**
+ * Sanitizes and formats font family names.
+ *
+ * - Applies `sanitize_text_field`.
+ * - Adds surrounding quotes to names containing any characters that are not alphabetic or dashes.
+ *
+ * It follows the recommendations from the CSS Fonts Module Level 4.
+ * @link https://www.w3.org/TR/css-fonts-4/#font-family-prop
+ *
+ * @since 6.5.0
+ * @access private
+ *
+ * @see sanitize_text_field()
+ *
+ * @param string $font_family Font family name(s), comma-separated.
+ * @return string Sanitized and formatted font family name(s).
+ */
+ public static function sanitize_font_family( $font_family ) {
+ if ( ! $font_family ) {
+ return '';
+ }
+
+ $output = sanitize_text_field( $font_family );
+ $formatted_items = array();
+ if ( str_contains( $output, ',' ) ) {
+ $items = explode( ',', $output );
+ foreach ( $items as $item ) {
+ $formatted_item = self::maybe_add_quotes( $item );
+ if ( ! empty( $formatted_item ) ) {
+ $formatted_items[] = $formatted_item;
+ }
+ }
+ return implode( ', ', $formatted_items );
+ }
+ return self::maybe_add_quotes( $output );
+ }
+
+ /**
+ * Generates a slug from font face properties, e.g. `open sans;normal;400;100%;U+0-10FFFF`
+ *
+ * Used for comparison with other font faces in the same family, to prevent duplicates
+ * that would both match according the CSS font matching spec. Uses only simple case-insensitive
+ * matching for fontFamily and unicodeRange, so does not handle overlapping font-family lists or
+ * unicode ranges.
+ *
+ * @since 6.5.0
+ * @access private
+ *
+ * @link https://drafts.csswg.org/css-fonts/#font-style-matching
+ *
+ * @param array $settings {
+ * Font face settings.
+ *
+ * @type string $fontFamily Font family name.
+ * @type string $fontStyle Optional font style, defaults to 'normal'.
+ * @type string $fontWeight Optional font weight, defaults to 400.
+ * @type string $fontStretch Optional font stretch, defaults to '100%'.
+ * @type string $unicodeRange Optional unicode range, defaults to 'U+0-10FFFF'.
+ * }
+ * @return string Font face slug.
+ */
+ public static function get_font_face_slug( $settings ) {
+ $defaults = array(
+ 'fontFamily' => '',
+ 'fontStyle' => 'normal',
+ 'fontWeight' => '400',
+ 'fontStretch' => '100%',
+ 'unicodeRange' => 'U+0-10FFFF',
+ );
+ $settings = wp_parse_args( $settings, $defaults );
+ if ( function_exists( 'mb_strtolower' ) ) {
+ $font_family = mb_strtolower( $settings['fontFamily'] );
+ } else {
+ $font_family = strtolower( $settings['fontFamily'] );
+ }
+ $font_style = strtolower( $settings['fontStyle'] );
+ $font_weight = strtolower( $settings['fontWeight'] );
+ $font_stretch = strtolower( $settings['fontStretch'] );
+ $unicode_range = strtoupper( $settings['unicodeRange'] );
+
+ // Convert weight keywords to numeric strings.
+ $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%',
+ 'condensed' => '75%',
+ 'semi-condensed' => '87.5%',
+ 'normal' => '100%',
+ 'semi-expanded' => '112.5%',
+ 'expanded' => '125%',
+ 'extra-expanded' => '150%',
+ 'ultra-expanded' => '200%',
+ );
+ $font_stretch = str_replace( array_keys( $font_stretch_map ), array_values( $font_stretch_map ), $font_stretch );
+
+ $slug_elements = array( $font_family, $font_style, $font_weight, $font_stretch, $unicode_range );
+
+ $slug_elements = array_map(
+ function ( $elem ) {
+ // Remove quotes to normalize font-family names, and ';' to use as a separator.
+ $elem = trim( str_replace( array( '"', "'", ';' ), '', $elem ) );
+
+ // Normalize comma separated lists by removing whitespace in between items,
+ // but keep whitespace within items (e.g. "Open Sans" and "OpenSans" are different fonts).
+ // CSS spec for whitespace includes: U+000A LINE FEED, U+0009 CHARACTER TABULATION, or U+0020 SPACE,
+ // which by default are all matched by \s in PHP.
+ return preg_replace( '/,\s+/', ',', $elem );
+ },
+ $slug_elements
+ );
+
+ return sanitize_text_field( implode( ';', $slug_elements ) );
+ }
+
+ /**
+ * Sanitizes a tree of data using a schema.
+ *
+ * The schema structure should mirror the data tree. Each value provided in the
+ * schema should be a callable that will be applied to sanitize the corresponding
+ * value in the data tree. Keys that are in the data tree, but not present in the
+ * schema, will be removed in the sanitized data. Nested arrays are traversed recursively.
+ *
+ * @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 ] ) && ! is_callable( $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;
+ }
+
+ /**
+ * Applies a sanitizer function to a value.
+ *
+ * @since 6.5.0
+ *
+ * @param mixed $value The value to sanitize.
+ * @param mixed $sanitizer The sanitizer function 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 );
+ }
+
+ /**
+ * Returns the expected mime-type values for font files, depending on PHP version.
+ *
+ * This is needed because font mime types vary by PHP version, so checking the PHP version
+ * is necessary until a list of valid mime-types for each file extension can be provided to
+ * the 'upload_mimes' filter.
+ *
+ * @since 6.5.0
+ *
+ * @access private
+ *
+ * @return array A collection of mime types keyed by file extension.
+ */
+ public static function get_allowed_font_mime_types() {
+ $php_7_ttf_mime_type = PHP_VERSION_ID >= 70300 ? 'application/font-sfnt' : 'application/x-font-ttf';
+
+ return array(
+ 'otf' => 'application/vnd.ms-opentype',
+ 'ttf' => PHP_VERSION_ID >= 70400 ? 'font/sfnt' : $php_7_ttf_mime_type,
+ 'woff' => PHP_VERSION_ID >= 80112 ? 'font/woff' : 'application/font-woff',
+ 'woff2' => PHP_VERSION_ID >= 80112 ? 'font/woff2' : 'application/font-woff2',
+ );
+ }
+}