diff --git a/lib/load.php b/lib/load.php index a0996f3b94f4ff..35b49b2ead5b95 100644 --- a/lib/load.php +++ b/lib/load.php @@ -41,6 +41,7 @@ require dirname( __FILE__ ) . '/blocks.php'; require dirname( __FILE__ ) . '/templates.php'; +require dirname( __FILE__ ) . '/template-loader.php'; require dirname( __FILE__ ) . '/client-assets.php'; require dirname( __FILE__ ) . '/demo.php'; require dirname( __FILE__ ) . '/widgets.php'; diff --git a/lib/template-canvas.php b/lib/template-canvas.php new file mode 100644 index 00000000000000..a0e0da7ea01752 --- /dev/null +++ b/lib/template-canvas.php @@ -0,0 +1,23 @@ + + +> + + + + + +> + + + + + + + diff --git a/lib/template-loader.php b/lib/template-loader.php new file mode 100644 index 00000000000000..1c6923091ce323 --- /dev/null +++ b/lib/template-loader.php @@ -0,0 +1,177 @@ + 'wp_template', + 'post_status' => 'publish', + 'post_name__in' => $slugs, + 'orderby' => 'post_name__in', + 'posts_per_page' => 1, + ) + ); + + if ( $template_query->have_posts() ) { + $template_posts = $template_query->get_posts(); + $_wp_current_template_post = array_shift( $template_posts ); + } + + // Add extra hooks for template canvas. + add_action( 'wp_head', 'gutenberg_viewport_meta_tag', 0 ); + remove_action( 'wp_head', '_wp_render_title_tag', 1 ); + add_action( 'wp_head', 'gutenberg_render_title_tag', 1 ); + + // This file will be included instead of the theme's template file. + return gutenberg_dir_path() . 'lib/template-canvas.php'; +} + +/** + * Displays title tag with content, regardless of whether theme has title-tag support. + * + * @see _wp_render_title_tag() + */ +function gutenberg_render_title_tag() { + echo '' . wp_get_document_title() . '' . "\n"; +} + +/** + * Renders the markup for the current template. + */ +function gutenberg_render_the_template() { + global $_wp_current_template_post; + global $wp_embed; + + if ( ! $_wp_current_template_post || 'wp_template' !== $_wp_current_template_post->post_type ) { + echo '

' . esc_html__( 'No matching template found', 'gutenberg' ) . '

'; + return; + } + + $content = $_wp_current_template_post->post_content; + + $content = $wp_embed->run_shortcode( $content ); + $content = $wp_embed->autoembed( $content ); + $content = do_blocks( $content ); + $content = wptexturize( $content ); + $content = wp_make_content_images_responsive( $content ); + $content = str_replace( ']]>', ']]>', $content ); + + // Wrap block template in .wp-site-blocks to allow for specific descendant styles + // (e.g. `.wp-site-blocks > *`). + echo '
'; + echo $content; // phpcs:ignore WordPress.Security.EscapeOutput + echo '
'; +} + +/** + * Renders a 'viewport' meta tag. + * + * This is hooked into {@see 'wp_head'} to decouple its output from the default template canvas. + */ +function gutenberg_viewport_meta_tag() { + echo '' . "\n"; +} + +/** + * Strips .php suffix from template file names. + * + * @access private + * + * @param string $template_file Template file name. + * @return string Template file name without extension. + */ +function gutenberg_strip_php_suffix( $template_file ) { + return preg_replace( '/\.php$/', '', $template_file ); +} diff --git a/lib/templates.php b/lib/templates.php index dce2905b0ae52d..35b81aaf41100e 100644 --- a/lib/templates.php +++ b/lib/templates.php @@ -10,7 +10,7 @@ */ function gutenberg_register_template_post_type() { if ( - get_option( 'gutenberg-experiments' ) && + ! get_option( 'gutenberg-experiments' ) || ! array_key_exists( 'gutenberg-full-site-editing', get_option( 'gutenberg-experiments' ) ) ) { return; @@ -65,3 +65,32 @@ function gutenberg_grant_template_caps( array $allcaps ) { return $allcaps; } add_filter( 'user_has_cap', 'gutenberg_grant_template_caps' ); + +/** + * Filters capabilities to prevent deletion of the 'wp_template' post with slug 'index'. + * + * Similar to today's themes, this template should always exist. + * + * @param array $caps Array of the user's capabilities. + * @param string $cap Capability name. + * @param int $user_id The user ID. + * @param array $args Adds the context to the cap. Typically the object ID. + * @return array Filtered $caps. + */ +function gutenberg_prevent_index_template_deletion( $caps, $cap, $user_id, $args ) { + if ( 'delete_post' !== $cap || ! isset( $args[0] ) ) { + return $caps; + } + + $post = get_post( $args[0] ); + if ( ! $post || 'wp_template' !== $post->post_type ) { + return $caps; + } + + if ( 'index' === $post->post_name ) { + $caps[] = 'do_not_allow'; + } + + return $caps; +} +add_filter( 'map_meta_cap', 'gutenberg_prevent_index_template_deletion', 10, 4 );