|
1 <?php |
|
2 /** |
|
3 * Theme previews using the Site Editor for block themes. |
|
4 * |
|
5 * @package WordPress |
|
6 */ |
|
7 |
|
8 /** |
|
9 * Filters the blog option to return the path for the previewed theme. |
|
10 * |
|
11 * @since 6.3.0 |
|
12 * |
|
13 * @param string $current_stylesheet The current theme's stylesheet or template path. |
|
14 * @return string The previewed theme's stylesheet or template path. |
|
15 */ |
|
16 function wp_get_theme_preview_path( $current_stylesheet = null ) { |
|
17 if ( ! current_user_can( 'switch_themes' ) ) { |
|
18 return $current_stylesheet; |
|
19 } |
|
20 |
|
21 $preview_stylesheet = ! empty( $_GET['wp_theme_preview'] ) ? sanitize_text_field( wp_unslash( $_GET['wp_theme_preview'] ) ) : null; |
|
22 $wp_theme = wp_get_theme( $preview_stylesheet ); |
|
23 if ( ! is_wp_error( $wp_theme->errors() ) ) { |
|
24 if ( current_filter() === 'template' ) { |
|
25 $theme_path = $wp_theme->get_template(); |
|
26 } else { |
|
27 $theme_path = $wp_theme->get_stylesheet(); |
|
28 } |
|
29 |
|
30 return sanitize_text_field( $theme_path ); |
|
31 } |
|
32 |
|
33 return $current_stylesheet; |
|
34 } |
|
35 |
|
36 /** |
|
37 * Adds a middleware to `apiFetch` to set the theme for the preview. |
|
38 * This adds a `wp_theme_preview` URL parameter to API requests from the Site Editor, so they also respond as if the theme is set to the value of the parameter. |
|
39 * |
|
40 * @since 6.3.0 |
|
41 */ |
|
42 function wp_attach_theme_preview_middleware() { |
|
43 // Don't allow non-admins to preview themes. |
|
44 if ( ! current_user_can( 'switch_themes' ) ) { |
|
45 return; |
|
46 } |
|
47 |
|
48 wp_add_inline_script( |
|
49 'wp-api-fetch', |
|
50 sprintf( |
|
51 'wp.apiFetch.use( wp.apiFetch.createThemePreviewMiddleware( %s ) );', |
|
52 wp_json_encode( sanitize_text_field( wp_unslash( $_GET['wp_theme_preview'] ) ) ) |
|
53 ), |
|
54 'after' |
|
55 ); |
|
56 } |
|
57 |
|
58 /** |
|
59 * Set a JavaScript constant for theme activation. |
|
60 * |
|
61 * Sets the JavaScript global WP_BLOCK_THEME_ACTIVATE_NONCE containing the nonce |
|
62 * required to activate a theme. For use within the site editor. |
|
63 * |
|
64 * @see https://github.com/WordPress/gutenberg/pull/41836 |
|
65 * |
|
66 * @since 6.3.0 |
|
67 * @access private |
|
68 */ |
|
69 function wp_block_theme_activate_nonce() { |
|
70 $nonce_handle = 'switch-theme_' . wp_get_theme_preview_path(); |
|
71 ?> |
|
72 <script type="text/javascript"> |
|
73 window.WP_BLOCK_THEME_ACTIVATE_NONCE = <?php echo wp_json_encode( wp_create_nonce( $nonce_handle ) ); ?>; |
|
74 </script> |
|
75 <?php |
|
76 } |
|
77 |
|
78 /** |
|
79 * Add filters and actions to enable Block Theme Previews in the Site Editor. |
|
80 * |
|
81 * The filters and actions should be added after `pluggable.php` is included as they may |
|
82 * trigger code that uses `current_user_can()` which requires functionality from `pluggable.php`. |
|
83 * |
|
84 * @since 6.3.2 |
|
85 */ |
|
86 function wp_initialize_theme_preview_hooks() { |
|
87 if ( ! empty( $_GET['wp_theme_preview'] ) ) { |
|
88 add_filter( 'stylesheet', 'wp_get_theme_preview_path' ); |
|
89 add_filter( 'template', 'wp_get_theme_preview_path' ); |
|
90 add_action( 'init', 'wp_attach_theme_preview_middleware' ); |
|
91 add_action( 'admin_head', 'wp_block_theme_activate_nonce' ); |
|
92 } |
|
93 } |