diff -r be944660c56a -r 3d72ae0968f4 wp/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php --- a/wp/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php Wed Sep 21 18:19:35 2022 +0200 +++ b/wp/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php Tue Sep 27 16:37:53 2022 +0200 @@ -19,6 +19,14 @@ class WP_REST_Sidebars_Controller extends WP_REST_Controller { /** + * Tracks whether {@see retrieve_widgets()} has been called in the current request. + * + * @since 5.9.0 + * @var bool + */ + protected $widgets_retrieved = false; + + /** * Sidebars controller constructor. * * @since 5.8.0 @@ -86,6 +94,19 @@ * @return true|WP_Error True if the request has read access, WP_Error object otherwise. */ public function get_items_permissions_check( $request ) { + $this->retrieve_widgets(); + foreach ( wp_get_sidebars_widgets() as $id => $widgets ) { + $sidebar = $this->get_sidebar( $id ); + + if ( ! $sidebar ) { + continue; + } + + if ( $this->check_read_permission( $sidebar ) ) { + return true; + } + } + return $this->do_permissions_check(); } @@ -95,12 +116,14 @@ * @since 5.8.0 * * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + * @return WP_REST_Response Response object on success. */ public function get_items( $request ) { - retrieve_widgets(); + $this->retrieve_widgets(); - $data = array(); + $data = array(); + $permissions_check = $this->do_permissions_check(); + foreach ( wp_get_sidebars_widgets() as $id => $widgets ) { $sidebar = $this->get_sidebar( $id ); @@ -108,6 +131,10 @@ continue; } + if ( is_wp_error( $permissions_check ) && ! $this->check_read_permission( $sidebar ) ) { + continue; + } + $data[] = $this->prepare_response_for_collection( $this->prepare_item_for_response( $sidebar, $request ) ); @@ -125,10 +152,29 @@ * @return true|WP_Error True if the request has read access, WP_Error object otherwise. */ public function get_item_permissions_check( $request ) { + $this->retrieve_widgets(); + + $sidebar = $this->get_sidebar( $request['id'] ); + if ( $sidebar && $this->check_read_permission( $sidebar ) ) { + return true; + } + return $this->do_permissions_check(); } /** + * Checks if a sidebar can be read publicly. + * + * @since 5.9.0 + * + * @param array $sidebar The registered sidebar configuration. + * @return bool Whether the side can be read. + */ + protected function check_read_permission( $sidebar ) { + return ! empty( $sidebar['show_in_rest'] ); + } + + /** * Retrieves one sidebar from the collection. * * @since 5.8.0 @@ -137,10 +183,9 @@ * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. */ public function get_item( $request ) { - retrieve_widgets(); + $this->retrieve_widgets(); $sidebar = $this->get_sidebar( $request['id'] ); - if ( ! $sidebar ) { return new WP_Error( 'rest_sidebar_not_found', __( 'No sidebar exists with that id.' ), array( 'status' => 404 ) ); } @@ -174,12 +219,12 @@ foreach ( $sidebars as $sidebar_id => $widgets ) { foreach ( $widgets as $i => $widget_id ) { - // This automatically removes the passed widget ids from any other sidebars in use. + // This automatically removes the passed widget IDs from any other sidebars in use. if ( $sidebar_id !== $request['id'] && in_array( $widget_id, $request['widgets'], true ) ) { unset( $sidebars[ $sidebar_id ][ $i ] ); } - // This automatically removes omitted widget ids to the inactive sidebar. + // This automatically removes omitted widget IDs to the inactive sidebar. if ( $sidebar_id === $request['id'] && ! in_array( $widget_id, $request['widgets'], true ) ) { $sidebars['wp_inactive_widgets'][] = $widget_id; } @@ -234,47 +279,47 @@ * * @since 5.8.0 * - * @global array $wp_registered_sidebars The registered sidebars. - * * @param string|int $id ID of the sidebar. * @return array|null The discovered sidebar, or null if it is not registered. */ protected function get_sidebar( $id ) { - global $wp_registered_sidebars; - - foreach ( (array) $wp_registered_sidebars as $sidebar ) { - if ( $sidebar['id'] === $id ) { - return $sidebar; - } - } + return wp_get_sidebar( $id ); + } - if ( 'wp_inactive_widgets' === $id ) { - return array( - 'id' => 'wp_inactive_widgets', - 'name' => __( 'Inactive widgets' ), - ); + /** + * Looks for "lost" widgets once per request. + * + * @since 5.9.0 + * + * @see retrieve_widgets() + */ + protected function retrieve_widgets() { + if ( ! $this->widgets_retrieved ) { + retrieve_widgets(); + $this->widgets_retrieved = true; } - - return null; } /** * Prepares a single sidebar output for response. * * @since 5.8.0 + * @since 5.9.0 Renamed `$raw_sidebar` to `$item` to match parent class for PHP 8 named parameter support. * * @global array $wp_registered_sidebars The registered sidebars. * @global array $wp_registered_widgets The registered widgets. * - * @param array $raw_sidebar Sidebar instance. - * @param WP_REST_Request $request Full details about the request. + * @param array $item Sidebar instance. + * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response Prepared response object. */ - public function prepare_item_for_response( $raw_sidebar, $request ) { + public function prepare_item_for_response( $item, $request ) { global $wp_registered_sidebars, $wp_registered_widgets; - $id = $raw_sidebar['id']; - $sidebar = array( 'id' => $id ); + // Restores the more descriptive, specific name for use within this method. + $raw_sidebar = $item; + $id = $raw_sidebar['id']; + $sidebar = array( 'id' => $id ); if ( isset( $wp_registered_sidebars[ $id ] ) ) { $registered_sidebar = $wp_registered_sidebars[ $id ];