1<?php 2/** 3 * Server-side rendering of the `core/legacy-widget` block. 4 * 5 * @package WordPress 6 */ 7 8/** 9 * Renders the 'core/legacy-widget' block. 10 * 11 * @param array $attributes The block attributes. 12 * 13 * @return string Rendered block. 14 */ 15function render_block_core_legacy_widget( $attributes ) { 16 global $wp_widget_factory; 17 18 if ( isset( $attributes['id'] ) ) { 19 $sidebar_id = wp_find_widgets_sidebar( $attributes['id'] ); 20 return wp_render_widget( $attributes['id'], $sidebar_id ); 21 } 22 23 if ( ! isset( $attributes['idBase'] ) ) { 24 return ''; 25 } 26 27 $id_base = $attributes['idBase']; 28 if ( method_exists( $wp_widget_factory, 'get_widget_key' ) && method_exists( $wp_widget_factory, 'get_widget_object' ) ) { 29 $widget_key = $wp_widget_factory->get_widget_key( $id_base ); 30 $widget_object = $wp_widget_factory->get_widget_object( $id_base ); 31 } else { 32 /* 33 * This file is copied from the published @wordpress/widgets package when WordPress 34 * Core is built. Because the package is a dependency of both WordPress Core and the 35 * Gutenberg plugin where the block editor is developed, this fallback condition is 36 * required until the minimum required version of WordPress for the plugin is raised 37 * to 5.8. 38 */ 39 $widget_key = gutenberg_get_widget_key( $id_base ); 40 $widget_object = gutenberg_get_widget_object( $id_base ); 41 } 42 43 if ( ! $widget_key || ! $widget_object ) { 44 return ''; 45 } 46 47 if ( isset( $attributes['instance']['encoded'], $attributes['instance']['hash'] ) ) { 48 $serialized_instance = base64_decode( $attributes['instance']['encoded'] ); 49 if ( wp_hash( $serialized_instance ) !== $attributes['instance']['hash'] ) { 50 return ''; 51 } 52 $instance = unserialize( $serialized_instance ); 53 } else { 54 $instance = array(); 55 } 56 57 $args = array( 58 'widget_id' => $widget_object->id, 59 'widget_name' => $widget_object->name, 60 ); 61 62 ob_start(); 63 the_widget( $widget_key, $instance, $args ); 64 return ob_get_clean(); 65} 66 67/** 68 * Registers the 'core/legacy-widget' block. 69 */ 70function register_block_core_legacy_widget() { 71 register_block_type_from_metadata( 72 __DIR__ . '/legacy-widget', 73 array( 74 'render_callback' => 'render_block_core_legacy_widget', 75 ) 76 ); 77} 78 79add_action( 'init', 'register_block_core_legacy_widget' ); 80 81/** 82 * Intercepts any request with legacy-widget-preview in the query param and, if 83 * set, renders a page containing a preview of the requested Legacy Widget 84 * block. 85 */ 86function handle_legacy_widget_preview_iframe() { 87 if ( empty( $_GET['legacy-widget-preview'] ) ) { 88 return; 89 } 90 91 if ( ! current_user_can( 'edit_theme_options' ) ) { 92 return; 93 } 94 95 define( 'IFRAME_REQUEST', true ); 96 97 ?> 98 <!doctype html> 99 <html <?php language_attributes(); ?>> 100 <head> 101 <meta charset="<?php bloginfo( 'charset' ); ?>" /> 102 <meta name="viewport" content="width=device-width, initial-scale=1" /> 103 <link rel="profile" href="https://gmpg.org/xfn/11" /> 104 <?php wp_head(); ?> 105 <style> 106 /* Reset theme styles */ 107 html, body, #page, #content { 108 padding: 0 !important; 109 margin: 0 !important; 110 } 111 </style> 112 </head> 113 <body <?php body_class(); ?>> 114 <div id="page" class="site"> 115 <div id="content" class="site-content"> 116 <?php 117 $registry = WP_Block_Type_Registry::get_instance(); 118 $block = $registry->get_registered( 'core/legacy-widget' ); 119 echo $block->render( $_GET['legacy-widget-preview'] ); 120 ?> 121 </div><!-- #content --> 122 </div><!-- #page --> 123 <?php wp_footer(); ?> 124 </body> 125 </html> 126 <?php 127 128 exit; 129} 130 131// Use admin_init instead of init to ensure get_current_screen function is already available. 132// This isn't strictly required, but enables better compatibility with existing plugins. 133// See: https://github.com/WordPress/gutenberg/issues/32624. 134add_action( 'admin_init', 'handle_legacy_widget_preview_iframe', 20 ); 135