diff --git a/includes/class-create-block-theme-api.php b/includes/class-create-block-theme-api.php
index 604fa75b..54d23104 100644
--- a/includes/class-create-block-theme-api.php
+++ b/includes/class-create-block-theme-api.php
@@ -144,6 +144,17 @@ public function register_rest_routes() {
},
),
);
+ register_rest_route(
+ 'create-block-theme/v1',
+ '/reset-theme',
+ array(
+ 'methods' => WP_REST_Server::EDITABLE,
+ 'callback' => array( $this, 'rest_reset_theme' ),
+ 'permission_callback' => function () {
+ return current_user_can( 'edit_theme_options' );
+ },
+ ),
+ );
}
function rest_get_theme_data( $request ) {
@@ -371,6 +382,7 @@ function rest_save_theme( $request ) {
}
}
CBT_Theme_Templates::clear_user_templates_customizations();
+ CBT_Theme_Templates::clear_user_template_parts_customizations();
}
if ( isset( $options['saveStyle'] ) && true === $options['saveStyle'] ) {
@@ -410,6 +422,32 @@ function rest_get_font_families( $request ) {
);
}
+ /**
+ * Reset the theme to the default state.
+ */
+ function rest_reset_theme( $request ) {
+ $options = $request->get_params();
+
+ if ( isset( $options['resetStyles'] ) && true === $options['resetStyles'] ) {
+ CBT_Theme_Styles::clear_user_styles_customizations();
+ }
+
+ if ( isset( $options['resetTemplates'] ) && true === $options['resetTemplates'] ) {
+ CBT_Theme_Templates::clear_user_templates_customizations();
+ }
+
+ if ( isset( $options['resetTemplateParts'] ) && true === $options['resetTemplateParts'] ) {
+ CBT_Theme_Templates::clear_user_template_parts_customizations();
+ }
+
+ return rest_ensure_response(
+ array(
+ 'status' => 'SUCCESS',
+ 'message' => __( 'Theme Reset.', 'create-block-theme' ),
+ )
+ );
+ }
+
private function sanitize_theme_data( $theme ) {
$sanitized_theme['name'] = sanitize_text_field( $theme['name'] );
$sanitized_theme['description'] = sanitize_text_field( $theme['description'] ?? '' );
diff --git a/includes/create-theme/theme-templates.php b/includes/create-theme/theme-templates.php
index 3298e7ee..7b1ea1bf 100644
--- a/includes/create-theme/theme-templates.php
+++ b/includes/create-theme/theme-templates.php
@@ -106,17 +106,22 @@ public static function replace_template_namespace( $template, $new_slug ) {
* This will remove all user templates from the database.
*/
public static function clear_user_templates_customizations() {
- //remove all user templates (they have been saved in the theme)
- $templates = get_block_templates();
- $template_parts = get_block_templates( array(), 'wp_template_part' );
- foreach ( $template_parts as $template ) {
+ $templates = get_block_templates();
+ foreach ( $templates as $template ) {
if ( 'custom' !== $template->source ) {
continue;
}
wp_delete_post( $template->wp_id, true );
}
+ }
- foreach ( $templates as $template ) {
+ /**
+ * Clear all user template-parts customizations.
+ * This will remove all user template-parts from the database.
+ */
+ public static function clear_user_template_parts_customizations() {
+ $template_parts = get_block_templates( array(), 'wp_template_part' );
+ foreach ( $template_parts as $template ) {
if ( 'custom' !== $template->source ) {
continue;
}
diff --git a/src/editor-sidebar/reset-theme.js b/src/editor-sidebar/reset-theme.js
new file mode 100644
index 00000000..3ee5501b
--- /dev/null
+++ b/src/editor-sidebar/reset-theme.js
@@ -0,0 +1,160 @@
+/**
+ * WordPress dependencies
+ */
+import { __ } from '@wordpress/i18n';
+import { useDispatch, useSelect } from '@wordpress/data';
+import { store as noticesStore } from '@wordpress/notices';
+import {
+ // eslint-disable-next-line @wordpress/no-unsafe-wp-apis
+ __experimentalConfirmDialog as ConfirmDialog,
+ // eslint-disable-next-line @wordpress/no-unsafe-wp-apis
+ __experimentalVStack as VStack,
+ PanelBody,
+ Button,
+ CheckboxControl,
+} from '@wordpress/components';
+import { trash } from '@wordpress/icons';
+import { useState } from '@wordpress/element';
+import { store as preferencesStore } from '@wordpress/preferences';
+
+/**
+ * Internal dependencies
+ */
+import ScreenHeader from './screen-header';
+import { resetTheme } from '../resolvers';
+
+const PREFERENCE_SCOPE = 'create-block-theme';
+const PREFERENCE_KEY = 'reset-theme';
+
+function ResetTheme() {
+ const preferences = useSelect( ( select ) => {
+ const _preference = select( preferencesStore ).get(
+ PREFERENCE_SCOPE,
+ PREFERENCE_KEY
+ );
+ return {
+ resetStyles: _preference?.resetStyles ?? true,
+ resetTemplates: _preference?.resetTemplates ?? true,
+ resetTemplateParts: _preference?.resetTemplateParts ?? true,
+ };
+ }, [] );
+
+ const { set: setPreferences } = useDispatch( preferencesStore );
+ const { createErrorNotice } = useDispatch( noticesStore );
+ const [ isConfirmDialogOpen, setIsConfirmDialogOpen ] = useState( false );
+
+ const handleTogglePreference = ( key ) => {
+ setPreferences( PREFERENCE_SCOPE, PREFERENCE_KEY, {
+ ...preferences,
+ [ key ]: ! preferences[ key ],
+ } );
+ };
+
+ const toggleConfirmDialog = () => {
+ setIsConfirmDialogOpen( ! isConfirmDialogOpen );
+ };
+
+ const handleResetTheme = async () => {
+ try {
+ await resetTheme( preferences );
+ toggleConfirmDialog();
+ // eslint-disable-next-line no-alert
+ window.alert(
+ __(
+ 'Theme reset successfully. The editor will now reload.',
+ 'create-block-theme'
+ )
+ );
+ window.location.reload();
+ } catch ( error ) {
+ createErrorNotice(
+ __(
+ 'An error occurred while resetting the theme.',
+ 'create-block-theme'
+ )
+ );
+ }
+ };
+
+ return (
+ <>
+
+ { __(
+ 'Are you sure you want to reset the theme? This action cannot be undone.',
+ 'create-block-theme'
+ ) }
+
+
+
+
+
+ handleTogglePreference( 'resetStyles' )
+ }
+ />
+
+
+ handleTogglePreference( 'resetTemplates' )
+ }
+ />
+
+
+ handleTogglePreference( 'resetTemplateParts' )
+ }
+ />
+
+
+
+
+ >
+ );
+}
+
+export default ResetTheme;
diff --git a/src/plugin-sidebar.js b/src/plugin-sidebar.js
index 08c6e274..1c65631a 100644
--- a/src/plugin-sidebar.js
+++ b/src/plugin-sidebar.js
@@ -39,6 +39,7 @@ import {
addCard,
blockMeta,
help,
+ trash,
} from '@wordpress/icons';
/**
@@ -52,8 +53,9 @@ import { ThemeMetadataEditorModal } from './editor-sidebar/metadata-editor-modal
import ScreenHeader from './editor-sidebar/screen-header';
import { downloadExportedTheme } from './resolvers';
import downloadFile from './utils/download-file';
-import './plugin-styles.scss';
import AboutPlugin from './editor-sidebar/about';
+import ResetTheme from './editor-sidebar/reset-theme';
+import './plugin-styles.scss';
const CreateBlockThemePlugin = () => {
const [ isEditorOpen, setIsEditorOpen ] = useState( false );
@@ -190,6 +192,21 @@ const CreateBlockThemePlugin = () => {
+
+
+
+
+ { __(
+ 'Reset Theme',
+ 'create-block-theme'
+ ) }
+
+
+
+
+
+
+
{
+
+
+
+
diff --git a/src/resolvers.js b/src/resolvers.js
index e7a81f57..21d8f53d 100644
--- a/src/resolvers.js
+++ b/src/resolvers.js
@@ -144,3 +144,23 @@ export async function getFontFamilies() {
} );
return response.data;
}
+
+export async function resetTheme( preferences ) {
+ return apiFetch( {
+ path: '/create-block-theme/v1/reset-theme',
+ method: 'PATCH',
+ data: preferences,
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ } ).then( ( response ) => {
+ if ( 'SUCCESS' !== response?.status ) {
+ throw new Error(
+ `Failed to reset theme: ${
+ response?.message || response?.status
+ }`
+ );
+ }
+ return response;
+ } );
+}