Make WordPress Core

Changeset 49925

Timestamp:
01/03/2021 09:45:42 PM (4 years ago)
Author:
TimothyBlynJacobs
Message:

REST API: Expose all themes in the themes controller.

Previously, only the active theme was made available. This commit allows for all themes to be queried if the user has the switch_themes or manage_network_themes capabilities.

This commit also no longer exposes the page, per_page, search and context query parameters since they are not supported by this controller.

Props spacedmonkey, lpawlik, TimothyBlynJacobs.
Fixes #50152.

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/rest-api/class-wp-rest-server.php

    r49918 r49925  
    12451245
    12461246        $response = new WP_REST_Response( $available );
    1247 
    12481247        $response->add_link( 'help', 'http://v2.wp-api.org/' );
     1248
    12491249
    12501250        /**
     
    12601260         */
    12611261        return apply_filters( 'rest_index', $response );
     1262
     1263
     1264
     1265
     1266
     1267
     1268
     1269
     1270
     1271
     1272
     1273
     1274
     1275
     1276
     1277
     1278
     1279
     1280
     1281
     1282
     1283
     1284
     1285
     1286
     1287
     1288
     1289
     1290
    12621291    }
    12631292
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php

    r48782 r49925  
    4848            )
    4949        );
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
    5069    }
    5170
     
    5978     */
    6079    public function get_items_permissions_check( $request ) {
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
     100
     101
     102
     103
     104
     105
     106
     107
     108
     109
     110
     111
     112
     113
     114
     115
     116
     117
     118
     119
     120
     121
     122
     123
     124
     125
     126
     127
     128
     129
     130
    61131        if ( current_user_can( 'edit_posts' ) ) {
    62132            return true;
     
    70140
    71141        return new WP_Error(
    72             'rest_user_cannot_view',
    73             __( 'Sorry, you are not allowed to view themes.' ),
     142            'rest_',
     143            __( 'Sorry, you are not allowed to view the.' ),
    74144            array( 'status' => rest_authorization_required_code() )
    75145        );
     
    77147
    78148    /**
    79      * Retrieves a collection of themes.
    80      *
    81      * @since 5.0.0
     149     * Retrieves a .
     150     *
     151     * @since 5..0
    82152     *
    83153     * @param WP_REST_Request $request Full details about the request.
    84154     * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
    85155     */
     156
     157
     158
     159
     160
     161
     162
     163
     164
     165
     166
     167
     168
     169
     170
     171
     172
     173
     174
     175
     176
     177
    86178    public function get_items( $request ) {
    87         // Retrieve the list of registered collection query parameters.
    88         $registered = $this->get_collection_params();
    89         $themes     = array();
    90 
    91         if ( isset( $registered['status'], $request['status'] ) && in_array( 'active', $request['status'], true ) ) {
    92             $active_theme = wp_get_theme();
    93             $active_theme = $this->prepare_item_for_response( $active_theme, $request );
    94             $themes[]     = $this->prepare_response_for_collection( $active_theme );
     179        $themes = array();
     180
     181        $active_themes = wp_get_themes();
     182        $current_theme = wp_get_theme();
     183        $status        = $request['status'];
     184
     185        foreach ( $active_themes as $theme_name => $theme ) {
     186            $theme_status = ( $this->is_same_theme( $theme, $current_theme ) ) ? 'active' : 'inactive';
     187            if ( is_array( $status ) && ! in_array( $theme_status, $status, true ) ) {
     188                continue;
     189            }
     190
     191            $prepared = $this->prepare_item_for_response( $theme, $request );
     192            $themes[] = $this->prepare_response_for_collection( $prepared );
    95193        }
    96194
     
    98196
    99197        $response->header( 'X-WP-Total', count( $themes ) );
    100         $response->header( 'X-WP-TotalPages', count( $themes ) );
     198        $response->header( 'X-WP-TotalPages', );
    101199
    102200        return $response;
     
    167265        }
    168266
    169         if ( rest_is_field_included( 'theme_supports', $fields ) ) {
     267        $current_theme = wp_get_theme();
     268        if ( rest_is_field_included( 'status', $fields ) ) {
     269            $data['status'] = ( $this->is_same_theme( $theme, $current_theme ) ) ? 'active' : 'inactive';
     270        }
     271
     272        if ( rest_is_field_included( 'theme_supports', $fields ) && $this->is_same_theme( $theme, $current_theme ) ) {
    170273            foreach ( get_registered_theme_features() as $feature => $config ) {
    171274                if ( ! is_array( $config['show_in_rest'] ) ) {
     
    206309        // Wrap the data in a response object.
    207310        $response = rest_ensure_response( $data );
     311
     312
    208313
    209314        /**
     
    220325
    221326    /**
     327
     328
     329
     330
     331
     332
     333
     334
     335
     336
     337
     338
     339
     340
     341
     342
     343
     344
     345
     346
     347
     348
     349
     350
     351
     352
     353
     354
     355
     356
     357
     358
     359
    222360     * Prepares the theme support value for inclusion in the REST API response.
    223361     *
     
    400538                    'readonly'    => true,
    401539                ),
     540
     541
     542
     543
     544
    402545            ),
    403546        );
     
    426569     */
    427570    public function get_collection_params() {
    428         $query_params = parent::get_collection_params();
    429 
    430         $query_params['status'] = array(
    431             'description'       => __( 'Limit result set to themes assigned one or more statuses.' ),
    432             'type'              => 'array',
    433             'items'             => array(
    434                 'enum' => array( 'active' ),
    435                 'type' => 'string',
     571        $query_params =
     572            'status' => array(
     573       
     574            ,
     575           
     576           
     577                ,
     578                ,
    436579            ),
    437             'required'          => true,
    438             'sanitize_callback' => array( $this, 'sanitize_theme_status' ),
    439580        );
    440581
     
    453594     *
    454595     * @since 5.0.0
     596
    455597     *
    456598     * @param string|array    $statuses  One or more theme statuses.
     
    460602     */
    461603    public function sanitize_theme_status( $statuses, $request, $parameter ) {
     604
     605
    462606        $statuses = wp_parse_slug_list( $statuses );
    463607
  • trunk/tests/phpunit/tests/rest-api/rest-schema-setup.php

    r49334 r49925  
    130130            '/wp/v2/settings',
    131131            '/wp/v2/themes',
     132
    132133            '/wp/v2/plugins',
    133134            '/wp/v2/plugins/(?P<plugin>[^.\/]+(?:\/[^.\/]+)?)',
  • trunk/tests/phpunit/tests/rest-api/rest-server.php

    r49547 r49925  
    960960        $this->assertContains( 'DELETE', $route['methods'] );
    961961        $this->assertArrayHasKey( '_links', $route );
     962
     963
     964
    962965    }
    963966
     
    19972000    }
    19982001
     2002
     2003
     2004
     2005
     2006
     2007
     2008
     2009
     2010
     2011
    19992012    public function _validate_as_integer_123( $value, $request, $key ) {
    20002013        if ( ! is_int( $value ) ) {
  • trunk/tests/phpunit/tests/rest-api/rest-themes-controller.php

    r49603 r49925  
    3131
    3232    /**
     33
     34
     35
     36
     37
     38
     39
     40
     41
    3342     * The current theme object.
    3443     *
     
    92101     */
    93102    public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
     103
     104
     105
     106
     107
    94108        self::$subscriber_id  = $factory->user->create(
    95109            array(
     
    115129        self::delete_user( self::$subscriber_id );
    116130        self::delete_user( self::$contributor_id );
     131
    117132    }
    118133
     
    137152        $routes = rest_get_server()->get_routes();
    138153        $this->assertArrayHasKey( self::$themes_route, $routes );
     154
    139155    }
    140156
     
    152168        $this->check_get_theme_response( $response );
    153169        $fields = array(
     170
    154171            'author',
    155172            'author_uri',
     
    159176            'requires_wp',
    160177            'screenshot',
     178
    161179            'stylesheet',
    162180            'tags',
     
    171189
    172190    /**
     191
     192
     193
     194
     195
     196
     197
     198
     199
     200
     201
     202
     203
     204
     205
     206
     207
     208
     209
     210
     211
     212
     213
     214
     215
     216
     217
     218
     219
     220
     221
     222
     223
     224
     225
     226
     227
     228
     229
     230
     231
     232
     233
     234
     235
     236
     237
     238
     239
     240
     241
     242
     243
     244
     245
     246
     247
    173248     * @ticket 46723
    174      */
    175     public function test_get_items_logged_out() {
     249     * @ticket 50152
     250     * @dataProvider data_get_items_by_status
     251     */
     252    public function test_get_items_logged_out( $status, $error_code ) {
    176253        wp_set_current_user( 0 );
    177         $response = self::perform_active_theme_request();
    178         $this->assertErrorResponse( 'rest_user_cannot_view', $response, 401 );
     254        $request = new WP_REST_Request( 'GET', self::$themes_route );
     255        $request->set_param( 'status', $status );
     256
     257        $response = rest_get_server()->dispatch( $request );
     258        $this->assertErrorResponse( $error_code, $response, 401 );
    179259    }
    180260
     
    183263     *
    184264     * @ticket 45016
    185      */
    186     public function test_get_items_no_permission() {
     265     * @ticket 50152
     266     * @dataProvider data_get_items_by_status
     267     */
     268    public function test_get_items_no_permission( $status, $error_code ) {
    187269        wp_set_current_user( self::$subscriber_id );
    188         $response = self::perform_active_theme_request();
    189         $this->assertErrorResponse( 'rest_user_cannot_view', $response, 403 );
     270        $request = new WP_REST_Request( 'GET', self::$themes_route );
     271        $request->set_param( 'status', $status );
     272
     273        $response = rest_get_server()->dispatch( $request );
     274        $this->assertErrorResponse( $error_code, $response, 403 );
     275    }
     276
     277    public function data_get_items_by_status() {
     278        return array(
     279            array( 'active', 'rest_cannot_view_active_theme' ),
     280            array( 'active, inactive', 'rest_cannot_view_themes' ),
     281            array( 'inactive', 'rest_cannot_view_themes' ),
     282            array( '', 'rest_cannot_view_themes' ),
     283        );
     284    }
     285
     286    /**
     287     * @ticket 50152
     288     * @dataProvider data_get_items_by_status_for_contributor
     289     */
     290    public function test_get_items_contributor( $status, $error_code ) {
     291        wp_set_current_user( self::$contributor_id );
     292        $request = new WP_REST_Request( 'GET', self::$themes_route );
     293        $request->set_param( 'status', $status );
     294
     295        $response = rest_get_server()->dispatch( $request );
     296
     297        if ( $error_code ) {
     298            $this->assertErrorResponse( $error_code, $response, 403 );
     299        } else {
     300            $this->assertEquals( 200, $response->get_status() );
     301        }
     302    }
     303
     304    public function data_get_items_by_status_for_contributor() {
     305        return array(
     306            array( 'active', '' ),
     307            array( 'active, inactive', 'rest_cannot_view_themes' ),
     308            array( 'inactive', 'rest_cannot_view_themes' ),
     309            array( '', 'rest_cannot_view_themes' ),
     310        );
    190311    }
    191312
     
    222343        $data       = $response->get_data();
    223344        $properties = $data['schema']['properties'];
    224         $this->assertSame( 14, count( $properties ) );
     345        $this->assertSame( 1, count( $properties ) );
    225346
    226347        $this->assertArrayHasKey( 'author', $properties );
     
    243364        $this->assertArrayHasKey( 'requires_wp', $properties );
    244365        $this->assertArrayHasKey( 'screenshot', $properties );
     366
    245367        $this->assertArrayHasKey( 'stylesheet', $properties );
    246368
     
    10841206
    10851207    /**
    1086      * The get_item() method does not exist for themes.
    1087      */
    1088     public function test_get_item() {}
     1208     * Test single theme
     1209     *
     1210     * @ticket 50152
     1211     */
     1212    public function test_get_item() {
     1213        wp_set_current_user( self::$admin_id );
     1214        $route    = sprintf( '%s/%s', self::$themes_route, WP_DEFAULT_THEME );
     1215        $request  = new WP_REST_Request( 'GET', $route );
     1216        $response = rest_get_server()->dispatch( $request );
     1217
     1218        $this->assertEquals( 200, $response->get_status() );
     1219        $data         = $response->get_data();
     1220        $links        = $response->get_links();
     1221        $fields       = array(
     1222            'author',
     1223            'author_uri',
     1224            'description',
     1225            'name',
     1226            'requires_php',
     1227            'requires_wp',
     1228            'screenshot',
     1229            'status',
     1230            'stylesheet',
     1231            'tags',
     1232            'template',
     1233            'textdomain',
     1234            'theme_uri',
     1235            'version',
     1236        );
     1237        $fields_links = array( 'collection', 'self' );
     1238
     1239        $this->assertEqualSets( $fields, array_keys( $data ) );
     1240        $this->assertEqualSets( $fields_links, array_keys( $links ) );
     1241    }
     1242
     1243    /**
     1244     * @ticket 50152
     1245     */
     1246    public function test_get_item_no_permission() {
     1247        wp_set_current_user( self::$subscriber_id );
     1248        $request  = new WP_REST_Request( 'GET', self::$themes_route . '/' . WP_DEFAULT_THEME );
     1249        $response = rest_get_server()->dispatch( $request );
     1250        $this->assertErrorResponse( 'rest_cannot_view_themes', $response, 403 );
     1251    }
     1252
     1253    /**
     1254     * @ticket 50152
     1255     */
     1256    public function test_get_active_item_no_permission() {
     1257        wp_set_current_user( self::$subscriber_id );
     1258        $request  = new WP_REST_Request( 'GET', self::$themes_route . '/' . get_stylesheet() );
     1259        $response = rest_get_server()->dispatch( $request );
     1260        $this->assertErrorResponse( 'rest_cannot_view_active_theme', $response, 403 );
     1261    }
     1262
     1263    /**
     1264     * @ticket 50152
     1265     */
     1266    public function test_get_item_invalid() {
     1267        wp_set_current_user( self::$admin_id );
     1268        $request  = new WP_REST_Request( 'GET', self::$themes_route . '/invalid' );
     1269        $response = rest_get_server()->dispatch( $request );
     1270        $this->assertErrorResponse( 'rest_theme_not_found', $response, 404 );
     1271    }
     1272
     1273    /**
     1274     * @ticket 50152
     1275     */
     1276    public function test_get_active_item_as_contributor() {
     1277        $route    = sprintf( '%s/%s', self::$themes_route, get_stylesheet() );
     1278        $request  = new WP_REST_Request( 'GET', $route );
     1279        $response = rest_get_server()->dispatch( $request );
     1280
     1281        $this->assertEquals( 200, $response->get_status() );
     1282    }
    10891283
    10901284    /**
  • trunk/tests/qunit/fixtures/wp-api-generated.js

    r49476 r49925  
    57855785                    ],
    57865786                    "args": {
    5787                         "context": {
    5788                             "description": "Scope under which the request is made; determines fields present in response.",
    5789                             "type": "string",
    5790                             "required": false
    5791                         },
    5792                         "page": {
    5793                             "description": "Current page of the collection.",
    5794                             "type": "integer",
    5795                             "default": 1,
    5796                             "minimum": 1,
    5797                             "required": false
    5798                         },
    5799                         "per_page": {
    5800                             "description": "Maximum number of items to be returned in result set.",
    5801                             "type": "integer",
    5802                             "default": 10,
    5803                             "minimum": 1,
    5804                             "maximum": 100,
    5805                             "required": false
    5806                         },
    5807                         "search": {
    5808                             "description": "Limit results to those matching a string.",
    5809                             "type": "string",
    5810                             "required": false
    5811                         },
    58125787                        "status": {
    58135788                            "description": "Limit result set to themes assigned one or more statuses.",
     
    58155790                            "items": {
    58165791                                "enum": [
    5817                                     "active"
     5792                                    "active",
     5793                                    "inactive"
    58185794                                ],
    58195795                                "type": "string"
    58205796                            },
    5821                             "required": true
     5797                            "required": e
    58225798                        }
    58235799                    }
     
    58275803                "self": "http://example.org/index.php?rest_route=/wp/v2/themes"
    58285804            }
     5805
     5806
     5807
     5808
     5809
     5810
     5811
     5812
     5813
     5814
     5815
     5816
     5817
     5818
     5819
     5820
     5821
     5822
     5823
     5824
    58295825        },
    58305826        "/wp/v2/plugins": {
Note: See TracChangeset for help on using the changeset viewer.