PluginProbe
Gutenberg / 10.2.1
Gutenberg v10.2.1
24.0.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 All 403 releases
gutenberg / lib / class-wp-rest-widgets-controller.php

class-wp-rest-widgets-controller.php in Gutenberg 10.2.1, at lib/class-wp-rest-widgets-controller.php

816 lines 24.7 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_Widgets_Controller class
4 *
5 * @package WordPress
6 * @subpackage REST_API
7 * @since 5.6.0
8 */
9
10 /**
11 * Core class to access widgets via the REST API.
12 *
13 * @since 5.6.0
14 *
15 * @see WP_REST_Controller
16 */
17 class WP_REST_Widgets_Controller extends WP_REST_Controller {
18
19 /**
20 * Widgets controller constructor.
21 *
22 * @since 5.6.0
23 */
24 public function __construct() {
25 $this->namespace = 'wp/v2';
26 $this->rest_base = 'widgets';
27 }
28
29 /**
30 * Registers the widget routes for the controller.
31 *
32 * @since 5.6.0
33 */
34 public function register_routes() {
35 register_rest_route(
36 $this->namespace,
37 $this->rest_base,
38 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 array(
46 'methods' => WP_REST_Server::CREATABLE,
47 'callback' => array( $this, 'create_item' ),
48 'permission_callback' => array( $this, 'create_item_permissions_check' ),
49 'args' => $this->get_endpoint_args_for_item_schema(),
50 ),
51 'allow_batch' => array( 'v1' => true ),
52 'schema' => array( $this, 'get_public_item_schema' ),
53 )
54 );
55
56 register_rest_route(
57 $this->namespace,
58 $this->rest_base . '/(?P<id>[\w\-]+)',
59 array(
60 array(
61 'methods' => WP_REST_Server::READABLE,
62 'callback' => array( $this, 'get_item' ),
63 'permission_callback' => array( $this, 'get_item_permissions_check' ),
64 'args' => array(
65 'context' => $this->get_context_param( array( 'default' => 'view' ) ),
66 ),
67 ),
68 array(
69 'methods' => WP_REST_Server::EDITABLE,
70 'callback' => array( $this, 'update_item' ),
71 'permission_callback' => array( $this, 'update_item_permissions_check' ),
72 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
73 ),
74 array(
75 'methods' => WP_REST_Server::DELETABLE,
76 'callback' => array( $this, 'delete_item' ),
77 'permission_callback' => array( $this, 'delete_item_permissions_check' ),
78 'args' => array(
79 'force' => array(
80 'description' => __( 'Whether to force removal of the widget, or move it to the inactive sidebar.', 'gutenberg' ),
81 'type' => 'boolean',
82 ),
83 ),
84 ),
85 'allow_batch' => array( 'v1' => true ),
86 'schema' => array( $this, 'get_public_item_schema' ),
87 )
88 );
89 }
90
91 /**
92 * Checks if a given request has access to get widgets.
93 *
94 * @since 5.6.0
95 *
96 * @param WP_REST_Request $request Full details about the request.
97 * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
98 */
99 public function get_items_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
100 return $this->permissions_check();
101 }
102
103 /**
104 * Retrieves a collection of widgets.
105 *
106 * @since 5.6.0
107 *
108 * @param WP_REST_Request $request Full details about the request.
109 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
110 */
111 public function get_items( $request ) {
112 $prepared = array();
113
114 foreach ( wp_get_sidebars_widgets() as $sidebar_id => $widget_ids ) {
115 if ( isset( $request['sidebar'] ) && $sidebar_id !== $request['sidebar'] ) {
116 continue;
117 }
118
119 foreach ( $widget_ids as $widget_id ) {
120 $response = $this->prepare_item_for_response( compact( 'sidebar_id', 'widget_id' ), $request );
121
122 if ( ! is_wp_error( $response ) ) {
123 $prepared[] = $this->prepare_response_for_collection( $response );
124 }
125 }
126 }
127
128 return new WP_REST_Response( $prepared );
129 }
130
131 /**
132 * Checks if a given request has access to get a widget.
133 *
134 * @since 5.6.0
135 *
136 * @param WP_REST_Request $request Full details about the request.
137 * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
138 */
139 public function get_item_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
140 return $this->permissions_check();
141 }
142
143 /**
144 * Gets an individual widget.
145 *
146 * @since 5.6.0
147 *
148 * @param WP_REST_Request $request Full details about the request.
149 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
150 */
151 public function get_item( $request ) {
152 $widget_id = $request['id'];
153 $sidebar_id = $this->find_widgets_sidebar( $widget_id );
154
155 if ( is_wp_error( $sidebar_id ) ) {
156 return $sidebar_id;
157 }
158
159 return $this->prepare_item_for_response( compact( 'sidebar_id', 'widget_id' ), $request );
160 }
161
162 /**
163 * Checks if a given request has access to create widgets.
164 *
165 * @since 5.6.0
166 *
167 * @param WP_REST_Request $request Full details about the request.
168 * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
169 */
170 public function create_item_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
171 return $this->permissions_check();
172 }
173
174 /**
175 * Creates a widget.
176 *
177 * @since 5.6.0
178 *
179 * @param WP_REST_Request $request Full details about the request.
180 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
181 */
182 public function create_item( $request ) {
183 $sidebar_id = $request['sidebar'];
184
185 $backup_post = $_POST;
186 $widget_id = $this->save_widget( $request );
187 $_POST = $backup_post;
188
189 $this->assign_to_sidebar( $widget_id, $sidebar_id );
190
191 $request['context'] = 'edit';
192
193 $response = $this->prepare_item_for_response( compact( 'sidebar_id', 'widget_id' ), $request );
194
195 if ( is_wp_error( $response ) ) {
196 return $response;
197 }
198
199 $response->set_status( 201 );
200
201 return $response;
202 }
203
204 /**
205 * Checks if a given request has access to update widgets.
206 *
207 * @since 5.6.0
208 *
209 * @param WP_REST_Request $request Full details about the request.
210 * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
211 */
212 public function update_item_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
213 return $this->permissions_check();
214 }
215
216 /**
217 * Updates an existing widget.
218 *
219 * @since 5.6.0
220 *
221 * @param WP_REST_Request $request Full details about the request.
222 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
223 */
224 public function update_item( $request ) {
225 $widget_id = $request['id'];
226 $sidebar_id = $this->find_widgets_sidebar( $widget_id );
227
228 if ( is_wp_error( $sidebar_id ) ) {
229 // Allow for an update request to a reference widget if the widget hasn't been assigned to a sidebar yet.
230 if ( $request['sidebar'] && $this->is_reference_widget( $widget_id ) ) {
231 $sidebar_id = $request['sidebar'];
232 $this->assign_to_sidebar( $widget_id, $sidebar_id );
233 } else {
234 return $sidebar_id;
235 }
236 }
237
238 if ( isset( $request['settings'] ) ) {
239 $backup_post = $_POST;
240 $this->save_widget( $request );
241 $_POST = $backup_post;
242 }
243
244 if ( isset( $request['sidebar'] ) && $request['sidebar'] !== $sidebar_id ) {
245 $sidebar_id = $request['sidebar'];
246 $this->assign_to_sidebar( $widget_id, $sidebar_id );
247 }
248
249 $request['context'] = 'edit';
250
251 return $this->prepare_item_for_response( compact( 'sidebar_id', 'widget_id' ), $request );
252 }
253
254 /**
255 * Checks if a given request has access to delete widgets.
256 *
257 * @since 5.6.0
258 *
259 * @param WP_REST_Request $request Full details about the request.
260 * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
261 */
262 public function delete_item_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
263 return $this->permissions_check();
264 }
265
266 /**
267 * Deletes a widget.
268 *
269 * @since 5.6.0
270 *
271 * @param WP_REST_Request $request Full details about the request.
272 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
273 */
274 public function delete_item( $request ) {
275 $widget_id = $request['id'];
276 $sidebar_id = $this->find_widgets_sidebar( $widget_id );
277
278 if ( is_wp_error( $sidebar_id ) ) {
279 return $sidebar_id;
280 }
281
282 $request['context'] = 'edit';
283
284 if ( $request['force'] ) {
285 $prepared = $this->prepare_item_for_response( compact( 'sidebar_id', 'widget_id' ), $request );
286 $this->assign_to_sidebar( $widget_id, '' );
287 $prepared->set_data(
288 array(
289 'deleted' => true,
290 'previous' => $prepared->get_data(),
291 )
292 );
293 } else {
294 $this->assign_to_sidebar( $widget_id, 'wp_inactive_widgets' );
295 $prepared = $this->prepare_item_for_response(
296 array(
297 'sidebar_id' => 'wp_inactive_widgets',
298 'widget_id' => $widget_id,
299 ),
300 $request
301 );
302 }
303
304 return $prepared;
305 }
306
307 /**
308 * Assigns a widget to the given sidebar.
309 *
310 * @since 5.6.0
311 *
312 * @param string $widget_id The widget id to assign.
313 * @param string $sidebar_id The sidebar id to assign to. If empty, the widget won't be added to any sidebar.
314 */
315 protected function assign_to_sidebar( $widget_id, $sidebar_id ) {
316 $sidebars = wp_get_sidebars_widgets();
317
318 foreach ( $sidebars as $maybe_sidebar_id => $widgets ) {
319 foreach ( $widgets as $i => $maybe_widget_id ) {
320 if ( $widget_id === $maybe_widget_id && $sidebar_id !== $maybe_sidebar_id ) {
321 unset( $sidebars[ $maybe_sidebar_id ][ $i ] );
322 // We could technically break 2 here, but continue looping in case the id is duplicated.
323 continue 2;
324 }
325 }
326 }
327
328 if ( $sidebar_id ) {
329 $sidebars[ $sidebar_id ][] = $widget_id;
330 }
331
332 wp_set_sidebars_widgets( $sidebars );
333 }
334
335 /**
336 * Performs a permissions check for managing widgets.
337 *
338 * @since 5.6.0
339 *
340 * @return true|WP_Error
341 */
342 protected function permissions_check() {
343 if ( ! current_user_can( 'edit_theme_options' ) ) {
344 return new WP_Error(
345 'rest_cannot_manage_widgets',
346 __( 'Sorry, you are not allowed to manage widgets on this site.', 'gutenberg' ),
347 array(
348 'status' => rest_authorization_required_code(),
349 )
350 );
351 }
352
353 return true;
354 }
355
356 /**
357 * Finds the sidebar a widget belongs to.
358 *
359 * @since 5.6.0
360 *
361 * @param string $widget_id The widget id to search for.
362 * @return string|WP_Error The found sidebar id, or a WP_Error instance if it does not exist.
363 */
364 protected function find_widgets_sidebar( $widget_id ) {
365 foreach ( wp_get_sidebars_widgets() as $sidebar_id => $widget_ids ) {
366 foreach ( $widget_ids as $maybe_widget_id ) {
367 if ( $maybe_widget_id === $widget_id ) {
368 return (string) $sidebar_id;
369 }
370 }
371 }
372
373 return new WP_Error( 'rest_widget_not_found', __( 'No widget was found with that id.', 'gutenberg' ), array( 'status' => 404 ) );
374 }
375
376 /**
377 * Saves the widget in the request object.
378 *
379 * @since 5.6.0
380 *
381 * @param WP_REST_Request $request Full details about the request.
382 *
383 * @return string The saved widget ID.
384 */
385 protected function save_widget( $request ) {
386 global $wp_registered_widget_updates, $wp_registered_widgets;
387
388 $input_widget = $request->get_params();
389
390 if ( isset( $input_widget['id'] ) && ! $this->is_reference_widget( $input_widget['id'] ) ) {
391 $widget = $wp_registered_widgets[ $input_widget['id'] ];
392
393 $input_widget['number'] = (int) $widget['params'][0]['number'];
394 $input_widget['id_base'] = _get_widget_id_base( $input_widget['id'] );
395 }
396
397 ob_start();
398 if ( isset( $input_widget['id_base'] ) && isset( $wp_registered_widget_updates[ $input_widget['id_base'] ] ) ) {
399 // Class-based widget.
400 $update_control = $wp_registered_widget_updates[ $input_widget['id_base'] ];
401 if ( ! isset( $input_widget['id'] ) ) {
402 $number = $this->get_last_number_for_widget( $input_widget['id_base'] ) + 1;
403 $id = $input_widget['id_base'] . '-' . $number;
404
405 $input_widget['id'] = $id;
406 $input_widget['number'] = $number;
407 }
408 $field = 'widget-' . $input_widget['id_base'];
409 $number = $input_widget['number'];
410 $_POST = $input_widget;
411 $_POST[ $field ][ $number ] = wp_slash( $input_widget['settings'] );
412 call_user_func( $update_control['callback'] );
413 $update_control['callback'][0]->updated = false;
414
415 // Just because we saved new widget doesn't mean it was added to $wp_registered_widgets.
416 // Let's make sure it's there so that it's included in the response.
417 if ( ! isset( $wp_registered_widgets[ $input_widget['id'] ] ) || 1 === $number ) {
418 $widget_class = get_class( $update_control['callback'][0] );
419 $new_object = new $widget_class(
420 $input_widget['id_base'],
421 $input_widget['name'],
422 $input_widget['settings']
423 );
424 $new_object->_set( $number );
425 $new_object->_register();
426 }
427 } else {
428 $registered_widget_id = null;
429 if ( isset( $wp_registered_widget_updates[ $input_widget['id'] ] ) ) {
430 $registered_widget_id = $input_widget['id'];
431 } else {
432 $numberless_id = substr( $input_widget['id'], 0, strrpos( $input_widget['id'], '-' ) );
433 if ( isset( $wp_registered_widget_updates[ $numberless_id ] ) ) {
434 $registered_widget_id = $numberless_id;
435 }
436 }
437
438 if ( $registered_widget_id ) {
439 // Old-style widget.
440 $update_control = $wp_registered_widget_updates[ $registered_widget_id ];
441 $_POST = wp_slash( $input_widget['settings'] );
442 call_user_func( $update_control['callback'] );
443 }
444 }
445 ob_end_clean();
446
447 return $input_widget['id'];
448 }
449
450 /**
451 * Gets the last number used by the given widget.
452 *
453 * @since 5.6.0
454 *
455 * @global array $wp_registered_widget_updates List of widget update callbacks.
456 *
457 * @param string $id_base The widget id base.
458 * @return int The last number, or zero if the widget has not been used.
459 */
460 protected function get_last_number_for_widget( $id_base ) {
461 global $wp_registered_widget_updates;
462
463 if ( ! is_array( $wp_registered_widget_updates[ $id_base ]['callback'] ) ) {
464 return 0;
465 }
466
467 if ( ! $wp_registered_widget_updates[ $id_base ]['callback'][0] instanceof WP_Widget ) {
468 return 0;
469 }
470
471 $widget = $wp_registered_widget_updates[ $id_base ]['callback'][0];
472 $instances = array_filter( $widget->get_settings(), 'is_numeric', ARRAY_FILTER_USE_KEY );
473
474 if ( ! $instances ) {
475 return 0;
476 }
477
478 return $widget->number;
479 }
480
481 /**
482 * Prepares the widget for the REST response.
483 *
484 * @since 5.6.0
485 *
486 * @global array $wp_registered_sidebars The registered sidebars.
487 * @global array $wp_registered_widgets The registered widgets.
488 * @global array $wp_registered_widget_controls The registered widget controls.
489 *
490 * @param array $item An array containing a widget_id and sidebar_id.
491 * @param WP_REST_Request $request Request object.
492 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
493 */
494 public function prepare_item_for_response( $item, $request ) {
495 global $wp_registered_widgets, $wp_registered_sidebars, $wp_registered_widget_controls;
496
497 $widget_id = $item['widget_id'];
498 $sidebar_id = $item['sidebar_id'];
499
500 if ( ! isset( $wp_registered_widgets[ $widget_id ] ) ) {
501 return new WP_Error( 'rest_invalid_widget', __( 'The requested widget is invalid.', 'gutenberg' ), array( 'status' => 500 ) );
502 }
503
504 $fields = $this->get_fields_for_response( $request );
505
506 if ( isset( $wp_registered_sidebars[ $sidebar_id ] ) ) {
507 $registered_sidebar = $wp_registered_sidebars[ $sidebar_id ];
508 } elseif ( 'wp_inactive_widgets' === $sidebar_id ) {
509 $registered_sidebar = array();
510 } else {
511 $registered_sidebar = null;
512 }
513
514 $widget = $wp_registered_widgets[ $widget_id ];
515 $prepared = array(
516 'id' => $widget_id,
517 'id_base' => '',
518 'sidebar' => $sidebar_id,
519 'widget_class' => '',
520 'name' => $widget['name'],
521 'description' => ! empty( $widget['description'] ) ? $widget['description'] : '',
522 'number' => 0,
523 'rendered' => '',
524 'rendered_form' => '',
525 'settings' => array(),
526 );
527
528 // Get the widget output.
529 if ( is_callable( $widget['callback'] ) && rest_is_field_included( 'rendered', $fields ) && 'wp_inactive_widgets' !== $sidebar_id ) {
530 // @note: everything up to ob_start is taken from the dynamic_sidebar function.
531 $widget_parameters = array_merge(
532 array(
533 array_merge(
534 (array) $registered_sidebar,
535 array(
536 'widget_id' => $widget_id,
537 'widget_name' => $widget['name'],
538 )
539 ),
540 ),
541 (array) $widget['params']
542 );
543
544 $classname = '';
545 foreach ( (array) $widget['classname'] as $cn ) {
546 if ( is_string( $cn ) ) {
547 $classname .= '_' . $cn;
548 } elseif ( is_object( $cn ) ) {
549 $classname .= '_' . get_class( $cn );
550 }
551 }
552 $classname = ltrim( $classname, '_' );
553 if ( isset( $widget_parameters[0]['before_widget'] ) ) {
554 $widget_parameters[0]['before_widget'] = sprintf(
555 $widget_parameters[0]['before_widget'],
556 $widget_id,
557 $classname
558 );
559 }
560
561 ob_start();
562 call_user_func_array( $widget['callback'], $widget_parameters );
563 $prepared['rendered'] = trim( ob_get_clean() );
564 }
565
566 if ( is_array( $widget['callback'] ) && isset( $widget['callback'][0] ) ) {
567 $instance = $widget['callback'][0];
568 $prepared['widget_class'] = get_class( $instance );
569 $prepared['settings'] = $this->get_sidebar_widget_instance(
570 $registered_sidebar,
571 $widget_id
572 );
573 $prepared['number'] = (int) $widget['params'][0]['number'];
574 $prepared['id_base'] = $instance->id_base;
575 }
576
577 if (
578 rest_is_field_included( 'rendered_form', $fields ) &&
579 isset( $wp_registered_widget_controls[ $widget_id ]['callback'] )
580 ) {
581 $control = $wp_registered_widget_controls[ $widget_id ];
582 $arguments = array();
583 if ( ! empty( $prepared['number'] ) ) {
584 $arguments[0] = array( 'number' => $prepared['number'] );
585 }
586 ob_start();
587 call_user_func_array( $control['callback'], $arguments );
588 $prepared['rendered_form'] = trim( ob_get_clean() );
589 }
590
591 $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
592 $prepared = $this->add_additional_fields_to_object( $prepared, $request );
593 $prepared = $this->filter_response_by_context( $prepared, $context );
594
595 $response = rest_ensure_response( $prepared );
596
597 $response->add_links( $this->prepare_links( $prepared ) );
598
599 /**
600 * Filters the REST API response for a widget.
601 *
602 * @since 5.6.0
603 *
604 * @param WP_REST_Response $response The response object.
605 * @param array $widget The registered widget data.
606 * @param WP_REST_Request $request Request used to generate the response.
607 */
608 return apply_filters( 'rest_prepare_widget', $response, $widget, $request );
609 }
610
611 /**
612 * Prepares links for the widget.
613 *
614 * @since 5.6.0
615 *
616 * @param array $prepared Widget.
617 * @return array Links for the given widget.
618 */
619 protected function prepare_links( $prepared ) {
620 $id_base = ! empty( $prepared['id_base'] ) ? $prepared['id_base'] : $prepared['id'];
621
622 return array(
623 'self' => array(
624 'href' => rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $prepared['id'] ) ),
625 ),
626 'collection' => array(
627 'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
628 ),
629 'about' => array(
630 'href' => rest_url( sprintf( 'wp/v2/widget-types/%s', $id_base ) ),
631 'embeddable' => true,
632 ),
633 'https://api.w.org/sidebar' => array(
634 'href' => rest_url( sprintf( 'wp/v2/sidebars/%s/', $prepared['sidebar'] ) ),
635 ),
636 );
637 }
638
639 /**
640 * Retrieves a widget instance.
641 *
642 * @since 5.6.0
643 *
644 * @param array $sidebar The sidebar data registered with {@see register_sidebar()}.
645 * @param string $id Identifier of the widget instance.
646 * @return array Array containing the widget instance.
647 */
648 protected function get_sidebar_widget_instance( $sidebar, $id ) {
649 list( $object, $number, $name ) = $this->get_widget_info( $id );
650 if ( ! $object ) {
651 return array();
652 }
653
654 $object->_set( $number );
655
656 $instances = $object->get_settings();
657 $instance = $instances[ $number ];
658
659 $args = array_merge(
660 is_array( $sidebar ) ? $sidebar : array(),
661 array(
662 'widget_id' => $id,
663 'widget_name' => $name,
664 )
665 );
666
667 /** This filter is documented in wp-includes/class-wp-widget.php */
668 $instance = apply_filters( 'widget_display_callback', $instance, $object, $args );
669
670 if ( false === $instance ) {
671 return array();
672 }
673
674 return $instance;
675 }
676
677 /**
678 * Returns an array containing information about the requested widget.
679 *
680 * @since 5.6.0
681 *
682 * @global array $wp_registered_widgets The list of reigstered widgets.
683 *
684 * @param string $widget_id Identifier of the widget.
685 * @return array Array containing the the widget object, the number, and the name.
686 */
687 protected function get_widget_info( $widget_id ) {
688 global $wp_registered_widgets;
689
690 if (
691 ! is_array( $wp_registered_widgets[ $widget_id ]['callback'] ) ||
692 ! isset( $wp_registered_widgets[ $widget_id ]['callback'][0] ) ||
693 ! isset( $wp_registered_widgets[ $widget_id ]['params'][0]['number'] ) ||
694 ! isset( $wp_registered_widgets[ $widget_id ]['name'] ) ||
695 ! ( $wp_registered_widgets[ $widget_id ]['callback'][0] instanceof WP_Widget )
696 ) {
697 return array( null, null, null );
698 }
699
700 $object = $wp_registered_widgets[ $widget_id ]['callback'][0];
701 $number = $wp_registered_widgets[ $widget_id ]['params'][0]['number'];
702 $name = $wp_registered_widgets[ $widget_id ]['name'];
703
704 return array( $object, $number, $name );
705 }
706
707 /**
708 * Checks if the given widget id is a reference widget, ie one that does not use WP_Widget.
709 *
710 * @since 5.6.0
711 *
712 * @param string $widget_id The widget id to check.
713 * @return bool Whether this is a reference widget or not.
714 */
715 protected function is_reference_widget( $widget_id ) {
716 list ( $object ) = $this->get_widget_info( $widget_id );
717
718 return ! $object instanceof WP_Widget;
719 }
720
721 /**
722 * Gets the list of collection params.
723 *
724 * @since 5.6.0
725 *
726 * @return array[]
727 */
728 public function get_collection_params() {
729 return array(
730 'context' => $this->get_context_param( array( 'default' => 'view' ) ),
731 'sidebar' => array(
732 'description' => __( 'The sidebar to return widgets for.', 'gutenberg' ),
733 'type' => 'string',
734 ),
735 );
736 }
737
738 /**
739 * Retrieves the widget's schema, conforming to JSON Schema.
740 *
741 * @since 5.6.0
742 *
743 * @return array Item schema data.
744 */
745 public function get_item_schema() {
746 if ( $this->schema ) {
747 return $this->add_additional_fields_schema( $this->schema );
748 }
749
750 $this->schema = array(
751 '$schema' => 'http://json-schema.org/draft-04/schema#',
752 'title' => 'widget',
753 'type' => 'object',
754 'properties' => array(
755 'id' => array(
756 'description' => __( 'Unique identifier for the widget.', 'gutenberg' ),
757 'type' => 'string',
758 'context' => array( 'view', 'edit', 'embed' ),
759 ),
760 'id_base' => array(
761 'description' => __( 'Type of widget for the object.', 'gutenberg' ),
762 'type' => 'string',
763 'context' => array( 'view', 'edit', 'embed' ),
764 ),
765 'sidebar' => array(
766 'description' => __( 'The sidebar the widget belongs to.', 'gutenberg' ),
767 'type' => 'string',
768 'default' => 'wp_inactive_widgets',
769 'required' => true,
770 'context' => array( 'view', 'edit', 'embed' ),
771 ),
772 'widget_class' => array(
773 'description' => __( 'Class name of the widget implementation.', 'gutenberg' ),
774 'type' => 'string',
775 'context' => array( 'view', 'edit', 'embed' ),
776 ),
777 'name' => array(
778 'description' => __( 'Name of the widget.', 'gutenberg' ),
779 'type' => 'string',
780 'context' => array( 'view', 'edit', 'embed' ),
781 ),
782 'description' => array(
783 'description' => __( 'Description of the widget.', 'gutenberg' ),
784 'type' => 'string',
785 'context' => array( 'view', 'edit', 'embed' ),
786 ),
787 'number' => array(
788 'description' => __( 'Number of the widget.', 'gutenberg' ),
789 'type' => 'integer',
790 'context' => array( 'view', 'edit', 'embed' ),
791 ),
792 'rendered' => array(
793 'description' => __( 'HTML representation of the widget.', 'gutenberg' ),
794 'type' => 'string',
795 'context' => array( 'view', 'edit', 'embed' ),
796 'readonly' => true,
797 ),
798 'rendered_form' => array(
799 'description' => __( 'HTML representation of the widget admin form.', 'gutenberg' ),
800 'type' => 'string',
801 'context' => array( 'edit' ),
802 'readonly' => true,
803 ),
804 'settings' => array(
805 'description' => __( 'Settings of the widget.', 'gutenberg' ),
806 'type' => 'object',
807 'context' => array( 'view', 'edit', 'embed' ),
808 'default' => array(),
809 ),
810 ),
811 );
812
813 return $this->add_additional_fields_schema( $this->schema );
814 }
815 }
816