WordPress Version: 6.3
/**
* Renders the layout config to the block wrapper.
*
* @since 5.8.0
* @since 6.3.0 Adds compound class to layout wrapper for global spacing styles.
* @since 6.3.0 Check for layout support via the `layout` key with fallback to `__experimentalLayout`.
* @access private
*
* @param string $block_content Rendered block content.
* @param array $block Block object.
* @return string Filtered block content.
*/
function wp_render_layout_support_flag($block_content, $block)
{
$block_type = WP_Block_Type_Registry::get_instance()->get_registered($block['blockName']);
$support_layout = block_has_support($block_type, array('layout'), false) || block_has_support($block_type, array('__experimentalLayout'), false);
$has_child_layout = isset($block['attrs']['style']['layout']['selfStretch']);
if (!$support_layout && !$has_child_layout) {
return $block_content;
}
$outer_class_names = array();
if ($has_child_layout && ('fixed' === $block['attrs']['style']['layout']['selfStretch'] || 'fill' === $block['attrs']['style']['layout']['selfStretch'])) {
$container_content_class = wp_unique_id('wp-container-content-');
$child_layout_styles = array();
if ('fixed' === $block['attrs']['style']['layout']['selfStretch'] && isset($block['attrs']['style']['layout']['flexSize'])) {
$child_layout_styles[] = array('selector' => ".{$container_content_class}", 'declarations' => array('flex-basis' => $block['attrs']['style']['layout']['flexSize'], 'box-sizing' => 'border-box'));
} elseif ('fill' === $block['attrs']['style']['layout']['selfStretch']) {
$child_layout_styles[] = array('selector' => ".{$container_content_class}", 'declarations' => array('flex-grow' => '1'));
}
wp_style_engine_get_stylesheet_from_css_rules($child_layout_styles, array('context' => 'block-supports', 'prettify' => false));
$outer_class_names[] = $container_content_class;
}
// Return early if only child layout exists.
if (!$support_layout && !empty($outer_class_names)) {
$content = new WP_HTML_Tag_Processor($block_content);
$content->next_tag();
$content->add_class(implode(' ', $outer_class_names));
return (string) $content;
}
$global_settings = wp_get_global_settings();
$fallback_layout = (!empty(_wp_array_get($block_type->supports, array('layout', 'default'), array()))) ? _wp_array_get($block_type->supports, array('layout', 'default'), array()) : _wp_array_get($block_type->supports, array('__experimentalLayout', 'default'), array());
$used_layout = isset($block['attrs']['layout']) ? $block['attrs']['layout'] : $fallback_layout;
$class_names = array();
$layout_definitions = wp_get_layout_definitions();
$container_class = wp_unique_id('wp-container-');
$layout_classname = '';
// Set the correct layout type for blocks using legacy content width.
if (isset($used_layout['inherit']) && $used_layout['inherit'] || isset($used_layout['contentSize']) && $used_layout['contentSize']) {
$used_layout['type'] = 'constrained';
}
$root_padding_aware_alignments = _wp_array_get($global_settings, array('useRootPaddingAwareAlignments'), false);
if ($root_padding_aware_alignments && isset($used_layout['type']) && 'constrained' === $used_layout['type']) {
$class_names[] = 'has-global-padding';
}
/*
* The following section was added to reintroduce a small set of layout classnames that were
* removed in the 5.9 release (https://github.com/WordPress/gutenberg/issues/38719). It is
* not intended to provide an extended set of classes to match all block layout attributes
* here.
*/
if (!empty($block['attrs']['layout']['orientation'])) {
$class_names[] = 'is-' . sanitize_title($block['attrs']['layout']['orientation']);
}
if (!empty($block['attrs']['layout']['justifyContent'])) {
$class_names[] = 'is-content-justification-' . sanitize_title($block['attrs']['layout']['justifyContent']);
}
if (!empty($block['attrs']['layout']['flexWrap']) && 'nowrap' === $block['attrs']['layout']['flexWrap']) {
$class_names[] = 'is-nowrap';
}
// Get classname for layout type.
if (isset($used_layout['type'])) {
$layout_classname = _wp_array_get($layout_definitions, array($used_layout['type'], 'className'), '');
} else {
$layout_classname = _wp_array_get($layout_definitions, array('default', 'className'), '');
}
if ($layout_classname && is_string($layout_classname)) {
$class_names[] = sanitize_title($layout_classname);
}
/*
* Only generate Layout styles if the theme has not opted-out.
* Attribute-based Layout classnames are output in all cases.
*/
if (!current_theme_supports('disable-layout-styles')) {
$gap_value = _wp_array_get($block, array('attrs', 'style', 'spacing', 'blockGap'));
/*
* Skip if gap value contains unsupported characters.
* Regex for CSS value borrowed from `safecss_filter_attr`, and used here
* to only match against the value, not the CSS attribute.
*/
if (is_array($gap_value)) {
foreach ($gap_value as $key => $value) {
$gap_value[$key] = ($value && preg_match('%[\\\\(&=}]|/\*%', $value)) ? null : $value;
}
} else {
$gap_value = ($gap_value && preg_match('%[\\\\(&=}]|/\*%', $gap_value)) ? null : $gap_value;
}
$fallback_gap_value = _wp_array_get($block_type->supports, array('spacing', 'blockGap', '__experimentalDefault'), '0.5em');
$block_spacing = _wp_array_get($block, array('attrs', 'style', 'spacing'), null);
/*
* If a block's block.json skips serialization for spacing or spacing.blockGap,
* don't apply the user-defined value to the styles.
*/
$should_skip_gap_serialization = wp_should_skip_block_supports_serialization($block_type, 'spacing', 'blockGap');
$block_gap = _wp_array_get($global_settings, array('spacing', 'blockGap'), null);
$has_block_gap_support = isset($block_gap);
$style = wp_get_layout_style(".{$container_class}.{$container_class}", $used_layout, $has_block_gap_support, $gap_value, $should_skip_gap_serialization, $fallback_gap_value, $block_spacing);
// Only add container class and enqueue block support styles if unique styles were generated.
if (!empty($style)) {
$class_names[] = $container_class;
}
}
// Add combined layout and block classname for global styles to hook onto.
$block_name = explode('/', $block['blockName']);
$class_names[] = 'wp-block-' . end($block_name) . '-' . $layout_classname;
$content_with_outer_classnames = '';
if (!empty($outer_class_names)) {
$content_with_outer_classnames = new WP_HTML_Tag_Processor($block_content);
$content_with_outer_classnames->next_tag();
foreach ($outer_class_names as $outer_class_name) {
$content_with_outer_classnames->add_class($outer_class_name);
}
$content_with_outer_classnames = (string) $content_with_outer_classnames;
}
/**
* The first chunk of innerContent contains the block markup up until the inner blocks start.
* This targets the opening tag of the inner blocks wrapper, which is the last tag in that chunk.
*/
$inner_content_classnames = '';
if (isset($block['innerContent'][0]) && 'string' === gettype($block['innerContent'][0]) && count($block['innerContent']) > 1) {
$tags = new WP_HTML_Tag_Processor($block['innerContent'][0]);
$last_classnames = '';
while ($tags->next_tag()) {
$last_classnames = $tags->get_attribute('class');
}
$inner_content_classnames = (string) $last_classnames;
}
$content = $content_with_outer_classnames ? new WP_HTML_Tag_Processor($content_with_outer_classnames) : new WP_HTML_Tag_Processor($block_content);
if ($inner_content_classnames) {
$content->next_tag(array('class_name' => $inner_content_classnames));
foreach ($class_names as $class_name) {
$content->add_class($class_name);
}
} else {
$content->next_tag();
foreach ($class_names as $class_name) {
$content->add_class($class_name);
}
}
return (string) $content;
}