$post_id, 'wp_inactive_widgets' => array_merge( $sidebars['wp_inactive_widgets'], $sidebar ), ) ) ); } /** * Returns a sidebar as an array of legacy widget blocks. * * @since 5.7.0 * * @param string $sidebar_id Identifier of the sidebar. * @return array $post_id Post id. */ public static function get_sidebar_as_blocks( $sidebar_id ) { $blocks = array(); $sidebars_items = self::get_raw_sidebar_widgets(); $wp_registered_sidebars = self::get_wp_registered_sidebars(); foreach ( $sidebars_items[ $sidebar_id ] as $item ) { $widget_class = self::get_widget_class( $item ); list( $object, $number ) = self::get_widget_info( $item ); $new_block = array( 'blockName' => 'core/legacy-widget', 'attrs' => array( 'id' => $item, 'instance' => self::get_sidebar_widget_instance( $wp_registered_sidebars[ $sidebar_id ], $item ), ), 'innerHTML' => '', ); if ( null !== $widget_class ) { $new_block['attrs']['widgetClass'] = $widget_class; } if ( isset( $object->id_base ) ) { $new_block['attrs']['idBase'] = $object->id_base; } if ( is_int( $number ) ) { $new_block['attrs']['number'] = $number; } $blocks[] = $new_block; } return $blocks; } /** * Verifies if a sidebar id is valid or not. * * @since 5.7.0 * * @param string $sidebar_id Identifier of the sidebar. * @return boolean True if the $sidebar_id value is valid and false otherwise. */ public static function is_valid_sidebar_id( $sidebar_id ) { $wp_registered_sidebars = self::get_wp_registered_sidebars(); return isset( $wp_registered_sidebars[ $sidebar_id ] ); } /** * Given a widget id returns the name of the class the represents the widget. * * @since 5.7.0 * * @param string $widget_id Identifier of the widget. * @return string|null Name of the class that represents the widget or null if the widget is not represented by a class. */ private static function get_widget_class( $widget_id ) { $wp_registered_widgets = self::get_wp_registered_widgets(); if ( isset( $wp_registered_widgets[ $widget_id ]['callback'][0] ) && $wp_registered_widgets[ $widget_id ]['callback'][0] instanceof WP_Widget ) { return get_class( $wp_registered_widgets[ $widget_id ]['callback'][0] ); } return null; } /** * Retrieves a widget instance. * * @since 5.7.0 * * @param array $sidebar sidebar data available at $wp_registered_sidebars. * @param string $id Identifier of the widget instance. * @return array Array containing the widget instance. */ private static function get_sidebar_widget_instance( $sidebar, $id ) { list( $object, $number, $name ) = self::get_widget_info( $id ); if ( ! $object ) { return array(); } $object->_set( $number ); $instances = $object->get_settings(); $instance = $instances[ $number ]; $args = array_merge( $sidebar, array( 'widget_id' => $id, 'widget_name' => $name, ) ); /** * Filters the settings for a particular widget instance. * * Returning false will effectively short-circuit display of the widget. * * @since 2.8.0 * * @param array $instance The current widget instance's settings. * @param WP_Widget $this The current widget instance. * @param array $args An array of default widget arguments. */ $instance = apply_filters( 'widget_display_callback', $instance, $object, $args ); if ( false === $instance ) { return array(); } return $instance; } /** * Given a widget id returns an array containing information about the widget. * * @since 5.7.0 * * @param string $widget_id Identifier of the widget. * @return array Array containing the the widget object, the number, and the name. */ private static function get_widget_info( $widget_id ) { $wp_registered_widgets = self::get_wp_registered_widgets(); if ( ! isset( $wp_registered_widgets[ $widget_id ]['callback'][0] ) || ! isset( $wp_registered_widgets[ $widget_id ]['params'][0]['number'] ) || ! isset( $wp_registered_widgets[ $widget_id ]['name'] ) || ! ( $wp_registered_widgets[ $widget_id ]['callback'][0] instanceof WP_Widget ) ) { return array( null, null, null ); } $object = $wp_registered_widgets[ $widget_id ]['callback'][0]; $number = $wp_registered_widgets[ $widget_id ]['params'][0]['number']; $name = $wp_registered_widgets[ $widget_id ]['name']; return array( $object, $number, $name ); } /** * Serializes an array of blocks. * * @since 5.7.0 * * @param array $blocks Post Array of block objects. * @return string String representing the blocks. */ public static function serialize_blocks( $blocks ) { return implode( array_map( 'self::serialize_block', $blocks ) ); } /** * Serializes a block. * * @since 5.7.0 * * @param array $block Block object. * @return string String representing the block. */ public static function serialize_block( $block ) { if ( ! isset( $block['blockName'] ) ) { return false; } $name = $block['blockName']; if ( 0 === strpos( $name, 'core/' ) ) { $name = substr( $name, strlen( 'core/' ) ); } if ( empty( $block['attrs'] ) ) { $opening_tag_suffix = ''; } else { $opening_tag_suffix = ' ' . json_encode( $block['attrs'] ); } if ( empty( $block['innerHTML'] ) ) { return sprintf( '', $name, $opening_tag_suffix ); } else { return sprintf( '%3$s', $name, $opening_tag_suffix, $block['innerHTML'] ); } } /** * Outputs a block widget on the website frontend. * * @param array $options Widget options. * @param array $arguments Arguments array. */ public static function output_blocks_widget( $options, $arguments ) { echo $options['before_widget']; foreach ( $arguments['blocks'] as $block ) { echo render_block( $block ); } echo $options['after_widget']; } /** * Noop block widget control output function for the necessary call to `wp_register_widget_control`. */ public static function output_blocks_widget_control() {} /** * Registers a widget that should represent a set of blocks and returns its ID. * * @param array $blocks Array of blocks. */ public static function convert_blocks_to_widget( $blocks ) { $widget_id = 'blocks-widget-' . md5( self::serialize_blocks( $blocks ) ); global $wp_registered_widgets; if ( isset( $wp_registered_widgets[ $widget_id ] ) ) { return $widget_id; } wp_register_sidebar_widget( $widget_id, __( 'Blocks Area', 'gutenberg' ), 'Experimental_WP_Widget_Blocks_Manager::output_blocks_widget', array( 'classname' => 'widget-area', 'description' => __( 'Displays a set of blocks', 'gutenberg' ), ), array( 'blocks' => $blocks, ) ); wp_register_widget_control( $widget_id, __( 'Blocks Area', 'gutenberg' ), 'Experimental_WP_Widget_Blocks_Manager::output_blocks_widget_control', array( 'id_base' => 'blocks-widget' ) ); return $widget_id; } /** * Filters the $sidebars_widgets to exchange wp_area post id with a widget that renders that block area. * * @param array $sidebars_widgets_input An associative array of sidebars and their widgets. */ public static function swap_out_sidebars_blocks_for_block_widgets( $sidebars_widgets_input ) { global $sidebars_widgets; global $wp_customize; if ( null === self::$unfiltered_sidebar_widgets ) { self::$unfiltered_sidebar_widgets = $sidebars_widgets; } $changeset_data = null; if ( function_exists( 'is_customize_preview' ) && is_customize_preview() ) { $changeset_data = $wp_customize->changeset_data(); if ( isset( $changeset_data['gutenberg_widget_blocks']['value'] ) ) { $changeset_data = json_decode( $changeset_data['gutenberg_widget_blocks']['value'] ); } } $filtered_sidebar_widgets = array(); foreach ( $sidebars_widgets_input as $sidebar_id => $item ) { $changeset_value = $changeset_data && isset( $changeset_data->$sidebar_id ) ? $changeset_data->$sidebar_id : null; if ( ! is_numeric( $item ) && ! $changeset_value ) { $filtered_sidebar_widgets[ $sidebar_id ] = $item; continue; } $filtered_widgets = array(); $last_set_of_blocks = array(); $blocks = parse_blocks( $changeset_value ? $changeset_value : get_post( $item )->post_content ); foreach ( $blocks as $block ) { if ( ! isset( $block['blockName'] ) ) { continue; } if ( 'core/legacy-widget' === $block['blockName'] && isset( $block['attrs']['identifier'] ) ) { if ( ! empty( $last_set_of_blocks ) ) { $filtered_widgets[] = self::convert_blocks_to_widget( $last_set_of_blocks ); $last_set_of_blocks = array(); } $filtered_widgets[] = $block['attrs']['identifier']; } else { $last_set_of_blocks[] = $block; } } if ( ! empty( $last_set_of_blocks ) ) { $filtered_widgets[] = self::convert_blocks_to_widget( $last_set_of_blocks ); } $filtered_sidebar_widgets[ $sidebar_id ] = $filtered_widgets; } $sidebars_widgets = $filtered_sidebar_widgets; return $filtered_sidebar_widgets; } }