custom-fonts.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. // Font Migration
  3. require get_template_directory() . '/inc/fonts/custom-font-migration.php';
  4. add_action( 'init', 'enqueue_global_styles_fonts', 100 );
  5. add_action( 'admin_init', 'enqueue_fse_font_styles' );
  6. add_filter( 'pre_render_block', 'enqueue_block_fonts', 10, 2 );
  7. add_filter( 'jetpack_google_fonts_list', 'spearhead_blocks_filter_jetpack_google_fonts_list' );
  8. $spearhead_blocks_enqueued_font_slugs = array();
  9. /**
  10. * Get the CSS containing font_face values for a given slug
  11. *
  12. * @return string String of CSS
  13. */
  14. function get_style_css( $slug ) {
  15. $font_face_file = get_template_directory() . '/assets/fonts/' . $slug . '/font-face.css';
  16. if ( ! file_exists( $font_face_file ) ) {
  17. return '';
  18. }
  19. $contents = file_get_contents( $font_face_file );
  20. return str_replace( 'src: url(./', 'src: url(' . get_template_directory_uri() . '/assets/fonts/' . $slug . '/', $contents );
  21. }
  22. /**
  23. * Collect fonts set in Global Styles settings.
  24. *
  25. * @return array Font faces from Global Styles settings.
  26. */
  27. function collect_fonts_from_global_styles() {
  28. // NOTE: We have to use gutenberg_get_global_styles() here due to the potential changes to Global Styles on page load happening in font migration.
  29. // Since core users don't have anything to migrate we can use core get_styles
  30. if ( function_exists( 'gutenberg_get_global_styles' ) ) {
  31. $global_styles = gutenberg_get_global_styles();
  32. } else {
  33. $global_styles = wp_get_global_styles();
  34. }
  35. $found_webfonts = array();
  36. // Look for fonts in block presets...
  37. if ( isset( $global_styles['blocks'] ) ) {
  38. foreach ( $global_styles['blocks'] as $setting ) {
  39. $font_slug = extract_font_slug_from_setting( $setting );
  40. if ( $font_slug ) {
  41. $found_webfonts[] = $font_slug;
  42. }
  43. }
  44. }
  45. // Look for fonts in HTML element presets...
  46. if ( isset( $global_styles['elements'] ) ) {
  47. foreach ( $global_styles['elements'] as $setting ) {
  48. // die(json_encode($global_styles));
  49. // NOTE: It seems that the Global Styles assignment of fonts writes the font family string rather than the
  50. // global styles shorthand that is assigned to the body. This should be confirmed and reported if it isn't already.
  51. $font_slug = extract_font_slug_from_setting( $setting );
  52. if ( $font_slug ) {
  53. $found_webfonts[] = $font_slug;
  54. }
  55. }
  56. }
  57. // Check if a global typography setting was defined.
  58. $font_slug = extract_font_slug_from_setting( $global_styles );
  59. if ( $font_slug ) {
  60. $found_webfonts[] = $font_slug;
  61. }
  62. return array_unique( $found_webfonts );
  63. }
  64. /**
  65. * Extract the font family slug from a settings array.
  66. *
  67. * @param array $setting The settings object.
  68. *
  69. * @return string|null
  70. */
  71. function extract_font_slug_from_setting( $setting ) {
  72. if ( ! isset( $setting['typography']['fontFamily'] ) ) {
  73. return null;
  74. }
  75. $font_family = $setting['typography']['fontFamily'];
  76. // Full string: var(--wp--preset--font-family--slug).
  77. // We do not care about the origin of the font, only its slug.
  78. preg_match( '/font-family--(?P<slug>.+)\)$/', $font_family, $matches );
  79. if ( isset( $matches['slug'] ) ) {
  80. return $matches['slug'];
  81. }
  82. // Full string: var:preset|font-family|slug
  83. // We do not care about the origin of the font, only its slug.
  84. preg_match( '/font-family\|(?P<slug>.+)$/', $font_family, $matches );
  85. if ( isset( $matches['slug'] ) ) {
  86. return $matches['slug'];
  87. }
  88. return $font_family;
  89. }
  90. /**
  91. * Build a list of all font slugs provided by spearhead-blocks from theme.json
  92. *
  93. * @return array Collection of all font slugs defined in the theme.json file
  94. */
  95. function collect_fonts_from_spearhead_blocks() {
  96. $fonts = array();
  97. $parent_theme_json_data = json_decode( file_get_contents( get_template_directory() . '/theme.json' ), true );
  98. $font_families = $parent_theme_json_data['settings']['typography']['fontFamilies'];
  99. foreach ( $font_families as $font ) {
  100. // Only pick it up if we're claiming it as ours to manage
  101. if ( array_key_exists( 'provider', $font ) && 'spearhead-blocks-fonts' === $font['provider'] ) {
  102. $fonts[] = $font;
  103. }
  104. }
  105. return $fonts;
  106. }
  107. /**
  108. * Enqeue all of the fonts used in global styles settings.
  109. *
  110. * @return void
  111. */
  112. function enqueue_global_styles_fonts() {
  113. global $spearhead_blocks_enqueued_font_slugs;
  114. $font_slugs = array();
  115. $font_css = '';
  116. if ( is_admin() ) {
  117. $font_families = collect_fonts_from_spearhead_blocks();
  118. foreach ( $font_families as $font_family ) {
  119. $font_slugs[] = $font_family['slug'];
  120. }
  121. } else {
  122. $font_slugs = collect_fonts_from_global_styles();
  123. }
  124. $spearhead_blocks_enqueued_font_slugs = $font_slugs;
  125. foreach ( $font_slugs as $font_slug ) {
  126. $font_css .= get_style_css( $font_slug );
  127. }
  128. // Bail out if there are no styles to enqueue.
  129. if ( '' === $font_css ) {
  130. return;
  131. }
  132. // Enqueue the stylesheet.
  133. wp_register_style( 'spearhead-blocks_font_faces', '' );
  134. wp_enqueue_style( 'spearhead-blocks_font_faces' );
  135. // Add the styles to the stylesheet.
  136. wp_add_inline_style( 'spearhead-blocks_font_faces', $font_css );
  137. }
  138. /**
  139. * Enqueue all of the fonts provided by spearhead-blocks for FSE use
  140. */
  141. function enqueue_fse_font_styles( $fonts ) {
  142. $fonts = collect_fonts_from_spearhead_blocks();
  143. $font_css = '';
  144. foreach ( $fonts as $font ) {
  145. $font_css .= get_style_css( $font['slug'] );
  146. }
  147. wp_enqueue_style( 'wp-block-library' );
  148. wp_add_inline_style( 'wp-block-library', $font_css );
  149. }
  150. /**
  151. * Add fonts that have been assigned via CSS
  152. */
  153. function enqueue_block_fonts( $content, $parsed_block ) {
  154. global $spearhead_blocks_enqueued_font_slugs;
  155. if ( ! is_admin() && isset( $parsed_block['attrs']['fontFamily'] ) ) {
  156. $font_slug = $parsed_block['attrs']['fontFamily'];
  157. if ( ! in_array( $font_slug, $spearhead_blocks_enqueued_font_slugs, true ) ) {
  158. $font_css = get_style_css( $font_slug );
  159. if ( $font_css ) {
  160. $spearhead_blocks_enqueued_font_slugs[] = $font_slug;
  161. wp_add_inline_style( 'spearhead-blocks_font_faces', $font_css );
  162. }
  163. }
  164. }
  165. return $content;
  166. }
  167. /**
  168. * Jetpack may attempt to register fonts for the Google Font Provider.
  169. * If that happens on a child theme then ONLY Jetpack fonts are registered.
  170. * This 'filter' filters out all of the fonts Jetpack should register
  171. * so that we depend exclusively on those provided by spearhead-blocks.
  172. */
  173. function spearhead_blocks_filter_jetpack_google_fonts_list( $list_to_filter ) {
  174. return array();
  175. }