Skip to content

Commit

Permalink
Render widget areas referencing blocks in a wp_area post on the websi…
Browse files Browse the repository at this point in the history
…te frontend (#15651)

Here we implement a simple filter that makes a sidebar referencing a post_id reference a simple widget that renders the content of the post.
  • Loading branch information
jorgefilipecosta authored May 24, 2019
1 parent 1d3b632 commit 9b4f31a
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 6 deletions.
120 changes: 115 additions & 5 deletions lib/class-experimental-wp-widget-blocks-manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@
* @since 5.7.0
*/
class Experimental_WP_Widget_Blocks_Manager {

/**
* Array of sidebar_widgets as it was before the filter swap_out_sidebars_blocks_for_block_widgets was ever executed.
*
* @var array
*/
private static $unfiltered_sidebar_widgets = null;

/**
* Returns the $wp_registered_widgets global.
*
Expand Down Expand Up @@ -42,14 +50,23 @@ private static function get_wp_registered_sidebars() {
*
* @since 5.7.0
*
* @param string $sidebar_id Indentifier of the sidebar.
* @param string $sidebar_id Identifier of the sidebar.
* @return array Sidebar structure.
*/
public static function get_wp_registered_sidebars_sidebar( $sidebar_id ) {
$wp_registered_sidebars = self::get_wp_registered_sidebars();
return $wp_registered_sidebars[ $sidebar_id ];
}

/**
* Returns the result of wp_get_sidebars_widgets without swap_out_sidebars_blocks_for_block_widgets filter being applied.
*
* @since 5.7.0
*/
private static function get_raw_sidebar_widgets() {
return self::$unfiltered_sidebar_widgets;
}

/**
* Returns a post id being referenced in a sidebar area.
*
Expand All @@ -59,7 +76,7 @@ public static function get_wp_registered_sidebars_sidebar( $sidebar_id ) {
* @return integer Post id.
*/
public static function get_post_id_referenced_in_sidebar( $sidebar_id ) {
$sidebars = wp_get_sidebars_widgets();
$sidebars = self::get_raw_sidebar_widgets();
$sidebar = $sidebars[ $sidebar_id ];
return is_numeric( $sidebar ) ? $sidebar : 0;
}
Expand All @@ -73,7 +90,7 @@ public static function get_post_id_referenced_in_sidebar( $sidebar_id ) {
* @param integer $post_id Post id.
*/
public static function reference_post_id_in_sidebar( $sidebar_id, $post_id ) {
$sidebars = wp_get_sidebars_widgets();
$sidebars = self::get_raw_sidebar_widgets();
$sidebar = $sidebars[ $sidebar_id ];
wp_set_sidebars_widgets(
array_merge(
Expand All @@ -100,7 +117,8 @@ public static function reference_post_id_in_sidebar( $sidebar_id, $post_id ) {
public static function get_sidebar_as_blocks( $sidebar_id ) {
$blocks = array();

$sidebars_items = wp_get_sidebars_widgets();
$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 );
Expand All @@ -109,7 +127,7 @@ public static function get_sidebar_as_blocks( $sidebar_id ) {
'attrs' => array(
'class' => $widget_class,
'identifier' => $item,
'instance' => self::get_sidebar_widget_instance( $sidebar, $item ),
'instance' => self::get_sidebar_widget_instance( $wp_registered_sidebars[ $sidebar_id ], $item ),
),
'innerHTML' => '',
);
Expand Down Expand Up @@ -245,6 +263,9 @@ public static function serialize_blocks( $blocks ) {
* @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/' ) );
Expand All @@ -271,4 +292,93 @@ public static function serialize_block( $block ) {
);
}
}

/**
* 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'];
}

/**
* Registers of 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,
)
);
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;
if ( null === self::$unfiltered_sidebar_widgets ) {
self::$unfiltered_sidebar_widgets = $sidebars_widgets;
}
$filtered_sidebar_widgets = array();
foreach ( $sidebars_widgets_input as $sidebar_id => $item ) {
if ( ! is_numeric( $item ) ) {
$filtered_sidebar_widgets[ $sidebar_id ] = $item;
continue;
}

$filtered_widgets = array();
$last_set_of_blocks = array();
$post = get_post( $item );
$blocks = parse_blocks( $post->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;
}
}
2 changes: 1 addition & 1 deletion lib/class-wp-rest-widget-areas-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public function register_routes() {
'description' => __( 'The sidebar’s ID.', 'gutenberg' ),
'type' => 'string',
'required' => true,
'validate_callback' => array( $this, 'is_valid_sidabar_id' ),
'validate_callback' => 'Experimental_WP_Widget_Blocks_Manager::is_valid_sidabar_id',
);

$content_argument = array(
Expand Down
2 changes: 2 additions & 0 deletions lib/widgets.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,5 @@ function gutenberg_create_wp_area_post_type() {
);
}
add_action( 'init', 'gutenberg_create_wp_area_post_type' );

add_filter( 'sidebars_widgets', 'Experimental_WP_Widget_Blocks_Manager::swap_out_sidebars_blocks_for_block_widgets' );

0 comments on commit 9b4f31a

Please sign in to comment.