wp/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php
changeset 19 3d72ae0968f4
parent 18 be944660c56a
child 21 48c4eec2b7e6
--- 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 ];