diff --git a/src/wp-includes/rest-api/rest-functions.php b/src/wp-includes/rest-api/rest-functions.php index 09e530ad71..817368ca20 100644 --- a/src/wp-includes/rest-api/rest-functions.php +++ b/src/wp-includes/rest-api/rest-functions.php @@ -20,11 +20,25 @@ * multiple methods. Default empty array. * @param bool $override Optional. If the route already exists, should we override it? True overrides, * false merges (with newer overriding if duplicate keys exist). Default false. + * @return bool True on success, false on error. */ function register_rest_route( $namespace, $route, $args = array(), $override = false ) { /** @var WP_REST_Server $wp_rest_server */ global $wp_rest_server; + if ( empty( $namespace ) ) { + /* + * Non-namespaced routes are not allowed, with the exception of the main + * and namespace indexes. If you really need to register a + * non-namespaced route, call `WP_REST_Server::register_route` directly. + */ + _doing_it_wrong( 'register_rest_route', 'Routes must be namespaced with plugin or theme name and version.', '4.4.0' ); + return false; + } else if ( empty( $route ) ) { + _doing_it_wrong( 'register_rest_route', 'Route must be specified.', '4.4.0' ); + return false; + } + if ( isset( $args['callback'] ) ) { // Upgrade a single set to multiple. $args = array( $args ); @@ -44,20 +58,9 @@ function register_rest_route( $namespace, $route, $args = array(), $override = f $arg_group = array_merge( $defaults, $arg_group ); } - if ( $namespace ) { - $full_route = '/' . trim( $namespace, '/' ) . '/' . trim( $route, '/' ); - } else { - /* - * Non-namespaced routes are not allowed, with the exception of the main - * and namespace indexes. If you really need to register a - * non-namespaced route, call `WP_REST_Server::register_route` directly. - */ - _doing_it_wrong( 'register_rest_route', 'Routes must be namespaced with plugin name and version', '4.4.0' ); - - $full_route = '/' . trim( $route, '/' ); - } - + $full_route = '/' . trim( $namespace, '/' ) . '/' . trim( $route, '/' ); $wp_rest_server->register_route( $namespace, $full_route, $args, $override ); + return true; } /** diff --git a/tests/phpunit/tests/rest-api.php b/tests/phpunit/tests/rest-api.php index ff7e5cd56f..f417a93de2 100644 --- a/tests/phpunit/tests/rest-api.php +++ b/tests/phpunit/tests/rest-api.php @@ -148,6 +148,34 @@ class Tests_REST_API extends WP_UnitTestCase { $this->assertTrue( $endpoint[0]['should_exist'] ); } + /** + * Test that we reject routes without namespaces + * + * @expectedIncorrectUsage register_rest_route + */ + public function test_route_reject_empty_namespace() { + register_rest_route( '', '/test-empty-namespace', array( + 'methods' => array( 'POST' ), + 'callback' => '__return_null', + ), true ); + $endpoints = $GLOBALS['wp_rest_server']->get_routes(); + $this->assertFalse( isset( $endpoints['/test-empty-namespace'] ) ); + } + + /** + * Test that we reject empty routes + * + * @expectedIncorrectUsage register_rest_route + */ + public function test_route_reject_empty_route() { + register_rest_route( '/test-empty-route', '', array( + 'methods' => array( 'POST' ), + 'callback' => '__return_null', + ), true ); + $endpoints = $GLOBALS['wp_rest_server']->get_routes(); + $this->assertFalse( isset( $endpoints['/test-empty-route'] ) ); + } + /** * The rest_route query variable should be registered. */