-
Notifications
You must be signed in to change notification settings - Fork 34
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
priethor
wants to merge
47
commits into
trunk
Choose a base branch
from
add/origin-parameter-for-types-endpoint
base: trunk
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+963
−3
Open
Changes from all commits
Commits
Show all changes
47 commits
Select commit
Hold shift + click to select a range
6453b6c
Initial commit, still with errors
cbravobernal dda11f7
Default should be false
cbravobernal ff4c6b0
Remove unit to try e2e
cbravobernal 5e704c1
Add query parameter to filter by post type registration ori
priethor 9f5576e
Fix PHPCS error
priethor 4c27770
Don't require the sidebar experiment to be enabled
priethor f61d429
First attempt at filtering post types by registration origin
priethor bad53df
Refactor to make it more elegant
priethor 1e128a3
Optimization
priethor 9b29cdb
Add origin to schema
priethor a4fcb14
Clean up response
priethor 4386792
Simplify and use a more elegant filter
priethor a3b901a
Fix single type queries
priethor bc62377
Cleanup
priethor 1b30485
Initial commit, still with errors
cbravobernal 4938c71
Default should be false
cbravobernal 08c005c
Remove unit to try e2e
cbravobernal 53f3531
Clean up response
priethor 1ccf496
Simplify and use a more elegant filter
priethor cebf109
Fix single type queries
priethor 978e331
Cleanup
priethor 2b76395
Resolved conflicts from rebase
priethor 7382fcf
Fix the scf fields experiment
priethor b75c136
Rename `origin` to `source`
priethor 2a2dfe1
Add unit and e2e tests
priethor 70133ce
Optimization!
priethor 2263520
Fix error in comments
priethor f5b72e5
Remove checks for SCF internal types, we only work with managed CPTs
priethor cbcc576
Update version references to specify SCF
priethor c0b5198
Undo changes done by mistake
priethor 3dc5034
Comment cleanup
priethor 602ffa4
Merge trunk into add/origin-parameter-for-types-endpoint
priethor bbd12f5
Fix `@since`annotation
priethor 49c2460
Remove console logging from the tests
priethor 28d571e
Fix syntax error
priethor a6671a7
Fix comment
priethor 17003e9
Make the e2e test more accurate yet simple
priethor 525b240
Merge branch 'trunk' into add/origin-parameter-for-types-endpoint
priethor 221cec4
Fix typo
priethor e5588b7
Fix the tests cleanup
priethor 9003531
Clear post type cache after each request
priethor 8f37ea8
Cleanup based on feedback
priethor a525023
Remove the cache to make requests truly stateless
priethor a74cf08
Merge trunk into add/origin-parameter-for-types-endpoint
priethor 8091919
Remove redundant check
priethor a8a846d
Simplify code
priethor 6e224fb
Use a more precise regex that matches collection and individual post …
priethor File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,7 +14,7 @@ | |
/** | ||
* Class SCF_Rest_Types_Endpoint | ||
* | ||
* Extends the /wp/v2/types endpoint to include SCF fields. | ||
* Extends the /wp/v2/types endpoint to include SCF fields and source filtering. | ||
* | ||
* @since SCF 6.5.0 | ||
*/ | ||
|
@@ -27,6 +27,133 @@ class SCF_Rest_Types_Endpoint { | |
*/ | ||
public function __construct() { | ||
add_action( 'rest_api_init', array( $this, 'register_extra_fields' ) ); | ||
add_action( 'rest_api_init', array( $this, 'register_parameters' ) ); | ||
|
||
// Add filter to process REST API requests by route | ||
add_filter( 'rest_request_before_callbacks', array( $this, 'filter_types_request' ), 10, 3 ); | ||
|
||
// Add filter to process each post type individually | ||
add_filter( 'rest_prepare_post_type', array( $this, 'filter_post_type' ), 10, 3 ); | ||
|
||
// Clean up null entries from the response | ||
add_filter( 'rest_pre_echo_response', array( $this, 'clean_types_response' ), 10, 3 ); | ||
} | ||
|
||
/** | ||
* Filter post types requests, fires for both collection and individual requests. | ||
* We only want to handle individual requets to ensure the post type requested matches the source. | ||
* | ||
* @since SCF 6.5.0 | ||
* | ||
* @param mixed $response The current response, either response or null. | ||
* @param array $handler The handler for the route. | ||
* @param WP_REST_Request $request The request object. | ||
* @return mixed The response or null. | ||
*/ | ||
public function filter_types_request( $response, $handler, $request ) { | ||
// We only want to handle individual requests | ||
$route = $request->get_route(); | ||
if ( ! preg_match( '#^/wp/v2/types/([^/]+)$#', $route, $matches ) ) { | ||
return $response; | ||
} | ||
|
||
$source = $request->get_param( 'source' ); | ||
|
||
// Only proceed if source parameter is provided and valid | ||
if ( ! $source || ! in_array( $source, array( 'core', 'scf', 'other' ), true ) ) { | ||
return $response; | ||
} | ||
|
||
$source_post_types = $this->get_source_post_types( $source ); | ||
|
||
// Check if the requested type matches the source | ||
$requested_type = $matches[1]; | ||
if ( ! in_array( $requested_type, $source_post_types, true ) ) { | ||
return new WP_Error( | ||
'rest_post_type_invalid', | ||
__( 'Invalid post type.', 'secure-custom-fields' ), | ||
array( 'status' => 404 ) | ||
); | ||
} | ||
|
||
return $response; | ||
} | ||
|
||
/** | ||
* Filter individual post type in the response. | ||
* | ||
* @since SCF 6.5.0 | ||
* | ||
* @param WP_REST_Response $response The response object. | ||
* @param WP_Post_Type $post_type The post type object. | ||
* @param WP_REST_Request $request The request object. | ||
* @return WP_REST_Response|null The filtered response or null to filter it out. | ||
*/ | ||
public function filter_post_type( $response, $post_type, $request ) { | ||
$source = $request->get_param( 'source' ); | ||
|
||
// Only apply filtering if source parameter is provided and valid | ||
if ( ! $source || ! in_array( $source, array( 'core', 'scf', 'other' ), true ) ) { | ||
return $response; | ||
} | ||
|
||
$source_post_types = $this->get_source_post_types( $source ); | ||
|
||
if ( ! in_array( $post_type->name, $source_post_types, true ) ) { | ||
return null; | ||
} | ||
|
||
return $response; | ||
} | ||
|
||
/** | ||
* Get an array of post types for each source. | ||
* | ||
* @since SCF 6.5.0 | ||
* | ||
* @param string $source The source to get post types for. | ||
* @return array An array of post type names for the specified source. | ||
*/ | ||
private function get_source_post_types( $source ) { | ||
|
||
$core_types = array(); | ||
$scf_types = array(); | ||
|
||
if ( 'core' === $source || 'other' === $source ) { | ||
$all_post_types = get_post_types( array( '_builtin' => true ), 'objects' ); | ||
foreach ( $all_post_types as $post_type ) { | ||
$core_types[] = $post_type->name; | ||
} | ||
} | ||
|
||
if ( 'scf' === $source || 'other' === $source ) { | ||
// Get SCF-managed post types | ||
if ( function_exists( 'acf_get_internal_post_type_posts' ) ) { | ||
$scf_managed_post_types = acf_get_internal_post_type_posts( 'acf-post-type' ); | ||
foreach ( $scf_managed_post_types as $scf_post_type ) { | ||
$scf_types[] = $scf_post_type['post_type']; | ||
} | ||
} | ||
} | ||
|
||
switch ( $source ) { | ||
case 'core': | ||
$result = $core_types; | ||
break; | ||
case 'scf': | ||
$result = $scf_types; | ||
break; | ||
case 'other': | ||
$result = array_diff( | ||
array_keys( get_post_types( array(), 'objects' ) ), | ||
array_merge( $core_types, $scf_types ) | ||
); | ||
break; | ||
default: | ||
$result = array(); | ||
} | ||
|
||
return $result; | ||
Comment on lines
+139
to
+156
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT: We can return on each case. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like this too; why not? :) |
||
} | ||
|
||
/** | ||
|
@@ -40,6 +167,7 @@ public function register_extra_fields() { | |
if ( ! (bool) get_option( 'scf_beta_feature_editor_sidebar_enabled', false ) ) { | ||
return; | ||
} | ||
|
||
register_rest_field( | ||
'type', | ||
'scf_field_groups', | ||
|
@@ -123,4 +251,109 @@ private function get_field_schema() { | |
'context' => array( 'view', 'edit', 'embed' ), | ||
); | ||
} | ||
|
||
/** | ||
* Register the source parameter for the post types endpoint. | ||
* | ||
* @since SCF 6.5.0 | ||
*/ | ||
public function register_parameters() { | ||
if ( ! acf_get_setting( 'rest_api_enabled' ) ) { | ||
return; | ||
} | ||
|
||
// Register the query parameter with the REST API | ||
add_filter( 'rest_type_collection_params', array( $this, 'add_collection_params' ) ); | ||
add_filter( 'rest_types_collection_params', array( $this, 'add_collection_params' ) ); | ||
|
||
// Direct registration for OpenAPI documentation | ||
add_filter( 'rest_endpoints', array( $this, 'add_parameter_to_endpoints' ) ); | ||
} | ||
|
||
/** | ||
* Get the source parameter definition | ||
* | ||
* @since SCF 6.5.0 | ||
* | ||
* @return array Parameter definition | ||
*/ | ||
private function get_source_param_definition() { | ||
return array( | ||
'description' => __( 'Filter post types by their source.', 'secure-custom-fields' ), | ||
'type' => 'string', | ||
'enum' => array( 'core', 'scf', 'other' ), | ||
'required' => false, | ||
'validate_callback' => 'rest_validate_request_arg', | ||
'sanitize_callback' => 'sanitize_text_field', | ||
'default' => null, | ||
'in' => 'query', | ||
); | ||
} | ||
|
||
/** | ||
* Add source parameter directly to the endpoints for proper documentation | ||
* | ||
* @since SCF 6.5.0 | ||
* | ||
* @param array $endpoints The REST API endpoints. | ||
* @return array Modified endpoints | ||
*/ | ||
public function add_parameter_to_endpoints( $endpoints ) { | ||
$source_param = $this->get_source_param_definition(); | ||
$endpoints_to_modify = array( '/wp/v2/types', '/wp/v2/types/(?P<type>[\w-]+)' ); | ||
|
||
foreach ( $endpoints_to_modify as $route ) { | ||
if ( isset( $endpoints[ $route ] ) ) { | ||
foreach ( $endpoints[ $route ] as &$endpoint ) { | ||
if ( isset( $endpoint['args'] ) ) { | ||
$endpoint['args']['source'] = $source_param; | ||
} | ||
} | ||
} | ||
} | ||
|
||
return $endpoints; | ||
} | ||
|
||
/** | ||
* Add source parameter to the collection parameters for the types endpoint. | ||
* | ||
* @since SCF 6.5.0 | ||
* | ||
* @param array $query_params JSON Schema-formatted collection parameters. | ||
* @return array Modified collection parameters. | ||
*/ | ||
public function add_collection_params( $query_params ) { | ||
$query_params['source'] = $this->get_source_param_definition(); | ||
return $query_params; | ||
} | ||
|
||
/** | ||
* Clean up null entries from the response | ||
* | ||
* @since SCF 6.5.0 | ||
* | ||
* @param array $response The response data. | ||
* @param WP_REST_Server $server The REST server instance. | ||
* @param WP_REST_Request $request The original request. | ||
* @return array The filtered response data. | ||
*/ | ||
public function clean_types_response( $response, $server, $request ) { | ||
if ( ! preg_match( '#^/wp/v2/types(?:/|$)#', $request->get_route() ) ) { | ||
return $response; | ||
} | ||
|
||
// Only process collection responses (not single post type responses) | ||
// Single post type responses have a 'slug' property, collections don't | ||
if ( is_array( $response ) && ! isset( $response['slug'] ) ) { | ||
$response = array_filter( | ||
$response, | ||
function ( $entry ) { | ||
return null !== $entry; | ||
} | ||
); | ||
} | ||
|
||
return $response; | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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's
wp_list_pluck
, though I don't know if it performs worse. :)Ideally, there would be
array_column
, but AFAIK that operates on items of type array, not object.(This is an FYI, no need to change unless you'd prefer to.)