-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
REST API: new endpoint to fetch post counts by post status #7773
base: trunk
Are you sure you want to change the base?
REST API: new endpoint to fetch post counts by post status #7773
Conversation
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
202b1e6
to
95db722
Compare
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN:
To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
8ab940f
to
d67a6c1
Compare
24e7570
to
b27145f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This new endpoint needs tests.
return array( | ||
'$schema' => 'http://json-schema.org/draft-04/schema#', | ||
'title' => 'post-counts', | ||
'type' => 'object', | ||
/* | ||
* Use a pattern matcher for post status keys. | ||
* This allows for custom post statuses to be included, | ||
* which can be registered after the schema is generated. | ||
*/ | ||
'patternProperties' => array( | ||
'^\w+$' => array( | ||
'description' => __( 'The number of posts for a given status.' ), | ||
'type' => 'integer', | ||
'context' => array( 'view', 'edit', 'embed' ), | ||
'readonly' => true, | ||
), | ||
), | ||
'additionalProperties' => false, | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return array( | |
'$schema' => 'http://json-schema.org/draft-04/schema#', | |
'title' => 'post-counts', | |
'type' => 'object', | |
/* | |
* Use a pattern matcher for post status keys. | |
* This allows for custom post statuses to be included, | |
* which can be registered after the schema is generated. | |
*/ | |
'patternProperties' => array( | |
'^\w+$' => array( | |
'description' => __( 'The number of posts for a given status.' ), | |
'type' => 'integer', | |
'context' => array( 'view', 'edit', 'embed' ), | |
'readonly' => true, | |
), | |
), | |
'additionalProperties' => false, | |
); | |
$schema = array( | |
'$schema' => 'http://json-schema.org/draft-04/schema#', | |
'title' => 'post-counts', | |
'type' => 'object', | |
'properties' => []; | |
); | |
$post_stati = get_post_stati( array( 'internal' => false ) ); | |
if ( get_post_status_object( 'trash' ) ) { | |
$post_stati[] = 'trash'; | |
} | |
foreach( $post_stati as $post_status ) { | |
$schema['properties'] = array( | |
'description' => __( 'The number of posts for a given status.' ), | |
'type' => 'integer', | |
'context' => array( 'view', 'edit', 'embed' ), | |
'readonly' => true, | |
); | |
} | |
return $schema; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using get_post_stati
was the original implementation WordPress/gutenberg@3895345
(#66294)
We can use it, but the caveat is that all custom post statuses must be registered at the highest priority, otherwise the endpoint will not return them.
A comment here is probably enough for now.
return array( | ||
'$schema' => 'http://json-schema.org/draft-04/schema#', | ||
'title' => 'post-counts', | ||
'type' => 'object', | ||
/* | ||
* Use a pattern matcher for post status keys. | ||
* This allows for custom post statuses to be included, | ||
* which can be registered after the schema is generated. | ||
*/ | ||
'patternProperties' => array( | ||
'^\w+$' => array( | ||
'description' => __( 'The number of posts for a given status.' ), | ||
'type' => 'integer', | ||
'context' => array( 'view', 'edit', 'embed' ), | ||
'readonly' => true, | ||
), | ||
), | ||
'additionalProperties' => false, | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return array( | |
'$schema' => 'http://json-schema.org/draft-04/schema#', | |
'title' => 'post-counts', | |
'type' => 'object', | |
/* | |
* Use a pattern matcher for post status keys. | |
* This allows for custom post statuses to be included, | |
* which can be registered after the schema is generated. | |
*/ | |
'patternProperties' => array( | |
'^\w+$' => array( | |
'description' => __( 'The number of posts for a given status.' ), | |
'type' => 'integer', | |
'context' => array( 'view', 'edit', 'embed' ), | |
'readonly' => true, | |
), | |
), | |
'additionalProperties' => false, | |
); | |
} | |
if ( $this->schema ) { | |
return $this->add_additional_fields_schema( $this->schema ); | |
} | |
$schema = array( | |
'$schema' => 'http://json-schema.org/draft-04/schema#', | |
'title' => 'post-counts', | |
'type' => 'object', | |
/* | |
* Use a pattern matcher for post status keys. | |
* This allows for custom post statuses to be included, | |
* which can be registered after the schema is generated. | |
*/ | |
'patternProperties' => array( | |
'^\w+$' => array( | |
'description' => __( 'The number of posts for a given status.' ), | |
'type' => 'integer', | |
'context' => array( 'view', 'edit', 'embed' ), | |
'readonly' => true, | |
), | |
), | |
'additionalProperties' => false, | |
); | |
$this->schema = $schema; | |
return $this->add_additional_fields_schema( $this->schema ); | |
} |
It is important to add the add fields and this caching.
*/ | ||
public function get_count_permissions_check() { | ||
$post_type = get_post_type_object( $this->post_type ); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if ( ! $this->check_is_post_type_allowed( $post_type ) ) { | |
return false; | |
} |
$counts = wp_count_posts( $this->post_type ); | ||
$data = array(); | ||
|
||
if ( ! empty( $counts ) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is empty, I think this should return a 404 error ( wp_error here ).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about that for the following reasons:
- The
wp_count_posts
function always returns an stdClass object, even when no posts exist, so an empty count is still a valid count result. - A 404 status code only indicates that the resource is missing. The resource exists, it performs a count, but returns zero values.
- The endpoint should maintain consistent response structure regardless of count values.
Unless I'm missing something in wp_count_posts, 200 OK, therefore, is the most appropriate response code for this case as it's still a structured response.
public function get_count() { | ||
$counts = wp_count_posts( $this->post_type ); | ||
$data = array(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public function get_count() { | |
$counts = wp_count_posts( $this->post_type ); | |
$data = array(); | |
public function get_count( $request ) { | |
$counts = wp_count_posts( $this->post_type ); | |
$data = array(); | |
$fields = $this->get_fields_for_response( $request ); | |
} | ||
// Include all public statuses in the response if there is a count. | ||
foreach ( $post_stati as $status ) { | ||
if ( isset( $counts->$status ) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if ( isset( $counts->$status ) ) { | |
if ( rest_is_field_included( $status, $fields ) ) && isset( $counts->$status ) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The above suggestion had an extra parenthesis:
if ( rest_is_field_included( $status, $fields ) ) && isset( $counts->$status ) ) {
As I understand it, this will check against $this->get_item_schema()
so the fields won't exist.
/counts
requires a unique schema.
I'm finding the problem is that the schema
callback when registering a route is never fired, unless it's an OPTIONS request (the context is 'help'). So I'm not sure the REST API is set up to allow a response to have two separate schemas.
I guess this is a good thing.
It's part of the reason why I chose to add a separate endpoint in the first place WordPress/gutenberg#66294
There is the option to add a counts
field to the existing schema. 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is the option to add a counts field to the existing schema
Integrating it into the current item schema isn't appropriate as it's not an item, it's related to the collection
I appreciate the quick review and suggestions.
I am aware. I had already written a prominent TODO in the description to add them. |
Thanks for helping me think this over @spacedmonkey Given everything I've tested I have a mind to revert back to https://github.com/WordPress/wordpress-develop/blob/95db722a2f73fd238312ed026f442c88363b3cd6/src/wp-includes/rest-api/endpoints/class-wp-rest-post-counts-controller.php, which introduced an embeddable, separate endpoint with a dedicated schema. So far the only arguments to extend Is it worth trying add a custom schema for the |
'callback' => array( $this, 'get_count' ), | ||
'permission_callback' => array( $this, 'get_count_permissions_check' ), | ||
), | ||
'schema' => array( $this, 'get_count_schema' ), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does absolutely nothing in GET responses. It's only available in the 'help'
context, which is used for OPTIONS requests.
@TimothyBJacobs do you know if it's advisable, or even possible, to have a custom schema for a route here?
TODO
What?
Syncs WordPress/gutenberg#67719
The PR proposes to extend
WP_REST_Posts_Controller
with a new route/count
to fetch page counts, e.g.,wp/v2/pages/count
.Why?
The need for a performant post counts check for the block editor. See: WordPress/gutenberg#65223 (comment)
Contrast this with
$query->found_posts
which returns the total count for a specific query only and would degrade performance givenn
posts.How?
Via
wp/v2/pages/count
, the editor can fetch the total number of post counts.This is done using wp_count_posts.
Testing Instructions
Examples to run in the browser console (in the editor):
Also add a custom post status and ensure it appears in the response:
Trac ticket: https://core.trac.wordpress.org/ticket/62390
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.