--- 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 );
}