collect_globals( $settings ); // 1. Replace CSS color variables in the serialized content $block_content = $instance->replace_colors( $block_content ); // 2. Resolve global font sources in block attrs if ( function_exists( 'parse_blocks' ) && function_exists( 'serialize_blocks' ) ) { $blocks = parse_blocks( $block_content ); $instance->replace_fonts( $blocks ); $block_content = serialize_blocks( $blocks ); } return $block_content; } /** * Build $colors and $fonts from the settings array. */ private function collect_globals( array $settings ): void { $color_keys = [ 'gradient_colors', 'custom_gradient_colors', 'custom_colors', 'global_colors' ]; foreach ( $color_keys as $key ) { if ( ! empty( $settings[ $key ] ) ) { $this->colors = array_merge( $this->colors, $settings[ $key ] ); } } if ( ! empty( $settings['global_typography'] ) ) { foreach ( $settings['global_typography'] as $k => $v ) { if ( $k === 'custom' ) { // Custom entries are keyed by their ID foreach ( $v as $k2 => $v2 ) { $this->fonts[ $k2 ] = $v2; } } else { $this->fonts[ $k ] = $v; } } } } /** * Replace CSS variable references (e.g. var(--eb-global-...)) with * their actual color values. */ private function replace_colors( string $content ): string { foreach ( $this->colors as $color ) { if ( ! empty( $color['var'] ) && ! empty( $color['color'] ) ) { $content = str_replace( 'var(' . $color['var'] . ')', $color['color'], $content ); } } return $content; } /** * Walk parsed blocks recursively and resolve global font sources. */ private function replace_fonts( array &$blocks ): void { foreach ( $blocks as &$block ) { if ( ! empty( $block['attrs'] ) ) { foreach ( $block['attrs'] as $attr => $value ) { if ( $this->has_global_fonts( $attr, $value ) ) { $font_id = str_replace( 'global:', '', $block['attrs'][ $attr ] ); $tag_name = $block['attrs']['tagName'] ?? ''; $block['attrs'] = array_merge( $block['attrs'], $this->prepare_font_attrs( $font_id, $attr, $tag_name ) ); $block['attrs'][ $attr ] = 'custom'; } } } if ( ! empty( $block['innerBlocks'] ) ) { $this->replace_fonts( $block['innerBlocks'] ); } } } /** * Determine if an attribute is a global font source reference. */ private function has_global_fonts( string $attr, $value ): bool { // `strpos()`, not `str_contains()` (PHP 8.0+, core-polyfilled only from WP 5.9): // the plugin advertises WordPress 5.0 / PHP 7.2. return strpos( $attr, 'FontSource' ) !== false && is_string( $value ) && strpos( $value, 'global:' ) !== false; } /** * Build the concrete font attribute array for a given global font ID. */ private function prepare_font_attrs( string $font_id, string $attr, string $tag_name ): array { $styles = []; $prefix = str_replace( 'FontSource', '', $attr ); if ( $font_id === 'global' ) { if ( ! empty( $tag_name ) && isset( $this->fonts[ $tag_name ] ) ) { $styles = $this->fonts[ $tag_name ]; // If the font family is "Default", fall back to allHeadings if ( isset( $styles['fontFamily'] ) && trim( strtolower( $styles['fontFamily'] ) ) === 'default' ) { $styles['fontFamily'] = $this->fonts['allHeadings']['fontFamily'] ?? $styles['fontFamily']; } } elseif ( isset( $this->fonts['body'] ) ) { $styles = $this->fonts['body']; } } elseif ( isset( $this->fonts[ $font_id ] ) ) { $styles = $this->fonts[ $font_id ]; } if ( empty( $styles ) ) { return []; } $prepared = []; foreach ( $this->font_attrs as $font_attr ) { if ( ! empty( $styles[ $font_attr ] ) ) { $prepared[ $prefix . ucfirst( $font_attr ) ] = $styles[ $font_attr ]; } } foreach ( $this->responsive_font_attrs as $font_attr ) { if ( ! empty( $styles[ 'TAB' . $font_attr ] ) ) { $prepared[ 'TAB' . $prefix . ucfirst( $font_attr ) ] = $styles[ 'TAB' . $font_attr ]; } if ( ! empty( $styles[ 'MOB' . $font_attr ] ) ) { $prepared[ 'MOB' . $prefix . ucfirst( $font_attr ) ] = $styles[ 'MOB' . $font_attr ]; } } return $prepared; } }