Make WordPress Core

Changeset 54670


Ignore:
Timestamp:
10/24/2022 02:14:25 PM (20 months ago)
Author:
Bernhard Reiter
Message:

Blocks: Allow arrays for deprecated asset types in block registration.

In register_block_type, continue to allow passing arrays as the editor_script, script, view_script, editor_style, and style arguments. Note that those fields were soft-deprecated in favor of their _handles counterparts in [54155], which would allow specifying multiple items. At the same time, the deprecated fields were limited to string or null.

However, this broke existing code that passed an array as one of those arguments. For backwards compatibility, this change thus restores the previous behavior. It is implemented in WP_Block_Type as a pair of __get() and __set() methods that wrap around the corresponding _handles members, which are arrays of strings.

It also affects the REST API endpoint for block types. The latter’s schema has never allowed for anything other than string or null for any of those fields. For this reason, it now returns the first element of the array stored in the corresponding _handles member in WP_Block_Type.

Follow-up [54155].
Props nendeb55, costdev, gziolo, spacedmonkey, mukesh27, sergeybiryukov, audrasjb.
Fixes #56707.

Location:
trunk
Files:
4 edited

Legend:

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

    r54210 r54670  
    296296     * @param string $name Deprecated property name.
    297297     *
    298      * @return string|null|void The value read from the new property if the first item in the array provided,
    299      *                          null when value not found, or void when unknown property name provided.
     298     * @return string|string[]|null|void The value read from the new property if the first item in the array provided,
     299     *                                   null when value not found, or void when unknown property name provided.
    300300     */
    301301    public function __get( $name ) {
     
    305305
    306306        $new_name = $name . '_handles';
     307
     308        if ( ! property_exists( $this, $new_name ) || ! is_array( $this->{$new_name} ) ) {
     309            return null;
     310        }
     311
     312        if ( count( $this->{$new_name} ) > 1 ) {
     313            return $this->{$new_name};
     314        }
    307315        return isset( $this->{$new_name}[0] ) ? $this->{$new_name}[0] : null;
    308316    }
     
    344352        }
    345353
     354        $new_name = $name . '_handles';
     355
     356        if ( is_array( $value ) ) {
     357            $filtered = array_filter( $value, 'is_string' );
     358
     359            if ( count( $filtered ) !== count( $value ) ) {
     360                    _doing_it_wrong(
     361                        __METHOD__,
     362                        sprintf(
     363                            /* translators: %s: The '$value' argument. */
     364                            __( 'The %s argument must be a string or a string array.' ),
     365                            '<code>$value</code>'
     366                        ),
     367                        '6.1.0'
     368                    );
     369            }
     370
     371            $this->{$new_name} = array_values( $filtered );
     372            return;
     373        }
     374
    346375        if ( ! is_string( $value ) ) {
    347376            return;
    348377        }
    349378
    350         $new_name             = $name . '_handles';
    351         $this->{$new_name}[0] = $value;
     379        $this->{$new_name} = array( $value );
    352380    }
    353381
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php

    r54210 r54670  
    296296                if ( isset( $block_type->$extra_field ) ) {
    297297                    $field = $block_type->$extra_field;
     298                    if ( in_array( $extra_field, $deprecated_fields, true ) && is_array( $field ) ) {
     299                        // Since the schema only allows strings or null (but no arrays), we return the first array item.
     300                        $field = ! empty( $field ) ? array_shift( $field ) : '';
     301                    }
    298302                } elseif ( array_key_exists( 'default', $schema['properties'][ $extra_field ] ) ) {
    299303                    $field = $schema['properties'][ $extra_field ]['default'];
  • trunk/tests/phpunit/tests/blocks/register.php

    r54472 r54670  
    554554
    555555    /**
     556     * Tests that an array value for 'editor_script' is correctly set and retrieved.
     557     *
     558     * As 'editor_script' is now a deprecated property, this should also set
     559     * the value for the 'editor_script_handles' property.
     560     *
     561     * @ticket 56707
     562     *
     563     * @covers ::register_block_type
     564     * @covers WP_Block_Type::__set
     565     * @covers WP_Block_Type::__get
     566     *
     567     * @dataProvider data_register_block_type_accepts_editor_script_array
     568     *
     569     * @param array $editor_script The editor script array to register.
     570     * @param array $expected      The expected registered editor script.
     571     */
     572    public function test_register_block_type_accepts_editor_script_array( $editor_script, $expected ) {
     573        $settings = array( 'editor_script' => $editor_script );
     574        register_block_type( 'core/test-static', $settings );
     575
     576        $registry   = WP_Block_Type_Registry::get_instance();
     577        $block_type = $registry->get_registered( 'core/test-static' );
     578        $this->assertObjectHasAttribute( 'editor_script_handles', $block_type );
     579        $actual_script         = $block_type->editor_script;
     580        $actual_script_handles = $block_type->editor_script_handles;
     581
     582        $this->assertSame(
     583            $expected,
     584            $actual_script,
     585            'editor_script was not set to the correct value.'
     586        );
     587
     588        $this->assertSame(
     589            (array) $expected,
     590            $actual_script_handles,
     591            'editor_script_handles was not set to the correct value.'
     592        );
     593    }
     594
     595    /**
     596     * Data provider for test_register_block_type_accepts_editor_script_array().
     597     *
     598     * @return array
     599     */
     600    public function data_register_block_type_accepts_editor_script_array() {
     601        return array(
     602            'an empty array'      => array(
     603                'editor_script' => array(),
     604                'expected'      => null,
     605            ),
     606            'a single item array' => array(
     607                'editor_script' => array( 'hello' ),
     608                'expected'      => 'hello',
     609            ),
     610            'a multi-item array'  => array(
     611                'editor_script' => array( 'hello', 'world' ),
     612                'expected'      => array( 'hello', 'world' ),
     613            ),
     614        );
     615    }
     616
     617    /**
     618     * Tests that an array value for 'editor_script' containing invalid values
     619     * correctly triggers _doing_it_wrong(), filters the value, and sets the
     620     * property to the result.
     621     *
     622     * As 'editor_script' is now a deprecated property, this should also set
     623     * the value for the 'editor_script_handles' property.
     624     *
     625     * @ticket 56707
     626     *
     627     * @covers ::register_block_type
     628     * @covers WP_Block_Type::__set
     629     * @covers WP_Block_Type::__get
     630     *
     631     * @dataProvider data_register_block_type_throws_doing_it_wrong
     632     *
     633     * @expectedIncorrectUsage WP_Block_Type::__set
     634     *
     635     * @param array $editor_script The editor script array to register.
     636     * @param array $expected      The expected registered editor script.
     637     */
     638    public function test_register_block_type_throws_doing_it_wrong( $editor_script, $expected ) {
     639        $settings = array( 'editor_script' => $editor_script );
     640        register_block_type( 'core/test-static', $settings );
     641
     642        $registry   = WP_Block_Type_Registry::get_instance();
     643        $block_type = $registry->get_registered( 'core/test-static' );
     644        $this->assertObjectHasAttribute( 'editor_script_handles', $block_type );
     645        $actual_script         = $block_type->editor_script;
     646        $actual_script_handles = $block_type->editor_script_handles;
     647
     648        $this->assertSame(
     649            $expected,
     650            $actual_script,
     651            'editor_script was not set to the correct value.'
     652        );
     653
     654        $this->assertSame(
     655            (array) $expected,
     656            $actual_script_handles,
     657            'editor_script_handles was not set to the correct value.'
     658        );
     659    }
     660
     661    /**
     662     * Data provider for test_register_block_type_throws_doing_it_wrong().
     663     *
     664     * @return array
     665     */
     666    public function data_register_block_type_throws_doing_it_wrong() {
     667        return array(
     668            'a non-string array'     => array(
     669                'editor_script' => array( null, false, true, -1, 0, 1, -1.0, 0.0, 1.0, INF, NAN, new stdClass() ),
     670                'expected'      => null,
     671            ),
     672            'a partial string array' => array(
     673                'editor_script' => array( null, false, 'script.js', true, 0, 'actions.js', 1, INF ),
     674                'expected'      => array( 'script.js', 'actions.js' ),
     675            ),
     676            'a partial string array that results in one item with non-zero index' => array(
     677                'editor_script' => array( null, false, 'script.js' ),
     678                'expected'      => 'script.js',
     679            ),
     680        );
     681    }
     682
     683    /**
    556684     * @ticket 52301
    557685     */
  • trunk/tests/phpunit/tests/rest-api/rest-block-type-controller.php

    r54155 r54670  
    337337        $this->assertNull( $data['editor_style'] );
    338338        $this->assertNull( $data['style'] );
     339    }
     340
     341    /**
     342     * @ticket 56733
     343     */
     344    public function test_get_item_deprecated() {
     345        $block_type = 'fake/deprecated';
     346        $settings   = array(
     347            'editor_script' => 'hello_world',
     348            'script'        => 'gutenberg',
     349            'view_script'   => 'foo_bar',
     350            'editor_style'  => 'guten_tag',
     351            'style'         => 'out_of_style',
     352        );
     353        register_block_type( $block_type, $settings );
     354        wp_set_current_user( self::$admin_id );
     355        $request  = new WP_REST_Request( 'GET', '/wp/v2/block-types/' . $block_type );
     356        $response = rest_get_server()->dispatch( $request );
     357        $data     = $response->get_data();
     358        $this->assertSameSets(
     359            array( 'hello_world' ),
     360            $data['editor_script_handles'],
     361            "Endpoint doesn't return correct array for editor_script_handles."
     362        );
     363        $this->assertSameSets(
     364            array( 'gutenberg' ),
     365            $data['script_handles'],
     366            "Endpoint doesn't return correct array for script_handles."
     367        );
     368        $this->assertSameSets(
     369            array( 'foo_bar' ),
     370            $data['view_script_handles'],
     371            "Endpoint doesn't return correct array for view_script_handles."
     372        );
     373        $this->assertSameSets(
     374            array( 'guten_tag' ),
     375            $data['editor_style_handles'],
     376            "Endpoint doesn't return correct array for editor_style_handles."
     377        );
     378        $this->assertSameSets(
     379            array( 'out_of_style' ),
     380            $data['style_handles'],
     381            "Endpoint doesn't return correct array for style_handles."
     382        );
     383        // Deprecated properties.
     384        $this->assertSame(
     385            'hello_world',
     386            $data['editor_script'],
     387            "Endpoint doesn't return correct string for editor_script."
     388        );
     389        $this->assertSame(
     390            'gutenberg',
     391            $data['script'],
     392            "Endpoint doesn't return correct string for script."
     393        );
     394        $this->assertSame(
     395            'foo_bar',
     396            $data['view_script'],
     397            "Endpoint doesn't return correct string for view_script."
     398        );
     399        $this->assertSame(
     400            'guten_tag',
     401            $data['editor_style'],
     402            "Endpoint doesn't return correct string for editor_style."
     403        );
     404        $this->assertSame(
     405            'out_of_style',
     406            $data['style'],
     407            "Endpoint doesn't return correct string for style."
     408        );
     409    }
     410
     411    /**
     412     * @ticket 56733
     413     */
     414    public function test_get_item_deprecated_with_arrays() {
     415        $block_type = 'fake/deprecated-with-arrays';
     416        $settings   = array(
     417            'editor_script' => array( 'hello', 'world' ),
     418            'script'        => array( 'gutenberg' ),
     419            'view_script'   => array( 'foo', 'bar' ),
     420            'editor_style'  => array( 'guten', 'tag' ),
     421            'style'         => array( 'out', 'of', 'style' ),
     422        );
     423        register_block_type( $block_type, $settings );
     424        wp_set_current_user( self::$admin_id );
     425        $request  = new WP_REST_Request( 'GET', '/wp/v2/block-types/' . $block_type );
     426        $response = rest_get_server()->dispatch( $request );
     427        $data     = $response->get_data();
     428        $this->assertSameSets(
     429            $settings['editor_script'],
     430            $data['editor_script_handles'],
     431            "Endpoint doesn't return correct array for editor_script_handles."
     432        );
     433        $this->assertSameSets(
     434            $settings['script'],
     435            $data['script_handles'],
     436            "Endpoint doesn't return correct array for script_handles."
     437        );
     438        $this->assertSameSets(
     439            $settings['view_script'],
     440            $data['view_script_handles'],
     441            "Endpoint doesn't return correct array for view_script_handles."
     442        );
     443        $this->assertSameSets(
     444            $settings['editor_style'],
     445            $data['editor_style_handles'],
     446            "Endpoint doesn't return correct array for editor_style_handles."
     447        );
     448        $this->assertSameSets(
     449            $settings['style'],
     450            $data['style_handles'],
     451            "Endpoint doesn't return correct array for style_handles."
     452        );
     453        // Deprecated properties.
     454        // Since the schema only allows strings or null (but no arrays), we return the first array item.
     455        // Deprecated properties.
     456        $this->assertSame(
     457            'hello',
     458            $data['editor_script'],
     459            "Endpoint doesn't return first array element for editor_script."
     460        );
     461        $this->assertSame(
     462            'gutenberg',
     463            $data['script'],
     464            "Endpoint doesn't return first array element for script."
     465        );
     466        $this->assertSame(
     467            'foo',
     468            $data['view_script'],
     469            "Endpoint doesn't return first array element for view_script."
     470        );
     471        $this->assertSame(
     472            'guten',
     473            $data['editor_style'],
     474            "Endpoint doesn't return first array element for editor_style."
     475        );
     476        $this->assertSame(
     477            'out',
     478            $data['style'],
     479            "Endpoint doesn't return first array element for style."
     480        );
    339481    }
    340482
Note: See TracChangeset for help on using the changeset viewer.