PluginProbe
Gutenberg / 12.1.0
Gutenberg v12.1.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 12.1.0, at lib/class-wp-rest-sidebars-controller.php

464 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 retrieve_widgets();
120
121 $data = array();
122 foreach ( wp_get_sidebars_widgets() as $id => $widgets ) {
123 $sidebar = $this->get_sidebar( $id );
124
125 if ( ! $sidebar ) {
126 continue;
127 }
128
129 $data[] = $this->prepare_response_for_collection(
130 $this->prepare_item_for_response( $sidebar, $request )
131 );
132 }
133
134 return rest_ensure_response( $data );
135 }
136
137 /**
138 * Checks if a given request has access to get a single sidebar.
139 *
140 * @since 5.6.0
141 *
142 * @param WP_REST_Request $request Full details about the request.
143 * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
144 */
145 public function get_item_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
146 return $this->do_permissions_check();
147 }
148
149 /**
150 * Retrieves one sidebar from the collection.
151 *
152 * @since 5.6.0
153 *
154 * @param WP_REST_Request $request Full details about the request.
155 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
156 */
157 public function get_item( $request ) {
158 retrieve_widgets();
159
160 $sidebar = $this->get_sidebar( $request['id'] );
161
162 if ( ! $sidebar ) {
163 return new WP_Error( 'rest_sidebar_not_found', __( 'No sidebar exists with that id.', 'gutenberg' ), array( 'status' => 404 ) );
164 }
165
166 return $this->prepare_item_for_response( $sidebar, $request );
167 }
168
169 /**
170 * Checks if a given request has access to update sidebars.
171 *
172 * @since 5.6.0
173 *
174 * @param WP_REST_Request $request Full details about the request.
175 * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
176 */
177 public function update_item_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
178 return $this->do_permissions_check();
179 }
180
181 /**
182 * Updates a sidebar.
183 *
184 * @since 5.6.0
185 *
186 * @param WP_REST_Request $request Full details about the request.
187 * @return WP_REST_Response Response object on success, or WP_Error object on failure.
188 */
189 public function update_item( $request ) {
190 if ( isset( $request['widgets'] ) ) {
191 $sidebars = wp_get_sidebars_widgets();
192
193 foreach ( $sidebars as $sidebar_id => $widgets ) {
194 foreach ( $widgets as $i => $widget_id ) {
195 // This automatically removes the passed widget ids from any other sidebars in use.
196 if ( $sidebar_id !== $request['id'] && in_array( $widget_id, $request['widgets'], true ) ) {
197 unset( $sidebars[ $sidebar_id ][ $i ] );
198 }
199
200 // This automatically removes omitted widget ids to the inactive sidebar.
201 if ( $sidebar_id === $request['id'] && ! in_array( $widget_id, $request['widgets'], true ) ) {
202 $sidebars['wp_inactive_widgets'][] = $widget_id;
203 }
204 }
205 }
206
207 $sidebars[ $request['id'] ] = $request['widgets'];
208
209 wp_set_sidebars_widgets( $sidebars );
210 }
211
212 $request['context'] = 'edit';
213
214 $sidebar = $this->get_sidebar( $request['id'] );
215
216 return $this->prepare_item_for_response( $sidebar, $request );
217 }
218
219 /**
220 * Checks if the user has permissions to make the request.
221 *
222 * @since 5.6.0
223 *
224 * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
225 */
226 protected function do_permissions_check() {
227 // Verify if the current user has edit_theme_options capability.
228 // This capability is required to access the widgets screen.
229 if ( ! current_user_can( 'edit_theme_options' ) ) {
230 return new WP_Error(
231 'rest_cannot_manage_widgets',
232 __( 'Sorry, you are not allowed to manage widgets on this site.', 'gutenberg' ),
233 array( 'status' => rest_authorization_required_code() )
234 );
235 }
236
237 return true;
238 }
239
240 /**
241 * Retrieves the registered sidebar with the given id.
242 *
243 * @since 5.6.0
244 *
245 * @global array $wp_registered_sidebars The registered sidebars.
246 *
247 * @param string|int $id ID of the sidebar.
248 * @return array|null The discovered sidebar, or null if it is not registered.
249 */
250 protected function get_sidebar( $id ) {
251 global $wp_registered_sidebars;
252
253 foreach ( (array) $wp_registered_sidebars as $sidebar ) {
254 if ( $sidebar['id'] === $id ) {
255 return $sidebar;
256 }
257 }
258
259 if ( 'wp_inactive_widgets' === $id ) {
260 return array(
261 'id' => 'wp_inactive_widgets',
262 'name' => __( 'Inactive widgets', 'gutenberg' ),
263 );
264 }
265
266 return null;
267 }
268
269 /**
270 * Prepares a single sidebar output for response.
271 *
272 * @since 5.6.0
273 *
274 * @global array $wp_registered_sidebars The registered sidebars.
275 * @global array $wp_registered_widgets The registered widgets.
276 *
277 * @param array $raw_sidebar Sidebar instance.
278 * @param WP_REST_Request $request Full details about the request.
279 *
280 * @return WP_REST_Response Prepared response object.
281 */
282 public function prepare_item_for_response( $raw_sidebar, $request ) {
283 global $wp_registered_sidebars, $wp_registered_widgets;
284
285 $id = $raw_sidebar['id'];
286 $sidebar = array( 'id' => $id );
287
288 if ( isset( $wp_registered_sidebars[ $id ] ) ) {
289 $registered_sidebar = $wp_registered_sidebars[ $id ];
290
291 $sidebar['status'] = 'active';
292 $sidebar['name'] = isset( $registered_sidebar['name'] ) ? $registered_sidebar['name'] : '';
293 $sidebar['description'] = isset( $registered_sidebar['description'] ) ? $registered_sidebar['description'] : '';
294 $sidebar['class'] = isset( $registered_sidebar['class'] ) ? $registered_sidebar['class'] : '';
295 $sidebar['before_widget'] = isset( $registered_sidebar['before_widget'] ) ? $registered_sidebar['before_widget'] : '';
296 $sidebar['after_widget'] = isset( $registered_sidebar['after_widget'] ) ? $registered_sidebar['after_widget'] : '';
297 $sidebar['before_title'] = isset( $registered_sidebar['before_title'] ) ? $registered_sidebar['before_title'] : '';
298 $sidebar['after_title'] = isset( $registered_sidebar['after_title'] ) ? $registered_sidebar['after_title'] : '';
299 } else {
300 $sidebar['status'] = 'inactive';
301 $sidebar['name'] = $raw_sidebar['name'];
302 $sidebar['description'] = '';
303 $sidebar['class'] = '';
304 }
305
306 $fields = $this->get_fields_for_response( $request );
307 if ( rest_is_field_included( 'widgets', $fields ) ) {
308 $sidebars = wp_get_sidebars_widgets();
309 $widgets = array_filter(
310 isset( $sidebars[ $sidebar['id'] ] ) ? $sidebars[ $sidebar['id'] ] : array(),
311 static function ( $widget_id ) use ( $wp_registered_widgets ) {
312 return isset( $wp_registered_widgets[ $widget_id ] );
313 }
314 );
315
316 $sidebar['widgets'] = $widgets;
317 }
318
319 $schema = $this->get_item_schema();
320 $data = array();
321 foreach ( $schema['properties'] as $property_id => $property ) {
322 if ( isset( $sidebar[ $property_id ] ) && true === rest_validate_value_from_schema( $sidebar[ $property_id ], $property ) ) {
323 $data[ $property_id ] = $sidebar[ $property_id ];
324 } elseif ( isset( $property['default'] ) ) {
325 $data[ $property_id ] = $property['default'];
326 }
327 }
328
329 $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
330 $data = $this->add_additional_fields_to_object( $data, $request );
331 $data = $this->filter_response_by_context( $data, $context );
332
333 $response = rest_ensure_response( $data );
334
335 $response->add_links( $this->prepare_links( $sidebar ) );
336
337 /**
338 * Filters the REST API response for a sidebar.
339 *
340 * @since 5.6.0
341 *
342 * @param WP_REST_Response $response The response object.
343 * @param array $raw_sidebar The raw sidebar data.
344 * @param WP_REST_Request $request The request object.
345 */
346 return apply_filters( 'rest_prepare_sidebar', $response, $raw_sidebar, $request );
347 }
348
349 /**
350 * Prepares links for the sidebar.
351 *
352 * @since 5.6.0
353 *
354 * @param array $sidebar Sidebar.
355 *
356 * @return array Links for the given widget.
357 */
358 protected function prepare_links( $sidebar ) {
359 return array(
360 'collection' => array(
361 'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
362 ),
363 'self' => array(
364 'href' => rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $sidebar['id'] ) ),
365 ),
366 'https://api.w.org/widget' => array(
367 'href' => add_query_arg( 'sidebar', $sidebar['id'], rest_url( '/wp/v2/widgets' ) ),
368 'embeddable' => true,
369 ),
370 );
371 }
372
373 /**
374 * Retrieves the block type' schema, conforming to JSON Schema.
375 *
376 * @return array Item schema data.
377 */
378 public function get_item_schema() {
379 if ( $this->schema ) {
380 return $this->add_additional_fields_schema( $this->schema );
381 }
382
383 $schema = array(
384 '$schema' => 'http://json-schema.org/draft-04/schema#',
385 'title' => 'sidebar',
386 'type' => 'object',
387 'properties' => array(
388 'id' => array(
389 'description' => __( 'ID of sidebar.', 'gutenberg' ),
390 'type' => 'string',
391 'context' => array( 'embed', 'view', 'edit' ),
392 'readonly' => true,
393 ),
394 'name' => array(
395 'description' => __( 'Unique name identifying the sidebar.', 'gutenberg' ),
396 'type' => 'string',
397 'context' => array( 'embed', 'view', 'edit' ),
398 'readonly' => true,
399 ),
400 'description' => array(
401 'description' => __( 'Description of sidebar.', 'gutenberg' ),
402 'type' => 'string',
403 'context' => array( 'embed', 'view', 'edit' ),
404 'readonly' => true,
405 ),
406 'class' => array(
407 'description' => __( 'Extra CSS class to assign to the sidebar in the Widgets interface.', 'gutenberg' ),
408 'type' => 'string',
409 'context' => array( 'embed', 'view', 'edit' ),
410 'readonly' => true,
411 ),
412 'before_widget' => array(
413 'description' => __( 'HTML content to prepend to each widget\'s HTML output when assigned to this sidebar. Default is an opening list item element.', 'gutenberg' ),
414 'type' => 'string',
415 'default' => '',
416 'context' => array( 'embed', 'view', 'edit' ),
417 'readonly' => true,
418 ),
419 'after_widget' => array(
420 'description' => __( 'HTML content to append to each widget\'s HTML output when assigned to this sidebar. Default is a closing list item element.', 'gutenberg' ),
421 'type' => 'string',
422 'default' => '',
423 'context' => array( 'embed', 'view', 'edit' ),
424 'readonly' => true,
425 ),
426 'before_title' => array(
427 'description' => __( 'HTML content to prepend to the sidebar title when displayed. Default is an opening h2 element.', 'gutenberg' ),
428 'type' => 'string',
429 'default' => '',
430 'context' => array( 'embed', 'view', 'edit' ),
431 'readonly' => true,
432 ),
433 'after_title' => array(
434 'description' => __( 'HTML content to append to the sidebar title when displayed. Default is a closing h2 element.', 'gutenberg' ),
435 'type' => 'string',
436 'default' => '',
437 'context' => array( 'embed', 'view', 'edit' ),
438 'readonly' => true,
439 ),
440 'status' => array(
441 'description' => __( 'Status of sidebar.', 'gutenberg' ),
442 'type' => 'string',
443 'enum' => array( 'active', 'inactive' ),
444 'context' => array( 'embed', 'view', 'edit' ),
445 'readonly' => true,
446 ),
447 'widgets' => array(
448 'description' => __( 'Nested widgets.', 'gutenberg' ),
449 'type' => 'array',
450 'items' => array(
451 'type' => array( 'object', 'string' ),
452 ),
453 'default' => array(),
454 'context' => array( 'embed', 'view', 'edit' ),
455 ),
456 ),
457 );
458
459 $this->schema = $schema;
460
461 return $this->add_additional_fields_schema( $this->schema );
462 }
463 }
464