WordPress.org

Make WordPress Core

Ticket #45097: 45097.diff

File 45097.diff, 21.7 KB (added by adamsilverstein, 2 years ago)
  • new file src/wp-includes/class-wp-block-type-registry.php

    diff --git a/src/wp-includes/class-wp-block-type-registry.php b/src/wp-includes/class-wp-block-type-registry.php
    new file mode 100644
    index 0000000000..f95dec6ce4
    - +  
     1<?php
     2/**
     3 * Blocks API: WP_Block_Type_Registry class
     4 *
     5 * @package gutenberg
     6 * @since 0.6.0
     7 */
     8
     9/**
     10 * Core class used for interacting with block types.
     11 *
     12 * @since 0.6.0
     13 */
     14final class WP_Block_Type_Registry {
     15        /**
     16         * Registered block types, as `$name => $instance` pairs.
     17         *
     18         * @since 0.6.0
     19         * @access private
     20         * @var WP_Block_Type[]
     21         */
     22        private $registered_block_types = array();
     23
     24        /**
     25         * Container for the main instance of the class.
     26         *
     27         * @since 0.6.0
     28         * @access private
     29         * @static
     30         * @var WP_Block_Type_Registry|null
     31         */
     32        private static $instance = null;
     33
     34        /**
     35         * Registers a block type.
     36         *
     37         * @since 0.6.0
     38         * @access public
     39         *
     40         * @param string|WP_Block_Type $name Block type name including namespace, or alternatively a
     41         *                                   complete WP_Block_Type instance. In case a WP_Block_Type
     42         *                                   is provided, the $args parameter will be ignored.
     43         * @param array                $args {
     44         *     Optional. Array of block type arguments. Any arguments may be defined, however the
     45         *     ones described below are supported by default. Default empty array.
     46         *
     47         *     @type callable $render_callback Callback used to render blocks of this block type.
     48         *     @type array    $attributes      Block attributes mapping, property name to schema.
     49         * }
     50         * @return WP_Block_Type|false The registered block type on success, or false on failure.
     51         */
     52        public function register( $name, $args = array() ) {
     53                $block_type = null;
     54                if ( $name instanceof WP_Block_Type ) {
     55                        $block_type = $name;
     56                        $name       = $block_type->name;
     57                }
     58
     59                if ( ! is_string( $name ) ) {
     60                        $message = __( 'Block type names must be strings.', 'gutenberg' );
     61                        _doing_it_wrong( __METHOD__, $message, '0.1.0' );
     62                        return false;
     63                }
     64
     65                if ( preg_match( '/[A-Z]+/', $name ) ) {
     66                        $message = __( 'Block type names must not contain uppercase characters.', 'gutenberg' );
     67                        _doing_it_wrong( __METHOD__, $message, '1.5.0' );
     68                        return false;
     69                }
     70
     71                $name_matcher = '/^[a-z0-9-]+\/[a-z0-9-]+$/';
     72                if ( ! preg_match( $name_matcher, $name ) ) {
     73                        $message = __( 'Block type names must contain a namespace prefix. Example: my-plugin/my-custom-block-type', 'gutenberg' );
     74                        _doing_it_wrong( __METHOD__, $message, '0.1.0' );
     75                        return false;
     76                }
     77
     78                if ( $this->is_registered( $name ) ) {
     79                        /* translators: 1: block name */
     80                        $message = sprintf( __( 'Block type "%s" is already registered.', 'gutenberg' ), $name );
     81                        _doing_it_wrong( __METHOD__, $message, '0.1.0' );
     82                        return false;
     83                }
     84
     85                if ( ! $block_type ) {
     86                        $block_type = new WP_Block_Type( $name, $args );
     87                }
     88
     89                $this->registered_block_types[ $name ] = $block_type;
     90
     91                return $block_type;
     92        }
     93
     94        /**
     95         * Unregisters a block type.
     96         *
     97         * @since 0.6.0
     98         * @access public
     99         *
     100         * @param string|WP_Block_Type $name Block type name including namespace, or alternatively a
     101         *                                   complete WP_Block_Type instance.
     102         * @return WP_Block_Type|false The unregistered block type on success, or false on failure.
     103         */
     104        public function unregister( $name ) {
     105                if ( $name instanceof WP_Block_Type ) {
     106                        $name = $name->name;
     107                }
     108
     109                if ( ! $this->is_registered( $name ) ) {
     110                        /* translators: 1: block name */
     111                        $message = sprintf( __( 'Block type "%s" is not registered.', 'gutenberg' ), $name );
     112                        _doing_it_wrong( __METHOD__, $message, '0.1.0' );
     113                        return false;
     114                }
     115
     116                $unregistered_block_type = $this->registered_block_types[ $name ];
     117                unset( $this->registered_block_types[ $name ] );
     118
     119                return $unregistered_block_type;
     120        }
     121
     122        /**
     123         * Retrieves a registered block type.
     124         *
     125         * @since 0.6.0
     126         * @access public
     127         *
     128         * @param string $name Block type name including namespace.
     129         * @return WP_Block_Type|null The registered block type, or null if it is not registered.
     130         */
     131        public function get_registered( $name ) {
     132                if ( ! $this->is_registered( $name ) ) {
     133                        return null;
     134                }
     135
     136                return $this->registered_block_types[ $name ];
     137        }
     138
     139        /**
     140         * Retrieves all registered block types.
     141         *
     142         * @since 0.6.0
     143         * @access public
     144         *
     145         * @return WP_Block_Type[] Associative array of `$block_type_name => $block_type` pairs.
     146         */
     147        public function get_all_registered() {
     148                return $this->registered_block_types;
     149        }
     150
     151        /**
     152         * Checks if a block type is registered.
     153         *
     154         * @since 0.6.0
     155         * @access public
     156         *
     157         * @param string $name Block type name including namespace.
     158         * @return bool True if the block type is registered, false otherwise.
     159         */
     160        public function is_registered( $name ) {
     161                return isset( $this->registered_block_types[ $name ] );
     162        }
     163
     164        /**
     165         * Utility method to retrieve the main instance of the class.
     166         *
     167         * The instance will be created if it does not exist yet.
     168         *
     169         * @since 0.6.0
     170         * @access public
     171         * @static
     172         *
     173         * @return WP_Block_Type_Registry The main instance.
     174         */
     175        public static function get_instance() {
     176                if ( null === self::$instance ) {
     177                        self::$instance = new self();
     178                }
     179
     180                return self::$instance;
     181        }
     182}
  • new file src/wp-includes/class-wp-block-type.php

    diff --git a/src/wp-includes/class-wp-block-type.php b/src/wp-includes/class-wp-block-type.php
    new file mode 100644
    index 0000000000..0c18bb6efa
    - +  
     1<?php
     2/**
     3 * Blocks API: WP_Block_Type class
     4 *
     5 * @package gutenberg
     6 * @since 0.6.0
     7 */
     8
     9/**
     10 * Core class representing a block type.
     11 *
     12 * @since 0.6.0
     13 *
     14 * @see register_block_type()
     15 */
     16class WP_Block_Type {
     17        /**
     18         * Block type key.
     19         *
     20         * @since 0.6.0
     21         * @var string
     22         */
     23        public $name;
     24
     25        /**
     26         * Block type render callback.
     27         *
     28         * @since 0.6.0
     29         * @var callable
     30         */
     31        public $render_callback;
     32
     33        /**
     34         * Block type attributes property schemas.
     35         *
     36         * @since 0.10.0
     37         * @var array
     38         */
     39        public $attributes;
     40
     41        /**
     42         * Block type editor script handle.
     43         *
     44         * @since 2.0.0
     45         * @var string
     46         */
     47        public $editor_script;
     48
     49        /**
     50         * Block type front end script handle.
     51         *
     52         * @since 2.0.0
     53         * @var string
     54         */
     55        public $script;
     56
     57        /**
     58         * Block type editor style handle.
     59         *
     60         * @since 2.0.0
     61         * @var string
     62         */
     63        public $editor_style;
     64
     65        /**
     66         * Block type front end style handle.
     67         *
     68         * @since 2.0.0
     69         * @var string
     70         */
     71        public $style;
     72
     73        /**
     74         * Constructor.
     75         *
     76         * Will populate object properties from the provided arguments.
     77         *
     78         * @since 0.6.0
     79         *
     80         * @see register_block_type()
     81         *
     82         * @param string       $block_type Block type name including namespace.
     83         * @param array|string $args       Optional. Array or string of arguments for registering a block type.
     84         *                                 Default empty array.
     85         */
     86        public function __construct( $block_type, $args = array() ) {
     87                $this->name = $block_type;
     88
     89                $this->set_props( $args );
     90        }
     91
     92        /**
     93         * Renders the block type output for given attributes.
     94         *
     95         * @since 0.6.0
     96         *
     97         * @param array  $attributes Optional. Block attributes. Default empty array.
     98         * @param string $content    Optional. Block content. Default empty string.
     99         * @return string Rendered block type output.
     100         */
     101        public function render( $attributes = array(), $content = '' ) {
     102                if ( ! $this->is_dynamic() ) {
     103                        return '';
     104                }
     105
     106                $attributes = $this->prepare_attributes_for_render( $attributes );
     107
     108                return (string) call_user_func( $this->render_callback, $attributes, $content );
     109        }
     110
     111        /**
     112         * Returns true if the block type is dynamic, or false otherwise. A dynamic
     113         * block is one which defers its rendering to occur on-demand at runtime.
     114         *
     115         * @return boolean Whether block type is dynamic.
     116         */
     117        public function is_dynamic() {
     118                return is_callable( $this->render_callback );
     119        }
     120
     121        /**
     122         * Validates attributes against the current block schema, populating
     123         * defaulted and missing values, and omitting unknown attributes.
     124         *
     125         * @param  array $attributes Original block attributes.
     126         * @return array             Prepared block attributes.
     127         */
     128        public function prepare_attributes_for_render( $attributes ) {
     129                if ( ! isset( $this->attributes ) ) {
     130                        return $attributes;
     131                }
     132
     133                $prepared_attributes = array();
     134
     135                foreach ( $this->attributes as $attribute_name => $schema ) {
     136                        $value = null;
     137
     138                        if ( isset( $attributes[ $attribute_name ] ) ) {
     139                                $is_valid = rest_validate_value_from_schema( $attributes[ $attribute_name ], $schema );
     140                                if ( ! is_wp_error( $is_valid ) ) {
     141                                        $value = rest_sanitize_value_from_schema( $attributes[ $attribute_name ], $schema );
     142                                }
     143                        }
     144
     145                        if ( is_null( $value ) && isset( $schema['default'] ) ) {
     146                                $value = $schema['default'];
     147                        }
     148
     149                        $prepared_attributes[ $attribute_name ] = $value;
     150                }
     151
     152                return $prepared_attributes;
     153        }
     154
     155        /**
     156         * Sets block type properties.
     157         *
     158         * @since 0.6.0
     159         *
     160         * @param array|string $args Array or string of arguments for registering a block type.
     161         */
     162        public function set_props( $args ) {
     163                $args = wp_parse_args(
     164                        $args,
     165                        array(
     166                                'render_callback' => null,
     167                        )
     168                );
     169
     170                $args['name'] = $this->name;
     171
     172                foreach ( $args as $property_name => $property_value ) {
     173                        $this->$property_name = $property_value;
     174                }
     175        }
     176
     177        /**
     178         * Get all available block attributes including possible layout attribute from Columns block.
     179         *
     180         * @return array Array of attributes.
     181         */
     182        public function get_attributes() {
     183                return is_array( $this->attributes ) ?
     184                        array_merge(
     185                                $this->attributes,
     186                                array(
     187                                        'layout' => array(
     188                                                'type' => 'string',
     189                                        ),
     190                                )
     191                        ) :
     192                        array(
     193                                'layout' => array(
     194                                        'type' => 'string',
     195                                ),
     196                        );
     197        }
     198}
  • src/wp-settings.php

    diff --git a/src/wp-settings.php b/src/wp-settings.php
    index 44c8a91a07..ba0f9388d7 100644
    a b require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-comment-meta-fields.p 
    240240require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-post-meta-fields.php' );
    241241require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-term-meta-fields.php' );
    242242require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-user-meta-fields.php' );
     243require( ABSPATH . WPINC . '/class-wp-block-type.php' );
     244require( ABSPATH . WPINC . '/class-wp-block-type-registry.php' );
    243245
    244246$GLOBALS['wp_embed'] = new WP_Embed();
    245247
  • new file tests/phpunit/tests/blocks/class-block-type-registry-test.php

    diff --git a/tests/phpunit/tests/blocks/class-block-type-registry-test.php b/tests/phpunit/tests/blocks/class-block-type-registry-test.php
    new file mode 100644
    index 0000000000..0ba75cd8d0
    - +  
     1<?php
     2/**
     3 * WP_Block_Type_Registry Tests
     4 *
     5 * @package Gutenberg
     6 */
     7
     8/**
     9 * Tests for WP_Block_Type_Registry
     10 */
     11class Block_Type_Registry_Test extends WP_UnitTestCase {
     12
     13        /**
     14         * Dummy block type registry.
     15         *
     16         * @var WP_Block_Type_Registry
     17         */
     18        private $registry = null;
     19
     20        function setUp() {
     21                parent::setUp();
     22
     23                $this->registry = new WP_Block_Type_Registry();
     24        }
     25
     26        function tearDown() {
     27                parent::tearDown();
     28
     29                $this->registry = null;
     30        }
     31
     32        /**
     33         * Should reject numbers
     34         *
     35         * @expectedIncorrectUsage WP_Block_Type_Registry::register
     36         */
     37        function test_invalid_non_string_names() {
     38                $result = $this->registry->register( 1, array() );
     39                $this->assertFalse( $result );
     40        }
     41
     42        /**
     43         * Should reject blocks without a namespace
     44         *
     45         * @expectedIncorrectUsage WP_Block_Type_Registry::register
     46         */
     47        function test_invalid_names_without_namespace() {
     48                $result = $this->registry->register( 'paragraph', array() );
     49                $this->assertFalse( $result );
     50        }
     51
     52        /**
     53         * Should reject blocks with invalid characters
     54         *
     55         * @expectedIncorrectUsage WP_Block_Type_Registry::register
     56         */
     57        function test_invalid_characters() {
     58                $result = $this->registry->register( 'still/_doing_it_wrong', array() );
     59                $this->assertFalse( $result );
     60        }
     61
     62        /**
     63         * Should reject blocks with uppercase characters
     64         *
     65         * @expectedIncorrectUsage WP_Block_Type_Registry::register
     66         */
     67        function test_uppercase_characters() {
     68                $result = $this->registry->register( 'Core/Paragraph', array() );
     69                $this->assertFalse( $result );
     70        }
     71
     72        /**
     73         * Should accept valid block names
     74         */
     75        function test_register_block_type() {
     76                $name     = 'core/paragraph';
     77                $settings = array(
     78                        'icon' => 'editor-paragraph',
     79                );
     80
     81                $block_type = $this->registry->register( $name, $settings );
     82                $this->assertEquals( $name, $block_type->name );
     83                $this->assertEquals( $settings['icon'], $block_type->icon );
     84                $this->assertEquals( $block_type, $this->registry->get_registered( $name ) );
     85        }
     86
     87        /**
     88         * Should fail to re-register the same block
     89         *
     90         * @expectedIncorrectUsage WP_Block_Type_Registry::register
     91         */
     92        function test_register_block_type_twice() {
     93                $name     = 'core/paragraph';
     94                $settings = array(
     95                        'icon' => 'editor-paragraph',
     96                );
     97
     98                $result = $this->registry->register( $name, $settings );
     99                $this->assertNotFalse( $result );
     100                $result = $this->registry->register( $name, $settings );
     101                $this->assertFalse( $result );
     102        }
     103
     104        /**
     105         * Should accept a WP_Block_Type instance
     106         */
     107        function test_register_block_type_instance() {
     108                $block_type = new WP_Dummy_Block_Type( 'core/dummy' );
     109
     110                $result = $this->registry->register( $block_type );
     111                $this->assertSame( $block_type, $result );
     112        }
     113
     114        /**
     115         * Unregistering should fail if a block is not registered
     116         *
     117         * @expectedIncorrectUsage WP_Block_Type_Registry::unregister
     118         */
     119        function test_unregister_not_registered_block() {
     120                $result = $this->registry->unregister( 'core/unregistered' );
     121                $this->assertFalse( $result );
     122        }
     123
     124        /**
     125         * Should unregister existing blocks
     126         */
     127        function test_unregister_block_type() {
     128                $name     = 'core/paragraph';
     129                $settings = array(
     130                        'icon' => 'editor-paragraph',
     131                );
     132
     133                $this->registry->register( $name, $settings );
     134                $block_type = $this->registry->unregister( $name );
     135                $this->assertEquals( $name, $block_type->name );
     136                $this->assertEquals( $settings['icon'], $block_type->icon );
     137                $this->assertFalse( $this->registry->is_registered( $name ) );
     138        }
     139
     140        function test_get_all_registered() {
     141                $names    = array( 'core/paragraph', 'core/image', 'core/blockquote' );
     142                $settings = array(
     143                        'icon' => 'random',
     144                );
     145
     146                foreach ( $names as $name ) {
     147                        $this->registry->register( $name, $settings );
     148                }
     149
     150                $registered = $this->registry->get_all_registered();
     151                $this->assertEqualSets( $names, array_keys( $registered ) );
     152        }
     153}
  • new file tests/phpunit/tests/blocks/class-block-type-test.php

    diff --git a/tests/phpunit/tests/blocks/class-block-type-test.php b/tests/phpunit/tests/blocks/class-block-type-test.php
    new file mode 100644
    index 0000000000..cada34b83c
    - +  
     1<?php
     2/**
     3 * WP_Block_Type Tests
     4 *
     5 * @package Gutenberg
     6 */
     7
     8/**
     9 * Tests for WP_Block_Type
     10 */
     11class Block_Type_Test extends WP_UnitTestCase {
     12        function setUp() {
     13                parent::setUp();
     14        }
     15
     16        /**
     17         * Editor user ID.
     18         *
     19         * @var int
     20         */
     21        protected static $editor_user_id;
     22
     23        /**
     24         * ID for a post containing blocks.
     25         *
     26         * @var int
     27         */
     28        protected static $post_with_blocks;
     29
     30        /**
     31         * ID for a post without blocks.
     32         *
     33         * @var int
     34         */
     35        protected static $post_without_blocks;
     36
     37        /**
     38         * Set up before class.
     39         */
     40        public static function wpSetUpBeforeClass() {
     41                self::$editor_user_id = self::factory()->user->create(
     42                        array(
     43                                'role' => 'editor',
     44                        )
     45                );
     46
     47                self::$post_with_blocks = self::factory()->post->create(
     48                        array(
     49                                'post_title'   => 'Example',
     50                                'post_content' => "<!-- wp:core/text {\"dropCap\":true} -->\n<p class=\"has-drop-cap\">Tester</p>\n<!-- /wp:core/text -->",
     51                        )
     52                );
     53
     54                self::$post_without_blocks = self::factory()->post->create(
     55                        array(
     56                                'post_title'   => 'Example',
     57                                'post_content' => 'Tester',
     58                        )
     59                );
     60        }
     61
     62        function test_set_props() {
     63                $name = 'core/dummy';
     64                $args = array(
     65                        'render_callback' => array( $this, 'render_dummy_block' ),
     66                        'foo'             => 'bar',
     67                );
     68
     69                $block_type = new WP_Block_Type( $name, $args );
     70
     71                $this->assertSame( $name, $block_type->name );
     72                $this->assertSame( $args['render_callback'], $block_type->render_callback );
     73                $this->assertSame( $args['foo'], $block_type->foo );
     74        }
     75
     76        function test_render() {
     77                $attributes = array(
     78                        'foo' => 'bar',
     79                        'bar' => 'foo',
     80                );
     81
     82                $block_type = new WP_Block_Type(
     83                        'core/dummy',
     84                        array(
     85                                'render_callback' => array( $this, 'render_dummy_block' ),
     86                        )
     87                );
     88                $output     = $block_type->render( $attributes );
     89                $this->assertEquals( $attributes, json_decode( $output, true ) );
     90        }
     91
     92        function test_render_with_content() {
     93                $attributes = array(
     94                        'foo' => 'bar',
     95                        'bar' => 'foo',
     96                );
     97
     98                $content = 'baz';
     99
     100                $expected = array_merge( $attributes, array( '_content' => $content ) );
     101
     102                $block_type = new WP_Block_Type(
     103                        'core/dummy',
     104                        array(
     105                                'render_callback' => array( $this, 'render_dummy_block_with_content' ),
     106                        )
     107                );
     108                $output     = $block_type->render( $attributes, $content );
     109                $this->assertEquals( $expected, json_decode( $output, true ) );
     110        }
     111
     112        function test_render_for_static_block() {
     113                $block_type = new WP_Block_Type( 'core/dummy', array() );
     114                $output     = $block_type->render();
     115
     116                $this->assertEquals( '', $output );
     117        }
     118
     119        function test_is_dynamic_for_static_block() {
     120                $block_type = new WP_Block_Type( 'core/dummy', array() );
     121
     122                $this->assertFalse( $block_type->is_dynamic() );
     123        }
     124
     125        function test_is_dynamic_for_dynamic_block() {
     126                $block_type = new WP_Block_Type(
     127                        'core/dummy',
     128                        array(
     129                                'render_callback' => array( $this, 'render_dummy_block' ),
     130                        )
     131                );
     132
     133                $this->assertTrue( $block_type->is_dynamic() );
     134        }
     135
     136        function test_prepare_attributes() {
     137                $attributes = array(
     138                        'correct'            => 'include',
     139                        'wrongType'          => 5,
     140                        'wrongTypeDefaulted' => 5,
     141                        /* missingDefaulted */
     142                        'undefined'          => 'omit',
     143                );
     144
     145                $block_type = new WP_Block_Type(
     146                        'core/dummy',
     147                        array(
     148                                'attributes' => array(
     149                                        'correct'            => array(
     150                                                'type' => 'string',
     151                                        ),
     152                                        'wrongType'          => array(
     153                                                'type' => 'string',
     154                                        ),
     155                                        'wrongTypeDefaulted' => array(
     156                                                'type'    => 'string',
     157                                                'default' => 'defaulted',
     158                                        ),
     159                                        'missingDefaulted'   => array(
     160                                                'type'    => 'string',
     161                                                'default' => 'define',
     162                                        ),
     163                                ),
     164                        )
     165                );
     166
     167                $prepared_attributes = $block_type->prepare_attributes_for_render( $attributes );
     168
     169                $this->assertEquals(
     170                        array(
     171                                'correct'            => 'include',
     172                                'wrongType'          => null,
     173                                'wrongTypeDefaulted' => 'defaulted',
     174                                'missingDefaulted'   => 'define',
     175                        ),
     176                        $prepared_attributes
     177                );
     178        }
     179
     180        function test_has_block_with_mixed_content() {
     181                $mixed_post_content = 'before' .
     182                '<!-- wp:core/dummy --><!-- /wp:core/dummy -->' .
     183                '<!-- wp:core/dummy_atts {"value":"b1"} --><!-- /wp:core/dummy_atts -->' .
     184                '<!-- wp:core/dummy-child -->
     185                <p>testing the test</p>
     186                <!-- /wp:core/dummy-child -->' .
     187                'between' .
     188                '<!-- wp:core/self-close-dummy /-->' .
     189                '<!-- wp:custom/dummy {"value":"b2"} /-->' .
     190                'after';
     191
     192                $this->assertTrue( has_block( 'core/dummy', $mixed_post_content ) );
     193
     194                $this->assertTrue( has_block( 'core/dummy_atts', $mixed_post_content ) );
     195
     196                $this->assertTrue( has_block( 'core/dummy-child', $mixed_post_content ) );
     197
     198                $this->assertTrue( has_block( 'core/self-close-dummy', $mixed_post_content ) );
     199
     200                $this->assertTrue( has_block( 'custom/dummy', $mixed_post_content ) );
     201
     202                // checking for a partial block name should fail.
     203                $this->assertFalse( has_block( 'core/dumm', $mixed_post_content ) );
     204
     205                // checking for a wrong namespace should fail.
     206                $this->assertFalse( has_block( 'custom/dummy_atts', $mixed_post_content ) );
     207
     208                // checking for namespace only should not work. Or maybe ... ?
     209                $this->assertFalse( has_block( 'core', $mixed_post_content ) );
     210        }
     211
     212        function test_has_block_with_invalid_content() {
     213                // some content with invalid HMTL comments and a single valid block.
     214                $invalid_content = 'before' .
     215                '<!- - wp:core/weird-space --><!-- /wp:core/weird-space -->' .
     216                '<!--wp:core/untrimmed-left --><!-- /wp:core/untrimmed -->' .
     217                '<!-- wp:core/dummy --><!-- /wp:core/dummy -->' .
     218                '<!-- wp:core/untrimmed-right--><!-- /wp:core/untrimmed2 -->' .
     219                'after';
     220
     221                $this->assertFalse( has_block( 'core/text', self::$post_without_blocks ) );
     222
     223                $this->assertFalse( has_block( 'core/weird-space', $invalid_content ) );
     224
     225                $this->assertFalse( has_block( 'core/untrimmed-left', $invalid_content ) );
     226
     227                $this->assertFalse( has_block( 'core/untrimmed-right', $invalid_content ) );
     228
     229                $this->assertTrue( has_block( 'core/dummy', $invalid_content ) );
     230        }
     231
     232        function test_post_has_block() {
     233                // should fail for a non-existent block `custom/dummy`.
     234                $this->assertFalse( has_block( 'custom/dummy', self::$post_with_blocks ) );
     235
     236                // this functions should not work without the second param until the $post global is set.
     237                $this->assertFalse( has_block( 'core/text' ) );
     238                $this->assertFalse( has_block( 'core/dummy' ) );
     239
     240                global $post;
     241                $post = get_post( self::$post_with_blocks );
     242
     243                // check if the function correctly detects content from the $post global.
     244                $this->assertTrue( has_block( 'core/text' ) );
     245                // even if it detects a proper $post global it should still be false for a missing block.
     246                $this->assertFalse( has_block( 'core/dummy' ) );
     247        }
     248
     249        function render_dummy_block( $attributes ) {
     250                return json_encode( $attributes );
     251        }
     252
     253        function render_dummy_block_with_content( $attributes, $content ) {
     254                $attributes['_content'] = $content;
     255
     256                return json_encode( $attributes );
     257        }
     258}