diff -r 48c4eec2b7e6 -r 8c2e4d02f4ef wp/wp-includes/rest-api/class-wp-rest-server.php --- a/wp/wp-includes/rest-api/class-wp-rest-server.php Fri Sep 05 18:40:08 2025 +0200 +++ b/wp/wp-includes/rest-api/class-wp-rest-server.php Fri Sep 05 18:52:52 2025 +0200 @@ -636,7 +636,18 @@ foreach ( $items as $item ) { $attributes = $item['attributes']; $attributes['href'] = $item['href']; - $data[ $rel ][] = $attributes; + + if ( 'self' !== $rel ) { + $data[ $rel ][] = $attributes; + continue; + } + + $target_hints = self::get_target_hints_for_link( $attributes ); + if ( $target_hints ) { + $attributes['targetHints'] = $target_hints; + } + + $data[ $rel ][] = $attributes; } } @@ -644,6 +655,57 @@ } /** + * Gets the target links for a REST API Link. + * + * @since 6.7.0 + * + * @param array $link + * + * @return array|null + */ + protected static function get_target_hints_for_link( $link ) { + // Prefer targetHints that were specifically designated by the developer. + if ( isset( $link['targetHints']['allow'] ) ) { + return null; + } + + $request = WP_REST_Request::from_url( $link['href'] ); + if ( ! $request ) { + return null; + } + + $server = rest_get_server(); + $match = $server->match_request_to_handler( $request ); + + if ( is_wp_error( $match ) ) { + return null; + } + + if ( is_wp_error( $request->has_valid_params() ) ) { + return null; + } + + if ( is_wp_error( $request->sanitize_params() ) ) { + return null; + } + + $target_hints = array(); + + $response = new WP_REST_Response(); + $response->set_matched_route( $match[0] ); + $response->set_matched_handler( $match[1] ); + $headers = rest_send_allow_header( $response, $server, $request )->get_headers(); + + foreach ( $headers as $name => $value ) { + $name = WP_REST_Request::canonicalize_header_name( $name ); + + $target_hints[ $name ] = array_map( 'trim', explode( ',', $value ) ); + } + + return $target_hints; + } + + /** * Retrieves the CURIEs (compact URIs) used for relations. * * Extracts the links from a response into a structured hash, suitable for @@ -1309,6 +1371,9 @@ 'home' => home_url(), 'gmt_offset' => get_option( 'gmt_offset' ), 'timezone_string' => get_option( 'timezone_string' ), + 'page_for_posts' => (int) get_option( 'page_for_posts' ), + 'page_on_front' => (int) get_option( 'page_on_front' ), + 'show_on_front' => get_option( 'show_on_front' ), 'namespaces' => array_keys( $this->namespaces ), 'authentication' => array(), 'routes' => $this->get_data_for_routes( $this->get_routes(), $request['context'] ), @@ -1667,7 +1732,7 @@ $single_request = new WP_REST_Request( isset( $args['method'] ) ? $args['method'] : 'POST', $parsed_url['path'] ); if ( ! empty( $parsed_url['query'] ) ) { - $query_args = null; // Satisfy linter. + $query_args = array(); wp_parse_str( $parsed_url['query'], $query_args ); $single_request->set_query_params( $query_args ); }