| @@ -24,8 +24,10 @@ | ||
| 24 | 24 | * @since 3.0.0 |
| 25 | 25 | * @var array<int, string> |
| 26 | 26 | */ |
| 27 | 27 | private const SYSTEM_FONTS = array( |
| 28 | + // Posts saved before the picker stored an empty value for "inherit". | |
| 29 | + 'Default', | |
| 28 | 30 | 'Arial', |
| 29 | 31 | 'Tahoma', |
| 30 | 32 | 'Verdana', |
| 31 | 33 | 'Helvetica', |
| @@ -51,12 +53,90 @@ | ||
| 51 | 53 | */ |
| 52 | 54 | public function __construct() { |
| 53 | 55 | add_action( 'wp_enqueue_scripts', array( $this, 'fonts_loader' ), 10 ); |
| 54 | 56 | add_action( 'admin_enqueue_scripts', array( $this, 'fonts_loader' ), 10 ); |
| 57 | + add_action( 'enqueue_block_assets', array( $this, 'enqueue_editor_fonts' ) ); | |
| 55 | 58 | add_action( 'gutsliders_render_block', array( $this, 'font_generator' ) ); |
| 56 | 59 | } |
| 57 | 60 | |
| 58 | 61 | /** |
| 62 | + * Enqueue the fonts used by the post open in the block editor. | |
| 63 | + * | |
| 64 | + * Hooked to `enqueue_block_assets` because WordPress mirrors that hook into | |
| 65 | + * the editor canvas iframe, which is where apiVersion 3 blocks render. | |
| 66 | + * `admin_enqueue_scripts` only reaches the document around the canvas, so | |
| 67 | + * the preview would resolve `font-family` against a font that document has | |
| 68 | + * but the iframe never loaded. | |
| 69 | + * | |
| 70 | + * @since 3.0.0 | |
| 71 | + * | |
| 72 | + * @return void | |
| 73 | + */ | |
| 74 | + public function enqueue_editor_fonts(): void { | |
| 75 | + if ( ! is_admin() || ! function_exists( 'get_current_screen' ) ) { | |
| 76 | + return; | |
| 77 | + } | |
| 78 | + | |
| 79 | + $screen = get_current_screen(); | |
| 80 | + | |
| 81 | + if ( null === $screen || ! $screen->is_block_editor() ) { | |
| 82 | + return; | |
| 83 | + } | |
| 84 | + | |
| 85 | + $post = get_post(); | |
| 86 | + | |
| 87 | + if ( ! $post instanceof \WP_Post || ! has_blocks( $post->post_content ) ) { | |
| 88 | + return; | |
| 89 | + } | |
| 90 | + | |
| 91 | + $this->collect_fonts( parse_blocks( $post->post_content ) ); | |
| 92 | + $this->fonts_loader(); | |
| 93 | + } | |
| 94 | + | |
| 95 | + /** | |
| 96 | + * Walk a parsed block tree and record every font family it uses. | |
| 97 | + * | |
| 98 | + * The front end collects fonts from `render_block`, which fires for nested | |
| 99 | + * blocks too. A parsed tree has to be walked explicitly. | |
| 100 | + * | |
| 101 | + * @since 3.0.0 | |
| 102 | + * | |
| 103 | + * @param array<int, array<string, mixed>> $blocks Parsed blocks. | |
| 104 | + * @return void | |
| 105 | + */ | |
| 106 | + private function collect_fonts( array $blocks ): void { | |
| 107 | + foreach ( $blocks as $block ) { | |
| 108 | + if ( isset( $block['attrs'] ) && is_array( $block['attrs'] ) ) { | |
| 109 | + $this->collect_block_fonts( $block['attrs'] ); | |
| 110 | + } | |
| 111 | + | |
| 112 | + if ( ! empty( $block['innerBlocks'] ) && is_array( $block['innerBlocks'] ) ) { | |
| 113 | + $this->collect_fonts( $block['innerBlocks'] ); | |
| 114 | + } | |
| 115 | + } | |
| 116 | + } | |
| 117 | + | |
| 118 | + /** | |
| 119 | + * Record the font families named in a single block's attributes. | |
| 120 | + * | |
| 121 | + * @since 3.0.0 | |
| 122 | + * | |
| 123 | + * @param array<string, mixed> $attributes Block attributes. | |
| 124 | + * @return void | |
| 125 | + */ | |
| 126 | + private function collect_block_fonts( array $attributes ): void { | |
| 127 | + foreach ( $attributes as $key => $value ) { | |
| 128 | + if ( ! empty( $value ) | |
| 129 | + && is_string( $value ) | |
| 130 | + && strpos( $key, 'gutsliders_' ) === 0 | |
| 131 | + && strpos( $key, 'FontFamily' ) !== false | |
| 132 | + ) { | |
| 133 | + self::$all_fonts[] = sanitize_text_field( $value ); | |
| 134 | + } | |
| 135 | + } | |
| 136 | + } | |
| 137 | + | |
| 138 | + /** | |
| 59 | 139 | * Extract font families from a rendered block's attributes. |
| 60 | 140 | * |
| 61 | 141 | * Scans block attributes for font family values and triggers |
| 62 | 142 | * the font loader to enqueue any new fonts found. |
| @@ -67,20 +147,9 @@ | ||
| 67 | 147 | * @return void |
| 68 | 148 | */ |
| 69 | 149 | public function font_generator( array $block ): void { |
| 70 | 150 | if ( isset( $block['attrs'] ) && is_array( $block['attrs'] ) ) { |
| 71 | - $attributes = $block['attrs']; | |
| 72 | - | |
| 73 | - foreach ( $attributes as $key => $value ) { | |
| 74 | - if ( ! empty( $value ) | |
| 75 | - && is_string( $value ) | |
| 76 | - && strpos( $key, 'gutsliders_' ) === 0 | |
| 77 | - && strpos( $key, 'FontFamily' ) !== false | |
| 78 | - ) { | |
| 79 | - self::$all_fonts[] = sanitize_text_field( $value ); | |
| 80 | - } | |
| 81 | - } | |
| 82 | - | |
| 151 | + $this->collect_block_fonts( $block['attrs'] ); | |
| 83 | 152 | $this->fonts_loader(); |
| 84 | 153 | } |
| 85 | 154 | } |
| 86 | 155 | |
| @@ -94,8 +163,12 @@ | ||
| 94 | 163 | * |
| 95 | 164 | * @return void |
| 96 | 165 | */ |
| 97 | 166 | public function fonts_loader(): void { |
| 167 | + if ( ! $this->is_google_fonts_enabled() ) { | |
| 168 | + return; | |
| 169 | + } | |
| 170 | + | |
| 98 | 171 | if ( ! is_array( self::$all_fonts ) || count( self::$all_fonts ) === 0 ) { |
| 99 | 172 | return; |
| 100 | 173 | } |
| 101 | 174 | |
| @@ -125,6 +198,26 @@ | ||
| 125 | 198 | ); |
| 126 | 199 | |
| 127 | 200 | wp_enqueue_style( $font_handle ); |
| 128 | 201 | } |
| 202 | + } | |
| 203 | + | |
| 204 | + /** | |
| 205 | + * Whether Google Fonts requests are allowed. | |
| 206 | + * | |
| 207 | + * Site owners can turn this off from the GutSlider settings screen | |
| 208 | + * when the theme already loads the fonts or hosts them locally. | |
| 209 | + * | |
| 210 | + * @since 3.0.0 | |
| 211 | + * | |
| 212 | + * @return bool True when Google Fonts may be enqueued. | |
| 213 | + */ | |
| 214 | + private function is_google_fonts_enabled(): bool { | |
| 215 | + $settings = get_option( 'gutslider_settings', array() ); | |
| 216 | + | |
| 217 | + if ( is_array( $settings ) && array_key_exists( 'google_fonts', $settings ) ) { | |
| 218 | + return (bool) $settings['google_fonts']; | |
| 219 | + } | |
| 220 | + | |
| 221 | + return true; | |
| 129 | 222 | } |
| 130 | 223 | } |