Skip to content

Commit

Permalink
Added a 'save' option (#51)
Browse files Browse the repository at this point in the history
* Added a 'save' option to save the theme.json and template changes to local theme folder
* Remove user global styles settings when saving
* Remove templates from user-space when 'saving' theme
* Export theme.json with tabs not spaces
  • Loading branch information
pbking authored Mar 28, 2022
1 parent 4f33d0a commit 1f1c347
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 61 deletions.
241 changes: 181 additions & 60 deletions admin/class-create-block-theme-admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,45 @@ function create_admin_menu() {
add_theme_page( $page_title, $menu_title, 'edit_theme_options', 'create-block-theme', [ $this, 'create_admin_form_page' ] );
}

function save_theme_locally( $export_type ) {
$this->add_templates_to_local( $export_type );
$this->add_theme_json_to_local( $export_type );
}

function clear_user_customizations() {

// Clear all values in the user theme.json
$user_custom_post_type_id = WP_Theme_JSON_Resolver_Gutenberg::get_user_global_styles_post_id();
$global_styles_controller = new Gutenberg_REST_Global_Styles_Controller();
$update_request = new WP_REST_Request( 'PUT', '/wp/v2/global-styles/' );
$update_request->set_param( 'id', $user_custom_post_type_id );
$update_request->set_param( 'settings', [] );
$update_request->set_param( 'styles', [] );
$updated_global_styles = $global_styles_controller->update_item( $update_request );
delete_transient( 'global_styles' );
delete_transient( 'global_styles_' . get_stylesheet() );
delete_transient( 'gutenberg_global_styles' );
delete_transient( 'gutenberg_global_styles_' . get_stylesheet() );

//remove all user templates (they have been saved in the theme)
$templates = gutenberg_get_block_templates();
$template_parts = gutenberg_get_block_templates( array(), 'wp_template_part' );
foreach ( $template_parts as $template ) {
if ( $template->source !== 'custom' ) {
continue;
}
wp_delete_post($template->wp_id, true);
}

foreach ( $templates as $template ) {
if ( $template->source !== 'custom' ) {
continue;
}
wp_delete_post($template->wp_id, true);
}

}

/**
* Export activated child theme
*/
Expand Down Expand Up @@ -233,14 +272,20 @@ function export_theme( $theme ) {
}

function add_theme_json_to_zip ( $zip, $export_type ) {
$theme_json = MY_Theme_JSON_Resolver::export_theme_data( $export_type );
$zip->addFromString(
'theme.json',
wp_json_encode( $theme_json, JSON_PRETTY_PRINT )
MY_Theme_JSON_Resolver::export_theme_data( $export_type )
);
return $zip;
}

function add_theme_json_to_local ( $export_type ) {
file_put_contents(
get_template_directory() . '/theme.json',
MY_Theme_JSON_Resolver::export_theme_data( $export_type )
);
}

function copy_theme_to_zip( $zip, $new_slug, $new_name ) {

// Get real path for our folder
Expand Down Expand Up @@ -331,80 +376,116 @@ function get_theme_slug( $new_theme_name ) {
return $new_slug;
}

/**
* Add block templates and parts to the zip.
*
* @since 0.0.2
* @param object $zip The zip archive to add the templates to.
* @param string $export_type Determine the templates that should be exported.
* current = templates from currently activated theme (but not a parent theme if there is one) as well as user edited templates
* user = only user edited templates
* all = all templates no matter what
/*
* Filter a template out (return false) based on the export_type expected and the templates origin.
* Templates not filtered out are modified based on the slug information provided and cleaned up
* to have the expected exported value.
*/
function add_templates_to_zip( $zip, $export_type, $new_slug ) {

$templates = gutenberg_get_block_templates();
$template_parts = gutenberg_get_block_templates( array(), 'wp_template_part' );
$old_slug = wp_get_theme()->get( 'TextDomain' );

if ( $templates ) {
$zip->addEmptyDir( 'templates' );
function filter_theme_template( $template, $export_type, $path, $old_slug, $new_slug ) {
if ($template->source === 'theme' && $export_type === 'user') {
return false;
}
if (
$template->source === 'theme' &&
$export_type === 'current' &&
! file_exists( $path . $template->slug . '.html' )
) {
return false;
}

if ( $template_parts ) {
$zip->addEmptyDir( 'parts' );
$template->content = _remove_theme_attribute_in_block_template_content( $template->content );

// NOTE: Dashes are encoded as \u002d in the content that we get (noteably in things like css variables used in templates)
// This replaces that with dashes again. We should consider decoding the entire string but that is proving difficult.
$template->content = str_replace( '\u002d', '-', $template->content );

if ( $new_slug ) {
$template->content = str_replace( $old_slug, $new_slug, $template->content );
}

return $template;
}

/*
* Build a collection of templates and template-parts that should be exported (and modified) based on the given export_type and new slug
*/
function get_theme_templates( $export_type, $new_slug ) {

$old_slug = wp_get_theme()->get( 'TextDomain' );
$templates = gutenberg_get_block_templates();
$template_parts = gutenberg_get_block_templates ( array(), 'wp_template_part' );
$exported_templates = [];
$exported_parts = [];

// build collection of templates/parts in currently activated theme
$templates_paths = get_block_theme_folders();
$templates_path = get_stylesheet_directory() . '/' . $templates_paths['wp_template'] . '/';
$parts_path = get_stylesheet_directory() . '/' . $templates_paths['wp_template_part'] . '/';

foreach ( $templates as $template ) {
if ($template->source === 'theme' && $export_type === 'user') {
continue;
$template = $this->filter_theme_template(
$template,
$export_type,
$templates_path,
$old_slug,
$new_slug
);
if ( $template ) {
$exported_templates[] = $template;
}
}

if (
$template->source === 'theme' &&
$export_type === 'current' &&
! file_exists( $templates_path . $template->slug . '.html' )
) {
continue;
foreach ( $template_parts as $template ) {
$template = $this->filter_theme_template(
$template,
$export_type,
$parts_path,
$old_slug,
$new_slug

);
if ( $template ) {
$exported_parts[] = $template;
}
}

$template->content = _remove_theme_attribute_in_block_template_content( $template->content );
return (object)[
'templates'=>$exported_templates,
'parts'=>$exported_parts
];

}

if ( $new_slug ) {
$template->content = str_replace( $old_slug, $new_slug, $template->content );
}
/**
* Add block templates and parts to the zip.
*
* @since 0.0.2
* @param object $zip The zip archive to add the templates to.
* @param string $export_type Determine the templates that should be exported.
* current = templates from currently activated theme (but not a parent theme if there is one) as well as user edited templates
* user = only user edited templates
* all = all templates no matter what
*/
function add_templates_to_zip( $zip, $export_type, $new_slug ) {

$theme_templates = $this->get_theme_templates( $export_type, $new_slug );

if ( $theme_templates->templates ) {
$zip->addEmptyDir( 'templates' );
}

if ( $theme_templates->parts ) {
$zip->addEmptyDir( 'parts' );
}

foreach ( $theme_templates->templates as $template ) {
$zip->addFromString(
'templates/' . $template->slug . '.html',
$template->content
);
}

foreach ( $template_parts as $template_part ) {
if ($template_part->source === 'theme' && $export_type === 'user') {
continue;
}

if (
$template_part->source === 'theme' &&
$export_type === 'current' &&
! file_exists( $parts_path . $template_part->slug . '.html' )
) {
continue;
}

$template_part->content = _remove_theme_attribute_in_block_template_content( $template_part->content );

if ( $new_slug ) {
$template_part->content = str_replace( $old_slug, $new_slug, $template_part->content );
}

foreach ( $theme_templates->parts as $template_part ) {
$zip->addFromString(
'parts/' . $template_part->slug . '.html',
$template_part->content
Expand All @@ -414,6 +495,25 @@ function add_templates_to_zip( $zip, $export_type, $new_slug ) {
return $zip;
}

function add_templates_to_local( $export_type ) {

$theme_templates = $this->get_theme_templates( $export_type, null );

foreach ( $theme_templates->templates as $template ) {
file_put_contents(
get_template_directory() . '/templates/' . $template->slug . '.html',
$template->content
);
}

foreach ( $theme_templates->parts as $template_part ) {
file_put_contents(
get_template_directory() . '/parts/' . $template_part->slug . '.html',
$template_part->content
);
}
}

function create_zip( $filename ) {
if ( ! class_exists( 'ZipArchive' ) ) {
return new WP_Error( 'Zip Export not supported.' );
Expand Down Expand Up @@ -510,7 +610,7 @@ function create_admin_form_page() {
?>
<div class="wrap">
<h2><?php _e('Create Block Theme', 'create-block-theme'); ?></h2>
<p><?php _e('Save your current block them with changes you made to Templates, Template Parts and Global Styles.', 'create-block-theme'); ?></p>
<p><?php _e('Export your current block them with changes you made to Templates, Template Parts and Global Styles.', 'create-block-theme'); ?></p>
<form method="get">

<label><input checked value="export" type="radio" name="theme[type]" class="regular-text code" onchange="document.getElementById('new_theme_metadata_form').setAttribute('hidden', null);" /><?php _e('Export ', 'create-block-theme'); echo wp_get_theme()->get('Name'); ?></label>
Expand All @@ -525,6 +625,8 @@ function create_admin_form_page() {
<label><input value="clone" type="radio" name="theme[type]" class="regular-text code" onchange="document.getElementById('new_theme_metadata_form').removeAttribute('hidden');"/><?php _e('Clone ', 'create-block-theme'); echo wp_get_theme()->get('Name'); ?>
<?php _e('[Create a new theme cloning the activated theme. The resulting theme will have all of the assets of the activated theme as well as user changes.]', 'create-block-theme'); ?></label><br /><br />
<?php endif; ?>
<label><input value="save" type="radio" name="theme[type]" class="regular-text code" onchange="document.getElementById('new_theme_metadata_form').setAttribute('hidden', null);" /><?php _e('Overwrite ', 'create-block-theme'); echo wp_get_theme()->get('Name'); ?></label>
<?php _e('[Save USER changes as THEME changes and delete the USER changes. Your changes will be saved in the theme on the folder.]', 'create-block-theme'); ?></label><br /><br />

<div hidden id="new_theme_metadata_form">
<label><?php _e('Theme Name', 'create-block-theme'); ?><br /><input type="text" name="theme[name]" class="regular-text" /></label><br /><br />
Expand All @@ -535,15 +637,14 @@ function create_admin_form_page() {
</div>
<input type="hidden" name="page" value="create-block-theme" />
<input type="hidden" name="nonce" value="<?php echo wp_create_nonce( 'create_block_theme' ); ?>" />
<input type="submit" value="<?php _e('Create block theme', 'create-block-theme'); ?>" class="button button-primary" />
<input type="submit" value="<?php _e('Export theme', 'create-block-theme'); ?>" class="button button-primary" />
</form>
</div>
<?php
}

function blockbase_save_theme() {

// I can't work out how to call the API but this works for now.
if ( ! empty( $_GET['page'] ) && $_GET['page'] === 'create-block-theme' && ! empty( $_GET['theme'] ) ) {

// Check user capabilities.
Expand All @@ -556,14 +657,26 @@ function blockbase_save_theme() {
return add_action( 'admin_notices', [ $this, 'admin_notice_error' ] );
}

if ( is_child_theme() ) {
if ( $_GET['theme']['type'] === 'save' ) {
if ( is_child_theme() ) {
$this->save_theme_locally( 'current' );
}
else {
$this->save_theme_locally( 'all' );
}
$this->clear_user_customizations();

add_action( 'admin_notices', [ $this, 'admin_notice_save_success' ] );
}

else if ( is_child_theme() ) {
if ( $_GET['theme']['type'] === 'sibling' ) {
$this->create_sibling_theme( $_GET['theme'] );
}
else {
$this->export_child_theme( $_GET['theme'] );
}

add_action( 'admin_notices', [ $this, 'admin_notice_export_success' ] );
} else {
if( $_GET['theme']['type'] === 'child' ) {
$this->create_child_theme( $_GET['theme'] );
Expand All @@ -574,9 +687,9 @@ function blockbase_save_theme() {
else {
$this->export_theme( $_GET['theme'] );
}
add_action( 'admin_notices', [ $this, 'admin_notice_export_success' ] );
}

add_action( 'admin_notices', [ $this, 'admin_notice_success' ] );
}
}

Expand All @@ -587,10 +700,18 @@ function admin_notice_error() {
printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), esc_html( $message ) );
}

function admin_notice_success() {
function admin_notice_export_success() {
?>
<div class="notice notice-success is-dismissible">
<p><?php _e( 'Block theme exported sucessfuly!', 'create-block-theme' ); ?></p>
</div>
<?php
}

function admin_notice_save_success() {
?>
<div class="notice notice-success is-dismissible">
<p><?php _e( 'New block theme created!', 'create-block-theme' ); ?></p>
<p><?php _e( 'Block theme saved and user customizations cleared!', 'create-block-theme' ); ?></p>
</div>
<?php
}
Expand Down
4 changes: 3 additions & 1 deletion admin/gutenberg_additions.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ public static function export_theme_data( $content ) {

$data = MY_Theme_JSON_Resolver::flatten_theme_json($theme->get_raw_data(), null);

return $data;
$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 );

}

}
Expand Down

0 comments on commit 1f1c347

Please sign in to comment.