Make WordPress Core


Ignore:
Timestamp:
07/11/2018 09:20:10 AM (7 years ago)
Author:
pento
Message:

REST API: Declare user capabilities using JSON Hyper Schema's "targetSchema".

There are a variety of operations a WordPress user can only perform if they have the correct capabilities. A REST API client should only display UI for one of these operations if the WordPress user can perform the operation.

Rather than requiring REST API clients to calculate whether to display UI based on potentially complicated combinations of user capabilities, targetSchema allows us to expose a single flag to show whether the corresponding UI should be displayed.

This change also includes flags on post objects for the following actions:

  • action-publish: The current user can publish this post.
  • action-sticky: The current user can make this post sticky, and the post type supports sticking.
  • `action-assign-author': The current user can change the author on this post.
  • action-assign-{$taxonomy}: The current user can assign terms from the "$taxonomy" taxonomy to this post.
  • action-create-{$taxonomy}: The current user can create terms int the "$taxonomy" taxonomy.

Merges [43437] to the 4.9 branch.

Props TimothyBlynJacobs, danielbachhuber.
Fixes #44287.

Location:
branches/4.9
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/4.9

  • branches/4.9/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php

    r41979 r43438  
    15831583        $response = rest_ensure_response( $data );
    15841584
    1585         $response->add_links( $this->prepare_links( $post ) );
     1585        $links = $this->prepare_links( $post );
     1586        $response->add_links( $links );
     1587
     1588        if ( ! empty( $links['self']['href'] ) ) {
     1589            $actions = $this->get_available_actions( $post, $request );
     1590
     1591            $self = $links['self']['href'];
     1592
     1593            foreach ( $actions as $rel ) {
     1594                $response->add_link( $rel, $self );
     1595            }
     1596        }
    15861597
    15871598        /**
     
    17201731
    17211732        return $links;
     1733    }
     1734
     1735    /**
     1736     * Get the link relations available for the post and current user.
     1737     *
     1738     * @since 4.9.7
     1739     *
     1740     * @param WP_Post $post Post object.
     1741     * @param WP_REST_Request Request object.
     1742     *
     1743     * @return array List of link relations.
     1744     */
     1745    protected function get_available_actions( $post, $request ) {
     1746
     1747        if ( 'edit' !== $request['context'] ) {
     1748            return array();
     1749        }
     1750
     1751        $rels = array();
     1752
     1753        $post_type = get_post_type_object( $post->post_type );
     1754
     1755        if ( 'attachment' !== $this->post_type && current_user_can( $post_type->cap->publish_posts ) ) {
     1756            $rels[] = 'https://api.w.org/action-publish';
     1757        }
     1758
     1759        if ( 'post' === $post_type->name ) {
     1760            if ( current_user_can( $post_type->cap->edit_others_posts ) && current_user_can( $post_type->cap->publish_posts ) ) {
     1761                $rels[] = 'https://api.w.org/action-sticky';
     1762            }
     1763        }
     1764
     1765        if ( post_type_supports( $post_type->name, 'author' ) ) {
     1766            if ( current_user_can( $post_type->cap->edit_others_posts ) ) {
     1767                $rels[] = 'https://api.w.org/action-assign-author';
     1768            }
     1769        }
     1770
     1771        $taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) );
     1772
     1773        foreach ( $taxonomies as $tax ) {
     1774            $tax_base   = ! empty( $tax->rest_base ) ? $tax->rest_base : $tax->name;
     1775            $create_cap = is_taxonomy_hierarchical( $tax->name ) ? $tax->cap->edit_terms : $tax->cap->assign_terms;
     1776
     1777            if ( current_user_can( $create_cap ) ) {
     1778                $rels[] = 'https://api.w.org/action-create-' . $tax_base;
     1779            }
     1780
     1781            if ( current_user_can( $tax->cap->assign_terms ) ) {
     1782                $rels[] = 'https://api.w.org/action-assign-' . $tax_base;
     1783            }
     1784        }
     1785
     1786        return $rels;
    17221787    }
    17231788
     
    20622127        }
    20632128
     2129        $schema_links = $this->get_schema_links();
     2130
     2131        if ( $schema_links ) {
     2132            $schema['links'] = $schema_links;
     2133        }
     2134
    20642135        return $this->add_additional_fields_schema( $schema );
     2136    }
     2137
     2138    /**
     2139     * Retrieve Link Description Objects that should be added to the Schema for the posts collection.
     2140     *
     2141     * @since 4.9.7
     2142     *
     2143     * @return array
     2144     */
     2145    protected function get_schema_links() {
     2146
     2147        $href = rest_url( "{$this->namespace}/{$this->rest_base}/{id}" );
     2148
     2149        $links = array();
     2150
     2151        if ( 'attachment' !== $this->post_type ) {
     2152            $links[] = array(
     2153                'rel'          => 'https://api.w.org/action-publish',
     2154                'title'        => __( 'The current user can publish this post.' ),
     2155                'href'         => $href,
     2156                'targetSchema' => array(
     2157                    'type'       => 'object',
     2158                    'properties' => array(
     2159                        'status' => array(
     2160                            'type' => 'string',
     2161                            'enum' => array( 'publish', 'future' ),
     2162                        ),
     2163                    ),
     2164                ),
     2165            );
     2166        }
     2167
     2168        if ( 'post' === $this->post_type ) {
     2169            $links[] = array(
     2170                'rel'          => 'https://api.w.org/action-sticky',
     2171                'title'        => __( 'The current user can sticky this post.' ),
     2172                'href'         => $href,
     2173                'targetSchema' => array(
     2174                    'type'       => 'object',
     2175                    'properties' => array(
     2176                        'sticky' => array(
     2177                            'type' => 'boolean',
     2178                        ),
     2179                    ),
     2180                ),
     2181            );
     2182        }
     2183
     2184        if ( post_type_supports( $this->post_type, 'author' ) ) {
     2185            $links[] = array(
     2186                'rel'          => 'https://api.w.org/action-assign-author',
     2187                'title'        => __( 'The current user can change the author on this post.' ),
     2188                'href'         => $href,
     2189                'targetSchema' => array(
     2190                    'type'       => 'object',
     2191                    'properties' => array(
     2192                        'author' => array(
     2193                            'type' => 'integer',
     2194                        ),
     2195                    ),
     2196                ),
     2197            );
     2198        }
     2199
     2200        $taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) );
     2201
     2202        foreach ( $taxonomies as $tax ) {
     2203            $tax_base = ! empty( $tax->rest_base ) ? $tax->rest_base : $tax->name;
     2204
     2205            /* translators: %s: taxonomy name */
     2206            $assign_title = sprintf( __( 'The current user can assign terms in the %s taxonomy.' ), $tax->name );
     2207            /* translators: %s: taxonomy name */
     2208            $create_title = sprintf( __( 'The current user can create terms in the %s taxonomy.' ), $tax->name );
     2209
     2210            $links[] = array(
     2211                'rel'          => 'https://api.w.org/action-assign-' . $tax_base,
     2212                'title'        => $assign_title,
     2213                'href'         => $href,
     2214                'targetSchema' => array(
     2215                    'type'       => 'object',
     2216                    'properties' => array(
     2217                        $tax_base => array(
     2218                            'type'  => 'array',
     2219                            'items' => array(
     2220                                'type' => 'integer',
     2221                            ),
     2222                        ),
     2223                    ),
     2224                ),
     2225            );
     2226
     2227            $links[] = array(
     2228                'rel'          => 'https://api.w.org/action-create-' . $tax_base,
     2229                'title'        => $create_title,
     2230                'href'         => $href,
     2231                'targetSchema' => array(
     2232                    'type'       => 'object',
     2233                    'properties' => array(
     2234                        $tax_base => array(
     2235                            'type'  => 'array',
     2236                            'items' => array(
     2237                                'type' => 'integer',
     2238                            ),
     2239                        ),
     2240                    ),
     2241                ),
     2242            );
     2243        }
     2244
     2245        return $links;
    20652246    }
    20662247
Note: See TracChangeset for help on using the changeset viewer.