Skip to content

REST API: Add source parameter for types endpoint #128

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

Open
wants to merge 40 commits into
base: trunk
Choose a base branch
from

Conversation

priethor
Copy link
Contributor

@priethor priethor commented May 12, 2025

What

  • Added a new source parameter to the /wp/v2/types REST API endpoint that allows filtering post types by their origin: core (WordPress built-in), scf (for SCF managed types), or other for the rest of CPTs.
  • Works with both collection (/wp/v2/types) and single item (/wp/v2/types/{type}) endpoints
  • Properly documented in the OpenAPI schema

Why

When working on the Command Palette Integration and considering using the REST API to define CPT-related commands, requesting specifically for the CPTs managed by SCF became a need, and it will be needed, too, when implementing DataViews.

In fact, this branch is directly based on #124 and started in parallel, as we both realized we needed to tweak the Types endpoint if we wanted to leverage the API.

How

  • If the source parameter is not defined, nothing changes.
  • For specific, single-type requests:
    • Hooks to rest_request_before_callbacks for the single request, returning 404 if the requested type doesn't meet the criteria.
  • For collection requests:
    • Hooks to rest_prepare_post_type to filter each post type by source before WordPress prepares it.
    • Hooks to rest_pre_echo_response to remove null values returned by rest_prepare_post_type in the response array.
    • Since the filter rest_prepare_post_type fires once per post type, the Post Types belonging to the requested source are calculated in advance in rest_request_before_callbacks and reused throughout the whole request.

Testing Instructions

  1. API Endpoint Testing:
    - Make a GET request to /wp/v2/types to see all post types
    - Add ?source=core to filter for WordPress built-in post types only
    - Add ?source=scf to see only post types managed by SCF
    - Try ?source=other to see post types registered from other sources
    - Test single post type endpoints like/wp/v2/types/post?source=core
  2. Validation Testing:
    - Try an invalid source value (e.g., ?source=invalid) to verify validation works
    - Confirm a 404 error when requesting a post type with the wrong source (e.g., /wp/v2/types/post?source=scf`
  3. Unit and E2E Tests (heavily assisted by AI):
    - Run PHPUnit tests: composer test:php -- --filter=Test_REST_Types_Endpoint
    - Run E2E tests: npm run test:e2e tests/e2e/rest-api-types-endpoint.spec.ts

Potential follow-ups

  • Add a transient cache for the post type source calculation.
  • With the transient cache in place, return the post type source as a field in the response, as there would be no performance loss.
  • Add a hook so that other plugins can register their own sources.

@priethor priethor self-assigned this May 12, 2025
@priethor priethor marked this pull request as ready for review May 12, 2025 15:52
@priethor priethor added the [Type] Enhancement New feature or request label May 12, 2025
@priethor priethor marked this pull request as draft May 12, 2025 18:12
@priethor priethor marked this pull request as ready for review May 19, 2025 15:02
@cbravobernal cbravobernal self-requested a review May 20, 2025 14:55
Copy link
Contributor

@cbravobernal cbravobernal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion, most of console logs are not necessary. Let's avoid to fill the logs of CI with them. The rest of the PR is working as expected, nice job!! 🚀

@priethor priethor requested a review from cbravobernal May 21, 2025 11:21
Comment on lines 101 to 103
// Mark as created so we don't duplicate it
update_option( 'scf_test_post_type_created', true );
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: Delete option on plugin deactivation / uninstall.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually done here, although there was a typo.

What was missing was deleting the post type itself, which I fixed in the latest commit. Since post deletion is done on plugin deactivation on the PHP side, I've moved deleting the option to the same deactivation hook for consistency.

Copy link
Contributor

@cbravobernal cbravobernal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work!

Copy link

@mcsf mcsf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't comb through every little detail, but overall seems pretty good! I just left a concern about caching.

Comment on lines +78 to +81
if ( null === $this->cached_post_types ) {
$this->cached_post_types = $this->get_source_post_types( $source );
}
$source_post_types = $this->cached_post_types;
Copy link

@mcsf mcsf Jun 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In practice, the way the REST API works is that one request corresponds to one fresh execution of the WP stack, including running through SCF_Rest_Types_Endpoint's constructor and down that stack. However, semantically, cached_post_types is an instance property of a class that represents an endpoint, not a request. Here's my concern when I read this chunk:

Is there any scenario (e.g. request batching or sequential rest_do_request calls) where it's possible to process more than one request with the same endpoint instance? If so, this cache will need invalidation. At the very least, it should be source-indexed:

$source_post_types = $this->cached_post_types[ $source ];

… but ideally its lifetime should be that of a request.

No?

Comment on lines +96 to +98
// For collection requests, we don't need to add any filter here
// as clean_types_response will handle removing null values from the response
// and filter_post_type will handle individual filtering
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In light of this, why even check for $is_collection? Seems like a distraction, no?

}

if ( 'scf' === $source || 'other' === $source ) {
$scf_types = array();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the reassignment?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] Enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants