diff --git a/lib/experimental/class-old-wp-webfonts.php b/lib/experimental/class-old-wp-webfonts.php
new file mode 100644
index 00000000000000..4c66383765db9f
--- /dev/null
+++ b/lib/experimental/class-old-wp-webfonts.php
@@ -0,0 +1,397 @@
+register_provider( 'local', 'WP_Webfonts_Provider_Local' );
+
+ // 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' ) );
+ }
+
+ /**
+ * Get the list of all fonts.
+ *
+ * @return array[]
+ */
+ public function get_all_webfonts() {
+ return array_merge( $this->get_registered_webfonts(), $this->get_enqueued_webfonts() );
+ }
+
+ /**
+ * Get the list of providers.
+ *
+ * @since 6.0.0
+ *
+ * @return WP_Webfonts_Provider[] All registered providers, each keyed by their unique ID.
+ */
+ public function get_providers() {
+ return $this->providers;
+ }
+
+ /**
+ * Register a webfont.
+ *
+ * @since 6.0.0
+ *
+ * @param array $webfont Webfont to be registered.
+ * @return string|false The font family slug if successfully registered, else false.
+ */
+ public function register_webfont( array $webfont ) {
+ $webfont = $this->validate_webfont( $webfont );
+
+ // If not valid, bail out.
+ if ( ! $webfont ) {
+ return false;
+ }
+
+ $slug = $this->get_font_slug( $webfont );
+
+ // Initialize a new font-family collection.
+ if ( ! isset( $this->registered_webfonts[ $slug ] ) ) {
+ $this->registered_webfonts[ $slug ] = array();
+ }
+
+ $this->registered_webfonts[ $slug ][] = $webfont;
+ return $slug;
+ }
+
+ /**
+ * Enqueue a font-family that has been already registered.
+ *
+ * @param string $font_family_name The font family name to be enqueued.
+ * @return bool True if successfully enqueued, else false.
+ */
+ public function enqueue_webfont( $font_family_name ) {
+ $slug = $this->get_font_slug( $font_family_name );
+
+ if ( isset( $this->enqueued_webfonts[ $slug ] ) ) {
+ return true;
+ }
+
+ if ( ! isset( $this->registered_webfonts[ $slug ] ) ) {
+ /* translators: %s unique slug to identify the font family of the webfont */
+ _doing_it_wrong( __METHOD__, sprintf( __( 'The "%s" font family is not registered.', 'gutenberg' ), $slug ), '6.0.0' );
+
+ return false;
+ }
+
+ $this->enqueued_webfonts[ $slug ] = $this->registered_webfonts[ $slug ];
+ unset( $this->registered_webfonts[ $slug ] );
+ return true;
+ }
+
+ /**
+ * Get the font slug.
+ *
+ * @since 6.0.0
+ *
+ * @param array|string $to_convert The value to convert into a slug. Expected as the web font's array
+ * or a font-family as a string.
+ * @return string|false The font slug on success, or false if the font-family cannot be determined.
+ */
+ public static function get_font_slug( $to_convert ) {
+ if ( is_array( $to_convert ) ) {
+ if ( isset( $to_convert['font-family'] ) ) {
+ $to_convert = $to_convert['font-family'];
+ } elseif ( isset( $to_convert['fontFamily'] ) ) {
+ $to_convert = $to_convert['fontFamily'];
+ } else {
+ _doing_it_wrong( __METHOD__, __( 'Could not determine the font family name.', 'gutenberg' ), '6.0.0' );
+ return false;
+ }
+ }
+
+ return sanitize_title( $to_convert );
+ }
+
+ /**
+ * Validate a webfont.
+ *
+ * @since 6.0.0
+ *
+ * @param array $webfont The webfont arguments.
+ *
+ * @return array|false The validated webfont arguments, or false if the webfont is invalid.
+ */
+ public function validate_webfont( $webfont ) {
+ $webfont = wp_parse_args(
+ $webfont,
+ array(
+ 'provider' => 'local',
+ 'font-family' => '',
+ 'font-style' => 'normal',
+ 'font-weight' => '400',
+ 'font-display' => 'fallback',
+ )
+ );
+
+ // Check the font-family.
+ if ( empty( $webfont['font-family'] ) || ! is_string( $webfont['font-family'] ) ) {
+ trigger_error( __( 'Webfont font family must be a non-empty string.', 'gutenberg' ) );
+ return false;
+ }
+
+ // Local fonts need a "src".
+ if ( 'local' === $webfont['provider'] ) {
+ // Make sure that local fonts have 'src' defined.
+ if ( empty( $webfont['src'] ) || ( ! is_string( $webfont['src'] ) && ! is_array( $webfont['src'] ) ) ) {
+ trigger_error( __( 'Webfont src must be a non-empty string or an array of strings.', 'gutenberg' ) );
+ return false;
+ }
+ }
+
+ // Validate the 'src' property.
+ if ( ! empty( $webfont['src'] ) ) {
+ foreach ( (array) $webfont['src'] as $src ) {
+ if ( empty( $src ) || ! is_string( $src ) ) {
+ trigger_error( __( 'Each webfont src must be a non-empty string.', 'gutenberg' ) );
+ return false;
+ }
+ }
+ }
+
+ // Check the font-weight.
+ if ( ! is_string( $webfont['font-weight'] ) && ! is_int( $webfont['font-weight'] ) ) {
+ trigger_error( __( 'Webfont font weight must be a properly formatted string or integer.', 'gutenberg' ) );
+ return false;
+ }
+
+ // Check the font-display.
+ if ( ! in_array( $webfont['font-display'], array( 'auto', 'block', 'fallback', 'swap' ), true ) ) {
+ $webfont['font-display'] = 'fallback';
+ }
+
+ $valid_props = array(
+ 'ascend-override',
+ 'descend-override',
+ 'font-display',
+ 'font-family',
+ 'font-stretch',
+ 'font-style',
+ 'font-weight',
+ 'font-variant',
+ 'font-feature-settings',
+ 'font-variation-settings',
+ 'line-gap-override',
+ 'size-adjust',
+ 'src',
+ 'unicode-range',
+
+ // Exceptions.
+ 'provider',
+ );
+
+ foreach ( $webfont as $prop => $value ) {
+ if ( ! in_array( $prop, $valid_props, true ) ) {
+ unset( $webfont[ $prop ] );
+ }
+ }
+
+ return $webfont;
+ }
+
+ /**
+ * Register a provider.
+ *
+ * @since 6.0.0
+ *
+ * @param string $provider The provider name.
+ * @param string $class The provider class name.
+ * @return bool True if successfully registered, else false.
+ */
+ public function register_provider( $provider, $class ) {
+ if ( empty( $provider ) || empty( $class ) ) {
+ return false;
+ }
+ $this->providers[ $provider ] = $class;
+ return true;
+ }
+
+ /**
+ * Generate and enqueue webfonts styles.
+ *
+ * @since 6.0.0
+ */
+ public function generate_and_enqueue_styles() {
+ // Generate the styles.
+ $webfonts = $this->get_webfonts_by_provider( $this->get_enqueued_webfonts() );
+ $styles = $this->generate_styles( $webfonts );
+
+ // 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 6.0.0
+ */
+ public function generate_and_enqueue_editor_styles() {
+ // Generate the styles.
+ $webfonts = $this->get_webfonts_by_provider( $this->get_all_webfonts() );
+ $styles = $this->generate_styles( $webfonts );
+
+ // Bail out if there are no styles to enqueue.
+ if ( '' === $styles ) {
+ return;
+ }
+
+ wp_enqueue_style( 'wp-block-library' );
+ wp_add_inline_style( 'wp-block-library', $styles );
+ }
+
+ /**
+ * Generate styles for webfonts.
+ *
+ * @since 6.0.0
+ *
+ * @param array[] $webfonts_by_provider Webfonts organized by provider.
+ * @return string $styles Generated styles.
+ */
+ private function generate_styles( array $webfonts_by_provider ) {
+ $styles = '';
+ $providers = $this->get_providers();
+
+ /*
+ * 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_class ) {
+
+ // Bail out if the provider class does not exist.
+ if ( ! class_exists( $provider_class ) ) {
+ /* translators: %s is the provider name. */
+ trigger_error( sprintf( __( 'Webfont provider "%s" is not registered.', 'gutenberg' ), $provider_id ) );
+ continue;
+ }
+
+ $provider_webfonts = isset( $webfonts_by_provider[ $provider_id ] )
+ ? $webfonts_by_provider[ $provider_id ]
+ : array();
+
+ // If there are no registered webfonts for this provider, skip it.
+ if ( empty( $provider_webfonts ) ) {
+ continue;
+ }
+
+ /*
+ * Process the webfonts by first passing them to the provider via `set_webfonts()`
+ * and then getting the CSS from the provider.
+ */
+ $provider = new $provider_class();
+ $provider->set_webfonts( $provider_webfonts );
+ $styles .= $provider->get_css();
+ }
+
+ return $styles;
+ }
+
+
+ /**
+ * Reorganizes webfonts grouped by font-family into grouped by provider.
+ *
+ * @param array[] $font_families Font families and each of their webfonts.
+ * @return array[] Webfonts organized by providers.
+ */
+ private function get_webfonts_by_provider( array $font_families ) {
+ $providers = $this->get_providers();
+ $webfonts_by_provider = array();
+
+ foreach ( $font_families as $webfonts ) {
+ foreach ( $webfonts as $webfont ) {
+ $provider = $webfont['provider'];
+
+ // Skip if the provider is not registered.
+ if ( ! isset( $providers[ $provider ] ) ) {
+ /* translators: %s is the provider name. */
+ trigger_error( sprintf( __( 'Webfont provider "%s" is not registered.', 'gutenberg' ), $provider ) );
+ continue;
+ }
+
+ // Initialize a new provider collection.
+ if ( ! isset( $webfonts_by_provider[ $provider ] ) ) {
+ $webfonts_by_provider[ $provider ] = array();
+ }
+ $webfonts_by_provider[ $provider ][] = $webfont;
+ }
+ }
+
+ return $webfonts_by_provider;
+ }
+}
diff --git a/lib/experimental/class-wp-webfonts.php b/lib/experimental/class-wp-webfonts.php
index e422f51658befb..4341d341f3294d 100644
--- a/lib/experimental/class-wp-webfonts.php
+++ b/lib/experimental/class-wp-webfonts.php
@@ -1,38 +1,6 @@
register_provider( 'local', 'WP_Webfonts_Provider_Local' );
-
- // 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' ) );
+ public function __construct() {
+ /**
+ * Fires when the WP_Webfonts instance is initialized.
+ *
+ * @since X.X.X
+ *
+ * @param WP_Webfonts $wp_webfonts WP_Webfonts instance (passed by reference).
+ */
+ do_action_ref_array( 'wp_default_webfonts', array( &$this ) );
}
/**
- * Get the list of registered fonts.
+ * Get the list of all registered web fonts and variations.
*
* @since 6.0.0
*
- * @return array[]
+ * @return strings[]
*/
- public function get_registered_webfonts() {
- return $this->registered_webfonts;
+ public function get_registered() {
+ return array_keys( $this->registered );
}
/**
- * Get the list of enqueued fonts.
+ * Get the list of enqueued web fonts and variations.
*
* @return array[]
*/
- public function get_enqueued_webfonts() {
- return $this->enqueued_webfonts;
+ public function get_enqueued() {
+ return $this->queue;
}
/**
- * Get the list of all fonts.
+ * Gets a list of all variations registered for a font family.
*
- * @return array[]
+ * @param $font_family
+ * @return array
*/
- public function get_all_webfonts() {
- return array_merge( $this->get_registered_webfonts(), $this->get_enqueued_webfonts() );
+ public function get_variations( $font_family ) {
+ $font_family_handle = sanitize_title( $font_family );
+
+ if ( ! isset( $this->registered[ $font_family_handle ] ) ) {
+ return array();
+ }
+
+ return $this->registered[ $font_family_handle ]->deps;
}
/**
- * Get the list of providers.
- *
- * @since 6.0.0
+ * Removes a font family and all registered variations.
*
- * @return WP_Webfonts_Provider[] All registered providers, each keyed by their unique ID.
+ * @param mixed|string|string[] $font_family
*/
- public function get_providers() {
- return $this->providers;
+ function remove_family( $font_family ) {
+ $font_family_handle = sanitize_title( $font_family );
+
+ if ( ! isset( $this->registered[ $font_family_handle ] ) ) {
+ return;
+ }
+
+ $variations = $this->registered[ $font_family_handle ]->deps;
+
+ foreach ( $variations as $variation ) {
+ $this->remove( $variation );
+ }
+
+ $this->remove( $font_family_handle );
}
/**
- * Register a webfont.
+ * Removes a variation.
*
- * @since 6.0.0
- *
- * @param array $webfont Webfont to be registered.
- * @return string|false The font family slug if successfully registered, else false.
+ * @param $font_family
+ * @param $variation_handle
*/
- public function register_webfont( array $webfont ) {
- $webfont = $this->validate_webfont( $webfont );
-
- // If not valid, bail out.
- if ( ! $webfont ) {
- return false;
- }
+ function remove_variation( $font_family, $variation_handle ) {
+ $font_family_handle = sanitize_title( $font_family );
- $slug = $this->get_font_slug( $webfont );
+ $this->remove( $variation_handle );
- // Initialize a new font-family collection.
- if ( ! isset( $this->registered_webfonts[ $slug ] ) ) {
- $this->registered_webfonts[ $slug ] = array();
+ if ( ! isset( $this->registered[ $font_family_handle ] ) ) {
+ return;
}
- $this->registered_webfonts[ $slug ][] = $webfont;
- return $slug;
+ // Remove the variation as a dependency.
+ $this->registered[ $font_family_handle ]->deps = array_values( array_diff(
+ $this->registered[ $font_family_handle ]->deps,
+ array( $variation_handle )
+ ) );
}
/**
- * Enqueue a font-family that has been already registered.
+ * Registers a variation for a font family.
*
- * @param string $font_family_name The font family name to be enqueued.
- * @return bool True if successfully enqueued, else false.
+ * @param string $font_family
+ * @param string $variation_handle
+ * @param array $variation
*/
- public function enqueue_webfont( $font_family_name ) {
- $slug = $this->get_font_slug( $font_family_name );
+ public function add_variation( $font_family, $variation_handle, $variation ) {
+ $font_family_handle = sanitize_title( $font_family );
- if ( isset( $this->enqueued_webfonts[ $slug ] ) ) {
- return true;
+ // Register the font family when it does not yet exist.
+ if ( ! isset( $this->registered[ $font_family ] ) ) {
+ $this->add( $font_family_handle, false );
}
- if ( ! isset( $this->registered_webfonts[ $slug ] ) ) {
- /* translators: %s unique slug to identify the font family of the webfont */
- _doing_it_wrong( __METHOD__, sprintf( __( 'The "%s" font family is not registered.', 'gutenberg' ), $slug ), '6.0.0' );
+ $variation = $this->validate_variation( $font_family, $variation );
+ // Variation validation failed.
+ if ( ! $variation ) {
return false;
}
- $this->enqueued_webfonts[ $slug ] = $this->registered_webfonts[ $slug ];
- unset( $this->registered_webfonts[ $slug ] );
- return true;
+ $variation_handle = $font_family_handle . '-' . $variation_handle;
+
+ if ( $variation['src'] ) {
+ $result = $this->add( $variation_handle, $variation['src'], array(), false, array( 'font-properties' => $variation ) );
+ } else {
+ $result = $this->add( $variation_handle, false, array(), false, array( 'font-properties' => $variation ) );
+ }
+
+ if ( $result ) {
+ $this->providers[ $variation['provider'] ]['fonts'][] = $variation_handle;
+ }
+
+ return $result;
}
/**
- * Get the font slug.
- *
- * @since 6.0.0
+ * Adds a variation as a dependency for the main font alias.
*
- * @param array|string $to_convert The value to convert into a slug. Expected as the web font's array
- * or a font-family as a string.
- * @return string|false The font slug on success, or false if the font-family cannot be determined.
+ * @param $font_family_handle
+ * @param $variation_handle
*/
- public static function get_font_slug( $to_convert ) {
- if ( is_array( $to_convert ) ) {
- if ( isset( $to_convert['font-family'] ) ) {
- $to_convert = $to_convert['font-family'];
- } elseif ( isset( $to_convert['fontFamily'] ) ) {
- $to_convert = $to_convert['fontFamily'];
- } else {
- _doing_it_wrong( __METHOD__, __( 'Could not determine the font family name.', 'gutenberg' ), '6.0.0' );
- return false;
- }
- }
-
- return sanitize_title( $to_convert );
+ public function add_dependency( $font_family_handle, $variation_handle ) {
+ $this->registered[ $font_family_handle ]->deps[] = $variation_handle;
}
/**
- * Validate a webfont.
+ * Validates and sanitizes a variation.
*
- * @since 6.0.0
- *
- * @param array $webfont The webfont arguments.
- *
- * @return array|false The validated webfont arguments, or false if the webfont is invalid.
+ * @param $font_family
+ * @param $variation
+ * @return array|false|object
*/
- public function validate_webfont( $webfont ) {
- $webfont = wp_parse_args(
- $webfont,
- array(
- 'provider' => 'local',
- 'font-family' => '',
- 'font-style' => 'normal',
- 'font-weight' => '400',
- 'font-display' => 'fallback',
- )
+ function validate_variation( $font_family, $variation ) {
+ $defaults = array(
+ 'provider' => 'local',
+ 'font-style' => 'normal',
+ 'font-weight' => '400',
+ 'font-display' => 'fallback',
);
- // Check the font-family.
- if ( empty( $webfont['font-family'] ) || ! is_string( $webfont['font-family'] ) ) {
- trigger_error( __( 'Webfont font family must be a non-empty string.', 'gutenberg' ) );
- return false;
- }
+ $defaults = apply_filters( 'wp_web_font_variation_defaults', $defaults );
+
+ $defaults['font-family'] = $font_family;
+ $variation = wp_parse_args( $variation, $defaults );
// Local fonts need a "src".
- if ( 'local' === $webfont['provider'] ) {
+ if ( 'local' === $variation['provider'] ) {
// Make sure that local fonts have 'src' defined.
- if ( empty( $webfont['src'] ) || ( ! is_string( $webfont['src'] ) && ! is_array( $webfont['src'] ) ) ) {
+ if ( empty( $variation['src'] ) || ( ! is_string( $variation['src'] ) && ! is_array( $variation['src'] ) ) ) {
trigger_error( __( 'Webfont src must be a non-empty string or an array of strings.', 'gutenberg' ) );
return false;
}
+ } elseif ( ! class_exists( $variation['provider'] ) ) {
+ trigger_error( __( 'The provider class specified does not exist.', 'gutenberg' ) );
+ return false;
}
// Validate the 'src' property.
- if ( ! empty( $webfont['src'] ) ) {
- foreach ( (array) $webfont['src'] as $src ) {
+ if ( ! empty( $variation['src'] ) ) {
+ foreach ( (array) $variation['src'] as $src ) {
if ( empty( $src ) || ! is_string( $src ) ) {
trigger_error( __( 'Each webfont src must be a non-empty string.', 'gutenberg' ) );
return false;
@@ -238,14 +194,14 @@ public function validate_webfont( $webfont ) {
}
// Check the font-weight.
- if ( ! is_string( $webfont['font-weight'] ) && ! is_int( $webfont['font-weight'] ) ) {
+ if ( ! is_string( $variation['font-weight'] ) && ! is_int( $variation['font-weight'] ) ) {
trigger_error( __( 'Webfont font weight must be a properly formatted string or integer.', 'gutenberg' ) );
return false;
}
// Check the font-display.
- if ( ! in_array( $webfont['font-display'], array( 'auto', 'block', 'fallback', 'swap' ), true ) ) {
- $webfont['font-display'] = 'fallback';
+ if ( ! in_array( $variation['font-display'], array( 'auto', 'block', 'fallback', 'swap' ), true ) ) {
+ $variation['font-display'] = 'fallback';
}
$valid_props = array(
@@ -268,72 +224,13 @@ public function validate_webfont( $webfont ) {
'provider',
);
- foreach ( $webfont as $prop => $value ) {
+ foreach ( $variation as $prop => $value ) {
if ( ! in_array( $prop, $valid_props, true ) ) {
- unset( $webfont[ $prop ] );
+ unset( $variation[ $prop ] );
}
}
- return $webfont;
- }
-
- /**
- * Register a provider.
- *
- * @since 6.0.0
- *
- * @param string $provider The provider name.
- * @param string $class The provider class name.
- * @return bool True if successfully registered, else false.
- */
- public function register_provider( $provider, $class ) {
- if ( empty( $provider ) || empty( $class ) ) {
- return false;
- }
- $this->providers[ $provider ] = $class;
- return true;
- }
-
- /**
- * Generate and enqueue webfonts styles.
- *
- * @since 6.0.0
- */
- public function generate_and_enqueue_styles() {
- // Generate the styles.
- $webfonts = $this->get_webfonts_by_provider( $this->get_enqueued_webfonts() );
- $styles = $this->generate_styles( $webfonts );
-
- // 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 6.0.0
- */
- public function generate_and_enqueue_editor_styles() {
- // Generate the styles.
- $webfonts = $this->get_webfonts_by_provider( $this->get_all_webfonts() );
- $styles = $this->generate_styles( $webfonts );
-
- // Bail out if there are no styles to enqueue.
- if ( '' === $styles ) {
- return;
- }
-
- wp_enqueue_style( 'wp-block-library' );
- wp_add_inline_style( 'wp-block-library', $styles );
+ return $variation;
}
/**
@@ -344,74 +241,101 @@ public function generate_and_enqueue_editor_styles() {
* @param array[] $webfonts_by_provider Webfonts organized by provider.
* @return string $styles Generated styles.
*/
- private function generate_styles( array $webfonts_by_provider ) {
+ public function do_item( $handle, $group = false ) {
+ if ( ! parent::do_item( $handle ) ) {
+ return false;
+ }
+
$styles = '';
$providers = $this->get_providers();
+ $obj = $this->registered[ $handle ];
+
/*
* 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_class ) {
-
+ foreach ( $providers as $provider_id => $provider ) {
// Bail out if the provider class does not exist.
- if ( ! class_exists( $provider_class ) ) {
+ if ( ! class_exists( $provider['class'] ) ) {
/* translators: %s is the provider name. */
trigger_error( sprintf( __( 'Webfont provider "%s" is not registered.', 'gutenberg' ), $provider_id ) );
continue;
}
- $provider_webfonts = isset( $webfonts_by_provider[ $provider_id ] )
- ? $webfonts_by_provider[ $provider_id ]
- : array();
+ $fonts = $this->get_enqueued_fonts_for_provider( $provider_id );
// If there are no registered webfonts for this provider, skip it.
- if ( empty( $provider_webfonts ) ) {
+ if ( empty( $fonts ) ) {
continue;
}
+ $provider_fonts = array();
+
+ foreach ( $fonts as $font_handle ) {
+ $provider_fonts[ $font_handle ] = $this->get_data( $font_handle, 'font-properties' );
+ }
+
/*
* Process the webfonts by first passing them to the provider via `set_webfonts()`
* and then getting the CSS from the provider.
*/
- $provider = new $provider_class();
- $provider->set_webfonts( $provider_webfonts );
+ $provider = new $provider['class']();
+ $provider->set_webfonts( $provider_fonts );
$styles .= $provider->get_css();
}
return $styles;
}
+ /**
+ * Register a provider.
+ *
+ * @since 6.0.0
+ *
+ * @param string $provider The provider name.
+ * @param string $class The provider class name.
+ * @return bool True if successfully registered, else false.
+ */
+ public function register_provider( $provider, $class ) {
+ if ( empty( $provider ) || empty( $class ) || ! class_exists( $class ) ) {
+ return false;
+ }
+
+ $this->providers[ $provider ] = array(
+ 'class' => $class,
+ 'fonts' => array(),
+ );
+ return true;
+ }
/**
- * Reorganizes webfonts grouped by font-family into grouped by provider.
+ * Get the list of providers.
+ *
+ * @since 6.0.0
+ *
+ * @return WP_Webfonts_Provider[] All registered providers, each keyed by their unique ID.
+ */
+ public function get_providers() {
+ return $this->providers;
+ }
+
+ /**
+ * Retrieves a list of enqueued web font variations for a provider.
*
- * @param array[] $font_families Font families and each of their webfonts.
* @return array[] Webfonts organized by providers.
*/
- private function get_webfonts_by_provider( array $font_families ) {
- $providers = $this->get_providers();
- $webfonts_by_provider = array();
-
- foreach ( $font_families as $webfonts ) {
- foreach ( $webfonts as $webfont ) {
- $provider = $webfont['provider'];
-
- // Skip if the provider is not registered.
- if ( ! isset( $providers[ $provider ] ) ) {
- /* translators: %s is the provider name. */
- trigger_error( sprintf( __( 'Webfont provider "%s" is not registered.', 'gutenberg' ), $provider ) );
- continue;
- }
+ private function get_enqueued_fonts_for_provider( $provider ) {
+ $providers = $this->get_providers();
- // Initialize a new provider collection.
- if ( ! isset( $webfonts_by_provider[ $provider ] ) ) {
- $webfonts_by_provider[ $provider ] = array();
- }
- $webfonts_by_provider[ $provider ][] = $webfont;
- }
+ if ( empty( $providers[ $provider ] ) ) {
+ return array();
}
- return $webfonts_by_provider;
+ return array_intersect(
+ $providers[ $provider ]['fonts'],
+ $this->get_enqueued()
+ );
}
+
}
diff --git a/lib/experimental/register-webfonts-from-theme-json.php b/lib/experimental/register-webfonts-from-theme-json.php
index 576d74ab0c56b0..358e18a3881e4c 100644
--- a/lib/experimental/register-webfonts-from-theme-json.php
+++ b/lib/experimental/register-webfonts-from-theme-json.php
@@ -5,173 +5,180 @@
* @package gutenberg
*/
-/**
- * Register webfonts defined in theme.json.
- */
-function gutenberg_register_webfonts_from_theme_json() {
- // Get settings.
- $settings = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data()->get_settings();
-
- // If in the editor, add webfonts defined in variations.
- if ( is_admin() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) {
- $variations = WP_Theme_JSON_Resolver_Gutenberg::get_style_variations();
-
- foreach ( $variations as $variation ) {
-
- // Sanity check: Skip if fontFamilies are not defined in the variation.
- if (
- empty( $variation['settings'] ) ||
- empty( $variation['settings']['typography'] ) ||
- empty( $variation['settings']['typography']['fontFamilies'] )
- ) {
- continue;
- }
+if ( ! function_exists( 'gutenberg_register_webfonts_from_theme_json' ) ) {
+ /**
+ * Register webfonts defined in theme.json.
+ */
+ function gutenberg_register_webfonts_from_theme_json() {
+ // Get settings.
+ $settings = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data()->get_settings();
- // Merge the variation settings with the global settings.
- $settings['typography'] = empty( $settings['typography'] ) ? array() : $settings['typography'];
- $settings['typography']['fontFamilies'] = empty( $settings['typography']['fontFamilies'] ) ? array() : $settings['typography']['fontFamilies'];
- $settings['typography']['fontFamilies']['theme'] = empty( $settings['typography']['fontFamilies'] ) ? array() : $settings['typography']['fontFamilies']['theme'];
- $settings['typography']['fontFamilies']['theme'] = array_merge( $settings['typography']['fontFamilies']['theme'], $variation['settings']['typography']['fontFamilies']['theme'] );
+ // If in the editor, add webfonts defined in variations.
+ if ( is_admin() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) {
+ $variations = WP_Theme_JSON_Resolver_Gutenberg::get_style_variations();
- // Make sure there are no duplicates.
- $settings['typography']['fontFamilies'] = array_unique( $settings['typography']['fontFamilies'] );
- }
- }
+ foreach ( $variations as $variation ) {
- // Bail out early if there are no settings for webfonts.
- if ( empty( $settings['typography'] ) || empty( $settings['typography']['fontFamilies'] ) ) {
- return;
- }
-
- $webfonts = array();
+ // Sanity check: Skip if fontFamilies are not defined in the variation.
+ if ( empty( $variation['settings'] ) || empty( $variation['settings']['typography'] ) || empty( $variation['settings']['typography']['fontFamilies'] ) ) {
+ continue;
+ }
- // Look for fontFamilies.
- foreach ( $settings['typography']['fontFamilies'] as $font_families ) {
- foreach ( $font_families as $font_family ) {
+ // Merge the variation settings with the global settings.
+ $settings['typography'] = empty( $settings['typography'] ) ? array() : $settings['typography'];
+ $settings['typography']['fontFamilies'] = empty( $settings['typography']['fontFamilies'] ) ? array() : $settings['typography']['fontFamilies'];
+ $settings['typography']['fontFamilies']['theme'] = empty( $settings['typography']['fontFamilies'] ) ? array() : $settings['typography']['fontFamilies']['theme'];
+ $settings['typography']['fontFamilies']['theme'] = array_merge( $settings['typography']['fontFamilies']['theme'], $variation['settings']['typography']['fontFamilies']['theme'] );
- // Skip if fontFace is not defined.
- if ( empty( $font_family['fontFace'] ) ) {
- continue;
+ // Make sure there are no duplicates.
+ $settings['typography']['fontFamilies'] = array_unique( $settings['typography']['fontFamilies'] );
}
+ }
+
+ // Bail out early if there are no settings for webfonts.
+ if ( empty( $settings['typography'] ) || empty( $settings['typography']['fontFamilies'] ) ) {
+ return;
+ }
+
+ $webfonts = array();
- $font_family['fontFace'] = (array) $font_family['fontFace'];
+ // Look for fontFamilies.
+ foreach ( $settings['typography']['fontFamilies'] as $font_families ) {
+ foreach ( $font_families as $font_family ) {
- foreach ( $font_family['fontFace'] as $font_face ) {
- // Skip if the webfont was registered through the Webfonts API.
- if ( isset( $font_face['origin'] ) && 'gutenberg_wp_webfonts_api' === $font_face['origin'] ) {
+ // Skip if fontFace is not defined.
+ if ( empty( $font_family['fontFace'] ) ) {
continue;
}
- // Check if webfonts have a "src" param, and if they do account for the use of "file:./".
- if ( ! empty( $font_face['src'] ) ) {
- $font_face['src'] = (array) $font_face['src'];
+ $font_family['fontFace'] = (array) $font_family['fontFace'];
+
+ foreach ( $font_family['fontFace'] as $font_face ) {
+ // Skip if the webfont was registered through the Webfonts API.
+ if ( isset( $font_face['origin'] ) && 'gutenberg_wp_webfonts_api' === $font_face['origin'] ) {
+ continue;
+ }
- foreach ( $font_face['src'] as $src_key => $url ) {
- // Tweak the URL to be relative to the theme root.
- if ( ! str_starts_with( $url, 'file:./' ) ) {
- continue;
+ // Check if webfonts have a "src" param, and if they do account for the use of "file:./".
+ if ( ! empty( $font_face['src'] ) ) {
+ $font_face['src'] = (array) $font_face['src'];
+
+ foreach ( $font_face['src'] as $src_key => $url ) {
+ // Tweak the URL to be relative to the theme root.
+ if ( ! str_starts_with( $url, 'file:./' ) ) {
+ continue;
+ }
+ $font_face['src'][ $src_key ] = get_theme_file_uri( str_replace( 'file:./', '', $url ) );
}
- $font_face['src'][ $src_key ] = get_theme_file_uri( str_replace( 'file:./', '', $url ) );
}
- }
- // Convert keys to kebab-case.
- foreach ( $font_face as $property => $value ) {
- $kebab_case = _wp_to_kebab_case( $property );
- $font_face[ $kebab_case ] = $value;
- if ( $kebab_case !== $property ) {
- unset( $font_face[ $property ] );
+ // Convert keys to kebab-case.
+ foreach ( $font_face as $property => $value ) {
+ $kebab_case = _wp_to_kebab_case( $property );
+ $font_face[ $kebab_case ] = $value;
+ if ( $kebab_case !== $property ) {
+ unset( $font_face[ $property ] );
+ }
}
- }
- $webfonts[] = $font_face;
+ $webfonts[] = $font_face;
+ }
}
}
- }
- foreach ( $webfonts as $webfont ) {
- wp_webfonts()->register_webfont( $webfont );
- }
- foreach ( $webfonts as $webfont ) {
- wp_webfonts()->enqueue_webfont( $webfont['font-family'] );
- }
-}
-/**
- * Add missing fonts data to the global styles.
- *
- * @param array $data The global styles.
- * @return array The global styles with missing fonts data.
- */
-function gutenberg_add_registered_webfonts_to_theme_json( $data ) {
- $font_families_registered = wp_webfonts()->get_all_webfonts();
- $font_families_from_theme = array();
- if ( ! empty( $data['settings'] ) && ! empty( $data['settings']['typography'] ) && ! empty( $data['settings']['typography']['fontFamilies'] ) ) {
- $font_families_from_theme = $data['settings']['typography']['fontFamilies'];
+ $to_enqueue = array();
+
+ foreach ( $webfonts as $webfont ) {
+ $font_family_handle = sanitize_title( $webfont['font-family'] );
+
+ wp_register_web_font_family( $font_family_handle );
+
+ $variation_handle = sanitize_title( implode( ' ', array( $webfont['font-weight'], $webfont['font-style'] ) ) );
+ wp_register_web_font_variation( $font_family_handle, $variation_handle, $webfont );
+ $to_enqueue[] = $font_family_handle;
+ }
+
+ foreach ( $to_enqueue as $font_family ) {
+ wp_webfonts()->enqueue( $font_family );
+ }
}
+}
+if ( ! function_exists( 'gutenberg_add_registered_webfonts_to_theme_json' ) ) {
/**
- * Helper to get an array of the font-families.
+ * Add missing fonts data to the global styles.
*
- * @param array $families_data The font-families data.
- * @return array The font-families array.
+ * @param array $data The global styles.
+ * @return array The global styles with missing fonts data.
*/
- $get_families = static function( $families_data ) {
- $families = array();
- foreach ( $families_data as $family ) {
- $families[] = WP_Webfonts::get_font_slug( $family );
+ function gutenberg_add_registered_webfonts_to_theme_json( $data ) {
+ $font_families_registered = wp_webfonts()->get_all_webfonts();
+ $font_families_from_theme = array();
+ if ( ! empty( $data['settings'] ) && ! empty( $data['settings']['typography'] ) && ! empty( $data['settings']['typography']['fontFamilies'] ) ) {
+ $font_families_from_theme = $data['settings']['typography']['fontFamilies'];
}
- // Micro-optimization: Use array_flip( array_flip( $array ) )
- // instead of array_unique( $array ) because it's faster.
- // The result is the same.
- return array_flip( array_flip( $families ) );
- };
+ /**
+ * Helper to get an array of the font-families.
+ *
+ * @param array $families_data The font-families data.
+ * @return array The font-families array.
+ */
+ $get_families = static function ( $families_data ) {
+ $families = array();
+ foreach ( $families_data as $family ) {
+ $families[] = WP_Webfonts::get_font_slug( $family );
+ }
- // Diff the arrays to find the missing fonts.
- $to_add = array_diff(
- array_keys( $font_families_registered ),
- $get_families( $font_families_from_theme )
- );
+ // Micro-optimization: Use array_flip( array_flip( $array ) )
+ // instead of array_unique( $array ) because it's faster.
+ // The result is the same.
+ return array_flip( array_flip( $families ) );
+ };
- // Bail out early if there are no missing fonts.
- if ( empty( $to_add ) ) {
- return $data;
- }
+ // Diff the arrays to find the missing fonts.
+ $to_add = array_diff( array_keys( $font_families_registered ), $get_families( $font_families_from_theme ) );
- // Make sure the path to settings.typography.fontFamilies.theme exists
- // before adding missing fonts.
- if ( empty( $data['settings'] ) ) {
- $data['settings'] = array();
- }
- if ( empty( $data['settings']['typography'] ) ) {
- $data['settings']['typography'] = array();
- }
- if ( empty( $data['settings']['typography']['fontFamilies'] ) ) {
- $data['settings']['typography']['fontFamilies'] = array();
- }
+ // Bail out early if there are no missing fonts.
+ if ( empty( $to_add ) ) {
+ return $data;
+ }
+
+ // Make sure the path to settings.typography.fontFamilies.theme exists
+ // before adding missing fonts.
+ if ( empty( $data['settings'] ) ) {
+ $data['settings'] = array();
+ }
+ if ( empty( $data['settings']['typography'] ) ) {
+ $data['settings']['typography'] = array();
+ }
+ if ( empty( $data['settings']['typography']['fontFamilies'] ) ) {
+ $data['settings']['typography']['fontFamilies'] = array();
+ }
- foreach ( $to_add as $slug ) {
- $font_faces_for_family = $font_families_registered[ $slug ];
- $family_name = $font_faces_for_family[0]['font-family'];
- $font_faces = array();
+ foreach ( $to_add as $slug ) {
+ $font_faces_for_family = $font_families_registered[ $slug ];
+ $family_name = $font_faces_for_family[0]['font-family'];
+ $font_faces = array();
- foreach ( $font_faces_for_family as $font_face ) {
- $camel_cased = array( 'origin' => 'gutenberg_wp_webfonts_api' );
- foreach ( $font_face as $key => $value ) {
- $camel_cased[ lcfirst( str_replace( '-', '', ucwords( $key, '-' ) ) ) ] = $value;
+ foreach ( $font_faces_for_family as $font_face ) {
+ $camel_cased = array( 'origin' => 'gutenberg_wp_webfonts_api' );
+ foreach ( $font_face as $key => $value ) {
+ $camel_cased[ lcfirst( str_replace( '-', '', ucwords( $key, '-' ) ) ) ] = $value;
+ }
+ $font_faces[] = $camel_cased;
}
- $font_faces[] = $camel_cased;
+
+ $data['settings']['typography']['fontFamilies'][] = array(
+ 'fontFamily' => str_contains( $family_name, ' ' ) ? "'{$family_name}'" : $family_name,
+ 'name' => $family_name,
+ 'slug' => $slug,
+ 'fontFace' => $font_faces,
+ );
}
- $data['settings']['typography']['fontFamilies'][] = array(
- 'fontFamily' => str_contains( $family_name, ' ' ) ? "'{$family_name}'" : $family_name,
- 'name' => $family_name,
- 'slug' => $slug,
- 'fontFace' => $font_faces,
- );
+ return $data;
}
-
- return $data;
}
add_action( 'init', 'gutenberg_register_webfonts_from_theme_json' );
diff --git a/lib/experimental/webfonts.php b/lib/experimental/webfonts.php
index 201101d1d7093e..0bbf0b8f405091 100644
--- a/lib/experimental/webfonts.php
+++ b/lib/experimental/webfonts.php
@@ -9,152 +9,116 @@
if ( ! function_exists( 'wp_webfonts' ) ) {
/**
- * Instantiates the webfonts controller, if not already set, and returns it.
+ * Initialize $wp_webfonts if it has not been set.
*
- * @since 6.0.0
+ * @since X.X.X
+ *
+ * @global WP_Webfonts $wp_webfonts
*
- * @return WP_Webfonts Instance of the controller.
+ * @return WP_Webfonts WP_Webfonts instance.
*/
function wp_webfonts() {
global $wp_webfonts;
- if ( ! $wp_webfonts instanceof WP_Webfonts ) {
+ if ( ! ( $wp_webfonts instanceof WP_Webfonts ) ) {
$wp_webfonts = new WP_Webfonts();
- $wp_webfonts->init();
}
return $wp_webfonts;
}
}
-if ( ! function_exists( 'wp_register_webfonts' ) ) {
+if ( ! function_exists( 'wp_register_web_font_family' ) ) {
/**
- * Registers a collection of webfonts.
- *
- * Example of how to register Source Serif Pro font with font-weight range of 200-900
- * and font-style of normal and italic:
- *
- * If the font files are contained within the theme:
- *
- * wp_register_webfonts(
- * array(
- * array(
- * 'provider' => 'local',
- * 'font-family' => 'Source Serif Pro',
- * 'font-weight' => '200 900',
- * 'font-style' => 'normal',
- * 'src' => get_theme_file_uri( 'assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2' ),
- * ),
- * array(
- * 'provider' => 'local',
- * 'font-family' => 'Source Serif Pro',
- * 'font-weight' => '200 900',
- * 'font-style' => 'italic',
- * 'src' => get_theme_file_uri( 'assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2' ),
- * ),
- * )
- * );
- *
- *
- * Webfonts should be registered in the `after_setup_theme` hook.
+ * Registers a font family as an alias.
*
- * @since 6.0.0
+ * @param $font_family
+ * @return array|bool
+ */
+ function wp_register_web_font_family( $font_family ) {
+ $wp_webfonts = wp_webfonts();
+
+ return $wp_webfonts->add( sanitize_title( $font_family ), false );
+ }
+}
+
+if ( ! function_exists( 'wp_register_web_font_variation' ) ) {
+ /**
+ * Registers a font variation.
+ *
+ * @param $font_family
+ * @return mixed
+ */
+ function wp_register_web_font_variation( $font_family, $variation_handle, $variation ) {
+ return wp_webfonts()->add_variation( $font_family, $variation_handle, $variation );
+ }
+}
+
+if ( ! function_exists( 'wp_register_webfonts' ) ) {
+ /**
+ * Registers a list of web fonts and variations.
*
- * @param array[] $webfonts Webfonts to be registered.
- * This contains an array of webfonts to be registered.
- * Each webfont is an array.
- * @return string[] The font family slug of the registered webfonts.
+ * @param $webfonts
+ * @return array
*/
- function wp_register_webfonts( array $webfonts ) {
- $registered_webfont_slugs = array();
+ function wp_register_webfonts( $webfonts, $enqueue = false ) {
+ $registered = array();
+
+ foreach ( $webfonts as $font_family => $variations ) {
+ wp_register_web_font_family( $font_family );
- foreach ( $webfonts as $webfont ) {
- $slug = wp_register_webfont( $webfont );
+ foreach ( $variations as $variation_handle => $variation ) {
+ $registered[] = wp_register_web_font_variation( $font_family, $variation_handle, $variation );
- if ( is_string( $slug ) ) {
- $registered_webfont_slugs[ $slug ] = true;
+ if ( $enqueue ) {
+ wp_enqueue_web_font( $variation_handle );
+ }
}
}
- return array_keys( $registered_webfont_slugs );
+ return $registered;
}
}
-if ( ! function_exists( 'wp_register_webfont' ) ) {
+if ( ! function_exists( 'wp_enqueue_web_font' ) ) {
/**
- * Registers a single webfont.
- *
- * Example of how to register Source Serif Pro font with font-weight range of 200-900:
- *
- * If the font file is contained within the theme:
- *
- *
- * wp_register_webfont(
- * array(
- * 'provider' => 'local',
- * 'font-family' => 'Source Serif Pro',
- * 'font-weight' => '200 900',
- * 'font-style' => 'normal',
- * 'src' => get_theme_file_uri( 'assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2' ),
- * )
- * );
- *
- *
- * @since 6.0.0
- *
- * @param array $webfont Webfont to be registered.
- * @return string|false The font family slug if successfully registered, else false.
+ * Enqueues a web font family and all variations.
*/
- function wp_register_webfont( array $webfont ) {
- return wp_webfonts()->register_webfont( $webfont );
+ function wp_enqueue_web_font( $handle ) {
+ $wp_webfonts = wp_webfonts();
+ $wp_webfonts->enqueue( $handle );
}
}
-if ( ! function_exists( 'wp_enqueue_webfonts' ) ) {
+if ( ! function_exists( 'wp_enqueue_web_font_variations' ) ) {
/**
- * Enqueues a collection of font families.
- *
- * Example of how to enqueue Source Serif Pro and Roboto font families, both registered beforehand.
- *
- *
- * wp_enqueue_webfonts(
- * 'Roboto',
- * 'Sans Serif Pro'
- * );
- *
- *
- * Font families should be enqueued from the `init` hook or later.
- *
- * @since 6.0.0
- *
- * @param string[] $webfonts Font families to be enqueued.
+ * Enqueues a specific set of web font variations.
*/
- function wp_enqueue_webfonts( array $webfonts ) {
- foreach ( $webfonts as $webfont ) {
- wp_enqueue_webfont( $webfont );
+ function wp_enqueue_web_font_variations( $variations ) {
+ $wp_webfonts = wp_webfonts();
+
+ // Looking to enqueue all variations of a font family.
+ foreach ( $variations as $variation ) {
+ $wp_webfonts->enqueue( $variation );
}
}
}
-if ( ! function_exists( 'wp_enqueue_webfont' ) ) {
+if ( ! function_exists( 'wp_deregister_web_font_family' ) ) {
/**
- * Enqueue a single font family that has been registered beforehand.
- *
- * Example of how to enqueue Source Serif Pro font:
- *
- *
- * wp_enqueue_webfont( 'Source Serif Pro' );
- *
- *
- * Font families should be enqueued from the `init` hook or later.
- *
- * @since 6.0.0
- *
- * @param string $font_family_name The font family name to be enqueued.
- * @return bool True if successfully enqueued, else false.
+ * Unregisters an entire font family and all variations.
+ */
+ function wp_deregister_web_font_family( $font_family ) {
+ wp_webfonts()->remove_family( $font_family );
+ }
+}
+
+if ( ! function_exists( 'wp_deregister_web_font_variation' ) ) {
+ /**
+ * @param $variation_handle
*/
- function wp_enqueue_webfont( $font_family_name ) {
- return wp_webfonts()->enqueue_webfont( $font_family_name );
+ function wp_deregister_web_font_variation( $font_family, $variation_handle ) {
+ wp_webfonts()->remove_variation( $font_family, $variation_handle );
}
}
@@ -211,6 +175,42 @@ function wp_get_webfont_providers() {
}
}
+if ( ! function_exists( 'wp_print_webfonts' ) ) {
+ function wp_print_webfonts( $handles = false ) {
+ global $wp_webfonts;
+
+ /**
+ * Fires before webfonts in the $handles queue are printed.
+ *
+ * @since X.X.X
+ */
+ do_action( 'wp_print_webfonts' );
+
+ if ( '' === $handles ) { // For 'wp_head'.
+ $handles = false;
+ }
+
+ _wp_scripts_maybe_doing_it_wrong( __FUNCTION__ );
+
+ if ( ! ( $wp_webfonts instanceof WP_Webfonts ) ) {
+ if ( ! $handles ) {
+ return array(); // No need to instantiate if nothing is there.
+ }
+ }
+
+ return wp_webfonts()->do_items( $handles );
+ }
+}
+
+
+
+
+
+
+
+
+
+
/**
* Add webfonts mime types.
*/