PluginProbe
Gutenberg / 10.4.0
Gutenberg v10.4.0
23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 7.4.0 All 402 releases
gutenberg / lib / class-wp-rest-sidebars-controller.php

class-wp-rest-sidebars-controller.php in Gutenberg 10.4.0, at lib/class-wp-rest-sidebars-controller.php

460 lines 14.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * REST API: WP_REST_Sidebars_Controller class
4 *
5 * @package WordPress
6 * @subpackage REST_API
7 * @since 5.6.0
8 *
9 * Copyright (C) 2015 Martin Pettersson
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 *
24 * @author Martin Pettersson <martin_pettersson@outlook.com>
25 * @copyright 2015 Martin Pettersson
26 * @license GPLv2
27 * @link https://github.com/martin-pettersson/wp-rest-api-sidebars
28 */
29
30 /**
31 * Core class used to manage a site's sidebars.
32 *
33 * @since 5.6.0
34 *
35 * @see WP_REST_Controller
36 */
37 class WP_REST_Sidebars_Controller extends WP_REST_Controller {
38
39 /**
40 * Sidebars controller constructor.
41 *
42 * @since 5.6.0
43 */
44 public function __construct() {
45 $this->namespace = 'wp/v2';
46 $this->rest_base = 'sidebars';
47 }
48
49 /**
50 * Registers the controllers routes.
51 *
52 * @return void
53 */
54 public function register_routes() {
55 register_rest_route(
56 $this->namespace,
57 '/' . $this->rest_base,
58 array(
59 array(
60 'methods' => WP_REST_Server::READABLE,
61 'callback' => array( $this, 'get_items' ),
62 'permission_callback' => array( $this, 'get_items_permissions_check' ),
63 'args' => array(
64 'context' => $this->get_context_param( array( 'default' => 'view' ) ),
65 ),
66 ),
67 'schema' => array( $this, 'get_public_item_schema' ),
68 )
69 );
70
71 register_rest_route(
72 $this->namespace,
73 '/' . $this->rest_base . '/(?P<id>[\w-]+)',
74 array(
75 array(
76 'methods' => WP_REST_Server::READABLE,
77 'callback' => array( $this, 'get_item' ),
78 'permission_callback' => array( $this, 'get_item_permissions_check' ),
79 'args' => array(
80 'id' => array(
81 'description' => __( 'The id of a registered sidebar', 'gutenberg' ),
82 'type' => 'string',
83 ),
84 'context' => $this->get_context_param( array( 'default' => 'view' ) ),
85 ),
86 ),
87 array(
88 'methods' => WP_REST_Server::EDITABLE,
89 'callback' => array( $this, 'update_item' ),
90 'permission_callback' => array( $this, 'update_item_permissions_check' ),
91 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
92 ),
93 'schema' => array( $this, 'get_public_item_schema' ),
94 )
95 );
96 }
97
98 /**
99 * Checks if a given request has access to get sidebars.
100 *
101 * @since 5.6.0
102 *
103 * @param WP_REST_Request $request Full details about the request.
104 * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
105 */
106 public function get_items_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
107 return $this->do_permissions_check();
108 }
109
110 /**
111 * Retrieves the list of sidebars (active or inactive).
112 *
113 * @since 5.6.0
114 *
115 * @param WP_REST_Request $request Full details about the request.
116 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
117 */
118 public function get_items( $request ) {
119 $data = array();
120 foreach ( (array) wp_get_sidebars_widgets() as $id => $widgets ) {
121 $sidebar = $this->get_sidebar( $id );
122
123 if ( ! $sidebar ) {
124 continue;
125 }
126
127 $data[] = $this->prepare_response_for_collection(
128 $this->prepare_item_for_response( $sidebar, $request )
129 );
130 }
131
132 return rest_ensure_response( $data );
133 }
134
135 /**
136 * Checks if a given request has access to get a single sidebar.
137 *
138 * @since 5.6.0
139 *
140 * @param WP_REST_Request $request Full details about the request.
141 * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
142 */
143 public function get_item_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
144 return $this->do_permissions_check();
145 }
146
147 /**
148 * Retrieves one sidebar from the collection.
149 *
150 * @since 5.6.0
151 *
152 * @param WP_REST_Request $request Full details about the request.
153 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
154 */
155 public function get_item( $request ) {
156 $sidebar = $this->get_sidebar( $request['id'] );
157
158 if ( ! $sidebar ) {
159 return new WP_Error( 'rest_sidebar_not_found', __( 'No sidebar exists with that id.', 'gutenberg' ), array( 'status' => 404 ) );
160 }
161
162 return $this->prepare_item_for_response( $sidebar, $request );
163 }
164
165 /**
166 * Checks if a given request has access to update sidebars.
167 *
168 * @since 5.6.0
169 *
170 * @param WP_REST_Request $request Full details about the request.
171 * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
172 */
173 public function update_item_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
174 return $this->do_permissions_check();
175 }
176
177 /**
178 * Updates a sidebar.
179 *
180 * @since 5.6.0
181 *
182 * @param WP_REST_Request $request Full details about the request.
183 * @return WP_REST_Response Response object on success, or WP_Error object on failure.
184 */
185 public function update_item( $request ) {
186 if ( isset( $request['widgets'] ) ) {
187 $sidebars = wp_get_sidebars_widgets();
188
189 foreach ( $sidebars as $sidebar_id => $widgets ) {
190 foreach ( $widgets as $i => $widget_id ) {
191 // This automatically removes the passed widget ids from any other sidebars in use.
192 if ( $sidebar_id !== $request['id'] && in_array( $widget_id, $request['widgets'], true ) ) {
193 unset( $sidebars[ $sidebar_id ][ $i ] );
194 }
195
196 // This automatically removes omitted widget ids to the inactive sidebar.
197 if ( $sidebar_id === $request['id'] && ! in_array( $widget_id, $request['widgets'], true ) ) {
198 $sidebars['wp_inactive_widgets'][] = $widget_id;
199 }
200 }
201 }
202
203 $sidebars[ $request['id'] ] = $request['widgets'];
204
205 wp_set_sidebars_widgets( $sidebars );
206 }
207
208 $request['context'] = 'edit';
209
210 $sidebar = $this->get_sidebar( $request['id'] );
211
212 return $this->prepare_item_for_response( $sidebar, $request );
213 }
214
215 /**
216 * Checks if the user has permissions to make the request.
217 *
218 * @since 5.6.0
219 *
220 * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
221 */
222 protected function do_permissions_check() {
223 // Verify if the current user has edit_theme_options capability.
224 // This capability is required to access the widgets screen.
225 if ( ! current_user_can( 'edit_theme_options' ) ) {
226 return new WP_Error(
227 'rest_cannot_manage_widgets',
228 __( 'Sorry, you are not allowed to manage widgets on this site.', 'gutenberg' ),
229 array( 'status' => rest_authorization_required_code() )
230 );
231 }
232
233 return true;
234 }
235
236 /**
237 * Retrieves the registered sidebar with the given id.
238 *
239 * @since 5.6.0
240 *
241 * @global array $wp_registered_sidebars The registered sidebars.
242 *
243 * @param string|int $id ID of the sidebar.
244 * @return array|null The discovered sidebar, or null if it is not registered.
245 */
246 protected function get_sidebar( $id ) {
247 global $wp_registered_sidebars;
248
249 foreach ( (array) $wp_registered_sidebars as $sidebar ) {
250 if ( $sidebar['id'] === $id ) {
251 return $sidebar;
252 }
253 }
254
255 if ( 'wp_inactive_widgets' === $id ) {
256 return array(
257 'id' => 'wp_inactive_widgets',
258 'name' => __( 'Inactive widgets', 'gutenberg' ),
259 );
260 }
261
262 return null;
263 }
264
265 /**
266 * Prepares a single sidebar output for response.
267 *
268 * @since 5.6.0
269 *
270 * @global array $wp_registered_sidebars The registered sidebars.
271 * @global array $wp_registered_widgets The registered widgets.
272 *
273 * @param array $raw_sidebar Sidebar instance.
274 * @param WP_REST_Request $request Full details about the request.
275 *
276 * @return WP_REST_Response Prepared response object.
277 */
278 public function prepare_item_for_response( $raw_sidebar, $request ) {
279 global $wp_registered_sidebars, $wp_registered_widgets;
280
281 $id = $raw_sidebar['id'];
282 $sidebar = array( 'id' => $id );
283
284 if ( isset( $wp_registered_sidebars[ $id ] ) ) {
285 $registered_sidebar = $wp_registered_sidebars[ $id ];
286
287 $sidebar['status'] = 'active';
288 $sidebar['name'] = isset( $registered_sidebar['name'] ) ? $registered_sidebar['name'] : '';
289 $sidebar['description'] = isset( $registered_sidebar['description'] ) ? $registered_sidebar['description'] : '';
290 $sidebar['class'] = isset( $registered_sidebar['class'] ) ? $registered_sidebar['class'] : '';
291 $sidebar['before_widget'] = isset( $registered_sidebar['before_widget'] ) ? $registered_sidebar['before_widget'] : '';
292 $sidebar['after_widget'] = isset( $registered_sidebar['after_widget'] ) ? $registered_sidebar['after_widget'] : '';
293 $sidebar['before_title'] = isset( $registered_sidebar['before_title'] ) ? $registered_sidebar['before_title'] : '';
294 $sidebar['after_title'] = isset( $registered_sidebar['after_title'] ) ? $registered_sidebar['after_title'] : '';
295 } else {
296 $sidebar['status'] = 'inactive';
297 $sidebar['name'] = $raw_sidebar['name'];
298 $sidebar['description'] = '';
299 $sidebar['class'] = '';
300 }
301
302 $fields = $this->get_fields_for_response( $request );
303 if ( rest_is_field_included( 'widgets', $fields ) ) {
304 $sidebars = wp_get_sidebars_widgets();
305 $widgets = array_filter(
306 isset( $sidebars[ $sidebar['id'] ] ) ? $sidebars[ $sidebar['id'] ] : array(),
307 static function ( $widget_id ) use ( $wp_registered_widgets ) {
308 return isset( $wp_registered_widgets[ $widget_id ] );
309 }
310 );
311
312 $sidebar['widgets'] = $widgets;
313 }
314
315 $schema = $this->get_item_schema();
316 $data = array();
317 foreach ( $schema['properties'] as $property_id => $property ) {
318 if ( isset( $sidebar[ $property_id ] ) && true === rest_validate_value_from_schema( $sidebar[ $property_id ], $property ) ) {
319 $data[ $property_id ] = $sidebar[ $property_id ];
320 } elseif ( isset( $property['default'] ) ) {
321 $data[ $property_id ] = $property['default'];
322 }
323 }
324
325 $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
326 $data = $this->add_additional_fields_to_object( $data, $request );
327 $data = $this->filter_response_by_context( $data, $context );
328
329 $response = rest_ensure_response( $data );
330
331 $response->add_links( $this->prepare_links( $sidebar ) );
332
333 /**
334 * Filters the REST API response for a sidebar.
335 *
336 * @since 5.6.0
337 *
338 * @param WP_REST_Response $response The response object.
339 * @param array $raw_sidebar The raw sidebar data.
340 * @param WP_REST_Request $request The request object.
341 */
342 return apply_filters( 'rest_prepare_sidebar', $response, $raw_sidebar, $request );
343 }
344
345 /**
346 * Prepares links for the sidebar.
347 *
348 * @since 5.6.0
349 *
350 * @param array $sidebar Sidebar.
351 *
352 * @return array Links for the given widget.
353 */
354 protected function prepare_links( $sidebar ) {
355 return array(
356 'collection' => array(
357 'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
358 ),
359 'self' => array(
360 'href' => rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $sidebar['id'] ) ),
361 ),
362 'https://api.w.org/widget' => array(
363 'href' => add_query_arg( 'sidebar', $sidebar['id'], rest_url( '/wp/v2/widgets' ) ),
364 'embeddable' => true,
365 ),
366 );
367 }
368
369 /**
370 * Retrieves the block type' schema, conforming to JSON Schema.
371 *
372 * @return array Item schema data.
373 */
374 public function get_item_schema() {
375 if ( $this->schema ) {
376 return $this->add_additional_fields_schema( $this->schema );
377 }
378
379 $schema = array(
380 '$schema' => 'http://json-schema.org/draft-04/schema#',
381 'title' => 'sidebar',
382 'type' => 'object',
383 'properties' => array(
384 'id' => array(
385 'description' => __( 'ID of sidebar.', 'gutenberg' ),
386 'type' => 'string',
387 'context' => array( 'embed', 'view', 'edit' ),
388 'readonly' => true,
389 ),
390 'name' => array(
391 'description' => __( 'Unique name identifying the sidebar.', 'gutenberg' ),
392 'type' => 'string',
393 'context' => array( 'embed', 'view', 'edit' ),
394 'readonly' => true,
395 ),
396 'description' => array(
397 'description' => __( 'Description of sidebar.', 'gutenberg' ),
398 'type' => 'string',
399 'context' => array( 'embed', 'view', 'edit' ),
400 'readonly' => true,
401 ),
402 'class' => array(
403 'description' => __( 'Extra CSS class to assign to the sidebar in the Widgets interface.', 'gutenberg' ),
404 'type' => 'string',
405 'context' => array( 'embed', 'view', 'edit' ),
406 'readonly' => true,
407 ),
408 'before_widget' => array(
409 'description' => __( 'HTML content to prepend to each widget\'s HTML output when assigned to this sidebar. Default is an opening list item element.', 'gutenberg' ),
410 'type' => 'string',
411 'default' => '',
412 'context' => array( 'embed', 'view', 'edit' ),
413 'readonly' => true,
414 ),
415 'after_widget' => array(
416 'description' => __( 'HTML content to append to each widget\'s HTML output when assigned to this sidebar. Default is a closing list item element.', 'gutenberg' ),
417 'type' => 'string',
418 'default' => '',
419 'context' => array( 'embed', 'view', 'edit' ),
420 'readonly' => true,
421 ),
422 'before_title' => array(
423 'description' => __( 'HTML content to prepend to the sidebar title when displayed. Default is an opening h2 element.', 'gutenberg' ),
424 'type' => 'string',
425 'default' => '',
426 'context' => array( 'embed', 'view', 'edit' ),
427 'readonly' => true,
428 ),
429 'after_title' => array(
430 'description' => __( 'HTML content to append to the sidebar title when displayed. Default is a closing h2 element.', 'gutenberg' ),
431 'type' => 'string',
432 'default' => '',
433 'context' => array( 'embed', 'view', 'edit' ),
434 'readonly' => true,
435 ),
436 'status' => array(
437 'description' => __( 'Status of sidebar.', 'gutenberg' ),
438 'type' => 'string',
439 'enum' => array( 'active', 'inactive' ),
440 'context' => array( 'embed', 'view', 'edit' ),
441 'readonly' => true,
442 ),
443 'widgets' => array(
444 'description' => __( 'Nested widgets.', 'gutenberg' ),
445 'type' => 'array',
446 'items' => array(
447 'type' => array( 'object', 'string' ),
448 ),
449 'default' => array(),
450 'context' => array( 'embed', 'view', 'edit' ),
451 ),
452 ),
453 );
454
455 $this->schema = $schema;
456
457 return $this->add_additional_fields_schema( $this->schema );
458 }
459 }
460