if ( in_array( $inner_block['blockName'], $allowed_blocks, true ) && empty( $inner_block['innerBlocks'] ) ) { $output .= render_block( $inner_block ); } } } return $output; } /** * Renders a single block into a HTML string. * * @since 5.0.0 * * @global WP_Post $post The post to edit. * @global WP_Query $wp_query WordPress Query object. * * @param array $parsed_block A single parsed block object. * @return string String of rendered HTML. */ function render_block( $parsed_block ) { global $post, $wp_query; /** * Allows render_block() to be short-circuited, by returning a non-null value. * * @since 5.1.0 * * @param string|null $pre_render The pre-rendered content. Default null. * @param array $parsed_block The block being rendered. */ $pre_render = apply_filters( 'pre_render_block', null, $parsed_block ); if ( ! is_null( $pre_render ) ) { return $pre_render; } $source_block = $parsed_block; /** * Filters the block being rendered in render_block(), before it's processed. * * @since 5.1.0 * * @param array $parsed_block The block being rendered. * @param array $source_block An un-modified copy of $parsed_block, as it appeared in the source content. */ $parsed_block = apply_filters( 'render_block_data', $parsed_block, $source_block ); $context = array(); if ( $post instanceof WP_Post ) { $context['postId'] = $post->ID; /* * The `postType` context is largely unnecessary server-side, since the ID * is usually sufficient on its own. That being said, since a block's * manifest is expected to be shared between the server and the client, * it should be included to consistently fulfill the expectation. */ $context['postType'] = $post->post_type; } if ( $wp_query instanceof WP_Query && isset( $wp_query->tax_query->queried_terms['category'] ) ) { $context['query'] = array( 'categoryIds' => array() ); foreach ( $wp_query->tax_query->queried_terms['category']['terms'] as $category_slug_or_id ) { $context['query']['categoryIds'][] = 'slug' === $wp_query->tax_query->queried_terms['category']['field'] ? get_cat_ID( $category_slug_or_id ) : $category_slug_or_id; } } /** * Filters the default context provided to a rendered block. * * @since 5.5.0 * * @param array $context Default context. * @param array $parsed_block Block being rendered, filtered by `render_block_data`. */ $context = apply_filters( 'render_block_context', $context, $parsed_block ); $block = new WP_Block( $parsed_block, $context ); return $block->render(); } /** * Parses blocks out of a content string. * * @since 5.0.0 * * @param string $content Post content. * @return array[] Array of parsed block objects. */ function parse_blocks( $content ) { /** * Filter to allow plugins to replace the server-side block parser * * @since 5.0.0 * * @param string $parser_class Name of block parser class. */ $parser_class = apply_filters( 'block_parser_class', 'WP_Block_Parser' ); $parser = new $parser_class(); return $parser->parse( $content ); } /** * Parses dynamic blocks out of `post_content` and re-renders them. * * @since 5.0.0 * * @param string $content Post content. * @return string Updated post content. */ function do_blocks( $content ) { $blocks = parse_blocks( $content ); $output = ''; foreach ( $blocks as $block ) { $output .= render_block( $block ); } // If there are blocks in this content, we shouldn't run wpautop() on it later. $priority = has_filter( 'the_content', 'wpautop' ); if ( false !== $priority && doing_filter( 'the_content' ) && has_blocks( $content ) ) { remove_filter( 'the_content', 'wpautop', $priority ); add_filter( 'the_content', '_restore_wpautop_hook', $priority + 1 ); } return $output; } /** * If do_blocks() needs to remove wpautop() from the `the_content` filter, this re-adds it afterwards, * for subsequent `the_content` usage. * * @access private * * @since 5.0.0 * * @param string $content The post content running through this filter. * @return string The unmodified content. */ function _restore_wpautop_hook( $content ) { $current_priority = has_filter( 'the_content', '_restore_wpautop_hook' ); add_filter( 'the_content', 'wpautop', $current_priority - 1 ); remove_filter( 'the_content', '_restore_wpautop_hook', $current_priority ); return $content; } /** * Returns the current version of the block format that the content string is using. * * If the string doesn't contain blocks, it returns 0. * * @since 5.0.0 * * @param string $content Content to test. * @return int The block format version is 1 if the content contains one or more blocks, 0 otherwise. */ function block_version( $content ) { return has_blocks( $content ) ? 1 : 0; } /** * Registers a new block style. * * @since 5.3.0 * * @param string $block_name Block type name including namespace. * @param array $style_properties Array containing the properties of the style name, * label, style (name of the stylesheet to be enqueued), * inline_style (string containing the CSS to be added). * @return boolean True if the block style was registered with success and false otherwise. */ function register_block_style( $block_name, $style_properties ) { return WP_Block_Styles_Registry::get_instance()->register( $block_name, $style_properties ); } /** * Unregisters a block style. * * @since 5.3.0 * * @param string $block_name Block type name including namespace. * @param array $block_style_name Block style name. * @return boolean True if the block style was unregistered with success and false otherwise. */ function unregister_block_style( $block_name, $block_style_name ) { return WP_Block_Styles_Registry::get_instance()->unregister( $block_name, $block_style_name ); }