legacy-widget.php 3.8 KB

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