wp/wp-includes/block-supports/layout.php
changeset 18 be944660c56a
child 19 3d72ae0968f4
equal deleted inserted replaced
17:34716fd837a4 18:be944660c56a
       
     1 <?php
       
     2 /**
       
     3  * Layout block support flag.
       
     4  *
       
     5  * @package WordPress
       
     6  * @since 5.8.0
       
     7  */
       
     8 
       
     9 /**
       
    10  * Registers the layout block attribute for block types that support it.
       
    11  *
       
    12  * @since 5.8.0
       
    13  * @access private
       
    14  *
       
    15  * @param WP_Block_Type $block_type Block Type.
       
    16  */
       
    17 function wp_register_layout_support( $block_type ) {
       
    18 	$support_layout = block_has_support( $block_type, array( '__experimentalLayout' ), false );
       
    19 	if ( $support_layout ) {
       
    20 		if ( ! $block_type->attributes ) {
       
    21 			$block_type->attributes = array();
       
    22 		}
       
    23 
       
    24 		if ( ! array_key_exists( 'layout', $block_type->attributes ) ) {
       
    25 			$block_type->attributes['layout'] = array(
       
    26 				'type' => 'object',
       
    27 			);
       
    28 		}
       
    29 	}
       
    30 }
       
    31 
       
    32 /**
       
    33  * Renders the layout config to the block wrapper.
       
    34  *
       
    35  * @since 5.8.0
       
    36  * @access private
       
    37  *
       
    38  * @param  string $block_content Rendered block content.
       
    39  * @param  array  $block         Block object.
       
    40  * @return string                Filtered block content.
       
    41  */
       
    42 function wp_render_layout_support_flag( $block_content, $block ) {
       
    43 	$block_type     = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
       
    44 	$support_layout = block_has_support( $block_type, array( '__experimentalLayout' ), false );
       
    45 	if ( ! $support_layout || ! isset( $block['attrs']['layout'] ) ) {
       
    46 		return $block_content;
       
    47 	}
       
    48 
       
    49 	$used_layout = $block['attrs']['layout'];
       
    50 	if ( isset( $used_layout['inherit'] ) && $used_layout['inherit'] ) {
       
    51 		$tree           = WP_Theme_JSON_Resolver::get_merged_data();
       
    52 		$default_layout = _wp_array_get( $tree->get_settings(), array( 'layout' ) );
       
    53 		if ( ! $default_layout ) {
       
    54 			return $block_content;
       
    55 		}
       
    56 		$used_layout = $default_layout;
       
    57 	}
       
    58 
       
    59 	$id           = uniqid();
       
    60 	$content_size = isset( $used_layout['contentSize'] ) ? $used_layout['contentSize'] : null;
       
    61 	$wide_size    = isset( $used_layout['wideSize'] ) ? $used_layout['wideSize'] : null;
       
    62 
       
    63 	$all_max_width_value  = $content_size ? $content_size : $wide_size;
       
    64 	$wide_max_width_value = $wide_size ? $wide_size : $content_size;
       
    65 
       
    66 	// Make sure there is a single CSS rule, and all tags are stripped for security.
       
    67 	$all_max_width_value  = safecss_filter_attr( explode( ';', $all_max_width_value )[0] );
       
    68 	$wide_max_width_value = safecss_filter_attr( explode( ';', $wide_max_width_value )[0] );
       
    69 
       
    70 	$style = '';
       
    71 	if ( $content_size || $wide_size ) {
       
    72 		$style  = ".wp-container-$id > * {";
       
    73 		$style .= 'max-width: ' . esc_html( $all_max_width_value ) . ';';
       
    74 		$style .= 'margin-left: auto !important;';
       
    75 		$style .= 'margin-right: auto !important;';
       
    76 		$style .= '}';
       
    77 
       
    78 		$style .= ".wp-container-$id > .alignwide { max-width: " . esc_html( $wide_max_width_value ) . ';}';
       
    79 
       
    80 		$style .= ".wp-container-$id .alignfull { max-width: none; }";
       
    81 	}
       
    82 
       
    83 	$style .= ".wp-container-$id .alignleft { float: left; margin-right: 2em; }";
       
    84 	$style .= ".wp-container-$id .alignright { float: right; margin-left: 2em; }";
       
    85 
       
    86 	// This assumes the hook only applies to blocks with a single wrapper.
       
    87 	// I think this is a reasonable limitation for that particular hook.
       
    88 	$content = preg_replace(
       
    89 		'/' . preg_quote( 'class="', '/' ) . '/',
       
    90 		'class="wp-container-' . $id . ' ',
       
    91 		$block_content,
       
    92 		1
       
    93 	);
       
    94 
       
    95 	return $content . '<style>' . $style . '</style>';
       
    96 }
       
    97 
       
    98 // Register the block support.
       
    99 WP_Block_Supports::get_instance()->register(
       
   100 	'layout',
       
   101 	array(
       
   102 		'register_attribute' => 'wp_register_layout_support',
       
   103 	)
       
   104 );
       
   105 add_filter( 'render_block', 'wp_render_layout_support_flag', 10, 2 );
       
   106 
       
   107 /**
       
   108  * For themes without theme.json file, make sure
       
   109  * to restore the inner div for the group block
       
   110  * to avoid breaking styles relying on that div.
       
   111  *
       
   112  * @since 5.8.0
       
   113  * @access private
       
   114  *
       
   115  * @param string $block_content Rendered block content.
       
   116  * @param array  $block         Block object.
       
   117  *
       
   118  * @return string Filtered block content.
       
   119  */
       
   120 function wp_restore_group_inner_container( $block_content, $block ) {
       
   121 	$group_with_inner_container_regex = '/(^\s*<div\b[^>]*wp-block-group(\s|")[^>]*>)(\s*<div\b[^>]*wp-block-group__inner-container(\s|")[^>]*>)((.|\S|\s)*)/';
       
   122 
       
   123 	if (
       
   124 		'core/group' !== $block['blockName'] ||
       
   125 		WP_Theme_JSON_Resolver::theme_has_support() ||
       
   126 		1 === preg_match( $group_with_inner_container_regex, $block_content )
       
   127 	) {
       
   128 		return $block_content;
       
   129 	}
       
   130 
       
   131 	$replace_regex   = '/(^\s*<div\b[^>]*wp-block-group[^>]*>)(.*)(<\/div>\s*$)/ms';
       
   132 	$updated_content = preg_replace_callback(
       
   133 		$replace_regex,
       
   134 		function( $matches ) {
       
   135 			return $matches[1] . '<div class="wp-block-group__inner-container">' . $matches[2] . '</div>' . $matches[3];
       
   136 		},
       
   137 		$block_content
       
   138 	);
       
   139 	return $updated_content;
       
   140 }
       
   141 
       
   142 add_filter( 'render_block', 'wp_restore_group_inner_container', 10, 2 );