wp/wp-includes/rest-api/endpoints/class-wp-rest-menu-locations-controller.php
changeset 19 3d72ae0968f4
child 21 48c4eec2b7e6
equal deleted inserted replaced
18:be944660c56a 19:3d72ae0968f4
       
     1 <?php
       
     2 /**
       
     3  * REST API: WP_REST_Menu_Locations_Controller class
       
     4  *
       
     5  * @package WordPress
       
     6  * @subpackage REST_API
       
     7  * @since 5.9.0
       
     8  */
       
     9 
       
    10 /**
       
    11  * Core class used to access menu locations via the REST API.
       
    12  *
       
    13  * @since 5.9.0
       
    14  *
       
    15  * @see WP_REST_Controller
       
    16  */
       
    17 class WP_REST_Menu_Locations_Controller extends WP_REST_Controller {
       
    18 
       
    19 	/**
       
    20 	 * Menu Locations Constructor.
       
    21 	 *
       
    22 	 * @since 5.9.0
       
    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 5.9.0
       
    33 	 *
       
    34 	 * @see register_rest_route()
       
    35 	 */
       
    36 	public function register_routes() {
       
    37 		register_rest_route(
       
    38 			$this->namespace,
       
    39 			'/' . $this->rest_base,
       
    40 			array(
       
    41 				array(
       
    42 					'methods'             => WP_REST_Server::READABLE,
       
    43 					'callback'            => array( $this, 'get_items' ),
       
    44 					'permission_callback' => array( $this, 'get_items_permissions_check' ),
       
    45 					'args'                => $this->get_collection_params(),
       
    46 				),
       
    47 				'schema' => array( $this, 'get_public_item_schema' ),
       
    48 			)
       
    49 		);
       
    50 
       
    51 		register_rest_route(
       
    52 			$this->namespace,
       
    53 			'/' . $this->rest_base . '/(?P<location>[\w-]+)',
       
    54 			array(
       
    55 				'args'   => array(
       
    56 					'location' => array(
       
    57 						'description' => __( 'An alphanumeric identifier for the menu location.' ),
       
    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 					'args'                => array(
       
    66 						'context' => $this->get_context_param( array( 'default' => 'view' ) ),
       
    67 					),
       
    68 				),
       
    69 				'schema' => array( $this, 'get_public_item_schema' ),
       
    70 			)
       
    71 		);
       
    72 	}
       
    73 
       
    74 	/**
       
    75 	 * Checks whether a given request has permission to read menu locations.
       
    76 	 *
       
    77 	 * @since 5.9.0
       
    78 	 *
       
    79 	 * @param WP_REST_Request $request Full details about the request.
       
    80 	 * @return WP_Error|bool True if the request has read access, WP_Error object otherwise.
       
    81 	 */
       
    82 	public function get_items_permissions_check( $request ) {
       
    83 		if ( ! current_user_can( 'edit_theme_options' ) ) {
       
    84 			return new WP_Error(
       
    85 				'rest_cannot_view',
       
    86 				__( 'Sorry, you are not allowed to view menu locations.' ),
       
    87 				array( 'status' => rest_authorization_required_code() )
       
    88 			);
       
    89 		}
       
    90 
       
    91 		return true;
       
    92 	}
       
    93 
       
    94 	/**
       
    95 	 * Retrieves all menu locations, depending on user context.
       
    96 	 *
       
    97 	 * @since 5.9.0
       
    98 	 *
       
    99 	 * @param WP_REST_Request $request Full details about the request.
       
   100 	 * @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure.
       
   101 	 */
       
   102 	public function get_items( $request ) {
       
   103 		$data = array();
       
   104 
       
   105 		foreach ( get_registered_nav_menus() as $name => $description ) {
       
   106 			$location              = new stdClass();
       
   107 			$location->name        = $name;
       
   108 			$location->description = $description;
       
   109 
       
   110 			$location      = $this->prepare_item_for_response( $location, $request );
       
   111 			$data[ $name ] = $this->prepare_response_for_collection( $location );
       
   112 		}
       
   113 
       
   114 		return rest_ensure_response( $data );
       
   115 	}
       
   116 
       
   117 	/**
       
   118 	 * Checks if a given request has access to read a menu location.
       
   119 	 *
       
   120 	 * @since 5.9.0
       
   121 	 *
       
   122 	 * @param WP_REST_Request $request Full details about the request.
       
   123 	 * @return WP_Error|bool True if the request has read access for the item, WP_Error object otherwise.
       
   124 	 */
       
   125 	public function get_item_permissions_check( $request ) {
       
   126 		if ( ! current_user_can( 'edit_theme_options' ) ) {
       
   127 			return new WP_Error(
       
   128 				'rest_cannot_view',
       
   129 				__( 'Sorry, you are not allowed to view menu locations.' ),
       
   130 				array( 'status' => rest_authorization_required_code() )
       
   131 			);
       
   132 		}
       
   133 
       
   134 		return true;
       
   135 	}
       
   136 
       
   137 	/**
       
   138 	 * Retrieves a specific menu location.
       
   139 	 *
       
   140 	 * @since 5.9.0
       
   141 	 *
       
   142 	 * @param WP_REST_Request $request Full details about the request.
       
   143 	 * @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure.
       
   144 	 */
       
   145 	public function get_item( $request ) {
       
   146 		$registered_menus = get_registered_nav_menus();
       
   147 		if ( ! array_key_exists( $request['location'], $registered_menus ) ) {
       
   148 			return new WP_Error( 'rest_menu_location_invalid', __( 'Invalid menu location.' ), array( 'status' => 404 ) );
       
   149 		}
       
   150 
       
   151 		$location              = new stdClass();
       
   152 		$location->name        = $request['location'];
       
   153 		$location->description = $registered_menus[ $location->name ];
       
   154 
       
   155 		$data = $this->prepare_item_for_response( $location, $request );
       
   156 
       
   157 		return rest_ensure_response( $data );
       
   158 	}
       
   159 
       
   160 	/**
       
   161 	 * Prepares a menu location object for serialization.
       
   162 	 *
       
   163 	 * @since 5.9.0
       
   164 	 *
       
   165 	 * @param stdClass        $item    Post status data.
       
   166 	 * @param WP_REST_Request $request Full details about the request.
       
   167 	 * @return WP_REST_Response Menu location data.
       
   168 	 */
       
   169 	public function prepare_item_for_response( $item, $request ) {
       
   170 		// Restores the more descriptive, specific name for use within this method.
       
   171 		$location  = $item;
       
   172 		$locations = get_nav_menu_locations();
       
   173 		$menu      = isset( $locations[ $location->name ] ) ? $locations[ $location->name ] : 0;
       
   174 
       
   175 		$fields = $this->get_fields_for_response( $request );
       
   176 		$data   = array();
       
   177 
       
   178 		if ( rest_is_field_included( 'name', $fields ) ) {
       
   179 			$data['name'] = $location->name;
       
   180 		}
       
   181 
       
   182 		if ( rest_is_field_included( 'description', $fields ) ) {
       
   183 			$data['description'] = $location->description;
       
   184 		}
       
   185 
       
   186 		if ( rest_is_field_included( 'menu', $fields ) ) {
       
   187 			$data['menu'] = (int) $menu;
       
   188 		}
       
   189 
       
   190 		$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
       
   191 		$data    = $this->add_additional_fields_to_object( $data, $request );
       
   192 		$data    = $this->filter_response_by_context( $data, $context );
       
   193 
       
   194 		$response = rest_ensure_response( $data );
       
   195 
       
   196 		$response->add_links( $this->prepare_links( $location ) );
       
   197 
       
   198 		/**
       
   199 		 * Filters menu location data returned from the REST API.
       
   200 		 *
       
   201 		 * @since 5.9.0
       
   202 		 *
       
   203 		 * @param WP_REST_Response $response The response object.
       
   204 		 * @param object           $location The original location object.
       
   205 		 * @param WP_REST_Request  $request  Request used to generate the response.
       
   206 		 */
       
   207 		return apply_filters( 'rest_prepare_menu_location', $response, $location, $request );
       
   208 	}
       
   209 
       
   210 	/**
       
   211 	 * Retrieves the menu location's schema, conforming to JSON Schema.
       
   212 	 *
       
   213 	 * @since 5.9.0
       
   214 	 *
       
   215 	 * @return array Item schema data.
       
   216 	 */
       
   217 	public function get_item_schema() {
       
   218 		if ( $this->schema ) {
       
   219 			return $this->add_additional_fields_schema( $this->schema );
       
   220 		}
       
   221 
       
   222 		$this->schema = array(
       
   223 			'$schema'    => 'http://json-schema.org/draft-04/schema#',
       
   224 			'title'      => 'menu-location',
       
   225 			'type'       => 'object',
       
   226 			'properties' => array(
       
   227 				'name'        => array(
       
   228 					'description' => __( 'The name of the menu location.' ),
       
   229 					'type'        => 'string',
       
   230 					'context'     => array( 'embed', 'view', 'edit' ),
       
   231 					'readonly'    => true,
       
   232 				),
       
   233 				'description' => array(
       
   234 					'description' => __( 'The description of the menu location.' ),
       
   235 					'type'        => 'string',
       
   236 					'context'     => array( 'embed', 'view', 'edit' ),
       
   237 					'readonly'    => true,
       
   238 				),
       
   239 				'menu'        => array(
       
   240 					'description' => __( 'The ID of the assigned menu.' ),
       
   241 					'type'        => 'integer',
       
   242 					'context'     => array( 'embed', 'view', 'edit' ),
       
   243 					'readonly'    => true,
       
   244 				),
       
   245 			),
       
   246 		);
       
   247 
       
   248 		return $this->add_additional_fields_schema( $this->schema );
       
   249 	}
       
   250 
       
   251 	/**
       
   252 	 * Retrieves the query params for collections.
       
   253 	 *
       
   254 	 * @since 5.9.0
       
   255 	 *
       
   256 	 * @return array Collection parameters.
       
   257 	 */
       
   258 	public function get_collection_params() {
       
   259 		return array(
       
   260 			'context' => $this->get_context_param( array( 'default' => 'view' ) ),
       
   261 		);
       
   262 	}
       
   263 
       
   264 	/**
       
   265 	 * Prepares links for the request.
       
   266 	 *
       
   267 	 * @since 5.9.0
       
   268 	 *
       
   269 	 * @param stdClass $location Menu location.
       
   270 	 * @return array Links for the given menu location.
       
   271 	 */
       
   272 	protected function prepare_links( $location ) {
       
   273 		$base = sprintf( '%s/%s', $this->namespace, $this->rest_base );
       
   274 
       
   275 		// Entity meta.
       
   276 		$links = array(
       
   277 			'self'       => array(
       
   278 				'href' => rest_url( trailingslashit( $base ) . $location->name ),
       
   279 			),
       
   280 			'collection' => array(
       
   281 				'href' => rest_url( $base ),
       
   282 			),
       
   283 		);
       
   284 
       
   285 		$locations = get_nav_menu_locations();
       
   286 		$menu      = isset( $locations[ $location->name ] ) ? $locations[ $location->name ] : 0;
       
   287 		if ( $menu ) {
       
   288 			$path = rest_get_route_for_term( $menu );
       
   289 			if ( $path ) {
       
   290 				$url = rest_url( $path );
       
   291 
       
   292 				$links['https://api.w.org/menu'][] = array(
       
   293 					'href'       => $url,
       
   294 					'embeddable' => true,
       
   295 				);
       
   296 			}
       
   297 		}
       
   298 
       
   299 		return $links;
       
   300 	}
       
   301 }