Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WC Fonts: Register imported google fonts for use in the editor #868

Merged
merged 1 commit into from
Apr 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 97 additions & 3 deletions public_html/wp-content/plugins/wc-fonts/wc-fonts.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<?php

/*
* Plugin Name: WordCamp.org Fonts
*/

require_once __DIR__ . '/wc-google-fonts-provider.php';

class WordCamp_Fonts_Plugin {
protected $options;

Expand All @@ -19,6 +20,7 @@ public function __construct() {
add_action( 'wp_head', array( $this, 'wp_head_google_web_fonts' ) );
add_action( 'wp_head', array( $this, 'wp_head_font_awesome' ) );
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_core_fonts' ) );
add_action( 'init', array( $this, 'register_fonts_for_editor' ) );
}

/**
Expand Down Expand Up @@ -49,8 +51,10 @@ public function wp_head_google_web_fonts() {
return;
}

// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
printf( '<style>%s</style>', $this->options['google-web-fonts'] );
if ( ! wp_is_block_theme() ) {
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
printf( '<style>%s</style>', $this->options['google-web-fonts'] );
}
}

/**
Expand Down Expand Up @@ -310,6 +314,96 @@ public function validate_options( $input ) {

return $output;
}

/**
* Register the google fonts into WordPress so they can be used in the Site Editor.
*/
public function register_fonts_for_editor() {
if ( ! function_exists( 'wp_register_fonts' ) ) {
return;
}

if ( ! isset( $this->options['google-web-fonts'] ) || empty( $this->options['google-web-fonts'] ) ) {
return;
}

$lines = explode( "\n", $this->options['google-web-fonts'] );
$fonts = array();
foreach ( $lines as $line ) {
if ( preg_match( '#https?://fonts\.googleapis\.com/css2?\?family=[^\)\'"]+#', $line, $matches ) ) {
$url = $matches[0];
$query = explode( '&', wp_parse_url( $url, PHP_URL_QUERY ) );

// Multiple families can be added to one URL, so we need to loop over to parse them.
// We can't just use wp_parse_str because each `family` will overwrite the previous.
foreach ( $query as $family ) {
// Make sure we're working with a `family=` value and not `display=` or anything else.
if ( ! str_starts_with( $family, 'family=' ) ) {
continue;
}
$details = explode( ':', $family );
$name = str_replace( 'family=', '', $details[0] );
$styles = $details[1] ?? '';

$variations = array(
array(
'font-family' => urldecode( $name ),
'provider' => 'wordcamp-google',
),
);

if ( str_contains( $styles, '@' ) ) {
$variations = array_map(
function( $var ) use ( $name ) {
$variation = array(
'font-family' => urldecode( $name ),
'provider' => 'wordcamp-google',
);
if ( isset( $var['ital'] ) ) {
$variation['font-style'] = '0' === $var['ital'] ? 'normal' : 'italic';
}
if ( isset( $var['wght'] ) ) {
$variation['font-weight'] = str_replace( '..', ' ', $var['wght'] );
}
return $variation;
},
$this->parse_google_font_variations( $styles )
);
}

$fonts[ urldecode( $name ) ] = $variations;
}
}
}

wp_register_fonts( $fonts );
wp_enqueue_fonts( array_keys( $fonts ) );
}

/**
* Parse the google font options.
*
* Converts the string in a google fonts URL into an array of variations.
* For example, `ital,wght@0,700;1,700` should return:
* [
* [ 'ital' => 0, 'wght' => '700' ],
* [ 'ital' => 1, 'wght' => '700' ],
* ]
*/
public function parse_google_font_variations( $styles ) {
list( $props, $values ) = explode( '@', $styles );
$props = explode( ',', $props );
$values = explode( ';', $values );

$result = array();
foreach ( $values as $i => $value ) {
$style = explode( ',', $value );
foreach ( $props as $j => $prop ) {
$result[ $i ][ $prop ] = $style[ $j ];
}
}
return $result;
}
}

new WordCamp_Fonts_Plugin();
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php
/**
* Google Fonts provider for WP Fonts API.
*
* Eventually this should be supported by core, and this file can be deprecated.
*/

if ( ! class_exists( 'WP_Fonts_Provider' ) ) {
return;
}

add_action(
'init',
function() {
if ( function_exists( 'wp_fonts' ) ) {
wp_fonts()->register_provider( 'wordcamp-google', 'WC_Fonts_Provider_Google' );
}
}
);

class WC_Fonts_Provider_Google extends WP_Fonts_Provider {

/**
* The provider's unique ID.
*
* @var string
*/
protected $id = 'wordcamp-google';

/**
* Constructor.
*/
public function __construct() {
if (
function_exists( 'is_admin' ) && ! is_admin() &&
function_exists( 'current_theme_supports' ) && ! current_theme_supports( 'html5', 'style' )
) {
$this->style_tag_atts = array( 'type' => 'text/css' );
}
}

/**
* Build the `@import` statement for Google's font API.
*
* @return string The `@font-face` CSS.
*/
public function get_css() {
$css = '';

foreach ( $this->fonts as $font ) {
$font_style = $font['font-style'] ?? 'normal';
$font_weight = $font['font-weight'] ?? '400';
// Rebuild the google font URL to explicitly load the enqueued font.
$css .= sprintf(
'@import url("https://fonts.googleapis.com/css2?family=%1$s:ital,wght@%2$s,%3$s");',
urlencode( $font['font-family'] ),
'normal' === $font_style ? '0' : '1',
str_replace( ' ', '..', $font_weight )
);
}

return $css;
}
}