Skip to content

Commit

Permalink
Permit unbounded per_page=-1 requests for Pages and Shared Blocks (#6657
Browse files Browse the repository at this point in the history
)

* Permit unbounded requests for Pages and Shared Blocks

* Fix PHPCS issue

* Use a strict check
  • Loading branch information
danielbachhuber authored May 10, 2018
1 parent e0f8003 commit fb804e2
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 4 deletions.
2 changes: 1 addition & 1 deletion editor/components/page-attributes/parent.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const applyWithAPIDataItems = withAPIData( ( props, { type } ) => {
const isHierarchical = get( props, [ 'postType', 'hierarchical' ], false );
const queryString = stringify( {
context: 'edit',
per_page: 100,
per_page: -1,
exclude: postId,
parent_exclude: postId,
_fields: [ 'id', 'parent', 'title' ],
Expand Down
2 changes: 1 addition & 1 deletion editor/store/effects.js
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ export default {
if ( id ) {
result = wp.apiRequest( { path: `/wp/v2/${ basePath }/${ id }` } );
} else {
result = wp.apiRequest( { path: `/wp/v2/${ basePath }` } );
result = wp.apiRequest( { path: `/wp/v2/${ basePath }?per_page=-1` } );
}

result.then(
Expand Down
54 changes: 52 additions & 2 deletions lib/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,8 @@ function gutenberg_register_post_prepare_functions( $post_type ) {
add_filter( "rest_prepare_{$post_type}", 'gutenberg_add_permalink_template_to_posts', 10, 3 );
add_filter( "rest_prepare_{$post_type}", 'gutenberg_add_block_format_to_post_content', 10, 3 );
add_filter( "rest_prepare_{$post_type}", 'gutenberg_add_target_schema_to_links', 10, 3 );
add_filter( "rest_{$post_type}_collection_params", 'gutenberg_filter_post_collection_parameters', 10, 2 );
add_filter( "rest_{$post_type}_query", 'gutenberg_filter_post_query_arguments', 10, 2 );
return $post_type;
}
add_filter( 'registered_post_type', 'gutenberg_register_post_prepare_functions' );
Expand Down Expand Up @@ -461,7 +463,12 @@ function gutenberg_ensure_wp_json_has_theme_supports( $response ) {
* @param WP_REST_Request $request Request used to generate the response.
*/
function gutenberg_handle_early_callback_checks( $response, $handler, $request ) {
if ( '/wp/v2/users' === $request->get_route() ) {
$routes = array(
'/wp/v2/blocks',
'/wp/v2/pages',
'/wp/v2/users',
);
if ( in_array( $request->get_route(), $routes, true ) ) {
$can_view_authors = false;
$can_unbounded_query = false;
$types = get_post_types( array( 'show_in_rest' => true ), 'objects' );
Expand All @@ -478,7 +485,8 @@ function gutenberg_handle_early_callback_checks( $response, $handler, $request )
return new WP_Error( 'rest_forbidden_per_page', __( 'Sorry, you are not allowed make unbounded queries.', 'gutenberg' ), array( 'status' => rest_authorization_required_code() ) );
}
}
if ( ! empty( $request['who'] ) && 'authors' === $request['who'] ) {
if ( '/wp/v2/users' === $request->get_route()
&& ! empty( $request['who'] ) && 'authors' === $request['who'] ) {
if ( ! $can_view_authors ) {
return new WP_Error( 'rest_forbidden_who', __( 'Sorry, you are not allowed to query users by this parameter.', 'gutenberg' ), array( 'status' => rest_authorization_required_code() ) );
}
Expand All @@ -488,6 +496,48 @@ function gutenberg_handle_early_callback_checks( $response, $handler, $request )
}
add_filter( 'rest_request_before_callbacks', 'gutenberg_handle_early_callback_checks', 10, 3 );

/**
* Include additional query parameters on the posts query endpoint.
*
* @see https://core.trac.wordpress.org/ticket/43998
*
* @param array $query_params JSON Schema-formatted collection parameters.
* @param string $post_type Post type being accessed.
* @return array
*/
function gutenberg_filter_post_collection_parameters( $query_params, $post_type ) {
$post_types = array( 'page', 'wp_block' );
if ( in_array( $post_type->name, $post_types, true )
&& isset( $query_params['per_page'] ) ) {
// Change from '1' to '-1', which means unlimited.
$query_params['per_page']['minimum'] = -1;
// Default sanitize callback is 'absint', which won't work in our case.
$query_params['per_page']['sanitize_callback'] = 'rest_sanitize_request_arg';
}
return $query_params;
}

/**
* Filter post collection query parameters to include specific behavior.
*
* @see https://core.trac.wordpress.org/ticket/43998
*
* @param array $prepared_args Array of arguments for WP_Query.
* @param WP_REST_Request $request The current request.
* @return array
*/
function gutenberg_filter_post_query_arguments( $prepared_args, $request ) {
$post_types = array( 'page', 'wp_block' );
if ( in_array( $prepared_args['post_type'], $post_types, true ) ) {
// Avoid triggering 'rest_post_invalid_page_number' error
// which will need to be addressed in https://core.trac.wordpress.org/ticket/43998.
if ( -1 === $prepared_args['posts_per_page'] ) {
$prepared_args['posts_per_page'] = 100000;
}
}
return $prepared_args;
}

/**
* Include additional query parameters on the user query endpoint.
*
Expand Down
20 changes: 20 additions & 0 deletions phpunit/class-gutenberg-rest-api-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -279,4 +279,24 @@ public function test_get_items_unbounded_per_page_unauthorized() {
$data = $response->get_data();
$this->assertEquals( 'rest_forbidden_per_page', $data['code'] );
}

public function test_get_pages_unbounded_per_page() {
wp_set_current_user( $this->author );
$this->factory->post->create( array( 'post_type' => 'page' ) );
$request = new WP_REST_Request( 'GET', '/wp/v2/pages' );
$request->set_param( 'per_page', '-1' );
$response = rest_get_server()->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
}

public function test_get_pages_unbounded_per_page_unauthorized() {
wp_set_current_user( $this->subscriber );
$this->factory->post->create( array( 'post_type' => 'page' ) );
$request = new WP_REST_Request( 'GET', '/wp/v2/pages' );
$request->set_param( 'per_page', '-1' );
$response = rest_get_server()->dispatch( $request );
$this->assertEquals( 403, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 'rest_forbidden_per_page', $data['code'] );
}
}

0 comments on commit fb804e2

Please sign in to comment.