|
1 <?php |
|
2 /** |
|
3 * WP_REST_Navigation_Fallback_Controller class |
|
4 * |
|
5 * REST Controller to create/fetch a fallback Navigation Menu. |
|
6 * |
|
7 * @package WordPress |
|
8 * @subpackage REST_API |
|
9 * @since 6.3.0 |
|
10 */ |
|
11 |
|
12 /** |
|
13 * REST Controller to fetch a fallback Navigation Block Menu. If needed it creates one. |
|
14 * |
|
15 * @since 6.3.0 |
|
16 */ |
|
17 class WP_REST_Navigation_Fallback_Controller extends WP_REST_Controller { |
|
18 |
|
19 /** |
|
20 * The Post Type for the Controller |
|
21 * |
|
22 * @since 6.3.0 |
|
23 * |
|
24 * @var string |
|
25 */ |
|
26 private $post_type; |
|
27 |
|
28 /** |
|
29 * Constructs the controller. |
|
30 * |
|
31 * @since 6.3.0 |
|
32 */ |
|
33 public function __construct() { |
|
34 $this->namespace = 'wp-block-editor/v1'; |
|
35 $this->rest_base = 'navigation-fallback'; |
|
36 $this->post_type = 'wp_navigation'; |
|
37 } |
|
38 |
|
39 /** |
|
40 * Registers the controllers routes. |
|
41 * |
|
42 * @since 6.3.0 |
|
43 */ |
|
44 public function register_routes() { |
|
45 |
|
46 // Lists a single nav item based on the given id or slug. |
|
47 register_rest_route( |
|
48 $this->namespace, |
|
49 '/' . $this->rest_base, |
|
50 array( |
|
51 array( |
|
52 'methods' => WP_REST_Server::READABLE, |
|
53 'callback' => array( $this, 'get_item' ), |
|
54 'permission_callback' => array( $this, 'get_item_permissions_check' ), |
|
55 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::READABLE ), |
|
56 ), |
|
57 'schema' => array( $this, 'get_item_schema' ), |
|
58 ) |
|
59 ); |
|
60 } |
|
61 |
|
62 /** |
|
63 * Checks if a given request has access to read fallbacks. |
|
64 * |
|
65 * @since 6.3.0 |
|
66 * |
|
67 * @param WP_REST_Request $request Full details about the request. |
|
68 * @return true|WP_Error True if the request has read access, WP_Error object otherwise. |
|
69 */ |
|
70 public function get_item_permissions_check( $request ) { |
|
71 |
|
72 $post_type = get_post_type_object( $this->post_type ); |
|
73 |
|
74 // Getting fallbacks requires creating and reading `wp_navigation` posts. |
|
75 if ( ! current_user_can( $post_type->cap->create_posts ) || ! current_user_can( 'edit_theme_options' ) || ! current_user_can( 'edit_posts' ) ) { |
|
76 return new WP_Error( |
|
77 'rest_cannot_create', |
|
78 __( 'Sorry, you are not allowed to create Navigation Menus as this user.' ), |
|
79 array( 'status' => rest_authorization_required_code() ) |
|
80 ); |
|
81 } |
|
82 |
|
83 if ( 'edit' === $request['context'] && ! current_user_can( $post_type->cap->edit_posts ) ) { |
|
84 return new WP_Error( |
|
85 'rest_forbidden_context', |
|
86 __( 'Sorry, you are not allowed to edit Navigation Menus as this user.' ), |
|
87 array( 'status' => rest_authorization_required_code() ) |
|
88 ); |
|
89 } |
|
90 |
|
91 return true; |
|
92 } |
|
93 |
|
94 /** |
|
95 * Gets the most appropriate fallback Navigation Menu. |
|
96 * |
|
97 * @since 6.3.0 |
|
98 * |
|
99 * @param WP_REST_Request $request Full details about the request. |
|
100 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. |
|
101 */ |
|
102 public function get_item( $request ) { |
|
103 $post = WP_Navigation_Fallback::get_fallback(); |
|
104 |
|
105 if ( empty( $post ) ) { |
|
106 return rest_ensure_response( new WP_Error( 'no_fallback_menu', __( 'No fallback menu found.' ), array( 'status' => 404 ) ) ); |
|
107 } |
|
108 |
|
109 $response = $this->prepare_item_for_response( $post, $request ); |
|
110 |
|
111 return $response; |
|
112 } |
|
113 |
|
114 /** |
|
115 * Retrieves the fallbacks' schema, conforming to JSON Schema. |
|
116 * |
|
117 * @since 6.3.0 |
|
118 * |
|
119 * @return array Item schema data. |
|
120 */ |
|
121 public function get_item_schema() { |
|
122 if ( $this->schema ) { |
|
123 return $this->add_additional_fields_schema( $this->schema ); |
|
124 } |
|
125 |
|
126 $this->schema = array( |
|
127 '$schema' => 'http://json-schema.org/draft-04/schema#', |
|
128 'title' => 'navigation-fallback', |
|
129 'type' => 'object', |
|
130 'properties' => array( |
|
131 'id' => array( |
|
132 'description' => __( 'The unique identifier for the Navigation Menu.' ), |
|
133 'type' => 'integer', |
|
134 'context' => array( 'view', 'edit', 'embed' ), |
|
135 'readonly' => true, |
|
136 ), |
|
137 ), |
|
138 ); |
|
139 |
|
140 return $this->add_additional_fields_schema( $this->schema ); |
|
141 } |
|
142 |
|
143 /** |
|
144 * Matches the post data to the schema we want. |
|
145 * |
|
146 * @since 6.3.0 |
|
147 * |
|
148 * @param WP_Post $item The wp_navigation Post object whose response is being prepared. |
|
149 * @param WP_REST_Request $request Request object. |
|
150 * @return WP_REST_Response $response The response data. |
|
151 */ |
|
152 public function prepare_item_for_response( $item, $request ) { |
|
153 $data = array(); |
|
154 |
|
155 $fields = $this->get_fields_for_response( $request ); |
|
156 |
|
157 if ( rest_is_field_included( 'id', $fields ) ) { |
|
158 $data['id'] = (int) $item->ID; |
|
159 } |
|
160 |
|
161 $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; |
|
162 $data = $this->add_additional_fields_to_object( $data, $request ); |
|
163 $data = $this->filter_response_by_context( $data, $context ); |
|
164 |
|
165 $response = rest_ensure_response( $data ); |
|
166 |
|
167 if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { |
|
168 $links = $this->prepare_links( $item ); |
|
169 $response->add_links( $links ); |
|
170 } |
|
171 |
|
172 return $response; |
|
173 } |
|
174 |
|
175 /** |
|
176 * Prepares the links for the request. |
|
177 * |
|
178 * @since 6.3.0 |
|
179 * |
|
180 * @param WP_Post $post the Navigation Menu post object. |
|
181 * @return array Links for the given request. |
|
182 */ |
|
183 private function prepare_links( $post ) { |
|
184 return array( |
|
185 'self' => array( |
|
186 'href' => rest_url( rest_get_route_for_post( $post->ID ) ), |
|
187 'embeddable' => true, |
|
188 ), |
|
189 ); |
|
190 } |
|
191 } |