class-wp-widget-block.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. <?php
  2. /**
  3. * Widget API: WP_Widget_Block class
  4. *
  5. * @package WordPress
  6. * @subpackage Widgets
  7. * @since 5.8.0
  8. */
  9. /**
  10. * Core class used to implement a Block widget.
  11. *
  12. * @since 5.8.0
  13. *
  14. * @see WP_Widget
  15. */
  16. class WP_Widget_Block extends WP_Widget {
  17. /**
  18. * Default instance.
  19. *
  20. * @since 5.8.0
  21. * @var array
  22. */
  23. protected $default_instance = array(
  24. 'content' => '',
  25. );
  26. /**
  27. * Sets up a new Block widget instance.
  28. *
  29. * @since 5.8.0
  30. */
  31. public function __construct() {
  32. $widget_ops = array(
  33. 'classname' => 'widget_block',
  34. 'description' => __( 'A widget containing a block.' ),
  35. 'customize_selective_refresh' => true,
  36. 'show_instance_in_rest' => true,
  37. );
  38. $control_ops = array(
  39. 'width' => 400,
  40. 'height' => 350,
  41. );
  42. parent::__construct( 'block', __( 'Block' ), $widget_ops, $control_ops );
  43. add_filter( 'is_wide_widget_in_customizer', array( $this, 'set_is_wide_widget_in_customizer' ), 10, 2 );
  44. }
  45. /**
  46. * Outputs the content for the current Block widget instance.
  47. *
  48. * @since 5.8.0
  49. *
  50. * @param array $args Display arguments including 'before_title', 'after_title',
  51. * 'before_widget', and 'after_widget'.
  52. * @param array $instance Settings for the current Block widget instance.
  53. */
  54. public function widget( $args, $instance ) {
  55. $instance = wp_parse_args( $instance, $this->default_instance );
  56. echo str_replace(
  57. 'widget_block',
  58. $this->get_dynamic_classname( $instance['content'] ),
  59. $args['before_widget']
  60. );
  61. /**
  62. * Filters the content of the Block widget before output.
  63. *
  64. * @since 5.8.0
  65. *
  66. * @param string $content The widget content.
  67. * @param array $instance Array of settings for the current widget.
  68. * @param WP_Widget_Block $widget Current Block widget instance.
  69. */
  70. echo apply_filters(
  71. 'widget_block_content',
  72. $instance['content'],
  73. $instance,
  74. $this
  75. );
  76. echo $args['after_widget'];
  77. }
  78. /**
  79. * Calculates the classname to use in the block widget's container HTML.
  80. *
  81. * Usually this is set to `$this->widget_options['classname']` by
  82. * dynamic_sidebar(). In this case, however, we want to set the classname
  83. * dynamically depending on the block contained by this block widget.
  84. *
  85. * If a block widget contains a block that has an equivalent legacy widget,
  86. * we display that legacy widget's class name. This helps with theme
  87. * backwards compatibility.
  88. *
  89. * @since 5.8.0
  90. *
  91. * @param string $content The HTML content of the current block widget.
  92. * @return string The classname to use in the block widget's container HTML.
  93. */
  94. private function get_dynamic_classname( $content ) {
  95. $blocks = parse_blocks( $content );
  96. $block_name = isset( $blocks[0] ) ? $blocks[0]['blockName'] : null;
  97. switch ( $block_name ) {
  98. case 'core/paragraph':
  99. $classname = 'widget_block widget_text';
  100. break;
  101. case 'core/calendar':
  102. $classname = 'widget_block widget_calendar';
  103. break;
  104. case 'core/search':
  105. $classname = 'widget_block widget_search';
  106. break;
  107. case 'core/html':
  108. $classname = 'widget_block widget_custom_html';
  109. break;
  110. case 'core/archives':
  111. $classname = 'widget_block widget_archive';
  112. break;
  113. case 'core/latest-posts':
  114. $classname = 'widget_block widget_recent_entries';
  115. break;
  116. case 'core/latest-comments':
  117. $classname = 'widget_block widget_recent_comments';
  118. break;
  119. case 'core/tag-cloud':
  120. $classname = 'widget_block widget_tag_cloud';
  121. break;
  122. case 'core/categories':
  123. $classname = 'widget_block widget_categories';
  124. break;
  125. case 'core/audio':
  126. $classname = 'widget_block widget_media_audio';
  127. break;
  128. case 'core/video':
  129. $classname = 'widget_block widget_media_video';
  130. break;
  131. case 'core/image':
  132. $classname = 'widget_block widget_media_image';
  133. break;
  134. case 'core/gallery':
  135. $classname = 'widget_block widget_media_gallery';
  136. break;
  137. case 'core/rss':
  138. $classname = 'widget_block widget_rss';
  139. break;
  140. default:
  141. $classname = 'widget_block';
  142. }
  143. /**
  144. * The classname used in the block widget's container HTML.
  145. *
  146. * This can be set according to the name of the block contained by the block widget.
  147. *
  148. * @since 5.8.0
  149. *
  150. * @param string $classname The classname to be used in the block widget's container HTML,
  151. * e.g. 'widget_block widget_text'.
  152. * @param string $block_name The name of the block contained by the block widget,
  153. * e.g. 'core/paragraph'.
  154. */
  155. return apply_filters( 'widget_block_dynamic_classname', $classname, $block_name );
  156. }
  157. /**
  158. * Handles updating settings for the current Block widget instance.
  159. *
  160. * @since 5.8.0
  161. * @param array $new_instance New settings for this instance as input by the user via
  162. * WP_Widget::form().
  163. * @param array $old_instance Old settings for this instance.
  164. * @return array Settings to save or bool false to cancel saving.
  165. */
  166. public function update( $new_instance, $old_instance ) {
  167. $instance = array_merge( $this->default_instance, $old_instance );
  168. if ( current_user_can( 'unfiltered_html' ) ) {
  169. $instance['content'] = $new_instance['content'];
  170. } else {
  171. $instance['content'] = wp_kses_post( $new_instance['content'] );
  172. }
  173. return $instance;
  174. }
  175. /**
  176. * Outputs the Block widget settings form.
  177. *
  178. * @since 5.8.0
  179. *
  180. * @see WP_Widget_Custom_HTML::render_control_template_scripts()
  181. *
  182. * @param array $instance Current instance.
  183. */
  184. public function form( $instance ) {
  185. $instance = wp_parse_args( (array) $instance, $this->default_instance );
  186. ?>
  187. <p>
  188. <label for="<?php echo $this->get_field_id( 'content' ); ?>">
  189. <?php
  190. /* translators: HTML code of the block, not an option that blocks HTML. */
  191. _e( 'Block HTML:' );
  192. ?>
  193. </label>
  194. <textarea id="<?php echo $this->get_field_id( 'content' ); ?>" name="<?php echo $this->get_field_name( 'content' ); ?>" rows="6" cols="50" class="widefat code"><?php echo esc_textarea( $instance['content'] ); ?></textarea>
  195. </p>
  196. <?php
  197. }
  198. /**
  199. * Makes sure no block widget is considered to be wide.
  200. *
  201. * @since 5.8.0
  202. *
  203. * @param bool $is_wide Whether the widget is considered wide.
  204. * @param string $widget_id Widget ID.
  205. * @return bool Updated `is_wide` value.
  206. */
  207. public function set_is_wide_widget_in_customizer( $is_wide, $widget_id ) {
  208. if ( strpos( $widget_id, 'block-' ) === 0 ) {
  209. return false;
  210. }
  211. return $is_wide;
  212. }
  213. }