Skip to content

Commit

Permalink
This ensures that any theme exports get the benefit of the latest cha…
Browse files Browse the repository at this point in the history
…nges to theme json and resolver.
  • Loading branch information
ramonjd committed May 10, 2024
1 parent 0a1cc1f commit 1f9b09c
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 2 deletions.
108 changes: 108 additions & 0 deletions lib/compat/wordpress-6.6/block-template-utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -360,3 +360,111 @@ function gutenberg_get_block_templates( $query = array(), $template_type = 'wp_t
*/
return apply_filters( 'get_block_templates', $query_result, $query, $template_type );
}

/**
* Creates an export of the current templates and
* template parts from the site editor at the
* specified path in a ZIP file.
*
* @since 5.9.0
* @since 6.0.0 Adds the whole theme to the export archive.
*
* @global string $wp_version The WordPress version string.
*
* @return WP_Error|string Path of the ZIP file or error on failure.
*/
function gutenberg_generate_block_templates_export_file() {
global $wp_version;

if ( ! class_exists( 'ZipArchive' ) ) {
return new WP_Error( 'missing_zip_package', __( 'Zip Export not supported.' ) );
}

$obscura = wp_generate_password( 12, false, false );
$theme_name = basename( get_stylesheet() );
$filename = get_temp_dir() . $theme_name . $obscura . '.zip';

$zip = new ZipArchive();
if ( true !== $zip->open( $filename, ZipArchive::CREATE | ZipArchive::OVERWRITE ) ) {
return new WP_Error( 'unable_to_create_zip', __( 'Unable to open export file (archive) for writing.' ) );
}

$zip->addEmptyDir( 'templates' );
$zip->addEmptyDir( 'parts' );

// Get path of the theme.
$theme_path = wp_normalize_path( get_stylesheet_directory() );

// Create recursive directory iterator.
$theme_files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator( $theme_path ),
RecursiveIteratorIterator::LEAVES_ONLY
);

// Make a copy of the current theme.
foreach ( $theme_files as $file ) {
// Skip directories as they are added automatically.
if ( ! $file->isDir() ) {
// Get real and relative path for current file.
$file_path = wp_normalize_path( $file );
$relative_path = substr( $file_path, strlen( $theme_path ) + 1 );

if ( ! wp_is_theme_directory_ignored( $relative_path ) ) {
$zip->addFile( $file_path, $relative_path );
}
}
}

// Load templates into the zip file.
$templates = gutenberg_get_block_templates();
foreach ( $templates as $template ) {
$template->content = traverse_and_serialize_blocks(
parse_blocks( $template->content ),
'_remove_theme_attribute_from_template_part_block'
);

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

// Load template parts into the zip file.
$template_parts = gutenberg_get_block_templates( array(), 'wp_template_part' );
foreach ( $template_parts as $template_part ) {
$zip->addFromString(
'parts/' . $template_part->slug . '.html',
$template_part->content
);
}

// Load theme.json into the zip file.
$tree = WP_Theme_JSON_Resolver_Gutenberg::get_theme_data( array(), array( 'with_supports' => false ) );
// Merge with user data.
$tree->merge( WP_Theme_JSON_Resolver_Gutenberg::get_user_data() );

$theme_json_raw = $tree->get_data();
// If a version is defined, add a schema.
if ( $theme_json_raw['version'] ) {
$theme_json_version = 'wp/' . substr( $wp_version, 0, 3 );
$schema = array( '$schema' => 'https://schemas.wp.org/' . $theme_json_version . '/theme.json' );
$theme_json_raw = array_merge( $schema, $theme_json_raw );
}

// Convert to a string.
$theme_json_encoded = wp_json_encode( $theme_json_raw, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );

// Replace 4 spaces with a tab.
$theme_json_tabbed = preg_replace( '~(?:^|\G)\h{4}~m', "\t", $theme_json_encoded );

// Add the theme.json file to the zip.
$zip->addFromString(
'theme.json',
$theme_json_tabbed
);

// Save changes to the zip file.
$zip->close();

return $filename;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
/**
* REST API: WP_REST_Edit_Site_Export_Controller class
*
* @package WordPress
* @subpackage REST_API
*/

/**
* Controller which provides REST endpoint for exporting current templates
* and template parts.
*
* @since 5.9.0
*
* @see WP_REST_Controller
*/

if ( class_exists( 'Gutenberg_REST_Edit_Site_Export_Controller_6_6' ) ) {
return;
}

class Gutenberg_REST_Edit_Site_Export_Controller_6_6 extends WP_REST_Edit_Site_Export_Controller {
/**
* Output a ZIP file with an export of the current templates
* and template parts from the site editor, and close the connection.
*
* @since 5.9.0
*
* @return WP_Error|void
*/
public function export() {
// Generate the export file.
$filename = gutenberg_generate_block_templates_export_file();

if ( is_wp_error( $filename ) ) {
$filename->add_data( array( 'status' => 500 ) );

return $filename;
}

$theme_name = basename( get_stylesheet() );
header( 'Content-Type: application/zip' );
header( 'Content-Disposition: attachment; filename=' . $theme_name . '.zip' );
header( 'Content-Length: ' . filesize( $filename ) );
flush();
readfile( $filename );
unlink( $filename );
exit;
}
}
10 changes: 10 additions & 0 deletions lib/compat/wordpress-6.6/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,13 @@ function gutenberg_add_class_list_to_public_post_types() {
}
}
add_action( 'rest_api_init', 'gutenberg_add_class_list_to_public_post_types' );

/**
* Registers the Edit Site Export REST API routes.
*/
function gutenberg_register_edit_site_export_controller_endpoints() {
$edit_site_export_controller = new Gutenberg_REST_Edit_Site_Export_Controller_6_6();
$edit_site_export_controller->register_routes();
}

add_action( 'rest_api_init', 'gutenberg_register_edit_site_export_controller_endpoints' );
7 changes: 5 additions & 2 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ function gutenberg_is_experiment_enabled( $name ) {
require_once __DIR__ . '/compat/wordpress-6.5/class-gutenberg-rest-global-styles-revisions-controller-6-5.php';
require_once __DIR__ . '/compat/wordpress-6.5/rest-api.php';

// WordPress 6.6 compat.
require_once __DIR__ . '/compat/wordpress-6.6/class-gutenberg-rest-edit-site-export-controller-6-6.php';
require __DIR__ . '/compat/wordpress-6.6/class-gutenberg-rest-templates-controller-6-6.php';
require __DIR__ . '/compat/wordpress-6.6/rest-api.php';

// Plugin specific code.
require_once __DIR__ . '/class-wp-rest-global-styles-controller-gutenberg.php';
require_once __DIR__ . '/rest-api.php';
Expand Down Expand Up @@ -130,8 +135,6 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/compat/wordpress-6.6/block-bindings/pattern-overrides.php';
require __DIR__ . '/compat/wordpress-6.6/block-template-utils.php';
require __DIR__ . '/compat/wordpress-6.6/option.php';
require __DIR__ . '/compat/wordpress-6.6/class-gutenberg-rest-templates-controller-6-6.php';
require __DIR__ . '/compat/wordpress-6.6/rest-api.php';
require __DIR__ . '/compat/wordpress-6.6/post.php';

// Experimental features.
Expand Down

0 comments on commit 1f9b09c

Please sign in to comment.