wp_render_layout_support_flag()WP 5.8.0

Renders the layout config to the block wrapper.

Внутренняя функция — эта функция рассчитана на использование самим ядром. Не рекомендуется использовать эту функцию в своем коде.

Хуков нет.

Возвращает

Строку. Filtered block content.

Использование

wp_render_layout_support_flag( $block_content, $block );
$block_content(строка) (обязательный)
Rendered block content.
$block(массив) (обязательный)
Block object.

Список изменений

С версии 5.8.0 Введена.
С версии 6.3.0 Adds compound class to layout wrapper for global spacing styles.
С версии 6.3.0 Check for layout support via the layout key with fallback to __experimentalLayout.

Код wp_render_layout_support_flag() WP 6.4.3

function wp_render_layout_support_flag( $block_content, $block ) {
	$block_type            = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
	$block_supports_layout = block_has_support( $block_type, 'layout', false ) || block_has_support( $block_type, '__experimentalLayout', false );
	$layout_from_parent    = isset( $block['attrs']['style']['layout']['selfStretch'] ) ? $block['attrs']['style']['layout']['selfStretch'] : null;

	if ( ! $block_supports_layout && ! $layout_from_parent ) {
		return $block_content;
	}

	$outer_class_names = array();

	if ( 'fixed' === $layout_from_parent || 'fill' === $layout_from_parent ) {
		$container_content_class = wp_unique_id( 'wp-container-content-' );

		$child_layout_styles = array();

		if ( 'fixed' === $layout_from_parent && 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' === $layout_from_parent ) {
			$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;
	}

	// Prep the processor for modifying the block output.
	$processor = new WP_HTML_Tag_Processor( $block_content );

	// Having no tags implies there are no tags onto which to add class names.
	if ( ! $processor->next_tag() ) {
		return $block_content;
	}

	/*
	 * A block may not support layout but still be affected by a parent block's layout.
	 *
	 * In these cases add the appropriate class names and then return early; there's
	 * no need to investigate on this block whether additional layout constraints apply.
	 */
	if ( ! $block_supports_layout && ! empty( $outer_class_names ) ) {
		foreach ( $outer_class_names as $class_name ) {
			$processor->add_class( $class_name );
		}
		return $processor->get_updated_html();
	}

	$global_settings = wp_get_global_settings();
	$fallback_layout = isset( $block_type->supports['layout']['default'] )
		? $block_type->supports['layout']['default']
		: array();
	if ( empty( $fallback_layout ) ) {
		$fallback_layout = isset( $block_type->supports['__experimentalLayout']['default'] )
			? $block_type->supports['__experimentalLayout']['default']
			: array();
	}
	$used_layout = isset( $block['attrs']['layout'] ) ? $block['attrs']['layout'] : $fallback_layout;

	$class_names        = array();
	$layout_definitions = wp_get_layout_definitions();

	/*
	 * Uses an incremental ID that is independent per prefix to make sure that
	 * rendering different numbers of blocks doesn't affect the IDs of other
	 * blocks. Makes the CSS class names stable across paginations
	 * for features like the enhanced pagination of the Query block.
	 */
	$container_class = wp_unique_prefixed_id(
		'wp-container-' . sanitize_title( $block['blockName'] ) . '-layout-'
	);

	// 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 = isset( $global_settings['useRootPaddingAwareAlignments'] )
		? $global_settings['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 = isset( $layout_definitions[ $used_layout['type'] ]['className'] )
			? $layout_definitions[ $used_layout['type'] ]['className']
			: '';
	} else {
		$layout_classname = isset( $layout_definitions['default']['className'] )
			? $layout_definitions['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 = isset( $block['attrs']['style']['spacing']['blockGap'] )
			? $block['attrs']['style']['spacing']['blockGap']
			: null;
		/*
		 * 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 = isset( $block_type->supports['spacing']['blockGap']['__experimentalDefault'] )
			? $block_type->supports['spacing']['blockGap']['__experimentalDefault']
			: '0.5em';
		$block_spacing      = isset( $block['attrs']['style']['spacing'] )
			? $block['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             = isset( $global_settings['spacing']['blockGap'] )
			? $global_settings['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;

	// Add classes to the outermost HTML tag if necessary.
	if ( ! empty( $outer_class_names ) ) {
		foreach ( $outer_class_names as $outer_class_name ) {
			$processor->add_class( $outer_class_name );
		}
	}

	/**
	 * Attempts to refer to the inner-block wrapping element by its class attribute.
	 *
	 * When examining a block's inner content, if a block has inner blocks, then
	 * the first content item will likely be a text (HTML) chunk immediately
	 * preceding the inner blocks. The last HTML tag in that chunk would then be
	 * an opening tag for an element that wraps the inner blocks.
	 *
	 * There's no reliable way to associate this wrapper in $block_content because
	 * it may have changed during the rendering pipeline (as inner contents is
	 * provided before rendering) and through previous filters. In many cases,
	 * however, the `class` attribute will be a good-enough identifier, so this
	 * code finds the last tag in that chunk and stores the `class` attribute
	 * so that it can be used later when working through the rendered block output
	 * to identify the wrapping element and add the remaining class names to it.
	 *
	 * It's also possible that no inner block wrapper even exists. If that's the
	 * case this code could apply the class names to an invalid element.
	 *
	 * Example:
	 *
	 *     $block['innerBlocks']  = array( $list_item );
	 *     $block['innerContent'] = array( '<ul class="list-wrapper is-unordered">', null, '</ul>' );
	 *
	 *     // After rendering, the initial contents may have been modified by other renderers or filters.
	 *     $block_content = <<<HTML
	 *         <figure>
	 *             <ul class="annotated-list list-wrapper is-unordered">
	 *                 <li>Code</li>
	 *             </ul><figcaption>It's a list!</figcaption>
	 *         </figure>
	 *     HTML;
	 *
	 * Although it is possible that the original block-wrapper classes are changed in $block_content
	 * from how they appear in $block['innerContent'], it's likely that the original class attributes
	 * are still present in the wrapper as they are in this example. Frequently, additional classes
	 * will also be present; rarely should classes be removed.
	 *
	 * @TODO: Find a better way to match the first inner block. If it's possible to identify where the
	 *        first inner block starts, then it will be possible to find the last tag before it starts
	 *        and then that tag, if an opening tag, can be solidly identified as a wrapping element.
	 *        Can some unique value or class or ID be added to the inner blocks when they process
	 *        so that they can be extracted here safely without guessing? Can the block rendering function
	 *        return information about where the rendered inner blocks start?
	 *
	 * @var string|null
	 */
	$inner_block_wrapper_classes = null;
	$first_chunk                 = isset( $block['innerContent'][0] ) ? $block['innerContent'][0] : null;
	if ( is_string( $first_chunk ) && count( $block['innerContent'] ) > 1 ) {
		$first_chunk_processor = new WP_HTML_Tag_Processor( $first_chunk );
		while ( $first_chunk_processor->next_tag() ) {
			$class_attribute = $first_chunk_processor->get_attribute( 'class' );
			if ( is_string( $class_attribute ) && ! empty( $class_attribute ) ) {
				$inner_block_wrapper_classes = $class_attribute;
			}
		}
	}

	/*
	 * If necessary, advance to what is likely to be an inner block wrapper tag.
	 *
	 * This advances until it finds the first tag containing the original class
	 * attribute from above. If none is found it will scan to the end of the block
	 * and fail to add any class names.
	 *
	 * If there is no block wrapper it won't advance at all, in which case the
	 * class names will be added to the first and outermost tag of the block.
	 * For cases where this outermost tag is the only tag surrounding inner
	 * blocks then the outer wrapper and inner wrapper are the same.
	 */
	do {
		if ( ! $inner_block_wrapper_classes ) {
			break;
		}

		if ( false !== strpos( $processor->get_attribute( 'class' ), $inner_block_wrapper_classes ) ) {
			break;
		}
	} while ( $processor->next_tag() );

	// Add the remaining class names.
	foreach ( $class_names as $class_name ) {
		$processor->add_class( $class_name );
	}

	return $processor->get_updated_html();
}