Make WordPress Core

Changeset 57562


Ignore:
Timestamp:
02/08/2024 08:55:18 AM (2 months ago)
Author:
gziolo
Message:

Editor: Introduce WP_Block_Bindings_Source class

Abstracts the block bindings source array into a well-defined object.

Fixes #60447.
See #60282.
Follow-up [57373].
Props czapla, santosguillamot, gziolo.

Location:
trunk
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/block-bindings.php

    r57560 r57562  
    8989 *                                        the block's original value, null, false to remove an attribute, etc.
    9090 * }
    91  * @return array|false Source when the registration was successful, or `false` on failure.
     91 * @return WP_Block_Bindings_Source|false Source when the registration was successful, or `false` on failure.
    9292 */
    9393function register_block_bindings_source( string $source_name, array $source_properties ) {
     
    101101 *
    102102 * @param string $source_name Block bindings source name including namespace.
    103  * @return array|false The unregistered block bindings source on success and `false` otherwise.
     103 * @return WP_Block_Bindings_Source|false The unregistered block bindings source on success and `false` otherwise.
    104104 */
    105105function unregister_block_bindings_source( string $source_name ) {
     
    112112 * @since 6.5.0
    113113 *
    114  * @return array The array of registered block bindings sources.
     114 * @return WP_Block_Bindings_Source[] The array of registered block bindings sources.
    115115 */
    116116function get_all_registered_block_bindings_sources() {
     
    124124 *
    125125 * @param string $source_name The name of the source.
    126  * @return array|null The registered block bindings source, or `null` if it is not registered.
     126 * @return WP_Block_Bindings_Source|null The registered block bindings source, or `null` if it is not registered.
    127127 */
    128128function get_block_bindings_source( string $source_name ) {
  • trunk/src/wp-includes/class-wp-block-bindings-registry.php

    r57560 r57562  
    2121     *
    2222     * @since 6.5.0
    23      * @var array
     23     * @var WP_Block_Bindings_Source[]
    2424     */
    2525    private $sources = array();
     
    6767     *                                        the block's original value, null, false to remove an attribute, etc.
    6868     * }
    69      * @return array|false Source when the registration was successful, or `false` on failure.
     69     * @return WP_Block_Bindings_Source|false Source when the registration was successful, or `false` on failure.
    7070     */
    7171    public function register( string $source_name, array $source_properties ) {
     
    108108        }
    109109
    110         $source = array_merge(
    111             array( 'name' => $source_name ),
     110        /* Validate that the source properties contain the label */
     111        if ( ! isset( $source_properties['label'] ) ) {
     112            _doing_it_wrong(
     113                __METHOD__,
     114                __( 'The $source_properties must contain a "label".' ),
     115                '6.5.0'
     116            );
     117            return false;
     118        }
     119
     120        /* Validate that the source properties contain the get_value_callback */
     121        if ( ! isset( $source_properties['get_value_callback'] ) ) {
     122            _doing_it_wrong(
     123                __METHOD__,
     124                __( 'The $source_properties must contain a "get_value_callback".' ),
     125                '6.5.0'
     126            );
     127            return false;
     128        }
     129
     130        /* Validate that the get_value_callback is a valid callback */
     131        if ( ! is_callable( $source_properties['get_value_callback'] ) ) {
     132            _doing_it_wrong(
     133                __METHOD__,
     134                __( 'The "get_value_callback" parameter must be a valid callback.' ),
     135                '6.5.0'
     136            );
     137            return false;
     138        }
     139
     140        $source = new WP_Block_Bindings_Source(
     141            $source_name,
    112142            $source_properties
    113143        );
     
    124154     *
    125155     * @param string $source_name Block bindings source name including namespace.
    126      * @return array|false The unregistered block bindings source on success and `false` otherwise.
     156     * @return WP_Block_Bindings_Source|false The unregistered block bindings source on success and `false` otherwise.
    127157     */
    128158    public function unregister( string $source_name ) {
     
    148178     * @since 6.5.0
    149179     *
    150      * @return array The array of registered sources.
     180     * @return WP_Block_Bindings_Source[] The array of registered sources.
    151181     */
    152182    public function get_all_registered() {
     
    160190     *
    161191     * @param string $source_name The name of the source.
    162      * @return array|null The registered block bindings source, or `null` if it is not registered.
     192     * @return WP_Block_Bindings_Source|null The registered block bindings source, or `null` if it is not registered.
    163193     */
    164194    public function get_registered( string $source_name ) {
  • trunk/src/wp-includes/class-wp-block.php

    r57561 r57562  
    271271            }
    272272
    273             $source_callback = $block_binding_source['get_value_callback'];
    274             $source_args     = ! empty( $block_binding['args'] ) && is_array( $block_binding['args'] ) ? $block_binding['args'] : array();
    275             $source_value    = call_user_func_array( $source_callback, array( $source_args, $this, $attribute_name ) );
     273            $source_args  = ! empty( $block_binding['args'] ) && is_array( $block_binding['args'] ) ? $block_binding['args'] : array();
     274            $source_value = $block_binding_source->get_value( $source_args, $this, $attribute_name );
    276275
    277276            // If the value is not null, process the HTML based on the block and the attribute.
  • trunk/src/wp-settings.php

    r57548 r57562  
    333333require ABSPATH . WPINC . '/sitemaps/providers/class-wp-sitemaps-taxonomies.php';
    334334require ABSPATH . WPINC . '/sitemaps/providers/class-wp-sitemaps-users.php';
     335require ABSPATH . WPINC . '/class-wp-block-bindings-source.php';
    335336require ABSPATH . WPINC . '/class-wp-block-bindings-registry.php';
    336337require ABSPATH . WPINC . '/class-wp-block-editor-context.php';
  • trunk/tests/phpunit/tests/block-bindings/register.php

    r57526 r57562  
    1212class Tests_Block_Bindings_Register extends WP_UnitTestCase {
    1313
    14     const TEST_SOURCE_NAME       = 'test/source';
    15     const TEST_SOURCE_PROPERTIES = array(
    16         'label' => 'Test source',
    17     );
     14    public static $test_source_name       = 'test/source';
     15    public static $test_source_properties = array();
     16
     17    /**
     18     * Set up before each test.
     19     *
     20     * @since 6.5.0
     21     */
     22    public function set_up() {
     23        parent::set_up();
     24
     25        self::$test_source_properties = array(
     26            'label'              => 'Test source',
     27            'get_value_callback' => function () {
     28                return 'test-value';
     29            },
     30        );
     31    }
    1832
    1933    /**
     
    4054     * @covers ::get_all_registered_block_bindings_sources
    4155     * @covers ::get_block_bindings_source
     56     * @covers WP_Block_Bindings_Source::__construct
    4257     */
    4358    public function test_get_all_registered() {
    4459        $source_one_name       = 'test/source-one';
    45         $source_one_properties = self::TEST_SOURCE_PROPERTIES;
     60        $source_one_properties = self::$test_source_properties;
    4661        register_block_bindings_source( $source_one_name, $source_one_properties );
    4762
    4863        $source_two_name       = 'test/source-two';
    49         $source_two_properties = self::TEST_SOURCE_PROPERTIES;
     64        $source_two_properties = self::$test_source_properties;
    5065        register_block_bindings_source( $source_two_name, $source_two_properties );
    5166
    5267        $source_three_name       = 'test/source-three';
    53         $source_three_properties = self::TEST_SOURCE_PROPERTIES;
     68        $source_three_properties = self::$test_source_properties;
    5469        register_block_bindings_source( $source_three_name, $source_three_properties );
    5570
    5671        $expected = array(
    57             $source_one_name         => array_merge( array( 'name' => $source_one_name ), $source_one_properties ),
    58             $source_two_name         => array_merge( array( 'name' => $source_two_name ), $source_two_properties ),
    59             $source_three_name       => array_merge( array( 'name' => $source_three_name ), $source_three_properties ),
     72            $source_one_name         => new WP_Block_Bindings_Source( $source_one_name, $source_one_properties ),
     73            $source_two_name         => new WP_Block_Bindings_Source( $source_two_name, $source_two_properties ),
     74            $source_three_name       => new WP_Block_Bindings_Source( $source_three_name, $source_three_properties ),
    6075            'core/post-meta'         => get_block_bindings_source( 'core/post-meta' ),
    6176            'core/pattern-overrides' => get_block_bindings_source( 'core/pattern-overrides' ),
     
    7388     * @covers ::register_block_bindings_source
    7489     * @covers ::unregister_block_bindings_source
     90     * @covers WP_Block_Bindings_Source::__construct
    7591     */
    7692    public function test_unregister_block_source() {
    77         register_block_bindings_source( self::TEST_SOURCE_NAME, self::TEST_SOURCE_PROPERTIES );
     93        register_block_bindings_source( self::$test_source_name, self::$test_source_properties );
    7894
    79         $result = unregister_block_bindings_source( self::TEST_SOURCE_NAME );
    80         $this->assertSame(
    81             array_merge(
    82                 array( 'name' => self::TEST_SOURCE_NAME ),
    83                 self::TEST_SOURCE_PROPERTIES
     95        $result = unregister_block_bindings_source( self::$test_source_name );
     96        $this->assertEquals(
     97            new WP_Block_Bindings_Source(
     98                self::$test_source_name,
     99                self::$test_source_properties
    84100            ),
    85101            $result
  • trunk/tests/phpunit/tests/block-bindings/wpBlockBindingsRegistry.php

    r57375 r57562  
    1414class Tests_Blocks_wpBlockBindingsRegistry extends WP_UnitTestCase {
    1515
    16     const TEST_SOURCE_NAME       = 'test/source';
    17     const TEST_SOURCE_PROPERTIES = array(
    18         'label' => 'Test source',
    19     );
     16    public static $test_source_name       = 'test/source';
     17    public static $test_source_properties = array();
    2018
    2119    /**
     
    3634
    3735        $this->registry = new WP_Block_Bindings_Registry();
     36
     37        self::$test_source_properties = array(
     38            'label'              => 'Test source',
     39            'get_value_callback' => function () {
     40                return 'test-value';
     41            },
     42        );
    3843    }
    3944
     
    5964     */
    6065    public function test_register_invalid_non_string_names() {
    61         $result = $this->registry->register( 1, self::TEST_SOURCE_PROPERTIES );
     66        $result = $this->registry->register( 1, self::$test_source_properties );
    6267        $this->assertFalse( $result );
    6368    }
     
    7378     */
    7479    public function test_register_invalid_names_without_namespace() {
    75         $result = $this->registry->register( 'post-meta', self::TEST_SOURCE_PROPERTIES );
     80        $result = $this->registry->register( 'post-meta', self::$test_source_properties );
    7681        $this->assertFalse( $result );
    7782    }
     
    101106     */
    102107    public function test_register_invalid_uppercase_characters() {
    103         $result = $this->registry->register( 'Core/PostMeta', self::TEST_SOURCE_PROPERTIES );
     108        $result = $this->registry->register( 'Core/PostMeta', self::$test_source_properties );
     109        $this->assertFalse( $result );
     110    }
     111
     112    /**
     113     * Should reject block bindings registration without a label.
     114     *
     115     * @ticket 60282
     116     *
     117     * @covers WP_Block_Bindings_Registry::register
     118     *
     119     * @expectedIncorrectUsage WP_Block_Bindings_Registry::register
     120     */
     121    public function test_register_invalid_missing_label() {
     122
     123        // Remove the label from the properties.
     124        unset( self::$test_source_properties['label'] );
     125
     126        $result = $this->registry->register( self::$test_source_name, self::$test_source_properties );
     127        $this->assertFalse( $result );
     128    }
     129
     130    /**
     131     * Should reject block bindings registration without a get_value_callback.
     132     *
     133     * @ticket 60282
     134     *
     135     * @covers WP_Block_Bindings_Registry::register
     136     *
     137     * @expectedIncorrectUsage WP_Block_Bindings_Registry::register
     138     */
     139    public function test_register_invalid_missing_get_value_callback() {
     140
     141        // Remove the get_value_callback from the properties.
     142        unset( self::$test_source_properties['get_value_callback'] );
     143
     144        $result = $this->registry->register( self::$test_source_name, self::$test_source_properties );
     145        $this->assertFalse( $result );
     146    }
     147
     148    /**
     149     * Should reject block bindings registration if `get_value_callback` is not a callable.
     150     *
     151     * @ticket 60282
     152     *
     153     * @covers WP_Block_Bindings_Registry::register
     154     *
     155     * @expectedIncorrectUsage WP_Block_Bindings_Registry::register
     156     */
     157    public function test_register_invalid_incorrect_callback_type() {
     158
     159        self::$test_source_properties['get_value_callback'] = 'not-a-callback';
     160
     161        $result = $this->registry->register( self::$test_source_name, self::$test_source_properties );
    104162        $this->assertFalse( $result );
    105163    }
     
    111169     *
    112170     * @covers WP_Block_Bindings_Registry::register
     171     * @covers WP_Block_Bindings_Source::__construct
    113172     */
    114173    public function test_register_block_binding_source() {
    115         $result = $this->registry->register( self::TEST_SOURCE_NAME, self::TEST_SOURCE_PROPERTIES );
    116         $this->assertSame(
    117             array_merge(
    118                 array( 'name' => self::TEST_SOURCE_NAME ),
    119                 self::TEST_SOURCE_PROPERTIES
     174        $result = $this->registry->register( self::$test_source_name, self::$test_source_properties );
     175        $this->assertEquals(
     176            new WP_Block_Bindings_Source(
     177                self::$test_source_name,
     178                self::$test_source_properties
    120179            ),
    121180            $result
     
    144203     * @covers WP_Block_Bindings_Registry::register
    145204     * @covers WP_Block_Bindings_Registry::unregister
     205     * WP_Block_Bindings_Source::__construct
    146206     */
    147207    public function test_unregister_block_source() {
    148         $this->registry->register( self::TEST_SOURCE_NAME, self::TEST_SOURCE_PROPERTIES );
    149 
    150         $result = $this->registry->unregister( self::TEST_SOURCE_NAME );
    151         $this->assertSame(
    152             array_merge(
    153                 array( 'name' => self::TEST_SOURCE_NAME ),
    154                 self::TEST_SOURCE_PROPERTIES
     208        $this->registry->register( self::$test_source_name, self::$test_source_properties );
     209
     210        $result = $this->registry->unregister( self::$test_source_name );
     211        $this->assertEquals(
     212            new WP_Block_Bindings_Source(
     213                self::$test_source_name,
     214                self::$test_source_properties
    155215            ),
    156216            $result
     
    165225     * @covers WP_Block_Bindings_Registry::register
    166226     * @covers WP_Block_Bindings_Registry::get_all_registered
     227     * WP_Block_Bindings_Source::__construct
    167228     */
    168229    public function test_get_all_registered() {
    169230        $source_one_name       = 'test/source-one';
    170         $source_one_properties = self::TEST_SOURCE_PROPERTIES;
     231        $source_one_properties = self::$test_source_properties;
    171232        $this->registry->register( $source_one_name, $source_one_properties );
    172233
    173234        $source_two_name       = 'test/source-two';
    174         $source_two_properties = self::TEST_SOURCE_PROPERTIES;
     235        $source_two_properties = self::$test_source_properties;
    175236        $this->registry->register( $source_two_name, $source_two_properties );
    176237
    177238        $source_three_name       = 'test/source-three';
    178         $source_three_properties = self::TEST_SOURCE_PROPERTIES;
     239        $source_three_properties = self::$test_source_properties;
    179240        $this->registry->register( $source_three_name, $source_three_properties );
    180241
    181242        $expected = array(
    182             $source_one_name   => array_merge( array( 'name' => $source_one_name ), $source_one_properties ),
    183             $source_two_name   => array_merge( array( 'name' => $source_two_name ), $source_two_properties ),
    184             $source_three_name => array_merge( array( 'name' => $source_three_name ), $source_three_properties ),
     243            $source_one_name   => new WP_Block_Bindings_Source( $source_one_name, $source_one_properties ),
     244            $source_two_name   => new WP_Block_Bindings_Source( $source_two_name, $source_two_properties ),
     245            $source_three_name => new WP_Block_Bindings_Source( $source_three_name, $source_three_properties ),
    185246        );
    186247
    187248        $registered = $this->registry->get_all_registered();
    188         $this->assertSame( $expected, $registered );
     249        $this->assertEquals( $expected, $registered );
    189250    }
    190251
     
    198259     */
    199260    public function test_get_registered_rejects_unknown_source_name() {
    200         $this->registry->register( self::TEST_SOURCE_NAME, self::TEST_SOURCE_PROPERTIES );
     261        $this->registry->register( self::$test_source_name, self::$test_source_properties );
    201262
    202263        $source = $this->registry->get_registered( 'test/unknown-source' );
     
    211272     * @covers WP_Block_Bindings_Registry::register
    212273     * @covers WP_Block_Bindings_Registry::get_registered
     274     * @covers WP_Block_Bindings_Source::__construct
    213275     */
    214276    public function test_get_registered() {
    215277        $source_one_name       = 'test/source-one';
    216         $source_one_properties = self::TEST_SOURCE_PROPERTIES;
     278        $source_one_properties = self::$test_source_properties;
    217279        $this->registry->register( $source_one_name, $source_one_properties );
    218280
    219281        $source_two_name       = 'test/source-two';
    220         $source_two_properties = self::TEST_SOURCE_PROPERTIES;
     282        $source_two_properties = self::$test_source_properties;
    221283        $this->registry->register( $source_two_name, $source_two_properties );
    222284
    223285        $source_three_name       = 'test/source-three';
    224         $source_three_properties = self::TEST_SOURCE_PROPERTIES;
     286        $source_three_properties = self::$test_source_properties;
    225287        $this->registry->register( $source_three_name, $source_three_properties );
    226288
    227         $result = $this->registry->get_registered( 'test/source-two' );
    228         $this->assertSame(
    229             array_merge(
    230                 array( 'name' => $source_two_name ),
    231                 $source_two_properties
    232             ),
     289        $expected = new WP_Block_Bindings_Source( $source_two_name, $source_two_properties );
     290        $result   = $this->registry->get_registered( 'test/source-two' );
     291
     292        $this->assertEquals(
     293            $expected,
    233294            $result
    234295        );
     
    256317     */
    257318    public function test_is_registered_for_known_source() {
    258         $this->registry->register( self::TEST_SOURCE_NAME, self::TEST_SOURCE_PROPERTIES );
    259 
    260         $result = $this->registry->is_registered( self::TEST_SOURCE_NAME );
     319        $this->registry->register( self::$test_source_name, self::$test_source_properties );
     320
     321        $result = $this->registry->is_registered( self::$test_source_name );
    261322        $this->assertTrue( $result );
    262323    }
Note: See TracChangeset for help on using the changeset viewer.