Skip to content

Commit

Permalink
Merge pull request #49 from humanmade/support-5-8-pagination-headers
Browse files Browse the repository at this point in the history
Add MediaResponse object to support pagination headers
  • Loading branch information
roborourke authored Sep 27, 2021
2 parents 843edad + a845dfa commit 8c47862
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 11 deletions.
4 changes: 2 additions & 2 deletions inc/LocalProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ public function get_name() : string {
return apply_filters( 'amf/local_provider/name', __( 'Local Media', 'asset-manager-framework' ) );
}

protected function request( array $args ) : MediaList {
protected function request( array $args ) : MediaResponse {
// Call the default core attachment query AJAX handler.
// This will return JSON and exit before the return statement below.
wp_ajax_query_attachments();
return new MediaList();
return new MediaResponse();
}

public function supports_asset_create() : bool {
Expand Down
75 changes: 75 additions & 0 deletions inc/MediaResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php
/**
* Media Response object.
*
* @package asset-manager-framework
*/

declare( strict_types=1 );

namespace AssetManagerFramework;

use RangeException;

class MediaResponse {

/**
* The reponse media list.
*
* @var MediaList
*/
private $media_list;

/**
* Total available items.
*
* @var int
*/
private $total;

/**
* Items requested per page.
*
* @var int
*/
private $per_page;

/**
* Sets up the MediaResponse object.
*
* @param ?MediaList $media_list The list of returned items.
* @param int $total The total number of results available.
* @param int $per_page The number of items requested per page, defaults to 40 in media
* modal requests.
* @throws RangeException If $per_page value is less than or equal to 0.
*/
public function __construct( ?MediaList $media_list = null, int $total = 0, int $per_page = 40 ) {
// Fail early if provided per page value is not valid.
if ( $per_page <= 0 ) {
throw new RangeException(
sprintf(
/* translators: %d: Items per page value in error message */
__( 'Media items per page value must be greater than zero, %d given.', 'asset-manager-framework' ),
$per_page
)
);
}

$this->media_list = $media_list ?? new MediaList();
$this->total = $total;
$this->per_page = $per_page;
}

public function get_items() : MediaList {
return $this->media_list;
}

public function get_total() : int {
return $this->total;
}

public function get_total_pages() : int {
return (int) ceil( $this->total / $this->per_page );
}

}
34 changes: 27 additions & 7 deletions inc/Provider.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

use Exception;
use RangeException;
use WP_HTTP_Requests_Response;
use WP_Query;

abstract class Provider {
Expand Down Expand Up @@ -49,9 +50,10 @@ abstract public function get_name() : string;
* @type int $monthnum Optional. One or two digit month number if results are filtered by date.
* }
* @throws Exception Thrown if an unrecoverable error occurs.
* @return MediaList The collection of Media items. Can be an empty collection if there are no matching results.
* @return MediaResponse The response object containing pagination data and list of Media items.
* Can be an empty collection if there are no matching results.
*/
abstract protected function request( array $args ) : MediaList;
abstract protected function request( array $args ) : MediaResponse;

public function supports_asset_create() : bool {
return false;
Expand Down Expand Up @@ -135,7 +137,12 @@ final public function request_items( array $args ) : MediaList {

$args['paged'] = intval( $args['paged'] ?? 1 );

$items = $this->request( $args );
$response = $this->request( $args );

// Send headers for media library pagination.
$this->send_pagination_headers( $response );

$items = $response->get_items();
$array = $items->toArray();

if ( ! $array ) {
Expand Down Expand Up @@ -182,9 +189,9 @@ final public function request_items( array $args ) : MediaList {
* @param string $url The URL for the request.
* @param array $args The arguments to pass to `wp_remote_request()`.
* @throws Exception Thrown if there is an error with the request or its response code is not 200.
* @return string The response body.
* @return WP_HTTP_Requests_Response The response object.
*/
final public function remote_request( string $url, array $args ) : string {
final public function remote_request( string $url, array $args ) : WP_HTTP_Requests_Response {
$response = wp_remote_request(
$url,
$args
Expand All @@ -202,7 +209,6 @@ final public function remote_request( string $url, array $args ) : string {

$response_code = wp_remote_retrieve_response_code( $response );
$response_message = wp_remote_retrieve_response_message( $response );
$response_body = wp_remote_retrieve_body( $response );

if ( 200 !== $response_code ) {
$message = sprintf(
Expand All @@ -220,7 +226,21 @@ final public function remote_request( string $url, array $args ) : string {
);
}

return $response_body;
return $response['http_response'];
}

/**
* Sends the pagination headers for the media response.
*
* @param MediaResponse $response The media response object.
* @return void
*/
final protected function send_pagination_headers( MediaResponse $response ) {
if ( headers_sent() ) {
return;
}
header( sprintf( 'X-WP-Total: %d', $response->get_total() ) );
header( sprintf( 'X-WP-TotalPages: %d', $response->get_total_pages() ) );
}

}
11 changes: 9 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ use AssetManagerFramework\{
ProviderRegistry
Provider,
MediaList,
MediaResponse,
Image
};

Expand All @@ -98,7 +99,7 @@ class KittenProvider extends Provider {
return __( 'Place Kitten' );
}

protected function request( array $args ) : MediaList {
protected function request( array $args ) : MediaResponse {
$kittens = [
500 => 'Boop',
600 => 'Fuzzy',
Expand All @@ -119,7 +120,11 @@ class KittenProvider extends Provider {
$items[] = $item;
}

return new MediaList( ...$items );
return new MediaResponse(
new MediaList( ...$items ),
count( $kittens ), // Total number of available results.
count( $kittens ) // Number of items requested per page.
);
}

}
Expand All @@ -133,6 +138,8 @@ Try it and your media library will be much improved:

![Kittens](assets/KittenProvider.png)

The `MediaResponse` object takes a `MediaList` along with the total number of available items and the number of items requested per page. This is to ensure pagination in the media library (introduced in WordPress 5.8) works.

You also have access to provider instances during registration via the `amf/provider` filter, so you could use it to decorate providers:

```php
Expand Down

0 comments on commit 8c47862

Please sign in to comment.