WordPress.org

Make WordPress Core

Ticket #40878: 40878.diff

File 40878.diff, 20.5 KB (added by ryelle, 2 years ago)
  • src/wp-includes/post.php

     
    118118
    119119        register_post_type(
    120120                'nav_menu_item', array(
    121                         'labels'           => array(
    122                                 'name'          => __( 'Navigation Menu Items' ),
    123                                 'singular_name' => __( 'Navigation Menu Item' ),
     121                        'labels'                => array(
     122                                'name'              => __( 'Navigation Menu Items' ),
     123                                'singular_name'     => __( 'Navigation Menu Item' ),
    124124                        ),
    125                         'public'           => false,
    126                         '_builtin'         => true, /* internal use only. don't use this when registering your own post type. */
    127                         'hierarchical'     => false,
    128                         'rewrite'          => false,
    129                         'delete_with_user' => false,
    130                         'query_var'        => false,
     125                        'public'                => false,
     126                        '_builtin'              => true, /* internal use only. don't use this when registering your own post type. */
     127                        'hierarchical'          => false,
     128                        'rewrite'               => false,
     129                        'delete_with_user'      => false,
     130                        'query_var'             => false,
     131                        'show_in_rest'          => true,
     132                        'rest_base'             => 'menu-items',
     133                        'rest_controller_class' => 'WP_REST_Menu_Items_Controller',
    131134                )
    132135        );
    133136
  • src/wp-includes/rest-api/endpoints/class-wp-rest-menu-items-controller.php

     
     1<?php
     2/**
     3 * REST API: WP_REST_Attachments_Controller class
     4 *
     5 * @package WordPress
     6 * @subpackage REST_API
     7 * @since 4.7.0
     8 */
     9
     10/**
     11 * Core controller used to access attachments via the REST API.
     12 *
     13 * @since 4.7.0
     14 *
     15 * @see WP_REST_Posts_Controller
     16 */
     17class WP_REST_Menu_Items_Controller extends WP_REST_Posts_Controller {
     18
     19        /**
     20         * Registers the routes for the objects of the controller.
     21         *
     22         * @since 4.7.0
     23         *
     24         * @see register_rest_route()
     25         */
     26        public function register_routes() {
     27
     28                register_rest_route(
     29                        $this->namespace, '/' . $this->rest_base, array(
     30                                array(
     31                                        'methods'             => WP_REST_Server::READABLE,
     32                                        'callback'            => array( $this, 'get_items' ),
     33                                        'permission_callback' => array( $this, 'get_items_permissions_check' ),
     34                                        'args'                => $this->get_collection_params(),
     35                                ),
     36                                'schema' => array( $this, 'get_public_item_schema' ),
     37                        )
     38                );
     39
     40                $schema        = $this->get_item_schema();
     41                $get_item_args = array(
     42                        'context' => $this->get_context_param( array( 'default' => 'view' ) ),
     43                );
     44                register_rest_route(
     45                        $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
     46                                'args'   => array(
     47                                        'id' => array(
     48                                                'description' => __( 'Unique identifier for the object.' ),
     49                                                'type'        => 'integer',
     50                                        ),
     51                                ),
     52                                array(
     53                                        'methods'             => WP_REST_Server::READABLE,
     54                                        'callback'            => array( $this, 'get_item' ),
     55                                        'permission_callback' => array( $this, 'get_item_permissions_check' ),
     56                                        'args'                => $get_item_args,
     57                                ),
     58                                'schema' => array( $this, 'get_public_item_schema' ),
     59                        )
     60                );
     61        }
     62
     63        /**
     64         * Prepares a single attachment output for response.
     65         *
     66         * @since 4.7.0
     67         *
     68         * @param WP_Post         $post    Attachment object.
     69         * @param WP_REST_Request $request Request object.
     70         * @return WP_REST_Response Response object.
     71         */
     72        public function prepare_item_for_response( $post, $request ) {
     73                $response = parent::prepare_item_for_response( $post, $request );
     74                $data     = $response->get_data();
     75
     76                $menu_item = wp_setup_nav_menu_item( $post );
     77
     78                $data['id']               = (int) $menu_item->ID;
     79                $data['menu_item_parent'] = (int) $menu_item->menu_item_parent;
     80
     81                if ( isset( $menu_item->object_id ) ) {
     82                        $data['object_id'] = (int) $menu_item->object_id;
     83                }
     84
     85                $data['title']       = $menu_item->title;
     86                $data['object']      = $menu_item->object;
     87                $data['target']      = $menu_item->target;
     88                $data['attr_title']  = $menu_item->attr_title;
     89                $data['description'] = $menu_item->description;
     90                $data['classes']     = $menu_item->classes;
     91                $data['xfn']         = $menu_item->xfn;
     92
     93                $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
     94
     95                $data = $this->filter_response_by_context( $data, $context );
     96
     97                // Wrap the data in a response object.
     98                $response = rest_ensure_response( $data );
     99
     100                $response->add_links( $this->prepare_links( $post ) );
     101
     102                /**
     103                 * Filters an attachment returned from the REST API.
     104                 *
     105                 * Allows modification of the attachment right before it is returned.
     106                 *
     107                 * @since 4.7.0
     108                 *
     109                 * @param WP_REST_Response $response The response object.
     110                 * @param WP_Post          $post     The original attachment post.
     111                 * @param WP_REST_Request  $request  Request used to generate the response.
     112                 */
     113                return apply_filters( 'rest_prepare_nav_menu_item', $response, $post, $request );
     114        }
     115
     116        /**
     117         * Retrieves the attachment's schema, conforming to JSON Schema.
     118         *
     119         * @since 4.7.0
     120         *
     121         * @return array Item schema as an array.
     122         */
     123        public function get_item_schema() {
     124
     125                $schema = parent::get_item_schema();
     126
     127                $schema['properties']['object'] = array(
     128                        'description' => __( 'The type of object originally represented, such as "category," "post", or "attachment."' ),
     129                        'type'        => 'string',
     130                        'context'     => array( 'view' ),
     131                );
     132
     133                $schema['properties']['object_id'] = array(
     134                        'description' => __( 'The DB ID of the original object this menu item represents, e.g. ID for posts and term_id for categories.' ),
     135                        'type'        => 'integer',
     136                        'context'     => array( 'view' ),
     137                );
     138
     139                $schema['properties']['menu_item_parent'] = array(
     140                        'description' => __( 'The DB ID of the nav_menu_item that is this item\'s menu parent, if any. 0 otherwise.' ),
     141                        'type'        => 'integer',
     142                        'context'     => array( 'view' ),
     143                );
     144
     145                $schema['properties']['menu_order'] = array(
     146                        'description' => __( 'The order of the object in relation to other object of its type.' ),
     147                        'type'        => 'integer',
     148                        'context'     => array( 'view', 'embed' ),
     149                );
     150
     151                $schema['properties']['attr_title'] = array(
     152                        'description' => __( 'Text for the title attribute of the link element for this menu item.' ),
     153                        'type'        => 'string',
     154                        'context'     => array( 'view', 'embed' ),
     155                );
     156
     157                $schema['properties']['classes'] = array(
     158                        'description' => __( 'Array of class attribute values for the link element of this menu item.' ),
     159                        'type'        => 'array',
     160                        'items'       => array(
     161                                'type' => 'string',
     162                        ),
     163                        'context'     => array( 'view', 'embed' ),
     164                );
     165
     166                $schema['properties']['target'] = array(
     167                        'description' => __( 'The target attribute of the link element for this menu item.' ),
     168                        'type'        => 'string',
     169                        'context'     => array( 'view', 'embed' ),
     170                );
     171
     172                $schema['properties']['xfn'] = array(
     173                        'description' => __( 'The XFN relationship expressed in the link of this menu item.' ),
     174                        'type'        => 'string',
     175                        'context'     => array( 'view', 'embed' ),
     176                );
     177
     178                $schema['properties']['description'] = array(
     179                        'description' => __( 'The description of this menu item.' ),
     180                        'type'        => 'string',
     181                        'context'     => array( 'view', 'embed' ),
     182                );
     183
     184                $schema['properties']['link'] = array(
     185                        'description' => __( 'The URL to which this menu item points.' ),
     186                        'type'        => 'string',
     187                        'context'     => array( 'view', 'embed' ),
     188                );
     189
     190                unset( $schema['properties']['password'] );
     191
     192                return $schema;
     193        }
     194}
  • src/wp-includes/rest-api/endpoints/class-wp-rest-menu-locations-controller.php

    Property changes on: src/wp-includes/rest-api/endpoints/class-wp-rest-menu-items-controller.php
    ___________________________________________________________________
    Added: svn:executable
    ## -0,0 +1 ##
    +*
    \ No newline at end of property
     
     1<?php
     2/**
     3 * REST API: WP_REST_Menu_Locations_Controller class
     4 *
     5 * @package WordPress
     6 * @subpackage REST_API
     7 * @since 4.x.x
     8 */
     9
     10/**
     11 * Core class used to access menu locations via the REST API.
     12 *
     13 * @since 4.x.x
     14 *
     15 * @see WP_REST_Controller
     16 */
     17class WP_REST_Menu_Locations_Controller extends WP_REST_Controller {
     18
     19        /**
     20         * Constructor.
     21         *
     22         * @since 4.x.x
     23         */
     24        public function __construct() {
     25                $this->namespace = 'wp/v2';
     26                $this->rest_base = 'menu-locations';
     27        }
     28
     29        /**
     30         * Registers the routes for the objects of the controller.
     31         *
     32         * @since 4.x.x
     33         *
     34         * @see register_rest_route()
     35         */
     36        public function register_routes() {
     37
     38                register_rest_route( $this->namespace, '/' . $this->rest_base, array(
     39                        array(
     40                                'methods'             => WP_REST_Server::READABLE,
     41                                'callback'            => array( $this, 'get_items' ),
     42                                'permission_callback' => array( $this, 'get_items_permissions_check' ),
     43                                'args'                => $this->get_collection_params(),
     44                        ),
     45                        'schema' => array( $this, 'get_public_item_schema' ),
     46                ) );
     47
     48                register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<location>[\w-]+)', array(
     49                        'args' => array(
     50                                'location' => array(
     51                                        'description' => __( 'An alphanumeric identifier for the menu location.' ),
     52                                        'type'        => 'string',
     53                                ),
     54                        ),
     55                        array(
     56                                'methods'             => WP_REST_Server::READABLE,
     57                                'callback'            => array( $this, 'get_item' ),
     58                                'permission_callback' => array( $this, 'get_item_permissions_check' ),
     59                                'args'                => array(
     60                                        'context' => $this->get_context_param( array( 'default' => 'view' ) ),
     61                                ),
     62                        ),
     63                        'schema' => array( $this, 'get_public_item_schema' ),
     64                ) );
     65        }
     66
     67        /**
     68         * Checks whether a given request has permission to read menu locations.
     69         *
     70         * @since 4.x.x
     71         *
     72         * @param WP_REST_Request $request Full details about the request.
     73         * @return WP_Error|bool True if the request has read access, WP_Error object otherwise.
     74         */
     75        public function get_items_permissions_check( $request ) {
     76                if ( 'edit' === $request['context'] ) {
     77                        $types = get_post_types( array( 'show_in_rest' => true ), 'objects' );
     78
     79                        foreach ( $types as $type ) {
     80                                if ( current_user_can( $type->cap->edit_posts ) ) {
     81                                        return true;
     82                                }
     83                        }
     84                        return new WP_Error( 'rest_cannot_view', __( 'Sorry, you are not allowed to manage menu locations.' ), array( 'status' => rest_authorization_required_code() ) );
     85                }
     86
     87                return true;
     88        }
     89
     90        /**
     91         * Retrieves all menu locations, depending on user context.
     92         *
     93         * @since 4.x.x
     94         *
     95         * @param WP_REST_Request $request Full details about the request.
     96         * @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure.
     97         */
     98        public function get_items( $request ) {
     99                $data = array();
     100
     101                foreach ( get_registered_nav_menus() as $name => $description ) {
     102                        $location = new stdClass();
     103                        $location->name = $name;
     104                        $location->description = $description;
     105
     106                        $location = $this->prepare_item_for_response( $location, $request );
     107                        $data[ $name ] = $this->prepare_response_for_collection( $location );
     108                }
     109
     110                return rest_ensure_response( $data );
     111        }
     112
     113        /**
     114         * Checks if a given request has access to read a menu location.
     115         *
     116         * @since 4.x.x
     117         *
     118         * @param WP_REST_Request $request Full details about the request.
     119         * @return WP_Error|bool True if the request has read access for the item, WP_Error object otherwise.
     120         */
     121        public function get_item_permissions_check( $request ) {
     122                if ( ! array_key_exists( $request['location'], get_registered_nav_menus() ) ) {
     123                        return new WP_Error( 'rest_menu_location_invalid', __( 'Invalid menu location.' ), array( 'status' => 404 ) );
     124                }
     125
     126                return true;
     127        }
     128
     129        /**
     130         * Retrieves a specific menu location.
     131         *
     132         * @since 4.x.x
     133         *
     134         * @param WP_REST_Request $request Full details about the request.
     135         * @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure.
     136         */
     137        public function get_item( $request ) {
     138                $registered_menus = get_registered_nav_menus();
     139                if ( ! array_key_exists( $request['location'], $registered_menus ) ) {
     140                        return new WP_Error( 'rest_menu_location_invalid', __( 'Invalid menu location.' ), array( 'status' => 404 ) );
     141                }
     142
     143                $location = new stdClass();
     144                $location->name = $request['location'];
     145                $location->description = $registered_menus[ $location->name ];
     146
     147                $data = $this->prepare_item_for_response( $location, $request );
     148
     149                return rest_ensure_response( $data );
     150        }
     151
     152        /**
     153         * Prepares a menu location object for serialization.
     154         *
     155         * @since 4.x.x
     156         *
     157         * @param stdClass        $location  Post status data.
     158         * @param WP_REST_Request $request Full details about the request.
     159         * @return WP_REST_Response Post status data.
     160         */
     161        public function prepare_item_for_response( $location, $request ) {
     162
     163                $data = array(
     164                        'name'         => $location->name,
     165                        'description'  => $location->description,
     166                );
     167
     168                $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
     169                $data = $this->add_additional_fields_to_object( $data, $request );
     170                $data = $this->filter_response_by_context( $data, $context );
     171
     172                $response = rest_ensure_response( $data );
     173
     174                $response->add_links( $this->prepare_links( $location ) );
     175
     176                /**
     177                 * Filters a menu location returned from the REST API.
     178                 *
     179                 * Allows modification of the menu location data right before it is
     180                 * returned.
     181                 *
     182                 * @since 4.x.x
     183                 *
     184                 * @param WP_REST_Response $response The response object.
     185                 * @param object           $location The original status object.
     186                 * @param WP_REST_Request  $request  Request used to generate the response.
     187                 */
     188                return apply_filters( 'rest_prepare_menu_location', $response, $location, $request );
     189        }
     190
     191        /**
     192         * Retrieves the menu location's schema, conforming to JSON Schema.
     193         *
     194         * @since 4.x.x
     195         *
     196         * @return array Item schema data.
     197         */
     198        public function get_item_schema() {
     199                $schema = array(
     200                        '$schema'              => 'http://json-schema.org/draft-04/schema#',
     201                        'title'                => 'menu-location',
     202                        'type'                 => 'object',
     203                        'properties'           => array(
     204                                'name'             => array(
     205                                        'description'  => __( 'The name of the menu location.' ),
     206                                        'type'         => 'string',
     207                                        'context'      => array( 'embed', 'view', 'edit' ),
     208                                        'readonly'     => true,
     209                                ),
     210                                'description'      => array(
     211                                        'description'  => __( 'The description of the menu location.' ),
     212                                        'type'         => 'string',
     213                                        'context'      => array( 'embed', 'view', 'edit' ),
     214                                        'readonly'     => true,
     215                                ),
     216                        ),
     217                );
     218
     219                return $this->add_additional_fields_schema( $schema );
     220        }
     221
     222        /**
     223         * Retrieves the query params for collections.
     224         *
     225         * @since 4.x.x
     226         *
     227         * @return array Collection parameters.
     228         */
     229        public function get_collection_params() {
     230                return array(
     231                        'context' => $this->get_context_param( array( 'default' => 'view' ) ),
     232                );
     233        }
     234
     235        /**
     236         * Prepares links for the request.
     237         *
     238         * @since 4.x.x
     239         *
     240         * @param stdClass $location Menu location.
     241         * @return array Links for the given menu location.
     242         */
     243        protected function prepare_links( $location ) {
     244                $base = sprintf( '%s/%s', $this->namespace, $this->rest_base );
     245
     246                // Entity meta.
     247                $links = array(
     248                        'self' => array(
     249                                'href'   => rest_url( trailingslashit( $base ) . $location->name ),
     250                        ),
     251                        'collection' => array(
     252                                'href'   => rest_url( $base ),
     253                        ),
     254                );
     255
     256                $menus = get_nav_menu_locations();
     257                if ( array_key_exists( $location->name, $menus ) ) {
     258                        $id = $menus[ $location->name ];
     259                        $items_url = rest_url( "wp/v2/menus/${id}" );
     260
     261                        $links['menus'] = array(
     262                                'href'       => $items_url,
     263                                'embeddable' => true,
     264                        );
     265                }
     266
     267                return $links;
     268        }
     269}
  • src/wp-includes/rest-api/endpoints/class-wp-rest-menus-controller.php

    Property changes on: src/wp-includes/rest-api/endpoints/class-wp-rest-menu-locations-controller.php
    ___________________________________________________________________
    Added: svn:executable
    ## -0,0 +1 ##
    +*
    \ No newline at end of property
     
     1<?php
     2/**
     3 * REST API: WP_REST_Menus_Controller class
     4 *
     5 * @package WordPress
     6 * @subpackage REST_API
     7 * @since 4.x.x
     8 */
     9
     10/**
     11 * Core class used to access menus via the REST API.
     12 *
     13 * @since 4.x.x
     14 *
     15 * @see WP_REST_Controller
     16 */
     17class WP_REST_Menus_Controller extends WP_REST_Terms_Controller {
     18
     19        /**
     20         * Prepares links for the request.
     21         *
     22         * @since 4.x.x
     23         *
     24         * @param object $term Term object.
     25         * @return array Links for the given term.
     26         */
     27        protected function prepare_links( $term ) {
     28                $links = parent::prepare_links( $term );
     29
     30                // Let's make sure that menu items are embeddable for a menu collection.
     31                if ( array_key_exists( 'https://api.w.org/post_type', $links ) ) {
     32                        $post_type_links = $links['https://api.w.org/post_type'];
     33
     34                        foreach ( $post_type_links as $index => $post_type_link ) {
     35                                if ( ! array_key_exists( 'href', $post_type_link ) || strpos( $post_type_link['href'], '/menu-items?' ) === false ) {
     36                                        continue;
     37                                }
     38
     39                                $post_type_links[ $index ]['embeddable'] = true;
     40                        }
     41
     42                        $links['https://api.w.org/post_type'] = $post_type_links;
     43                }
     44
     45                return $links;
     46        }
     47}
  • src/wp-includes/rest-api.php

    Property changes on: src/wp-includes/rest-api/endpoints/class-wp-rest-menus-controller.php
    ___________________________________________________________________
    Added: svn:executable
    ## -0,0 +1 ##
    +*
    \ No newline at end of property
     
    233233        // Settings.
    234234        $controller = new WP_REST_Settings_Controller;
    235235        $controller->register_routes();
     236
     237        // Menu location.
     238        $controller = new WP_REST_Menu_Locations_Controller;
     239        $controller->register_routes();
    236240}
    237241
    238242/**
  • src/wp-includes/taxonomy.php

     
    101101
    102102        register_taxonomy(
    103103                'nav_menu', 'nav_menu_item', array(
    104                         'public'            => false,
    105                         'hierarchical'      => false,
    106                         'labels'            => array(
    107                                 'name'          => __( 'Navigation Menus' ),
    108                                 'singular_name' => __( 'Navigation Menu' ),
     104                        'public'                => false,
     105                        'hierarchical'          => false,
     106                        'labels'                => array(
     107                                'name'              => __( 'Navigation Menus' ),
     108                                'singular_name'     => __( 'Navigation Menu' ),
    109109                        ),
    110                         'query_var'         => false,
    111                         'rewrite'           => false,
    112                         'show_ui'           => false,
    113                         '_builtin'          => true,
    114                         'show_in_nav_menus' => false,
     110                        'query_var'             => false,
     111                        'rewrite'               => false,
     112                        'show_ui'               => false,
     113                        '_builtin'              => true,
     114                        'show_in_nav_menus'     => false,
     115                        'show_in_rest'          => true,
     116                        'rest_base'             => 'menus',
     117                        'rest_controller_class' => 'WP_REST_Menus_Controller',
    115118                )
    116119        );
    117120
  • src/wp-settings.php

     
    235235require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-users-controller.php' );
    236236require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-comments-controller.php' );
    237237require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-settings-controller.php' );
     238require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-menu-items-controller.php' );
     239require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-menu-locations-controller.php' );
     240require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-menus-controller.php' );
    238241require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-meta-fields.php' );
    239242require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-comment-meta-fields.php' );
    240243require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-post-meta-fields.php' );