diff --git a/includes/class-create-block-theme-api.php b/includes/class-create-block-theme-api.php
index 66fcfec0..01fc9646 100644
--- a/includes/class-create-block-theme-api.php
+++ b/includes/class-create-block-theme-api.php
@@ -239,8 +239,15 @@ function rest_create_child_theme( $request ) {
}
function rest_create_variation( $request ) {
+ $options = $request->get_params();
+
+ $save_fonts = isset( $options['saveFonts'] ) && true === $options['saveFonts'];
- $response = CBT_Theme_JSON::add_theme_json_variation_to_local( 'variation', $this->sanitize_theme_data( $request->get_params() ) );
+ $response = CBT_Theme_JSON::add_theme_json_variation_to_local(
+ 'variation',
+ $this->sanitize_theme_data( $options ),
+ $save_fonts
+ );
wp_cache_flush();
diff --git a/includes/create-theme/resolver_additions.php b/includes/create-theme/resolver_additions.php
index 1a6ad48f..0c684739 100644
--- a/includes/create-theme/resolver_additions.php
+++ b/includes/create-theme/resolver_additions.php
@@ -65,11 +65,7 @@ public static function export_theme_data( $content, $extra_theme_data = null ) {
}
// Merge the User Data
- if ( class_exists( 'WP_Theme_JSON_Resolver_Gutenberg' ) ) {
- $theme->merge( WP_Theme_JSON_Resolver_Gutenberg::get_user_data() );
- } else {
- $theme->merge( static::get_user_data() );
- }
+ $theme->merge( static::get_user_data() );
// Merge the extra theme data received as a parameter
if ( ! empty( $extra_theme_data ) ) {
@@ -93,8 +89,33 @@ public static function export_theme_data( $content, $extra_theme_data = null ) {
$schema = 'https://schemas.wp.org/' . $theme_json_version . '/theme.json';
}
$data['$schema'] = $schema;
- $theme_json = wp_json_encode( $data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
- return preg_replace( '~(?:^|\G)\h{4}~m', "\t", $theme_json );
+ return static::stringify( $data );
+ }
+
+ /**
+ * Get the user data.
+ *
+ * This is a copy of the parent function with the addition of the Gutenberg resolver.
+ *
+ * @return array
+ */
+ public static function get_user_data() {
+ // Determine the correct method to retrieve user data
+ return class_exists( 'WP_Theme_JSON_Resolver_Gutenberg' )
+ ? WP_Theme_JSON_Resolver_Gutenberg::get_user_data()
+ : parent::get_user_data();
+ }
+
+ /**
+ * Stringify the array data.
+ *
+ * $data is an array of data to be converted to a JSON string.
+ * @return string JSON string.
+ */
+ public static function stringify( $data ) {
+ $data = wp_json_encode( $data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
+ // Convert spaces to tabs
+ return preg_replace( '~(?:^|\G)\h{4}~m', "\t", $data );
}
public static function get_theme_file_contents() {
diff --git a/includes/create-theme/theme-fonts.php b/includes/create-theme/theme-fonts.php
index 9e889fd3..8a05c8a0 100644
--- a/includes/create-theme/theme-fonts.php
+++ b/includes/create-theme/theme-fonts.php
@@ -112,19 +112,18 @@ public static function make_filename_from_fontface( $font_face, $src, $src_index
return $font_filename;
}
- public static function copy_activated_fonts_to_theme() {
- $font_families_to_copy = self::get_user_activated_fonts();
-
- if ( is_null( $font_families_to_copy ) ) {
- return;
- }
-
- $theme_json = CBT_Theme_JSON_Resolver::get_theme_file_contents();
+ /*
+ * Copy the font assets to the theme.
+ *
+ * @param array $font_families The font families to copy.
+ * @return array $font_families The font families with the font face src updated to the theme font asset location.
+ */
+ public static function copy_font_assets_to_theme( $font_families ) {
$theme_font_asset_location = path_join( get_stylesheet_directory(), 'assets/fonts/' );
// Create the font asset directory if it does not exist.
wp_mkdir_p( $theme_font_asset_location );
- foreach ( $font_families_to_copy as &$font_family ) {
+ foreach ( $font_families as &$font_family ) {
if ( ! isset( $font_family['fontFace'] ) ) {
continue;
}
@@ -139,6 +138,10 @@ public static function copy_activated_fonts_to_theme() {
// if it is a string, cast it to an array
$font_face['src'] = (array) $font_face['src'];
foreach ( $font_face['src'] as $font_src_index => &$font_src ) {
+ if ( str_starts_with( $font_src, 'file:' ) ) {
+ // If the font source starts with 'file:' then it's already a theme asset.
+ continue;
+ }
$font_filename = basename( $font_src );
$font_pretty_filename = self::make_filename_from_fontface( $font_face, $font_src, $font_src_index );
$font_face_path = path_join( $font_family_dir_path, $font_pretty_filename );
@@ -158,9 +161,22 @@ public static function copy_activated_fonts_to_theme() {
}
}
+ return $font_families;
+ }
+
+ public static function copy_activated_fonts_to_theme() {
+ $font_families_to_copy = self::get_user_activated_fonts();
+
+ if ( is_null( $font_families_to_copy ) ) {
+ return;
+ }
+
+ $theme_json = CBT_Theme_JSON_Resolver::get_theme_file_contents();
+ $copied_font_families = self::copy_font_assets_to_theme( $font_families_to_copy );
+
$theme_json['settings']['typography']['fontFamilies'] = array_merge(
$theme_json['settings']['typography']['fontFamilies'] ?? array(),
- $font_families_to_copy
+ $copied_font_families
);
$user_settings = CBT_Theme_JSON_Resolver::get_user_data()->get_settings();
diff --git a/includes/create-theme/theme-json.php b/includes/create-theme/theme-json.php
index e8059de7..dfedb885 100644
--- a/includes/create-theme/theme-json.php
+++ b/includes/create-theme/theme-json.php
@@ -9,7 +9,7 @@ public static function add_theme_json_to_local( $export_type ) {
);
}
- public static function add_theme_json_variation_to_local( $export_type, $theme ) {
+ public static function add_theme_json_variation_to_local( $export_type, $theme, $save_fonts = false ) {
$variation_path = get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'styles' . DIRECTORY_SEPARATOR;
if ( ! file_exists( $variation_path ) ) {
@@ -20,18 +20,28 @@ public static function add_theme_json_variation_to_local( $export_type, $theme )
return new WP_Error( 'variation_already_exists', __( 'Variation already exists.', 'create-block-theme' ) );
}
- $_POST['theme']['variation_slug'] = $theme['slug'];
-
- $extra_theme_data = array(
- 'version' => WP_Theme_JSON::LATEST_SCHEMA,
- 'title' => $theme['name'],
- );
-
- $variation_theme_json = CBT_Theme_JSON_Resolver::export_theme_data( $export_type, $extra_theme_data );
+ $theme_json = class_exists( 'WP_Theme_JSON_Gutenberg' ) ? new WP_Theme_JSON_Gutenberg() : new WP_Theme_JSON();
+ $user_data = CBT_Theme_JSON_Resolver::get_user_data();
+ $theme_json->merge( $user_data );
+ $variation = $theme_json->get_data();
+ $variation['title'] = $theme['name'];
+
+ if (
+ $save_fonts &&
+ isset( $variation['settings']['typography']['fontFamilies'] )
+ ) {
+ $font_families = $variation['settings']['typography']['fontFamilies'];
+ // Copy the font assets to the theme assets folder.
+ $copied_font_families = CBT_Theme_Fonts::copy_font_assets_to_theme( $font_families );
+ // Update the the variation theme json with the font families with the new paths.
+ $variation['settings']['typography']['fontFamilies'] = $copied_font_families;
+ }
file_put_contents(
$variation_path . $theme['slug'] . '.json',
- $variation_theme_json
+ CBT_Theme_JSON_Resolver::stringify( $variation )
);
+
+ return $variation;
}
}
diff --git a/src/editor-sidebar/create-variation-panel.js b/src/editor-sidebar/create-variation-panel.js
index 6a26481a..daa00221 100644
--- a/src/editor-sidebar/create-variation-panel.js
+++ b/src/editor-sidebar/create-variation-panel.js
@@ -3,18 +3,24 @@
*/
import { __ } from '@wordpress/i18n';
import { useState } from '@wordpress/element';
-import { useDispatch } from '@wordpress/data';
+import { useDispatch, useSelect } from '@wordpress/data';
import { store as noticesStore } from '@wordpress/notices';
import {
// eslint-disable-next-line @wordpress/no-unsafe-wp-apis
__experimentalVStack as VStack,
// eslint-disable-next-line @wordpress/no-unsafe-wp-apis
__experimentalText as Text,
+ // eslint-disable-next-line @wordpress/no-unsafe-wp-apis
+ __experimentalSpacer as Spacer,
+ // eslint-disable-next-line @wordpress/no-unsafe-wp-apis
+ __experimentalView as View,
PanelBody,
Button,
TextControl,
+ CheckboxControl,
} from '@wordpress/components';
import { copy } from '@wordpress/icons';
+import { store as preferencesStore } from '@wordpress/preferences';
/**
* Internal dependencies
@@ -22,6 +28,9 @@ import { copy } from '@wordpress/icons';
import { postCreateThemeVariation } from '../resolvers';
import ScreenHeader from './screen-header';
+const PREFERENCE_SCOPE = 'create-block-theme';
+const PREFERENCE_KEY = 'create-variation';
+
export const CreateVariationPanel = () => {
const { createErrorNotice } = useDispatch( noticesStore );
@@ -29,8 +38,32 @@ export const CreateVariationPanel = () => {
name: '',
} );
+ const preference = useSelect( ( select ) => {
+ const _preference = select( preferencesStore ).get(
+ PREFERENCE_SCOPE,
+ PREFERENCE_KEY
+ );
+ return {
+ saveFonts: _preference?.saveFonts ?? true,
+ };
+ }, [] );
+
+ const handleTogglePreference = ( key ) => {
+ setPreference( PREFERENCE_SCOPE, PREFERENCE_KEY, {
+ ...preference,
+ [ key ]: ! preference[ key ],
+ } );
+ };
+
+ const { set: setPreference } = useDispatch( preferencesStore );
+
const handleCreateVariationClick = () => {
- postCreateThemeVariation( theme.name )
+ const variationPreferences = {
+ name: theme.name,
+ ...preference,
+ };
+
+ postCreateThemeVariation( variationPreferences )
.then( () => {
// eslint-disable-next-line no-alert
window.alert(
@@ -57,29 +90,57 @@ export const CreateVariationPanel = () => {
+
-
+
{ __(
'Save the Global Styles changes as a theme variation.',
'create-block-theme'
) }
-
-
- setTheme( { ...theme, name: value } )
- }
- />
-
-
+
+
+
+
+
+ setTheme( { ...theme, name: value } )
+ }
+ />
+
+
+ handleTogglePreference( 'saveFonts' )
+ }
+ />
+
+
+
+
+
);
diff --git a/src/resolvers.js b/src/resolvers.js
index 21d8f53d..1a9f75ac 100644
--- a/src/resolvers.js
+++ b/src/resolvers.js
@@ -101,11 +101,11 @@ export async function fetchReadmeData() {
} );
}
-export async function postCreateThemeVariation( name ) {
+export async function postCreateThemeVariation( preferences ) {
return apiFetch( {
path: '/create-block-theme/v1/create-variation',
method: 'POST',
- data: { name },
+ data: preferences,
headers: {
'Content-Type': 'application/json',
},