From d82ff7ff299a3cb3148c368ef4e47d95ae4c1a6d Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Wed, 24 Sep 2025 12:23:35 +1000 Subject: [PATCH 1/5] Attachments/media endpoint: Add an embeddedable post as a link in attachments REST API response --- .../class-wp-rest-attachments-controller.php | 21 +++++++++++ .../rest-api/rest-attachments-controller.php | 37 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php index 589e0e2ccec17..a0586525bdda7 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php @@ -970,6 +970,27 @@ public function prepare_item_for_response( $item, $request ) { return apply_filters( 'rest_prepare_attachment', $response, $post, $request ); } + /** + * Prepares links for the request. + * + * @since 6.9.0 + * + * @param WP_Post $post Post object. + * @return array Links for the given attachment. + */ + protected function prepare_links( $post ) { + $links = parent::prepare_links( $post ); + + if ( ! empty( $post->post_parent ) ) { + $links['post'] = array( + 'href' => rest_url( rest_get_route_for_post( $post->post_parent ) ), + 'embeddable' => true, + ); + } + + return $links; + } + /** * Retrieves the attachment's schema, conforming to JSON Schema. * diff --git a/tests/phpunit/tests/rest-api/rest-attachments-controller.php b/tests/phpunit/tests/rest-api/rest-attachments-controller.php index d065238b8beb7..43fd090b42b4a 100644 --- a/tests/phpunit/tests/rest-api/rest-attachments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-attachments-controller.php @@ -1848,12 +1848,49 @@ public function test_links_exist() { $this->assertArrayHasKey( 'self', $links ); $this->assertArrayHasKey( 'author', $links ); + $this->assertArrayNotHasKey( 'post', $links ); $this->assertCount( 1, $links['author'] ); $this->assertArrayHasKey( 'embeddable', $links['author'][0]['attributes'] ); $this->assertTrue( $links['author'][0]['attributes']['embeddable'] ); } + public function test_links_contain_parent() { + wp_set_current_user( self::$editor_id ); + + $post = self::factory()->post->create( + array( + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_title' => 'Test Post', + ) + ); + $attachment = self::factory()->attachment->create_object( + array( + 'file' => self::$test_file, + 'post_author' => self::$editor_id, + 'post_parent' => $post, + 'post_mime_type' => 'image/jpeg', + ) + ); + + $this->assertGreaterThan( 0, $attachment ); + + $request = new WP_REST_Request( 'GET', "/wp/v2/media/{$attachment}" ); + $request->set_query_params( array( 'context' => 'edit' ) ); + + $response = rest_get_server()->dispatch( $request ); + $links = $response->get_links(); + + $this->assertArrayHasKey( 'self', $links ); + $this->assertArrayHasKey( 'author', $links ); + $this->assertArrayHasKey( 'post', $links ); + + $this->assertCount( 1, $links['author'] ); + $this->assertSame( "http://example.org/index.php?rest_route=/wp/v2/posts/{$post}", $links['post'][0]['href'] ); + $this->assertTrue( $links['post'][0]['attributes']['embeddable'] ); + } + public function test_publish_action_ldo_not_registered() { $response = rest_get_server()->dispatch( new WP_REST_Request( 'OPTIONS', '/wp/v2/media' ) ); From 5a0429e2c10b77b48890dde388d2e0b5a38bed00 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Wed, 24 Sep 2025 13:11:42 +1000 Subject: [PATCH 2/5] Make sure test plays nicely if the base url is different --- tests/phpunit/tests/rest-api/rest-attachments-controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/phpunit/tests/rest-api/rest-attachments-controller.php b/tests/phpunit/tests/rest-api/rest-attachments-controller.php index 43fd090b42b4a..df37128ea3d16 100644 --- a/tests/phpunit/tests/rest-api/rest-attachments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-attachments-controller.php @@ -1887,7 +1887,7 @@ public function test_links_contain_parent() { $this->assertArrayHasKey( 'post', $links ); $this->assertCount( 1, $links['author'] ); - $this->assertSame( "http://example.org/index.php?rest_route=/wp/v2/posts/{$post}", $links['post'][0]['href'] ); + $this->assertSame( rest_url( '/wp/v2/posts/' . $post ), $links['post'][0]['href'] ); $this->assertTrue( $links['post'][0]['attributes']['embeddable'] ); } From f756f5574aecbb3d06ad6fc1934c2bc85f7d7e67 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Thu, 25 Sep 2025 13:50:45 +1000 Subject: [PATCH 3/5] Add ticket number --- tests/phpunit/tests/rest-api/rest-attachments-controller.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/phpunit/tests/rest-api/rest-attachments-controller.php b/tests/phpunit/tests/rest-api/rest-attachments-controller.php index df37128ea3d16..1c4cefc025d3e 100644 --- a/tests/phpunit/tests/rest-api/rest-attachments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-attachments-controller.php @@ -1855,6 +1855,9 @@ public function test_links_exist() { $this->assertTrue( $links['author'][0]['attributes']['embeddable'] ); } + /** + * @ticket 64034 + */ public function test_links_contain_parent() { wp_set_current_user( self::$editor_id ); From 43d53b4e20994cae40298b3a713a424c8e2d15ec Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Mon, 29 Sep 2025 10:17:48 +1000 Subject: [PATCH 4/5] Update src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php Co-authored-by: Mukesh Panchal --- .../rest-api/endpoints/class-wp-rest-attachments-controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php index a0586525bdda7..a5e5340326737 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php @@ -971,7 +971,7 @@ public function prepare_item_for_response( $item, $request ) { } /** - * Prepares links for the request. + * Prepares attachment links for the request. * * @since 6.9.0 * From 770e64ed2aba178ac2267bd2e6d640cce48fde73 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Tue, 30 Sep 2025 15:02:41 +1000 Subject: [PATCH 5/5] Add id and post_type to links --- .../class-wp-rest-attachments-controller.php | 14 ++++++++++---- .../tests/rest-api/rest-attachments-controller.php | 2 ++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php index a5e5340326737..53b94bf43947b 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php @@ -982,10 +982,16 @@ protected function prepare_links( $post ) { $links = parent::prepare_links( $post ); if ( ! empty( $post->post_parent ) ) { - $links['post'] = array( - 'href' => rest_url( rest_get_route_for_post( $post->post_parent ) ), - 'embeddable' => true, - ); + $post = get_post( $post->post_parent ); + + if ( ! empty( $post ) ) { + $links['post'] = array( + 'href' => rest_url( rest_get_route_for_post( $post ) ), + 'embeddable' => true, + 'post_type' => $post->post_type, + 'id' => $post->ID, + ); + } } return $links; diff --git a/tests/phpunit/tests/rest-api/rest-attachments-controller.php b/tests/phpunit/tests/rest-api/rest-attachments-controller.php index 1c4cefc025d3e..3bc9f798e6d7e 100644 --- a/tests/phpunit/tests/rest-api/rest-attachments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-attachments-controller.php @@ -1891,6 +1891,8 @@ public function test_links_contain_parent() { $this->assertCount( 1, $links['author'] ); $this->assertSame( rest_url( '/wp/v2/posts/' . $post ), $links['post'][0]['href'] ); + $this->assertSame( 'post', $links['post'][0]['attributes']['post_type'] ); + $this->assertSame( $post, $links['post'][0]['attributes']['id'] ); $this->assertTrue( $links['post'][0]['attributes']['embeddable'] ); }