317 | | $page = (int) $query_args['paged']; |
318 | | $total_posts = $posts_query->found_posts; |
319 | | |
320 | | if ( $total_posts < 1 ) { |
321 | | // Out-of-bounds, run the query again without LIMIT for total count. |
322 | | unset( $query_args['paged'] ); |
323 | | |
324 | | $count_query = new WP_Query(); |
325 | | $count_query->query( $query_args ); |
326 | | $total_posts = $count_query->found_posts; |
327 | | } |
328 | | |
329 | | $max_pages = ceil( $total_posts / (int) $posts_query->query_vars['posts_per_page'] ); |
330 | | |
331 | | if ( $page > $max_pages && $total_posts > 0 ) { |
332 | | return new WP_Error( 'rest_post_invalid_page_number', __( 'The page number requested is larger than the number of pages available.' ), array( 'status' => 400 ) ); |
333 | | } |
334 | | |
335 | | $response = rest_ensure_response( $posts ); |
336 | | |
337 | | $response->header( 'X-WP-Total', (int) $total_posts ); |
338 | | $response->header( 'X-WP-TotalPages', (int) $max_pages ); |
339 | | |
340 | | $request_params = $request->get_query_params(); |
341 | | $base = add_query_arg( $request_params, rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ) ); |
342 | | |
343 | | if ( $page > 1 ) { |
344 | | $prev_page = $page - 1; |
345 | | |
346 | | if ( $prev_page > $max_pages ) { |
347 | | $prev_page = $max_pages; |
348 | | } |
349 | | |
350 | | $prev_link = add_query_arg( 'page', $prev_page, $base ); |
351 | | $response->link_header( 'prev', $prev_link ); |
352 | | } |
353 | | if ( $max_pages > $page ) { |
354 | | $next_page = $page + 1; |
355 | | $next_link = add_query_arg( 'page', $next_page, $base ); |
356 | | |
357 | | $response->link_header( 'next', $next_link ); |
358 | | } |
| 308 | $response = $this->prepare_paginate_response( $request, $query_args, $posts_query, $posts ); |
| 2201 | |
| 2202 | /** |
| 2203 | * Create a collection of WordPress posts, formatted |
| 2204 | * |
| 2205 | * @since 4.7.3 |
| 2206 | * |
| 2207 | * @param WP_REST_Request $request Current request |
| 2208 | * @param array $query_results An array of WP_Post objects, as returned by WP_Query::query() |
| 2209 | * |
| 2210 | * @return array |
| 2211 | */ |
| 2212 | protected function prepare_posts_for_response( $request, $query_results ) { |
| 2213 | $posts = array(); |
| 2214 | |
| 2215 | foreach ( $query_results as $post ) { |
| 2216 | if ( ! $this->check_read_permission( $post ) ) { |
| 2217 | continue; |
| 2218 | } |
| 2219 | |
| 2220 | $data = $this->prepare_item_for_response( $post, $request ); |
| 2221 | $posts[] = $this->prepare_response_for_collection( $data ); |
| 2222 | } |
| 2223 | |
| 2224 | return $posts; |
| 2225 | |
| 2226 | } |
| 2227 | |
| 2228 | /** |
| 2229 | * Create a WP_REST_Response for a collection of posts, with the right pagination headers |
| 2230 | * |
| 2231 | * @since 4.7.3 |
| 2232 | * |
| 2233 | * @param WP_REST_Request $request Current request object. |
| 2234 | * @param array $query_args The request's prepared WP_Query arguments, used to do the count query. |
| 2235 | * @param WP_Query $posts_query The WP_Query object used to prepare the posts for the response. |
| 2236 | * @param array $prepared_posts The prepared posts to return in response body. |
| 2237 | * |
| 2238 | * @return WP_REST_Response |
| 2239 | */ |
| 2240 | protected function prepare_paginate_response( $request, $query_args, $posts_query, $prepared_posts ) { |
| 2241 | $page = (int) $query_args[ 'paged' ]; |
| 2242 | $total_posts = $posts_query->found_posts; |
| 2243 | |
| 2244 | if ( $total_posts < 1 ) { |
| 2245 | // Out-of-bounds, run the query again without LIMIT for total count. |
| 2246 | unset( $query_args[ 'paged' ] ); |
| 2247 | |
| 2248 | $count_query = new WP_Query(); |
| 2249 | $count_query->query( $query_args ); |
| 2250 | $total_posts = $count_query->found_posts; |
| 2251 | } |
| 2252 | |
| 2253 | $max_pages = ceil( $total_posts / (int) $posts_query->query_vars[ 'posts_per_page' ] ); |
| 2254 | $response = rest_ensure_response( $prepared_posts ); |
| 2255 | |
| 2256 | $response->header( 'X-WP-Total', (int) $total_posts ); |
| 2257 | $response->header( 'X-WP-TotalPages', (int) $max_pages ); |
| 2258 | |
| 2259 | $request_params = $request->get_query_params(); |
| 2260 | $base = add_query_arg( $request_params, rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ) ); |
| 2261 | |
| 2262 | if ( $page > 1 ) { |
| 2263 | $prev_page = $page - 1; |
| 2264 | |
| 2265 | if ( $prev_page > $max_pages ) { |
| 2266 | $prev_page = $max_pages; |
| 2267 | } |
| 2268 | |
| 2269 | $prev_link = add_query_arg( 'page', $prev_page, $base ); |
| 2270 | $response->link_header( 'prev', $prev_link ); |
| 2271 | } |
| 2272 | |
| 2273 | if ( $max_pages > $page ) { |
| 2274 | $next_page = $page + 1; |
| 2275 | $next_link = add_query_arg( 'page', $next_page, $base ); |
| 2276 | |
| 2277 | $response->link_header( 'next', $next_link ); |
| 2278 | |
| 2279 | return $response; |
| 2280 | |
| 2281 | } |
| 2282 | |
| 2283 | return $response; |
| 2284 | } |
| 2285 | |