WordPress.org

Make WordPress Core


Ignore:
Timestamp:
01/03/2021 09:45:42 PM (4 months 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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php

    r48782 r49925  
    4848            )
    4949        );
     50
     51        register_rest_route(
     52            $this->namespace,
     53            '/' . $this->rest_base . '/(?P<stylesheet>[\w-]+)',
     54            array(
     55                'args'   => array(
     56                    'stylesheet' => array(
     57                        'description' => __( "The theme's stylesheet. This uniquely identifies the theme." ),
     58                        'type'        => 'string',
     59                    ),
     60                ),
     61                array(
     62                    'methods'             => WP_REST_Server::READABLE,
     63                    'callback'            => array( $this, 'get_item' ),
     64                    'permission_callback' => array( $this, 'get_item_permissions_check' ),
     65                ),
     66                'schema' => array( $this, 'get_public_item_schema' ),
     67            )
     68        );
    5069    }
    5170
     
    5978     */
    6079    public function get_items_permissions_check( $request ) {
     80        if ( current_user_can( 'switch_themes' ) || current_user_can( 'manage_network_themes' ) ) {
     81            return true;
     82        }
     83
     84        $registered = $this->get_collection_params();
     85        if ( isset( $registered['status'], $request['status'] ) && is_array( $request['status'] ) && array( 'active' ) === $request['status'] ) {
     86            return $this->check_read_active_theme_permission();
     87        }
     88
     89        return new WP_Error(
     90            'rest_cannot_view_themes',
     91            __( 'Sorry, you are not allowed to view themes.' ),
     92            array( 'status' => rest_authorization_required_code() )
     93        );
     94    }
     95
     96    /**
     97     * Checks if a given request has access to read the theme.
     98     *
     99     * @since 5.7.0
     100     *
     101     * @param WP_REST_Request $request Full details about the request.
     102     * @return bool|WP_Error True if the request has read access for the item, otherwise WP_Error object.
     103     */
     104    public function get_item_permissions_check( $request ) {
     105        if ( current_user_can( 'switch_themes' ) || current_user_can( 'manage_network_themes' ) ) {
     106            return true;
     107        }
     108
     109        $wp_theme      = wp_get_theme( $request['stylesheet'] );
     110        $current_theme = wp_get_theme();
     111
     112        if ( $this->is_same_theme( $wp_theme, $current_theme ) ) {
     113            return $this->check_read_active_theme_permission();
     114        }
     115
     116        return new WP_Error(
     117            'rest_cannot_view_themes',
     118            __( 'Sorry, you are not allowed to view themes.' ),
     119            array( 'status' => rest_authorization_required_code() )
     120        );
     121    }
     122
     123    /**
     124     * Checks if a theme can be read.
     125     *
     126     * @since 5.7.0
     127     *
     128     * @return bool|WP_Error Whether the theme can be read.
     129     */
     130    protected function check_read_active_theme_permission() {
    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_cannot_view_active_theme',
     143            __( 'Sorry, you are not allowed to view the active theme.' ),
    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 single theme.
     150     *
     151     * @since 5.7.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    public function get_item( $request ) {
     157        $wp_theme = wp_get_theme( $request['stylesheet'] );
     158        if ( ! $wp_theme->exists() ) {
     159            return new WP_Error(
     160                'rest_theme_not_found',
     161                __( 'Theme not found.' ),
     162                array( 'status' => 404 )
     163            );
     164        }
     165        $data = $this->prepare_item_for_response( $wp_theme, $request );
     166
     167        return rest_ensure_response( $data );
     168    }
     169
     170    /**
     171     * Retrieves a collection of themes.
     172     *
     173     * @since 5.0.0
     174     *
     175     * @param WP_REST_Request $request Full details about the request.
     176     * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
     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', 1 );
    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        $response->add_links( $this->prepare_links( $theme ) );
    208313
    209314        /**
     
    220325
    221326    /**
     327     * Prepares links for the request.
     328     *
     329     * @since 5.7.0
     330     *
     331     * @param WP_Theme $theme Theme data.
     332     * @return array Links for the given block type.
     333     */
     334    protected function prepare_links( $theme ) {
     335        return array(
     336            'self'       => array(
     337                'href' => rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $theme->get_stylesheet() ) ),
     338            ),
     339            'collection' => array(
     340                'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
     341            ),
     342        );
     343    }
     344
     345    /**
     346     * Helper function to compare two themes.
     347     *
     348     * @since 5.7.0
     349     *
     350     * @param WP_Theme $theme_a First theme to compare.
     351     * @param WP_Theme $theme_b Second theme to compare.
     352     *
     353     * @return bool
     354     */
     355    protected function is_same_theme( $theme_a, $theme_b ) {
     356        return $theme_a->get_stylesheet() === $theme_b->get_stylesheet();
     357    }
     358
     359    /**
    222360     * Prepares the theme support value for inclusion in the REST API response.
    223361     *
     
    400538                    'readonly'    => true,
    401539                ),
     540                'status'         => array(
     541                    'description' => __( 'A named status for the theme.' ),
     542                    'type'        => 'string',
     543                    'enum'        => array( 'inactive', 'active' ),
     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 = array(
     572            'status' => array(
     573                'description' => __( 'Limit result set to themes assigned one or more statuses.' ),
     574                'type'        => 'array',
     575                'items'       => array(
     576                    'enum' => array( 'active', 'inactive' ),
     577                    'type' => 'string',
     578                ),
    436579            ),
    437             'required'          => true,
    438             'sanitize_callback' => array( $this, 'sanitize_theme_status' ),
    439580        );
    440581
     
    453594     *
    454595     * @since 5.0.0
     596     * @deprecated 5.7.0
    455597     *
    456598     * @param string|array    $statuses  One or more theme statuses.
     
    460602     */
    461603    public function sanitize_theme_status( $statuses, $request, $parameter ) {
     604        _deprecated_function( __METHOD__, '5.7.0' );
     605
    462606        $statuses = wp_parse_slug_list( $statuses );
    463607
Note: See TracChangeset for help on using the changeset viewer.