wp-customize-fonts.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. <?php
  2. require_once( __DIR__ . '/wp-customize-global-styles-setting.php' );
  3. require_once( __DIR__ . '/wp-customize-utils.php' );
  4. add_action( 'init', function() {
  5. return;
  6. // We've already transformed the data, no need to run this
  7. if ( get_option( 'blockbase_custom_fonts_data_migrated' ) ) {
  8. return;
  9. }
  10. $font_settings = wp_get_global_settings( array( 'typography', 'fontFamilies' ) );
  11. // No Customizer font settings found. Mark as transformed and hide the Customizer UI for fonts.
  12. if ( ! isset( $font_settings['custom'] ) || ! is_array( $font_settings['custom'] ) ) {
  13. add_option( 'blockbase_legacy_font_settings', '{}' );
  14. return;
  15. }
  16. // Extract font slugs from legacy data structure
  17. $heading_font_slug = '';
  18. $body_font_slug = '';
  19. foreach ( $font_settings['custom'] as $font_setting ) {
  20. if ( strpos( $font_setting['slug'], 'heading' ) !== false ) {
  21. $heading_font_slug = $font_setting['fontSlug'];
  22. }
  23. if ( strpos( $font_setting['slug'], 'body' ) !== false ) {
  24. $body_font_slug = $font_setting['fontSlug'];
  25. }
  26. }
  27. // Get the user's global styles CPT id
  28. $user_custom_post_type_id = WP_Theme_JSON_Resolver_Gutenberg::get_user_global_styles_post_id();
  29. // API request to get global styles
  30. $get_request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' );
  31. $get_request->set_param( 'id', $user_custom_post_type_id );
  32. $global_styles_controller = new Gutenberg_REST_Global_Styles_Controller();
  33. $global_styles = $global_styles_controller->get_item( $get_request );
  34. // converts data to array (in some cases settings and styles are objects insted of arrays)
  35. $new_settings = (array) $global_styles->data['settings'];
  36. $new_styles = (array) $global_styles->data['styles'];
  37. // Set new typography settings
  38. if ( isset( $new_settings['typography']['fontFamilies'] ) ) {
  39. unset( $new_settings['typography']['fontFamilies'] ); // TODO: Reconsider the depth of property we're unsetting
  40. }
  41. if ( $body_font_slug ) {
  42. $new_styles = array_merge(
  43. $new_styles,
  44. array(
  45. 'typography' => array(
  46. 'fontFamily' => "var:preset|font-family|$body_font_slug"
  47. )
  48. )
  49. );
  50. }
  51. if ( $heading_font_slug ) {
  52. $new_styles = array_merge(
  53. $new_styles,
  54. array(
  55. 'blocks' => array(
  56. 'core/post-title' => array(
  57. 'typography' => array(
  58. 'fontFamily' => "var:preset|font-family|$heading_font_slug"
  59. )
  60. ),
  61. 'core/heading' => array(
  62. 'typography' => array(
  63. 'fontFamily' => "var:preset|font-family|$heading_font_slug"
  64. )
  65. ),
  66. )
  67. ),
  68. );
  69. }
  70. // // Add the updated global styles to the update request
  71. $update_request = new WP_REST_Request( 'PUT', '/wp/v2/global-styles/' );
  72. $update_request->set_param( 'id', $user_custom_post_type_id );
  73. $update_request->set_param( 'settings', $new_settings );
  74. $update_request->set_param( 'styles', $new_styles );
  75. // // Update the theme.json with the new settings.
  76. $updated_global_styles = $global_styles_controller->update_item( $update_request );
  77. delete_transient( 'global_styles' );
  78. delete_transient( 'global_styles_' . get_stylesheet() );
  79. delete_transient( 'gutenberg_global_styles' );
  80. delete_transient( 'gutenberg_global_styles_' . get_stylesheet() );
  81. add_option( 'blockbase_legacy_font_settings', 'TODO' );
  82. } );
  83. function blockbase_supports_jetpack_google_fonts() {
  84. if ( defined( 'JETPACK__VERSION' ) ) {
  85. $jetpack_has_google_fonts_module = JETPACK__VERSION === 'wpcom' || version_compare( JETPACK__VERSION, '10.9', '>=' );
  86. }
  87. if ( defined( 'GUTENBERG_VERSION' ) ) {
  88. $gutenberg_webfonts_api_supports_enqueueing = version_compare( GUTENBERG_VERSION, '13.3', '>=' );
  89. }
  90. return $jetpack_has_google_fonts_module && $gutenberg_webfonts_api_supports_enqueueing && Jetpack::is_module_active( 'google-fonts' );
  91. }
  92. class GlobalStylesFontsCustomizer {
  93. private $section_key = 'customize-global-styles-fonts';
  94. private $font_settings;
  95. private $font_control_default_body;
  96. private $font_control_default_heading;
  97. //Not all fonts support v2 of the API that allows for the shorter URls
  98. //list of supported fonts: https://fonts.google.com/variablefonts
  99. private $fonts = array(
  100. 'system-font' => array(
  101. 'fontFamily' => '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif',
  102. 'slug' => 'system-font',
  103. 'name' => 'System Font',
  104. ),
  105. 'arvo' => array(
  106. 'fontFamily' => '"Arvo", serif',
  107. 'slug' => 'arvo',
  108. 'name' => 'Arvo',
  109. 'google' => 'family=Arvo:ital,wght@0,400;0,700;1,400;1,700',
  110. ),
  111. 'bodoni-moda' => array(
  112. 'fontFamily' => '"Bodoni Moda", serif',
  113. 'slug' => 'bodoni-moda',
  114. 'name' => 'Bodoni Moda',
  115. 'google' => 'family=Bodoni+Moda:ital,wght@0,400..900;1,400..900',
  116. ),
  117. 'cabin' => array(
  118. 'fontFamily' => '"Cabin", sans-serif',
  119. 'slug' => 'cabin',
  120. 'name' => 'Cabin',
  121. 'google' => 'family=Cabin:ital,wght@0,400..700;1,400..700',
  122. ),
  123. 'chivo' => array(
  124. 'fontFamily' => '"Chivo", sans-serif',
  125. 'slug' => 'chivo',
  126. 'name' => 'Chivo',
  127. 'google' => 'family=Chivo:ital,wght@0,300;0,400;0,700;0,900;1,300;1,400;1,700;1,900',
  128. ),
  129. 'courier-prime' => array(
  130. 'fontFamily' => '"Courier Prime", serif',
  131. 'slug' => 'courier-prime',
  132. 'name' => 'Courier Prime',
  133. 'google' => 'family=Courier+Prime:ital,wght@0,400;0,700;1,400;1,700',
  134. ),
  135. 'dm-sans' => array(
  136. 'fontFamily' => '"DM Sans", sans-serif',
  137. 'slug' => 'dm-sans',
  138. 'name' => 'DM Sans',
  139. 'google' => 'family=DM+Sans:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700"',
  140. ),
  141. 'domine' => array(
  142. 'fontFamily' => '"Domine", serif',
  143. 'slug' => 'domine',
  144. 'name' => 'Domine',
  145. 'google' => 'family=Domine:wght@400..700',
  146. ),
  147. 'eb-garamond' => array(
  148. 'fontFamily' => '"EB Garamond", serif',
  149. 'slug' => 'eb-garamond',
  150. 'name' => 'EB Garamond',
  151. 'google' => 'family=EB+Garamond:ital,wght@0,400..800;1,400..800',
  152. ),
  153. 'fira-sans' => array(
  154. 'fontFamily' => '"Fira Sans", sans-serif',
  155. 'slug' => 'fira-sans',
  156. 'name' => 'Fira Sans',
  157. 'google' => 'family=Fira+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900',
  158. ),
  159. 'ibm-plex-mono' => array(
  160. 'fontFamily' => '"IBM Plex Mono", monospace',
  161. 'slug' => 'ibm-plex-mono',
  162. 'name' => 'IBM Plex Mono',
  163. 'google' => 'family=IBM+Plex+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700',
  164. ),
  165. 'inter' => array(
  166. 'fontFamily' => '"Inter", sans-serif',
  167. 'slug' => 'inter',
  168. 'name' => 'Inter',
  169. 'google' => 'family=Inter:wght@100..900',
  170. ),
  171. 'josefin-sans' => array(
  172. 'fontFamily' => '"Josefin Sans", sans-serif',
  173. 'slug' => 'josefin-sans',
  174. 'name' => 'Josefin Sans',
  175. 'google' => 'family=Josefin+Sans:ital,wght@0,100..700;1,100..700',
  176. ),
  177. 'libre-baskerville' => array(
  178. 'fontFamily' => '"Libre Baskerville", serif',
  179. 'slug' => 'libre-baskerville',
  180. 'name' => 'Libre Baskerville',
  181. 'google' => 'family=Libre+Baskerville:ital,wght@0,400;0,700;1,400',
  182. ),
  183. 'libre-franklin' => array(
  184. 'fontFamily' => '"Libre Franklin", sans-serif',
  185. 'slug' => 'libre-franklin',
  186. 'name' => 'Libre Franklin',
  187. 'google' => 'family=Libre+Franklin:ital,wght@0,100..900;1,100..900',
  188. ),
  189. 'lora' => array(
  190. 'fontFamily' => '"Lora", serif',
  191. 'slug' => 'lora',
  192. 'name' => 'Lora',
  193. 'google' => 'family=Lora:ital,wght@0,400..700;1,400..700',
  194. ),
  195. 'merriweather' => array(
  196. 'fontFamily' => '"Merriweather", serif',
  197. 'slug' => 'merriweather',
  198. 'name' => 'Merriweather',
  199. 'google' => 'family=Merriweather:ital,wght@0,300;0,400;0,700;0,900;1,300;1,400;1,700;1,900',
  200. ),
  201. 'montserrat' => array(
  202. 'fontFamily' => '"Montserrat", sans-serif',
  203. 'slug' => 'montserrat',
  204. 'name' => 'Montserrat',
  205. 'google' => 'family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900',
  206. ),
  207. 'nunito' => array(
  208. 'fontFamily' => '"Nunito", sans-serif',
  209. 'slug' => 'nunito',
  210. 'name' => 'Nunito',
  211. 'google' => 'family=Nunito:ital,wght@0,200;0,300;0,400;0,600;0,700;0,800;0,900;1,200;1,300;1,400;1,600;1,700;1,800;1,900',
  212. ),
  213. 'open-sans' => array(
  214. 'fontFamily' => '"Open Sans", sans-serif',
  215. 'slug' => 'open-sans',
  216. 'name' => 'Open Sans',
  217. 'google' => 'family=Open+Sans:ital,wght@0,300;0,400;0,600;0,700;0,800;1,300;1,400;1,600;1,700;1,800',
  218. ),
  219. 'overpass' => array(
  220. 'fontFamily' => '"Overpass", sans-serif',
  221. 'slug' => 'overpass',
  222. 'name' => 'Overpass',
  223. 'google' => 'family=Overpass:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900',
  224. ),
  225. 'playfair-display' => array(
  226. 'fontFamily' => '"Playfair Display", serif',
  227. 'slug' => 'playfair-display',
  228. 'name' => 'Playfair Display',
  229. 'google' => 'family=Playfair+Display:ital,wght@0,400..900;1,400..900',
  230. ),
  231. 'poppins' => array(
  232. 'fontFamily' => '"Poppins", sans-serif',
  233. 'slug' => 'poppins',
  234. 'name' => 'Poppins',
  235. 'google' => 'family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900',
  236. ),
  237. 'raleway' => array(
  238. 'fontFamily' => '"Raleway", sans-serif',
  239. 'slug' => 'raleway',
  240. 'name' => 'Raleway',
  241. 'google' => 'family=Raleway:ital,wght@0,100..900;1,100..900',
  242. ),
  243. 'red-hat-display' => array(
  244. 'fontFamily' => '"Red Hat Display", sans-serif',
  245. 'slug' => 'red-hat-display',
  246. 'name' => 'Red Hat Display',
  247. 'google' => 'family=Red+Hat+Display:ital,wght@0,400;0,500;0,700;0,900;1,400;1,500;1,700;1,900',
  248. ),
  249. 'roboto' => array(
  250. 'fontFamily' => '"Roboto", sans-serif',
  251. 'slug' => 'roboto',
  252. 'name' => 'Roboto',
  253. 'google' => 'family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,800;1,900',
  254. ),
  255. 'roboto-slab' => array(
  256. 'fontFamily' => '"Roboto Slab", sans-serif',
  257. 'slug' => 'roboto-slab',
  258. 'name' => 'Roboto Slab',
  259. 'google' => 'family=Roboto+Slab:wght@100..900',
  260. ),
  261. 'rubik' => array(
  262. 'fontFamily' => '"Rubik", sans-serif',
  263. 'slug' => 'rubik',
  264. 'name' => 'Rubik',
  265. 'google' => 'family=Rubik:ital,wght@0,300..900;1,300..900',
  266. ),
  267. 'source-sans-pro' => array(
  268. 'fontFamily' => '"Source Sans Pro", sans-serif',
  269. 'slug' => 'source-sans-pro',
  270. 'name' => 'Source Sans Pro',
  271. 'google' => 'family=Source+Sans+Pro:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700;1,900',
  272. ),
  273. 'source-serif-pro' => array(
  274. 'fontFamily' => '"Source Serif Pro", serif',
  275. 'slug' => 'source-serif-pro',
  276. 'name' => 'Source Serif Pro',
  277. 'google' => 'family=Source+Serif+Pro:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700;1,900',
  278. ),
  279. 'space-mono' => array(
  280. 'fontFamily' => '"Space Mono", sans-serif',
  281. 'slug' => 'space-mono',
  282. 'name' => 'Space Mono',
  283. 'google' => 'family=Space+Mono:ital,wght@0,400;0,700;1,400;1,700',
  284. ),
  285. 'work-sans' => array(
  286. 'fontFamily' => '"Work Sans", sans-serif',
  287. 'slug' => 'work-sans',
  288. 'name' => 'Work Sans',
  289. 'google' => 'family=Work+Sans:ital,wght@0,100..900;1,100..900',
  290. ),
  291. );
  292. function __construct() {
  293. add_action( 'customize_register', array( $this, 'initialize' ) );
  294. add_action( 'customize_preview_init', array( $this, 'handle_customize_preview_init' ) );
  295. add_action( 'customize_register', array( $this, 'enqueue_google_fonts' ) );
  296. add_action( 'customize_save_after', array( $this, 'handle_customize_save_after' ) );
  297. add_action( 'customize_controls_enqueue_scripts', array( $this, 'customize_control_js' ) );
  298. }
  299. function handle_customize_preview_init( $wp_customize ) {
  300. $this->update_font_settings( $wp_customize );
  301. $this->customize_preview_js( $wp_customize );
  302. $this->create_customization_style_element( $wp_customize );
  303. }
  304. function customize_preview_js( $wp_customize ) {
  305. if ( $this->fonts && $this->font_settings ) {
  306. wp_enqueue_script( 'customizer-preview-fonts', get_template_directory_uri() . '/inc/customizer/wp-customize-fonts-preview.js', array( 'customize-preview' ) );
  307. wp_localize_script( 'customizer-preview-fonts', 'googleFonts', $this->fonts );
  308. wp_localize_script( 'customizer-preview-fonts', 'fontSettings', $this->font_settings );
  309. }
  310. }
  311. function customize_control_js() {
  312. if ( $this->font_control_default_body && $this->font_control_default_heading ) {
  313. wp_enqueue_script( 'customizer-font-control', get_template_directory_uri() . '/inc/customizer/wp-customize-fonts-control.js', array( 'customize-controls' ), null, true );
  314. wp_localize_script( 'customizer-font-control', 'fontControlDefaultBody', array( $this->font_control_default_body ) );
  315. wp_localize_script( 'customizer-font-control', 'fontControlDefaultHeading', array( $this->font_control_default_heading ) );
  316. }
  317. }
  318. function enqueue_google_fonts() {
  319. wp_enqueue_style( 'blockbase-google-fonts', $this->google_fonts_url(), array(), null );
  320. }
  321. function create_customization_style_element( $wp_customize ) {
  322. if ( $this->font_settings ) {
  323. wp_enqueue_style( 'global-styles-fonts-customizations', ' ', array( 'global-styles' ) ); // This needs to load after global_styles, hence the dependency
  324. $css = 'body {';
  325. $css .= '--wp--preset--font-family--body-font:' . $this->font_settings['body'] . ';';
  326. $css .= '--wp--preset--font-family--heading-font:' . $this->font_settings['heading'] . ';';
  327. $css .= '}';
  328. wp_add_inline_style( 'global-styles-fonts-customizations', $css );
  329. }
  330. }
  331. function update_font_settings( $wp_customize ) {
  332. $body_setting = $wp_customize->get_setting( $this->section_key . 'body' );
  333. $heading_setting = $wp_customize->get_setting( $this->section_key . 'heading' );
  334. if ( $body_setting && $heading_setting ) {
  335. $body_value = $body_setting->post_value();
  336. if ( $body_value ) {
  337. $body_font_setting = $this->fonts[ $body_value ];
  338. $this->font_settings['body'] = $body_font_setting['fontFamily'];
  339. }
  340. $heading_value = $heading_setting->post_value();
  341. if ( $heading_value ) {
  342. $heading_font_setting = $this->fonts[ $heading_value ];
  343. $this->font_settings['heading'] = $heading_font_setting['fontFamily'];
  344. }
  345. }
  346. }
  347. function google_fonts_url() {
  348. $font_families = array();
  349. foreach ( $this->fonts as $font ) {
  350. if ( ! empty( $font['google'] ) ) {
  351. $font_families[] = $font['google'];
  352. }
  353. }
  354. $font_families[] = 'display=swap';
  355. // Make a single request for the theme fonts.
  356. return esc_url_raw( 'https://fonts.googleapis.com/css2?' . implode( '&', $font_families ) );
  357. }
  358. function initialize( $wp_customize ) {
  359. $theme = wp_get_theme();
  360. //Add a Section to the Customizer for these bits
  361. $wp_customize->add_section(
  362. $this->section_key,
  363. array(
  364. 'capability' => 'edit_theme_options',
  365. 'description' => sprintf( __( 'Font Customization for %1$s', 'blockbase' ), $theme->name ),
  366. 'title' => __( 'Fonts', 'blockbase' ),
  367. )
  368. );
  369. $merged_json = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data()->get_raw_data();
  370. $theme_font_families = $merged_json['settings']['typography']['fontFamilies']['theme'];
  371. $body_font_default_array = array_filter(
  372. $theme_font_families,
  373. function( $font_family ) {
  374. return 'body-font' === $font_family['slug'];
  375. }
  376. );
  377. $body_font_default = array_shift( $body_font_default_array );
  378. $heading_font_default_array = array_filter(
  379. $theme_font_families,
  380. function( $font_family ) {
  381. return 'heading-font' === $font_family['slug'];
  382. }
  383. );
  384. $heading_font_default = array_shift( $heading_font_default_array );
  385. // See if the child theme has been updated. If not then show a notice.
  386. if ( ! $body_font_default && ! $heading_font_default ) {
  387. $wp_customize->add_control(
  388. $this->section_key . '-v1-blockbase-format-notice',
  389. array(
  390. 'type' => 'hidden',
  391. 'description' => '<div class="notice notice-warning">
  392. <p>' . __( 'Your theme needs to be updated before you can customize fonts', 'blockbase' ) . '</p>
  393. </div>',
  394. 'settings' => array(),
  395. 'section' => $this->section_key,
  396. )
  397. );
  398. return;
  399. }
  400. if ( array_key_exists( 'custom', $merged_json['settings']['typography']['fontFamilies'] ) ) {
  401. $merged_font_families = $merged_json['settings']['typography']['fontFamilies']['custom'];
  402. $body_font_selected_array = array_filter(
  403. $merged_font_families,
  404. function( $font_family ) {
  405. return 'body-font' === $font_family['slug'];
  406. }
  407. );
  408. $body_font_selected = array_shift( $body_font_selected_array );
  409. $heading_font_selected_array = array_filter(
  410. $merged_font_families,
  411. function( $font_family ) {
  412. return 'heading-font' === $font_family['slug'];
  413. }
  414. );
  415. $heading_font_selected = array_shift( $heading_font_selected_array );
  416. // NOTE: This should be removed once Gutenberg 12.1 lands stably in all environments
  417. } elseif ( array_key_exists( 'user', $merged_json['settings']['typography']['fontFamilies'] ) ) {
  418. $merged_font_families = $merged_json['settings']['typography']['fontFamilies']['user'];
  419. $body_font_selected_array = array_filter(
  420. $merged_font_families,
  421. function( $font_family ) {
  422. return 'body-font' === $font_family['slug'];
  423. }
  424. );
  425. $body_font_selected = array_shift( $body_font_selected_array );
  426. $heading_font_selected_array = array_filter(
  427. $merged_font_families,
  428. function( $font_family ) {
  429. return 'heading-font' === $font_family['slug'];
  430. }
  431. );
  432. $heading_font_selected = array_shift( $heading_font_selected_array );
  433. // End Gutenberg < 12.1 compatibility patch
  434. } else {
  435. $body_font_selected = $body_font_default;
  436. $heading_font_selected = $heading_font_default;
  437. }
  438. // If there's no selected font then the user is probably using the old format for font customization
  439. if ( $body_font_selected && $heading_font_selected ) {
  440. $body_font_selected_font_family = $body_font_selected['fontFamily'];
  441. $body_font_selected_font_slug = $body_font_selected['fontSlug'];
  442. $heading_font_selected_font_family = $heading_font_selected['fontFamily'];
  443. $heading_font_selected_font_slug = $heading_font_selected['fontSlug'];
  444. } else {
  445. $body_font_selected_font_family = null;
  446. $body_font_selected_font_slug = null;
  447. $heading_font_selected_font_family = null;
  448. $heading_font_selected_font_slug = null;
  449. }
  450. $this->font_settings = array(
  451. 'body' => $body_font_selected_font_family,
  452. 'heading' => $heading_font_selected_font_family,
  453. );
  454. // Add a reset button
  455. $this->font_control_default_body = $body_font_default['fontSlug'];
  456. $this->font_control_default_heading = $heading_font_default['fontSlug'];
  457. $wp_customize->add_control(
  458. $this->section_key . '-reset-button',
  459. array(
  460. 'type' => 'button',
  461. 'settings' => array(),
  462. 'section' => $this->section_key,
  463. 'input_attrs' => array(
  464. 'value' => __( 'Reset to Default', 'blockbase' ),
  465. 'class' => 'button button-link',
  466. ),
  467. )
  468. );
  469. $this->add_setting_and_control( $wp_customize, 'body', __( 'Body font', 'blockbase' ), $body_font_default['fontSlug'], $body_font_selected_font_slug, 'sanitize_title' );
  470. $this->add_setting_and_control( $wp_customize, 'heading', __( 'Heading font', 'blockbase' ), $heading_font_default['fontSlug'], $heading_font_selected_font_slug, 'sanitize_title' );
  471. }
  472. function get_font_family( $array, $configuration ) {
  473. $variable = get_settings_array( $array, $configuration );
  474. $slug = preg_replace( '/var\(--wp--preset--font-family--(.*)\)/', '$1', $variable );
  475. if ( ! isset( $this->fonts[ $slug ] ) ) {
  476. $this->fonts[ $slug ] = $this->build_font_from_theme_data( $slug, $configuration );
  477. }
  478. return $this->fonts[ $slug ];
  479. }
  480. function build_font_from_theme_data( $slug, $configuration ) {
  481. $new_font = array();
  482. $font_families = $configuration['settings']['typography']['fontFamilies']['theme'];
  483. foreach ( $font_families as $font_family ) {
  484. if ( $font_family['slug'] === $slug ) {
  485. $new_font['fontFamily'] = $font_family['fontFamily'];
  486. $new_font['name'] = $font_family['name'];
  487. if ( ! empty( $font_family['google'] ) ) {
  488. $new_font['google'] = $font_family['google'];
  489. }
  490. }
  491. }
  492. $new_font['slug'] = $slug;
  493. return $new_font;
  494. }
  495. function add_setting_and_control( $wp_customize, $name, $label, $default, $user_value, $sanitize_callback ) {
  496. $setting_name = $this->section_key . $name;
  497. $global_styles_setting = new WP_Customize_Global_Styles_Setting(
  498. $wp_customize,
  499. $setting_name,
  500. array(
  501. 'default' => $default,
  502. 'user_value' => $user_value,
  503. )
  504. );
  505. $wp_customize->add_setting(
  506. $global_styles_setting,
  507. array(
  508. 'sanitize_callback' => $sanitize_callback,
  509. )
  510. );
  511. $choices = array();
  512. foreach ( $this->fonts as $font_slug => $font_setting ) {
  513. $choices[ $font_slug ] = $font_setting['name'];
  514. }
  515. $wp_customize->add_control(
  516. $setting_name,
  517. array(
  518. 'section' => $this->section_key,
  519. 'label' => $label,
  520. 'type' => 'select',
  521. 'choices' => $choices,
  522. )
  523. );
  524. // Update the setting to the dirty value.
  525. // This is needed to preserve the settings when other Customizer settings change.
  526. $dirty_value = $wp_customize->get_setting( $setting_name )->post_value();
  527. if ( ! empty( $dirty_value ) ) {
  528. $wp_customize->get_setting( $setting_name )->user_value = $dirty_value;
  529. }
  530. }
  531. function handle_customize_save_after( $wp_customize ) {
  532. $body_value = $wp_customize->get_setting( $this->section_key . 'body' )->value();
  533. $heading_value = $wp_customize->get_setting( $this->section_key . 'heading' )->value();
  534. if ( ! isset( $body_value ) && ! isset( $heading_value ) ) {
  535. return;
  536. }
  537. $body_default = $wp_customize->get_setting( $this->section_key . 'body' )->default;
  538. $heading_default = $wp_customize->get_setting( $this->section_key . 'heading' )->default;
  539. if ( ! isset( $body_value ) ) {
  540. $body_value = $body_default;
  541. }
  542. if ( ! isset( $heading_value ) ) {
  543. $heading_value = $heading_default;
  544. }
  545. $body_setting = $this->fonts[ $body_value ];
  546. $body_setting['name'] = 'Body (' . $body_setting['name'] . ')';
  547. $body_setting['fontSlug'] = $body_setting['slug'];
  548. $body_setting['slug'] = 'body-font';
  549. $heading_setting = $this->fonts[ $heading_value ];
  550. $heading_setting['name'] = 'Heading (' . $heading_setting['name'] . ')';
  551. $heading_setting['fontSlug'] = $heading_setting['slug'];
  552. $heading_setting['slug'] = 'heading-font';
  553. // Set up variables for the theme.json.
  554. $font_families = array(
  555. $body_setting,
  556. $heading_setting,
  557. );
  558. $body_font_family_variable = 'var(--wp--preset--font-family--' . $body_setting['slug'] . ')';
  559. $heading_font_family_variable = 'var(--wp--preset--font-family--' . $heading_setting['slug'] . ')';
  560. // Get the user's global styles CPT id
  561. $user_custom_post_type_id = WP_Theme_JSON_Resolver_Gutenberg::get_user_global_styles_post_id();
  562. // API request to get global styles
  563. $get_request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' );
  564. $get_request->set_param( 'id', $user_custom_post_type_id );
  565. $global_styles_controller = new Gutenberg_REST_Global_Styles_Controller();
  566. $global_styles = $global_styles_controller->get_item( $get_request );
  567. // converts data to array (in some cases settings and styles are objects insted of arrays)
  568. $new_settings = (array) $global_styles->data['settings'];
  569. $new_styles = (array) $global_styles->data['styles'];
  570. // Set new typography settings
  571. if ( $font_families ) {
  572. $new_settings['typography']['fontFamilies']['custom'] = $font_families;
  573. }
  574. // Add the updated global styles to the update request
  575. $update_request = new WP_REST_Request( 'PUT', '/wp/v2/global-styles/' );
  576. $update_request->set_param( 'id', $user_custom_post_type_id );
  577. $update_request->set_param( 'settings', $new_settings );
  578. $update_request->set_param( 'styles', $new_styles );
  579. // Update the theme.json with the new settings.
  580. $updated_global_styles = $global_styles_controller->update_item( $update_request );
  581. delete_transient( 'global_styles' );
  582. delete_transient( 'global_styles_' . get_stylesheet() );
  583. delete_transient( 'gutenberg_global_styles' );
  584. delete_transient( 'gutenberg_global_styles_' . get_stylesheet() );
  585. }
  586. }
  587. new GlobalStylesFontsCustomizer;