diff --git a/wp-includes/class-wp-post-type.php b/wp-includes/class-wp-post-type.php index faf7a0d496..0099515050 100644 --- a/wp-includes/class-wp-post-type.php +++ b/wp-includes/class-wp-post-type.php @@ -335,6 +335,16 @@ final class WP_Post_Type { */ public $rest_controller_class; + /** + * The controller instance for this post type's REST API endpoints. + * + * Lazily computed. Should be accessed using {@see WP_Post_Type::get_rest_controller()}. + * + * @since 5.3.0 + * @var WP_REST_Controller $rest_controller + */ + private $rest_controller; + /** * Constructor. * @@ -682,4 +692,36 @@ final class WP_Post_Type { public function remove_hooks() { remove_action( 'future_' . $this->name, '_future_post_hook', 5 ); } + + /** + * Gets the REST API controller for this post type. + * + * Will only instantiate the controller class once per request. + * + * @since 5.3.0 + * + * @return WP_REST_Controller|null The controller instance, or null if the post type + * is set not to show in rest. + */ + public function get_rest_controller() { + if ( ! $this->show_in_rest ) { + return null; + } + + $class = $this->rest_controller_class ? $this->rest_controller_class : WP_REST_Posts_Controller::class; + + if ( ! class_exists( $class ) ) { + return null; + } + + if ( ! is_subclass_of( $class, WP_REST_Controller::class ) ) { + return null; + } + + if ( ! $this->rest_controller ) { + $this->rest_controller = new $class( $this->name ); + } + + return $this->rest_controller; + } } diff --git a/wp-includes/rest-api.php b/wp-includes/rest-api.php index a0bb8fba3a..c397bdc116 100644 --- a/wp-includes/rest-api.php +++ b/wp-includes/rest-api.php @@ -192,13 +192,9 @@ function rest_api_default_filters() { */ function create_initial_rest_routes() { foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) { - $class = ! empty( $post_type->rest_controller_class ) ? $post_type->rest_controller_class : 'WP_REST_Posts_Controller'; + $controller = $post_type->get_rest_controller(); - if ( ! class_exists( $class ) ) { - continue; - } - $controller = new $class( $post_type->name ); - if ( ! is_subclass_of( $controller, 'WP_REST_Controller' ) ) { + if ( ! $controller ) { continue; } diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php index 7b2e4b223c..a72541a1ee 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php @@ -59,11 +59,13 @@ class WP_REST_Autosaves_Controller extends WP_REST_Revisions_Controller { public function __construct( $parent_post_type ) { $this->parent_post_type = $parent_post_type; $post_type_object = get_post_type_object( $parent_post_type ); + $parent_controller = $post_type_object->get_rest_controller(); - // Ensure that post type-specific controller logic is available. - $parent_controller_class = ! empty( $post_type_object->rest_controller_class ) ? $post_type_object->rest_controller_class : 'WP_REST_Posts_Controller'; + if ( ! $parent_controller ) { + $parent_controller = new WP_REST_Posts_Controller( $parent_post_type ); + } - $this->parent_controller = new $parent_controller_class( $post_type_object->name ); + $this->parent_controller = $parent_controller; $this->revisions_controller = new WP_REST_Revisions_Controller( $parent_post_type ); $this->rest_namespace = 'wp/v2'; $this->rest_base = 'autosaves'; diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php index f2ead89ea0..0320efaae9 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php @@ -1592,8 +1592,14 @@ class WP_REST_Comments_Controller extends WP_REST_Controller { * @return bool Whether post can be read. */ protected function check_read_post_permission( $post, $request ) { - $posts_controller = new WP_REST_Posts_Controller( $post->post_type ); $post_type = get_post_type_object( $post->post_type ); + $posts_controller = $post_type->get_rest_controller(); + + // Ensure the posts controller is specifically a WP_REST_Posts_Controller instance + // before using methods specific to that controller. + if ( ! $posts_controller instanceof WP_REST_Posts_Controller ) { + $posts_controller = new WP_REST_Posts_Controller( $post->post_type ); + } $has_password_filter = false; diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php index d355c3d076..4a00336e34 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php @@ -16,6 +16,14 @@ */ class WP_REST_Posts_Controller extends WP_REST_Controller { + /** + * Instances of post type controllers keyed by post type. + * + * @since 5.3.0 + * @var WP_REST_Controller[] + */ + private static $post_type_controllers = array(); + /** * Post type. * diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php index 97c677d27c..9edf6eced6 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php @@ -49,11 +49,15 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller { */ public function __construct( $parent_post_type ) { $this->parent_post_type = $parent_post_type; - $this->parent_controller = new WP_REST_Posts_Controller( $parent_post_type ); $this->namespace = 'wp/v2'; $this->rest_base = 'revisions'; $post_type_object = get_post_type_object( $parent_post_type ); $this->parent_base = ! empty( $post_type_object->rest_base ) ? $post_type_object->rest_base : $post_type_object->name; + $this->parent_controller = $post_type_object->get_rest_controller(); + + if ( ! $this->parent_controller ) { + $this->parent_controller = new WP_REST_Posts_Controller( $parent_post_type ); + } } /** diff --git a/wp-includes/version.php b/wp-includes/version.php index ad45e1fb25..3d62d06cd4 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -13,7 +13,7 @@ * * @global string $wp_version */ -$wp_version = '5.3-alpha-46271'; +$wp_version = '5.3-alpha-46272'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.