Make WordPress Core

Changeset 54339


Ignore:
Timestamp:
09/27/2022 08:12:00 PM (4 years ago)
Author:
davidbaumwald
Message:

REST API: Ensure args is an array of arrays in register_rest_route().

When calling register_rest_route(), the args parameter for a route should be an array of arrays. However, some plugins/themes have passed an array of strings or key-value pairs which produces a PHP warning when array_intersect_key is used to filter the array keys based on an allowed list of schema keywords.

This change adds a check of the args parameter to ensure it's an array of arrays, presenting a _doing_it_wrong if any element of args is not an array and restructuring to an array of arrays. This change also adds a unit test for the incorrect usage described above, expecting that a _doing_it_wrong is produced.

Props slaFFik, desrosj, apermo, AndrewNZ, aristath, poena, dovyp, timothyblynjacobs, Hinjiriyo, johnmark8080, nateallen.
Fixes #51986.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/rest-api.php

    r53877 r54339  
    102102                                ),
    103103                                '5.5.0'
     104                        );
     105                }
     106
     107                if ( count( array_filter( $arg_group['args'], 'is_array' ) ) !== count( $arg_group['args'] ) ) {
     108                        _doing_it_wrong(
     109                                __FUNCTION__,
     110                                sprintf(
     111                                /* translators: %s: The REST API route being registered. */
     112                                        __( 'REST API $args should be an array of arrays. Non-array value detected for %s.' ),
     113                                        '<code>' . $clean_namespace . '/' . trim( $route, '/' ) . '</code>'
     114                                ),
     115                                '6.1.0'
    104116                        );
    105117                }
  • trunk/src/wp-includes/rest-api/class-wp-rest-server.php

    r54133 r54339  
    15141514
    15151515                                foreach ( $callback['args'] as $key => $opts ) {
     1516                                        if ( is_string( $opts ) ) {
     1517                                                $opts = array( $opts => 0 );
     1518                                        } elseif ( ! is_array( $opts ) ) {
     1519                                                $opts = array();
     1520                                        }
    15161521                                        $arg_data             = array_intersect_key( $opts, $allowed_schema_keywords );
    15171522                                        $arg_data['required'] = ! empty( $opts['required'] );
  • trunk/tests/phpunit/tests/rest-api.php

    r53217 r54339  
    25192519                );
    25202520        }
     2521
     2522        /**
     2523         * @ticket 51986
     2524         */
     2525        public function test_route_args_is_array_of_arrays() {
     2526                $this->setExpectedIncorrectUsage( 'register_rest_route' );
     2527
     2528                $registered = register_rest_route(
     2529                        'my-ns/v1',
     2530                        '/my-route',
     2531                        array(
     2532                                'callback'            => '__return_true',
     2533                                'permission_callback' => '__return_true',
     2534                                'args'                => array( 'pattern' ),
     2535                        )
     2536                );
     2537
     2538                $this->assertTrue( $registered );
     2539        }
    25212540}
Note: See TracChangeset for help on using the changeset viewer.