Make WordPress Core

Ticket #45677: 45677.6.diff

File 45677.6.diff, 11.3 KB (added by TimothyBlynJacobs, 5 years ago)
  • src/wp-includes/rest-api.php

    diff --git a/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php
    index 5ec557547c..80681d3845 100644
    a b function rest_api_default_filters() { 
    191191 * @since 4.7.0
    192192 */
    193193function create_initial_rest_routes() {
    194         foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) {
    195                 $class = ! empty( $post_type->rest_controller_class ) ? $post_type->rest_controller_class : 'WP_REST_Posts_Controller';
     194        foreach ( get_post_types( array( 'show_in_rest' => true ) ) as $post_type ) {
     195                $controller = WP_REST_Posts_Controller::get_for_post_type( $post_type );
    196196
    197                 if ( ! class_exists( $class ) ) {
    198                         continue;
    199                 }
    200                 $controller = new $class( $post_type->name );
    201                 if ( ! is_subclass_of( $controller, 'WP_REST_Controller' ) ) {
     197                if ( ! $controller ) {
    202198                        continue;
    203199                }
    204200
    205201                $controller->register_routes();
    206202
    207                 if ( post_type_supports( $post_type->name, 'revisions' ) ) {
    208                         $revisions_controller = new WP_REST_Revisions_Controller( $post_type->name );
     203                if ( post_type_supports( $post_type, 'revisions' ) ) {
     204                        $revisions_controller = new WP_REST_Revisions_Controller( $post_type );
    209205                        $revisions_controller->register_routes();
    210206                }
    211207
    212                 if ( 'attachment' !== $post_type->name ) {
    213                         $autosaves_controller = new WP_REST_Autosaves_Controller( $post_type->name );
     208                if ( 'attachment' !== $post_type ) {
     209                        $autosaves_controller = new WP_REST_Autosaves_Controller( $post_type );
    214210                        $autosaves_controller->register_routes();
    215211                }
    216212        }
  • src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php

    diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php
    index e55d3a3729..7f54d59f0a 100644
    a b class WP_REST_Autosaves_Controller extends WP_REST_Revisions_Controller { 
    5757         * @param string $parent_post_type Post type of the parent.
    5858         */
    5959        public function __construct( $parent_post_type ) {
    60                 $this->parent_post_type = $parent_post_type;
    61                 $post_type_object       = get_post_type_object( $parent_post_type );
     60                $parent_controller = WP_REST_Posts_Controller::get_for_post_type( $parent_post_type );
    6261
    63                 // Ensure that post type-specific controller logic is available.
    64                 $parent_controller_class = ! empty( $post_type_object->rest_controller_class ) ? $post_type_object->rest_controller_class : 'WP_REST_Posts_Controller';
     62                if ( ! $parent_controller ) {
     63                        $parent_controller = new WP_REST_Posts_Controller( $parent_post_type );
     64                }
    6565
    66                 $this->parent_controller    = new $parent_controller_class( $post_type_object->name );
     66                $this->parent_post_type     = $parent_post_type;
     67                $post_type_object           = get_post_type_object( $parent_post_type );
     68                $this->parent_controller    = $parent_controller;
    6769                $this->revisions_controller = new WP_REST_Revisions_Controller( $parent_post_type );
    6870                $this->rest_namespace       = 'wp/v2';
    6971                $this->rest_base            = 'autosaves';
  • src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php

    diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php
    index b730844fde..5ca9ce35bb 100644
    a b class WP_REST_Comments_Controller extends WP_REST_Controller { 
    15821582         * @return bool Whether post can be read.
    15831583         */
    15841584        protected function check_read_post_permission( $post, $request ) {
    1585                 $posts_controller = new WP_REST_Posts_Controller( $post->post_type );
    1586                 $post_type        = get_post_type_object( $post->post_type );
     1585                $posts_controller = WP_REST_Posts_Controller::get_for_post_type( $post->post_type );
     1586
     1587                if ( ! $posts_controller instanceof WP_REST_Posts_Controller ) {
     1588                        $posts_controller = new WP_REST_Posts_Controller( $post->post_type );
     1589                }
     1590
     1591                $post_type = get_post_type_object( $post->post_type );
    15871592
    15881593                $has_password_filter = false;
    15891594
  • src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php

    diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
    index 090ca2a5da..8fee7e7110 100644
    a b  
    1616 */
    1717class WP_REST_Posts_Controller extends WP_REST_Controller {
    1818
     19        /**
     20         * Instances of post type controllers keyed by post type.
     21         *
     22         * @since 5.3.0
     23         * @var WP_REST_Controller[]
     24         */
     25        private static $post_type_controllers = array();
     26
    1927        /**
    2028         * Post type.
    2129         *
    class WP_REST_Posts_Controller extends WP_REST_Controller { 
    4856                $this->meta = new WP_REST_Post_Meta_Fields( $this->post_type );
    4957        }
    5058
     59        /**
     60         * Gets the REST API controller for a post type.
     61         *
     62         * @since 5.3.0
     63         *
     64         * @param string $post_type
     65         * @return WP_REST_Controller|null The controller instance, or null if the specified is invalid or the post type
     66         *                                 is set not to show in rest.
     67         */
     68        public static function get_for_post_type( $post_type ) {
     69                if ( array_key_exists( $post_type, self::$post_type_controllers ) ) {
     70                        return self::$post_type_controllers[ $post_type ];
     71                }
     72
     73                $definition = get_post_type_object( $post_type );
     74
     75                if ( ! $definition ) {
     76                        self::$post_type_controllers[ $post_type ] = null;
     77
     78                        return self::$post_type_controllers[ $post_type ];
     79                }
     80
     81                $class = $definition->rest_controller_class ? $definition->rest_controller_class : WP_REST_Posts_Controller::class;
     82
     83                if ( ! class_exists( $class ) ) {
     84                        self::$post_type_controllers[ $post_type ] = null;
     85
     86                        return self::$post_type_controllers[ $post_type ];
     87                }
     88
     89                if ( ! is_subclass_of( $class, WP_REST_Controller::class ) ) {
     90                        self::$post_type_controllers[ $post_type ] = null;
     91
     92                        return self::$post_type_controllers[ $post_type ];
     93                }
     94
     95                self::$post_type_controllers[ $post_type ] = new $class( $post_type );
     96
     97                return self::$post_type_controllers[ $post_type ];
     98        }
     99
    51100        /**
    52101         * Registers the routes for the objects of the controller.
    53102         *
  • src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php

    diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php
    index 52df0f2206..ecced9f6df 100644
    a b class WP_REST_Revisions_Controller extends WP_REST_Controller { 
    4848         * @param string $parent_post_type Post type of the parent.
    4949         */
    5050        public function __construct( $parent_post_type ) {
     51                $parent_controller = WP_REST_Posts_Controller::get_for_post_type( $parent_post_type );
     52
     53                if ( ! $parent_controller ) {
     54                        $parent_controller = new WP_REST_Posts_Controller( $parent_post_type );
     55                }
     56
    5157                $this->parent_post_type  = $parent_post_type;
    52                 $this->parent_controller = new WP_REST_Posts_Controller( $parent_post_type );
     58                $this->parent_controller = $parent_controller;
    5359                $this->namespace         = 'wp/v2';
    5460                $this->rest_base         = 'revisions';
    5561                $post_type_object        = get_post_type_object( $parent_post_type );
  • tests/phpunit/tests/rest-api/rest-comments-controller.php

    diff --git a/tests/phpunit/tests/rest-api/rest-comments-controller.php b/tests/phpunit/tests/rest-api/rest-comments-controller.php
    index d1fe7aa34a..684ca0f44d 100644
    a b class WP_Test_REST_Comments_Controller extends WP_Test_REST_Controller_Testcase 
    30113011                $wp_rest_additional_fields = array();
    30123012        }
    30133013
     3014        /**
     3015         * @ticket 45677
     3016         */
     3017        public function test_comments_controller_uses_registered_post_type_controller_to_check_read_post_permission() {
     3018                register_post_type(
     3019                        'test',
     3020                        array(
     3021                                'show_in_rest' => true,
     3022                        )
     3023                );
     3024
     3025                $mock = $this->getMockBuilder( WP_REST_Posts_Controller::class )
     3026                                        ->setMethods( array( 'check_read_permission' ) )
     3027                                        ->setConstructorArgs( array( 'test' ) )
     3028                                        ->getMock();
     3029                $mock->expects( $this->once() )->method( 'check_read_permission' )->willReturn( false );
     3030
     3031                get_post_type_object( 'test' )->rest_controller_class = get_class( $mock );
     3032
     3033                $reflect = new ReflectionProperty( WP_REST_Posts_Controller::class, 'post_type_controllers' );
     3034                $reflect->setAccessible( true );
     3035                $reflect->setValue(
     3036                        array(
     3037                                'test' => $mock,
     3038                        )
     3039                );
     3040
     3041                $post_id    = self::factory()->post->create(
     3042                        array(
     3043                                'post_type' => 'test',
     3044                        )
     3045                );
     3046                $comment_id = self::factory()->comment->create(
     3047                        array(
     3048                                'comment_post_ID' => $post_id,
     3049                                'user_id'         => self::$subscriber_id,
     3050                        )
     3051                );
     3052
     3053                $request  = new WP_REST_Request( 'GET', sprintf( '/wp/v2/comments/%d', $comment_id ) );
     3054                $response = rest_get_server()->dispatch( $request );
     3055
     3056                $this->assertErrorResponse( 'rest_cannot_read', $response );
     3057        }
     3058
    30143059        public function additional_field_get_callback( $object ) {
    30153060                return get_comment_meta( $object['id'], 'my_custom_int', true );
    30163061        }
  • tests/phpunit/tests/rest-api/rest-posts-controller.php

    diff --git a/tests/phpunit/tests/rest-api/rest-posts-controller.php b/tests/phpunit/tests/rest-api/rest-posts-controller.php
    index f03eee8e83..93383c64e5 100644
    a b class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te 
    42774277
    42784278        }
    42794279
     4280        /**
     4281         * @ticket 45677
     4282         */
     4283        public function test_get_for_post_type_reuses_same_instance() {
     4284                $this->assertSame(
     4285                        WP_REST_Posts_Controller::get_for_post_type( 'post' ),
     4286                        WP_REST_Posts_Controller::get_for_post_type( 'post' )
     4287                );
     4288        }
     4289
     4290        /**
     4291         * @ticket 45677
     4292         */
     4293        public function test_get_for_post_type_returns_null_for_non_existent_post_type() {
     4294                $this->assertNull( WP_REST_Posts_Controller::get_for_post_type( 'doesnotexist' ) );
     4295        }
     4296
     4297        /**
     4298         * @ticket 45677
     4299         */
     4300        public function test_get_for_post_type_returns_null_if_class_does_not_exist() {
     4301                register_post_type(
     4302                        'class_not_found',
     4303                        array(
     4304                                'show_in_rest'          => true,
     4305                                'rest_controller_class' => 'Class_That_Does_Not_Exist',
     4306                        )
     4307                );
     4308
     4309                $this->assertNull( WP_REST_Posts_Controller::get_for_post_type( 'class_not_found' ) );
     4310        }
     4311
     4312        /**
     4313         * @ticket 45677
     4314         */
     4315        public function test_get_for_post_type_returns_null_if_class_does_not_subclass_rest_controller() {
     4316                register_post_type(
     4317                        'invalid_class',
     4318                        array(
     4319                                'show_in_rest'          => true,
     4320                                'rest_controller_class' => 'WP_Post',
     4321                        ),
     4322                );
     4323
     4324                $this->assertNull( WP_REST_Posts_Controller::get_for_post_type( 'invalid_class' ) );
     4325        }
     4326
     4327        /**
     4328         * @ticket 45677
     4329         */
     4330        public function test_get_for_post_type_returns_posts_controller_if_custom_class_not_specified() {
     4331                register_post_type(
     4332                        'test',
     4333                        array(
     4334                                'show_in_rest' => true,
     4335                        )
     4336                );
     4337
     4338                $this->assertInstanceOf(
     4339                        WP_REST_Posts_Controller::class,
     4340                        WP_REST_Posts_Controller::get_for_post_type( 'test' )
     4341                );
     4342        }
     4343
     4344        /**
     4345         * @ticket 45677
     4346         */
     4347        public function test_get_for_post_type_returns_provided_controller_class() {
     4348                $this->assertInstanceOf(
     4349                        WP_REST_Blocks_Controller::class,
     4350                        WP_REST_Posts_Controller::get_for_post_type( 'wp_block' )
     4351                );
     4352        }
     4353
    42804354        public function tearDown() {
    42814355                _unregister_post_type( 'private-post' );
    42824356                _unregister_post_type( 'youseeme' );