Make WordPress Core

Changeset 43752 for branches/5.0


Ignore:
Timestamp:
10/18/2018 11:53:49 AM (8 years ago)
Author:
pento
Message:

Blocks: Parse blocks when displaying posts.

Posts containing blocks are now correctly handled when displaying on the front end, including dynamic blocks and nested blocks.

See #45109.

Location:
branches/5.0
Files:
61 added
11 edited

Legend:

Unmodified
Added
Removed
  • branches/5.0/src/wp-includes/blocks.php

    r43751 r43752  
    112112
    113113        return $dynamic_block_names;
     114}
     115
     116/**
     117 * Remove all dynamic blocks from the given content.
     118 *
     119 * @since 5.0.0
     120 *
     121 * @param string $content Content of the current post.
     122 * @return string
     123 */
     124function strip_dynamic_blocks( $content ) {
     125        return _recurse_strip_dynamic_blocks( parse_blocks( $content ) );
     126}
     127
     128/**
     129 * Helper function for strip_dynamic_blocks(), to recurse through the block tree.
     130 *
     131 * @since 5.0.0
     132 * @access private
     133 *
     134 * @param array $blocks Array of blocks from parse_blocks().
     135 * @return string HTML from the non-dynamic blocks.
     136 */
     137function _recurse_strip_dynamic_blocks( $blocks ) {
     138        $clean_content  = '';
     139        $dynamic_blocks = get_dynamic_block_names();
     140
     141        foreach ( $blocks as $block ) {
     142                if ( ! in_array( $block['blockName'], $dynamic_blocks ) ) {
     143                        if ( $block['innerBlocks'] ) {
     144                                $clean_content .= _recurse_strip_dynamic_blocks( $block['innerBlocks'] );
     145                        } else {
     146                                $clean_content .= $block['innerHTML'];
     147                        }
     148                }
     149        }
     150
     151        return $clean_content;
    114152}
    115153
     
    143181         * @since 5.0.0
    144182         *
    145          * @param string $parser_class Name of block parser class
     183         * @param string $parser_class Name of block parser class.
    146184         */
    147185        $parser_class = apply_filters( 'block_parser_class', 'WP_Block_Parser' );
     
    150188        return $parser->parse( $content );
    151189}
     190
     191/**
     192 * Parses dynamic blocks out of `post_content` and re-renders them.
     193 *
     194 * @since 5.0.0
     195 * @global WP_Post $post The post to edit.
     196 *
     197 * @param  string $content Post content.
     198 * @return string Updated post content.
     199 */
     200function do_blocks( $content ) {
     201        $blocks = parse_blocks( $content );
     202        return _recurse_do_blocks( $blocks, $blocks );
     203}
     204
     205/**
     206 * Helper function for do_blocks(), to recurse through the block tree.
     207 *
     208 * @since 5.0.0
     209 * @access private
     210 *
     211 * @param array $blocks     Array of blocks from parse_blocks().
     212 * @param array $all_blocks The top level array of blocks.
     213 * @return string The block HTML.
     214 */
     215function _recurse_do_blocks( $blocks, $all_blocks ) {
     216        global $post;
     217
     218        /*
     219         * Back up global post, to restore after render callback.
     220         * Allows callbacks to run new WP_Query instances without breaking the global post.
     221         */
     222        $global_post = $post;
     223
     224        $rendered_content = '';
     225        $dynamic_blocks   = get_dynamic_block_names();
     226
     227        foreach ( $blocks as $block ) {
     228                $block = (array) $block;
     229                if ( in_array( $block['blockName'], $dynamic_blocks ) ) {
     230                        // Find registered block type. We can assume it exists since we use the
     231                        // `get_dynamic_block_names` function as a source for pattern matching.
     232                        $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
     233
     234                        // Replace dynamic block with server-rendered output.
     235                        $block_content = $block_type->render( (array) $block['attrs'], $block['innerHTML'] );
     236                } else if ( $block['innerBlocks'] ) {
     237                        $block_content = _recurse_do_blocks( $block['innerBlocks'], $blocks );
     238                } else {
     239                        $block_content = $block['innerHTML'];
     240                }
     241
     242                /**
     243                 * Filters the content of a single block.
     244                 *
     245                 * During the_content, each block is parsed and added to the output individually. This filter allows
     246                 * that content to be altered immediately before it's appended.
     247                 *
     248                 * @since 5.0.0
     249                 *
     250                 * @param string $block_content The block content about to be appended.
     251                 * @param array  $block         The full block, including name and attributes.
     252                 * @param array  $all_blocks    The array of all blocks being processed.
     253                 */
     254                $rendered_content .= apply_filters( 'do_block', $block_content, $block, $all_blocks );
     255
     256                // Restore global $post.
     257                $post = $global_post;
     258        }
     259
     260        // Strip remaining block comment demarcations.
     261        $rendered_content = preg_replace( '/<!--\s+\/?wp:.*?-->/m', '', $rendered_content );
     262
     263        return $rendered_content;
     264}
  • branches/5.0/src/wp-includes/class-wp-block-parser.php

    r43751 r43752  
    307307                                 */
    308308                                $stack_top = array_pop( $this->stack );
    309                                 $stack_top->block->innerHTML .= substr( $this->document, $stack_top->prev_offset, $start_offset - $stack_top->prev_offset );
     309
     310                                $html = substr( $this->document, $stack_top->prev_offset, $start_offset - $stack_top->prev_offset );
     311                                if ( $stack_top->block->innerBlocks ) {
     312                                        $stack_top->block->innerBlocks[] = (array) $this->freeform( $html );
     313                                } else {
     314                                        $stack_top->block->innerHTML = $html;
     315                                }
     316
    310317                                $stack_top->prev_offset = $start_offset + $token_length;
    311318
     
    441448        function add_inner_block( WP_Block_Parser_Block $block, $token_start, $token_length, $last_offset = null ) {
    442449                $parent = $this->stack[ count( $this->stack ) - 1 ];
    443                 $parent->block->innerBlocks[] = $block;
    444                 $parent->block->innerHTML .= substr( $this->document, $parent->prev_offset, $token_start - $parent->prev_offset );
     450                $parent->block->innerBlocks[] = (array) $this->freeform( substr( $this->document, $parent->prev_offset, $token_start - $parent->prev_offset ) );
     451                $parent->block->innerBlocks[] = (array) $block;
    445452                $parent->prev_offset = $last_offset ? $last_offset : $token_start + $token_length;
    446453        }
     
    457464                $prev_offset = $stack_top->prev_offset;
    458465
    459                 $stack_top->block->innerHTML .= isset( $end_offset )
     466                $html = isset( $end_offset )
    460467                        ? substr( $this->document, $prev_offset, $end_offset - $prev_offset )
    461468                        : substr( $this->document, $prev_offset );
     469
     470                if ( $stack_top->block->innerBlocks ) {
     471                        $stack_top->block->innerBlocks[] = (array) $this->freeform( $html );
     472                } else {
     473                        $stack_top->block->innerHTML = $html;
     474                }
    462475
    463476                if ( isset( $stack_top->leading_html_start ) ) {
  • branches/5.0/src/wp-includes/default-filters.php

    r43738 r43752  
    172172add_filter( 'the_title', 'trim'          );
    173173
     174add_filter( 'the_content', 'do_blocks',                      9 );
    174175add_filter( 'the_content', 'wptexturize'                       );
    175176add_filter( 'the_content', 'convert_smilies',               20 );
  • branches/5.0/src/wp-includes/formatting.php

    r43732 r43752  
    442442        if ( trim($pee) === '' )
    443443                return '';
     444
     445        // We don't need to autop posts with blocks in them.
     446        if ( has_blocks( $pee ) ) {
     447                return $pee;
     448        }
    444449
    445450        // Just to make things a little easier, pad the end.
     
    33723377
    33733378                $text = strip_shortcodes( $text );
     3379                $text = strip_dynamic_blocks( $text );
    33743380
    33753381                /** This filter is documented in wp-includes/post-template.php */
  • branches/5.0/src/wp-settings.php

    r43751 r43752  
    248248require( ABSPATH . WPINC . '/class-wp-block-parser.php' );
    249249require( ABSPATH . WPINC . '/blocks.php' );
     250require( ABSPATH . WPINC . '/blocks/archives.php' );
     251require( ABSPATH . WPINC . '/blocks/block.php' );
     252require( ABSPATH . WPINC . '/blocks/categories.php' );
     253require( ABSPATH . WPINC . '/blocks/latest-comments.php' );
     254require( ABSPATH . WPINC . '/blocks/latest-posts.php' );
     255require( ABSPATH . WPINC . '/blocks/shortcode.php' );
    250256
    251257$GLOBALS['wp_embed'] = new WP_Embed();
  • branches/5.0/tests/phpunit/data/blocks/do-blocks-expected.html

    r43743 r43752  
    33<!--more-->
    44
     5
    56<p>First Gutenberg Paragraph</p>
     7
    68
    79<p>Second Auto Paragraph</p>
    810
    911
     12
     13
    1014<p>Third Gutenberg Paragraph</p>
     15
    1116
    1217<p>Third Auto Paragraph</p>
  • branches/5.0/tests/phpunit/data/blocks/fixtures/core__column.parsed.json

    r43751 r43752  
    44        "attrs": {},
    55        "innerBlocks": [
     6                        {
     7                                "blockName": null,
     8                                "attrs": {},
     9                                "innerBlocks": [],
     10                                "innerHTML": "\n<div class=\"wp-block-column\">\n\t"
     11                        },
    612            {
    713                "blockName": "core/paragraph",
     
    1016                "innerHTML": "\n\t<p>Column One, Paragraph One</p>\n\t"
    1117            },
     18                        {
     19                                "blockName": null,
     20                                "attrs": {},
     21                                "innerBlocks": [],
     22                                "innerHTML": "\n\t"
     23                        },
    1224            {
    1325                "blockName": "core/paragraph",
     
    1527                "innerBlocks": [],
    1628                "innerHTML": "\n\t<p>Column One, Paragraph Two</p>\n\t"
    17             }
    18         ],
    19         "innerHTML": "\n<div class=\"wp-block-column\">\n\t\n\t\n</div>\n"
     29            },
     30                        {
     31                                "blockName": null,
     32                                "attrs": {},
     33                                "innerBlocks": [],
     34                                "innerHTML": "\n</div>\n"
     35                        }
     36                ],
     37                "innerHTML": ""
    2038    },
    2139    {
  • branches/5.0/tests/phpunit/data/blocks/fixtures/core__columns.parsed.json

    r43751 r43752  
    66        },
    77        "innerBlocks": [
     8                        {
     9                                "blockName": null,
     10                                "attrs": {},
     11                                "innerBlocks": [],
     12                                "innerHTML": "\n<div class=\"wp-block-columns has-3-columns\">\n\t"
     13                        },
    814            {
    915                "blockName": "core/column",
    1016                "attrs": {},
    1117                "innerBlocks": [
    12                     {
     18                                        {
     19                                                "blockName": null,
     20                                                "attrs": {},
     21                                                "innerBlocks": [],
     22                                                "innerHTML": "\n\t<div class=\"wp-block-column\">\n\t\t"
     23                                        },
     24                                        {
    1325                        "blockName": "core/paragraph",
    1426                        "attrs": {},
     
    1628                        "innerHTML": "\n\t\t<p>Column One, Paragraph One</p>\n\t\t"
    1729                    },
    18                     {
     30                                        {
     31                                                "blockName": null,
     32                                                "attrs": {},
     33                                                "innerBlocks": [],
     34                                                "innerHTML": "\n\t\t"
     35                                        },
     36                                        {
    1937                        "blockName": "core/paragraph",
    2038                        "attrs": {},
    2139                        "innerBlocks": [],
    2240                        "innerHTML": "\n\t\t<p>Column One, Paragraph Two</p>\n\t\t"
    23                     }
     41                    },
     42                                        {
     43                                                "blockName": null,
     44                                                "attrs": {},
     45                                                "innerBlocks": [],
     46                                                "innerHTML": "\n\t</div>\n\t"
     47                                        }
    2448                ],
    25                 "innerHTML": "\n\t<div class=\"wp-block-column\">\n\t\t\n\t\t\n\t</div>\n\t"
     49                "innerHTML": ""
    2650            },
     51                        {
     52                                "blockName": null,
     53                                "attrs": {},
     54                                "innerBlocks": [],
     55                                "innerHTML": "\n\t"
     56                        },
    2757            {
    2858                "blockName": "core/column",
    2959                "attrs": {},
    30                 "innerBlocks": [
    31                     {
     60                                "innerBlocks": [
     61                                        {
     62                                                "blockName": null,
     63                                                "attrs": {},
     64                                                "innerBlocks": [],
     65                                                "innerHTML": "\n\t<div class=\"wp-block-column\">\n\t\t"
     66                                        },
     67                                        {
    3268                        "blockName": "core/paragraph",
    3369                        "attrs": {},
     
    3571                        "innerHTML": "\n\t\t<p>Column Two, Paragraph One</p>\n\t\t"
    3672                    },
    37                     {
     73                                        {
     74                                                "blockName": null,
     75                                                "attrs": {},
     76                                                "innerBlocks": [],
     77                                                "innerHTML": "\n\t\t"
     78                                        },
     79                                        {
    3880                        "blockName": "core/paragraph",
    3981                        "attrs": {},
    4082                        "innerBlocks": [],
    4183                        "innerHTML": "\n\t\t<p>Column Three, Paragraph One</p>\n\t\t"
    42                     }
     84                    },
     85                                        {
     86                                                "blockName": null,
     87                                                "attrs": {},
     88                                                "innerBlocks": [],
     89                                                "innerHTML": "\n\t</div>\n\t"
     90                                        }
    4391                ],
    44                 "innerHTML": "\n\t<div class=\"wp-block-column\">\n\t\t\n\t\t\n\t</div>\n\t"
    45             }
     92                "innerHTML": ""
     93            },
     94                        {
     95                                "blockName": null,
     96                                "attrs": {},
     97                                "innerBlocks": [],
     98                                "innerHTML": "\n</div>\n"
     99                        }
    46100        ],
    47         "innerHTML": "\n<div class=\"wp-block-columns has-3-columns\">\n\t\n\t\n</div>\n"
     101        "innerHTML": ""
    48102    },
    49103    {
  • branches/5.0/tests/phpunit/includes/functions.php

    r41966 r43752  
    183183// Cannot modify header information - headers already sent by ...
    184184tests_add_filter( 'send_auth_cookies', '__return_false' );
     185
     186/**
     187 * After the init action has been run once, trying to re-register block types can cause
     188 * _doing_it_wrong warnings. To avoid this, unhook the block registration functions.
     189 *
     190 * @since 5.0.0
     191 */
     192function _unhook_block_registration() {
     193        remove_action( 'init', 'register_block_core_archives' );
     194        remove_action( 'init', 'register_block_core_categories' );
     195        remove_action( 'init', 'register_block_core_latest_posts' );
     196        remove_action( 'init', 'register_block_core_shortcode' );
     197}
     198tests_add_filter( 'init', '_unhook_block_registration', 1000 );
  • branches/5.0/tests/phpunit/tests/blocks/block-parser.php

    r43751 r43752  
    6060                foreach ( array( $html_path, $parsed_json_path ) as $filename ) {
    6161                        if ( ! file_exists( $filename ) ) {
    62                                 //throw new Exception( "Missing fixture file: '$filename'" );
     62                                throw new Exception( "Missing fixture file: '$filename'" );
    6363                        }
    6464                }
     
    117117                return str_replace( "\r", '', $input );
    118118        }
    119 
    120119}
  • branches/5.0/tools/webpack/packages.js

    r43751 r43752  
    118118
    119119        const phpFiles = {
    120                 'block-serialization-default-parser/parser.php': 'wp-includes/class-wp-block-parser.php',
     120                // Parser shouldn't be copied until nested block issues are resolved.
     121                // 'block-serialization-default-parser/parser.php': 'wp-includes/class-wp-block-parser.php',
     122                'block-library/src/archives/index.php': 'wp-includes/blocks/archives.php',
     123                'block-library/src/block/index.php': 'wp-includes/blocks/block.php',
     124                'block-library/src/categories/index.php': 'wp-includes/blocks/categories.php',
     125                'block-library/src/latest-comments/index.php': 'wp-includes/blocks/latest-comments.php',
     126                'block-library/src/latest-posts/index.php': 'wp-includes/blocks/latest-posts.php',
     127                'block-library/src/shortcode/index.php': 'wp-includes/blocks/shortcode.php',
    121128        };
    122129
Note: See TracChangeset for help on using the changeset viewer.