Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
Prev Previous commit
Next Next commit
Adding feedback:
- Introducing pagination
- Updating tests
  • Loading branch information
ramonjd committed Jun 26, 2023
commit 8ff968514c774fe7def34d65e6b8224852b72553
Original file line number Diff line number Diff line change
Expand Up @@ -435,9 +435,9 @@ protected function prepare_links( $id ) {
);

if ( post_type_supports( $this->post_type, 'revisions' ) ) {
$revisions = wp_get_latest_revision_id_and_total_count( $id );
$revisions_count = ! is_wp_error( $revisions ) ? $revisions['count'] : 0;
$revisions_base = sprintf( '/%s/%s/%d/revisions', $this->namespace, $this->rest_base, $id );
$revisions = wp_get_latest_revision_id_and_total_count( $id );
$revisions_count = ! is_wp_error( $revisions ) ? $revisions['count'] : 0;
$revisions_base = sprintf( '/%s/%d/revisions', $base, $id );
$links['version-history'] = array(
'href' => rest_url( $revisions_base ),
'count' => $revisions_count,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,74 @@ public function register_routes() {
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_items' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
'args' => $this->get_collection_params(),
),
'schema' => array( $this, 'get_public_item_schema' ),
)
);
}

/**
* Returns revisions of the given global styles config custom post type.
* Retrieves the query params for collections.
* Taken mostly from WP_REST_Controller->get_collection_params().
*
* @since 6.3.0
*
* @return array Collection parameters.
*/
public function get_collection_params() {
return array(
'context' => array( 'default' => 'view' ),
'page' => array(
'description' => __( 'Current page of the collection.' ),
'type' => 'integer',
'default' => 1,
'sanitize_callback' => 'absint',
'validate_callback' => 'rest_validate_request_arg',
'minimum' => 1,
),
'per_page' => array(
'description' => __( 'Maximum number of items to be returned in result set.' ),
'type' => 'integer',
'minimum' => 1,
'maximum' => 100,
'sanitize_callback' => 'absint',
'validate_callback' => 'rest_validate_request_arg',
),
'offset' => array(
'description' => __( 'Offset the result set by a specific number of items.' ),
'type' => 'integer',
),
);
}

/**
* Returns decoded JSON from post content string,
* or a 404 if not found.
*
* @since 6.3.0
*
* @param string $raw_json Encoded JSON from global styles custom post content.
* @return Array|WP_Error
*/
private function get_decoded_global_styles_json( $raw_json ) {
$decoded_json = json_decode( $raw_json, true );

if ( is_array( $decoded_json ) && isset( $decoded_json['isGlobalStylesUserThemeJSON'] ) && true === $decoded_json['isGlobalStylesUserThemeJSON'] ) {
return $decoded_json;
}

return new WP_Error(
'rest_global_styles_not_found',
__( 'Cannot find user global styles revisions.' ),
array( 'status' => 404 )
);
}

/**
* Returns paginated revisions of the given global styles config custom post type.
* The bulk of the body is taken from WP_REST_Revisions_Controller->get_items,
* but global styles does not require as many parameters.
*
* @since 6.3.0
*
Expand All @@ -83,27 +143,112 @@ public function get_items( $request ) {
if ( is_wp_error( $parent ) ) {
return $parent;
}
$response = array();
$raw_config = json_decode( $parent->post_content, true );
$is_global_styles_user_theme_json = isset( $raw_config['isGlobalStylesUserThemeJSON'] ) && true === $raw_config['isGlobalStylesUserThemeJSON'];

if ( $is_global_styles_user_theme_json ) {
$user_theme_revisions = wp_get_post_revisions(
$parent->ID,
array(
'posts_per_page' => 100,
)
$global_styles_config = $this->get_decoded_global_styles_json( $parent->post_content );

if ( is_wp_error( $global_styles_config ) ) {
return $global_styles_config;
}

if ( wp_revisions_enabled( $parent ) ) {
$registered = $this->get_collection_params();
$query_args = array(
'post_parent' => $parent->ID,
'post_type' => 'revision',
'post_status' => 'inherit',
'posts_per_page' => -1,
'orderby' => 'date ID',
'order' => 'DESC',
);

if ( ! empty( $user_theme_revisions ) ) {
foreach ( $user_theme_revisions as $revision ) {
$revision = $this->prepare_item_for_response( $revision, $request );
$response[] = $this->prepare_response_for_collection( $revision );
$parameter_mappings = array(
'offset' => 'offset',
'page' => 'paged',
'per_page' => 'posts_per_page',
);

foreach ( $parameter_mappings as $api_param => $wp_param ) {
if ( isset( $registered[ $api_param ], $request[ $api_param ] ) ) {
$query_args[ $wp_param ] = $request[ $api_param ];
}
}

$revisions_query = new WP_Query();
$revisions = $revisions_query->query( $query_args );
$offset = isset( $query_args['offset'] ) ? (int) $query_args['offset'] : 0;
$page = (int) $query_args['paged'];
$total_revisions = $revisions_query->found_posts;

if ( $total_revisions < 1 ) {
// Out-of-bounds, run the query again without LIMIT for total count.
unset( $query_args['paged'], $query_args['offset'] );
$count_query = new WP_Query();
$count_query->query( $query_args );

$total_revisions = $count_query->found_posts;
}

if ( $revisions_query->query_vars['posts_per_page'] > 0 ) {
$max_pages = ceil( $total_revisions / (int) $revisions_query->query_vars['posts_per_page'] );
} else {
$max_pages = $total_revisions > 0 ? 1 : 0;
}
if ( $total_revisions > 0 ) {
if ( $offset >= $total_revisions ) {
return new WP_Error(
'rest_revision_invalid_offset_number',
__( 'The offset number requested is larger than or equal to the number of available revisions.' ),
array( 'status' => 400 )
);
} elseif ( ! $offset && $page > $max_pages ) {
return new WP_Error(
'rest_revision_invalid_page_number',
__( 'The page number requested is larger than the number of pages available.' ),
array( 'status' => 400 )
);
}
}
} else {
$revisions = array();
$total_revisions = 0;
$max_pages = 0;
$page = (int) $request['page'];
}

return rest_ensure_response( $response );
$response = array();

foreach ( $revisions as $revision ) {
$data = $this->prepare_item_for_response( $revision, $request );
$response[] = $this->prepare_response_for_collection( $data );
}

$response = rest_ensure_response( $response );

$response->header( 'X-WP-Total', (int) $total_revisions );
$response->header( 'X-WP-TotalPages', (int) $max_pages );

$request_params = $request->get_query_params();
$base_path = rest_url( sprintf( '%s/%s/%d/%s', $this->namespace, $this->parent_base, $request['parent'], $this->rest_base ) );
$base = add_query_arg( urlencode_deep( $request_params ), $base_path );

if ( $page > 1 ) {
$prev_page = $page - 1;

if ( $prev_page > $max_pages ) {
$prev_page = $max_pages;
}

$prev_link = add_query_arg( 'page', $prev_page, $base );
$response->link_header( 'prev', $prev_link );
}
if ( $max_pages > $page ) {
$next_page = $page + 1;
$next_link = add_query_arg( 'page', $next_page, $base );

$response->link_header( 'next', $next_link );
}

return $response;
}

/**
Expand Down Expand Up @@ -139,13 +284,18 @@ protected function prepare_date_response( $date_gmt, $date = null ) {
* @return WP_REST_Response Response object.
*/
public function prepare_item_for_response( $post, $request ) {
$parent = $this->get_parent( $request['parent'] );
// Retrieves global styles config as JSON.
$raw_revision_config = json_decode( $post->post_content, true );
$config = ( new WP_Theme_JSON( $raw_revision_config, 'custom' ) )->get_raw_data();
$parent = $this->get_parent( $request['parent'] );
$global_styles_config = $this->get_decoded_global_styles_json( $post->post_content );
$data = array();

if ( is_wp_error( $global_styles_config ) ) {
return rest_ensure_response( $data );
}

if ( ! empty( $global_styles_config['styles'] ) || ! empty( $global_styles_config['settings'] ) ) {
$global_styles_config = ( new WP_Theme_JSON( $global_styles_config, 'custom' ) )->get_raw_data();
}

// Prepares item data.
$data = array();
$fields = $this->get_fields_for_response( $request );

if ( rest_is_field_included( 'author', $fields ) ) {
Expand Down Expand Up @@ -177,11 +327,11 @@ public function prepare_item_for_response( $post, $request ) {
}

if ( rest_is_field_included( 'settings', $fields ) ) {
$data['settings'] = ! empty( $config['settings'] ) ? $config['settings'] : new stdClass();
$data['settings'] = ! empty( $global_styles_config['settings'] ) ? $global_styles_config['settings'] : new stdClass();
}

if ( rest_is_field_included( 'styles', $fields ) ) {
$data['styles'] = ! empty( $config['styles'] ) ? $config['styles'] : new stdClass();
$data['styles'] = ! empty( $global_styles_config['styles'] ) ? $global_styles_config['styles'] : new stdClass();
}

$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,6 @@ public function get_items( $request ) {
'posts_per_page' => -1,
'orderby' => 'date ID',
'order' => 'DESC',
'suppress_filters' => true,
);

$parameter_mappings = array(
Expand Down
Loading