Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/wp-includes/rest-api/class-wp-rest-server.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@ class WP_REST_Server {
*/
protected $embed_cache = array();

/**
* Cached route maps keyed by namespace.
*
* @since 6.9.0
* @var array
*/
protected $route_map_cache = array();

/**
* Stores request objects that are currently being handled.
*
Expand Down Expand Up @@ -973,6 +981,9 @@ public function register_route( $route_namespace, $route, $route_args, $override
} else {
$this->endpoints[ $route ] = array_merge( $this->endpoints[ $route ], $route_args );
}

// Invalidate the route map cache when routes change.
$this->route_map_cache = array();
}

/**
Expand Down Expand Up @@ -1004,6 +1015,12 @@ public function register_route( $route_namespace, $route, $route_args, $override
* @phpstan-return array<non-empty-string, array<int, Route_Handler>>
*/
public function get_routes( $route_namespace = '' ) {
$cache_key = $route_namespace ? $route_namespace : '';

if ( isset( $this->route_map_cache[ $cache_key ] ) ) {
return $this->route_map_cache[ $cache_key ];
}

$endpoints = $this->endpoints;

if ( $route_namespace ) {
Expand Down Expand Up @@ -1087,6 +1104,8 @@ public function get_routes( $route_namespace = '' ) {
*/
/** @phpstan-var array<non-empty-string, array<int, Route_Handler>> $endpoints */

$this->route_map_cache[ $cache_key ] = $endpoints;

return $endpoints;
}

Expand Down
81 changes: 81 additions & 0 deletions tests/phpunit/tests/rest-api/rest-server.php
Original file line number Diff line number Diff line change
Expand Up @@ -2080,6 +2080,87 @@ public function test_get_routes_no_namespace_overriding() {
$this->assertSame( 204, $response->get_status(), '/test-ns/v1/test' );
}

/**
* @ticket 39473
* @covers WP_REST_Server::get_routes
*/
public function test_get_routes_caches_result() {
$filter_count = 0;
$counting_filter = static function ( $endpoints ) use ( &$filter_count ) {
++$filter_count;
return $endpoints;
};

add_filter( 'rest_endpoints', $counting_filter );

$server = rest_get_server();
$server->get_routes();
$server->get_routes();
$server->get_routes();

remove_filter( 'rest_endpoints', $counting_filter );

$this->assertSame( 1, $filter_count, 'The rest_endpoints filter should only fire once when get_routes() is called multiple times.' );
}

/**
* @ticket 39473
* @covers WP_REST_Server::get_routes
*/
public function test_get_routes_cache_is_keyed_by_namespace() {
$server = rest_get_server();

$all_routes = $server->get_routes();
$namespaced_routes = $server->get_routes( 'oembed/1.0' );

$this->assertNotEquals( $all_routes, $namespaced_routes, 'Cached routes for different namespaces should differ.' );

foreach ( $namespaced_routes as $route => $handlers ) {
$this->assertStringStartsWith( '/oembed/1.0', $route );
}
}

/**
* @ticket 39473
* @covers WP_REST_Server::register_route
* @covers WP_REST_Server::get_routes
*/
public function test_get_routes_cache_invalidated_on_register() {
$server = rest_get_server();

$routes_before = $server->get_routes();

register_rest_route(
'test-cache-ns',
'/test-cache',
array(
'methods' => array( 'GET' ),
'callback' => '__return_true',
'permission_callback' => '__return_true',
)
);

$routes_after = $server->get_routes();

$this->assertArrayNotHasKey( '/test-cache-ns/test-cache', $routes_before );
$this->assertArrayHasKey( '/test-cache-ns/test-cache', $routes_after );
}

/**
* @ticket 39473
* @covers WP_REST_Server::get_routes
*/
public function test_get_routes_cached_result_matches_uncached() {
$server = rest_get_server();

// First call populates cache.
$first_call = $server->get_routes();
// Second call returns from cache.
$second_call = $server->get_routes();

$this->assertSame( $first_call, $second_call, 'Cached routes should be identical to the initial result.' );
}

/**
* @ticket 50244
*/
Expand Down
Loading