From f6e433b25032b700d1d1f6fc84f6b432173bfe20 Mon Sep 17 00:00:00 2001 From: Ryan McCue Date: Tue, 8 Nov 2016 04:28:47 +0000 Subject: [PATCH] REST API: Change attachment caption & description to objects. Just like excerpt and content for regular posts, these have transformations applied that can make the content significantly different from the raw value. Props jnylen0. Fixes #38679. git-svn-id: https://develop.svn.wordpress.org/trunk@39154 602fd350-edb4-49c9-b593-d223f7449a82 --- .../class-wp-rest-attachments-controller.php | 75 +++++++++++++++---- .../rest-api/rest-attachments-controller.php | 39 +++++++++- 2 files changed, 96 insertions(+), 18 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 9d8e7d438f..bcbd524560 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 @@ -247,12 +247,22 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller { protected function prepare_item_for_database( $request ) { $prepared_attachment = parent::prepare_item_for_database( $request ); + // Attachment caption (post_excerpt internally) if ( isset( $request['caption'] ) ) { - $prepared_attachment->post_excerpt = $request['caption']; + if ( is_string( $request['caption'] ) ) { + $prepared_attachment->post_excerpt = wp_filter_post_kses( $request['caption'] ); + } elseif ( isset( $request['caption']['raw'] ) ) { + $prepared_attachment->post_excerpt = wp_filter_post_kses( $request['caption']['raw'] ); + } } + // Attachment description (post_content internally) if ( isset( $request['description'] ) ) { - $prepared_attachment->post_content = $request['description']; + if ( is_string( $request['description'] ) ) { + $prepared_attachment->post_content = wp_filter_post_kses( $request['description'] ); + } elseif ( isset( $request['description']['raw'] ) ) { + $prepared_attachment->post_content = wp_filter_post_kses( $request['description']['raw'] ); + } } if ( isset( $request['post'] ) ) { @@ -276,9 +286,20 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller { $response = parent::prepare_item_for_response( $post, $request ); $data = $response->get_data(); + $data['description'] = array( + 'raw' => $post->post_content, + /** This filter is documented in wp-includes/post-template.php */ + 'rendered' => apply_filters( 'the_content', $post->post_content ), + ); + + /** This filter is documented in wp-includes/post-template.php */ + $caption = apply_filters( 'the_excerpt', apply_filters( 'get_the_excerpt', $post->post_excerpt, $post ) ); + $data['caption'] = array( + 'raw' => $post->post_excerpt, + 'rendered' => $caption, + ); + $data['alt_text'] = get_post_meta( $post->ID, '_wp_attachment_image_alt', true ); - $data['caption'] = $post->post_excerpt; - $data['description'] = $post->post_content; $data['media_type'] = wp_attachment_is_image( $post->ID ) ? 'image' : 'file'; $data['mime_type'] = $post->post_mime_type; $data['media_details'] = wp_get_attachment_metadata( $post->ID ); @@ -366,20 +387,46 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller { ); $schema['properties']['caption'] = array( - 'description' => __( 'The caption for the resource.' ), - 'type' => 'string', - 'context' => array( 'view', 'edit' ), - 'arg_options' => array( - 'sanitize_callback' => 'wp_filter_post_kses', + 'description' => __( 'The caption for the resource.' ), + 'type' => 'object', + 'context' => array( 'view', 'edit', 'embed' ), + 'arg_options' => array( + 'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database() + ), + 'properties' => array( + 'raw' => array( + 'description' => __( 'Caption for the resource, as it exists in the database.' ), + 'type' => 'string', + 'context' => array( 'edit' ), + ), + 'rendered' => array( + 'description' => __( 'HTML caption for the resource, transformed for display.' ), + 'type' => 'string', + 'context' => array( 'view', 'edit', 'embed' ), + 'readonly' => true, + ), ), ); $schema['properties']['description'] = array( - 'description' => __( 'The description for the resource.' ), - 'type' => 'string', - 'context' => array( 'view', 'edit' ), - 'arg_options' => array( - 'sanitize_callback' => 'wp_filter_post_kses', + 'description' => __( 'The description for the resource.' ), + 'type' => 'object', + 'context' => array( 'view', 'edit' ), + 'arg_options' => array( + 'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database() + ), + 'properties' => array( + 'raw' => array( + 'description' => __( 'Description for the object, as it exists in the database.' ), + 'type' => 'string', + 'context' => array( 'edit' ), + ), + 'rendered' => array( + 'description' => __( 'HTML description for the object, transformed for display.' ), + 'type' => 'string', + 'context' => array( 'view', 'edit' ), + 'readonly' => true, + ), ), ); diff --git a/tests/phpunit/tests/rest-api/rest-attachments-controller.php b/tests/phpunit/tests/rest-api/rest-attachments-controller.php index 3fceb44e4e..b84b0ccc16 100644 --- a/tests/phpunit/tests/rest-api/rest-attachments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-attachments-controller.php @@ -460,14 +460,31 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control public function test_create_item() { wp_set_current_user( self::$author_id ); + $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); $request->set_header( 'Content-Type', 'image/jpeg' ); $request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' ); + $request->set_param( 'title', 'My title is very cool' ); + $request->set_param( 'caption', 'This is a better caption.' ); + $request->set_param( 'description', 'Without a description, my attachment is descriptionless.' ); + $request->set_param( 'alt_text', 'Alt text is stored outside post schema.' ); + $request->set_body( file_get_contents( $this->test_file ) ); $response = $this->server->dispatch( $request ); $data = $response->get_data(); + $this->assertEquals( 201, $response->get_status() ); $this->assertEquals( 'image', $data['media_type'] ); + + $attachment = get_post( $data['id'] ); + $this->assertEquals( 'My title is very cool', $data['title']['raw'] ); + $this->assertEquals( 'My title is very cool', $attachment->post_title ); + $this->assertEquals( 'This is a better caption.', $data['caption']['raw'] ); + $this->assertEquals( 'This is a better caption.', $attachment->post_excerpt ); + $this->assertEquals( 'Without a description, my attachment is descriptionless.', $data['description']['raw'] ); + $this->assertEquals( 'Without a description, my attachment is descriptionless.', $attachment->post_content ); + $this->assertEquals( 'Alt text is stored outside post schema.', $data['alt_text'] ); + $this->assertEquals( 'Alt text is stored outside post schema.', get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ) ); } public function test_create_item_default_filename_title() { @@ -650,9 +667,9 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control $attachment = get_post( $data['id'] ); $this->assertEquals( 'My title is very cool', $data['title']['raw'] ); $this->assertEquals( 'My title is very cool', $attachment->post_title ); - $this->assertEquals( 'This is a better caption.', $data['caption'] ); + $this->assertEquals( 'This is a better caption.', $data['caption']['raw'] ); $this->assertEquals( 'This is a better caption.', $attachment->post_excerpt ); - $this->assertEquals( 'Without a description, my attachment is descriptionless.', $data['description'] ); + $this->assertEquals( 'Without a description, my attachment is descriptionless.', $data['description']['raw'] ); $this->assertEquals( 'Without a description, my attachment is descriptionless.', $attachment->post_content ); $this->assertEquals( 'Alt text is stored outside post schema.', $data['alt_text'] ); $this->assertEquals( 'Alt text is stored outside post schema.', get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ) ); @@ -775,7 +792,11 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control $this->assertArrayHasKey( 'author', $properties ); $this->assertArrayHasKey( 'alt_text', $properties ); $this->assertArrayHasKey( 'caption', $properties ); + $this->assertArrayHasKey( 'raw', $properties['caption']['properties'] ); + $this->assertArrayHasKey( 'rendered', $properties['caption']['properties'] ); $this->assertArrayHasKey( 'description', $properties ); + $this->assertArrayHasKey( 'raw', $properties['description']['properties'] ); + $this->assertArrayHasKey( 'rendered', $properties['description']['properties'] ); $this->assertArrayHasKey( 'comment_status', $properties ); $this->assertArrayHasKey( 'date', $properties ); $this->assertArrayHasKey( 'date_gmt', $properties ); @@ -794,6 +815,8 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control $this->assertArrayHasKey( 'slug', $properties ); $this->assertArrayHasKey( 'source_url', $properties ); $this->assertArrayHasKey( 'title', $properties ); + $this->assertArrayHasKey( 'raw', $properties['title']['properties'] ); + $this->assertArrayHasKey( 'rendered', $properties['title']['properties'] ); $this->assertArrayHasKey( 'type', $properties ); } @@ -891,9 +914,17 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control protected function check_post_data( $attachment, $data, $context = 'view', $links ) { parent::check_post_data( $attachment, $data, $context, $links ); + $this->assertArrayNotHasKey( 'content', $data ); + $this->assertArrayNotHasKey( 'excerpt', $data ); + $this->assertEquals( get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ), $data['alt_text'] ); - $this->assertEquals( $attachment->post_excerpt, $data['caption'] ); - $this->assertEquals( $attachment->post_content, $data['description'] ); + if ( 'edit' === $context ) { + $this->assertEquals( $attachment->post_excerpt, $data['caption']['raw'] ); + $this->assertEquals( $attachment->post_content, $data['description']['raw'] ); + } else { + $this->assertFalse( isset( $data['caption']['raw'] ) ); + $this->assertFalse( isset( $data['description']['raw'] ) ); + } $this->assertTrue( isset( $data['media_details'] ) ); if ( $attachment->post_parent ) {