Changeset 60908
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php
r60893 r60908 544 544 * 545 545 * @since 5.5.0 546 * @since 6.9.0 Adds flips capability and editable fields for the newly-created attachment post. 546 547 * 547 548 * @param WP_REST_Request $request Full details about the request. … … 584 585 } else { 585 586 $modifiers = array(); 587 588 if ( isset( $request['flip']['horizontal'] ) || isset( $request['flip']['vertical'] ) ) { 589 $flip_args = array( 590 'vertical' => isset( $request['flip']['vertical'] ) ? (bool) $request['flip']['vertical'] : false, 591 'horizontal' => isset( $request['flip']['horizontal'] ) ? (bool) $request['flip']['horizontal'] : false, 592 ); 593 594 $modifiers[] = array( 595 'type' => 'flip', 596 'args' => array( 597 'flip' => $flip_args, 598 ), 599 ); 600 } 586 601 587 602 if ( ! empty( $request['rotation'] ) ) { … … 638 653 $args = $modifier['args']; 639 654 switch ( $modifier['type'] ) { 655 case 'flip': 656 /* 657 * Flips the current image. 658 * The vertical flip is the first argument (flip along horizontal axis), the horizontal flip is the second argument (flip along vertical axis). 659 * See: WP_Image_Editor::flip() 660 */ 661 $result = $image_editor->flip( $args['flip']['vertical'], $args['flip']['horizontal'] ); 662 if ( is_wp_error( $result ) ) { 663 return new WP_Error( 664 'rest_image_flip_failed', 665 __( 'Unable to flip this image.' ), 666 array( 'status' => 500 ) 667 ); 668 } 669 break; 640 670 case 'rotate': 641 671 // Rotation direction: clockwise vs. counterclockwise. … … 712 742 } 713 743 714 // Create new attachment post. 715 $new_attachment_post = array( 716 'post_mime_type' => $saved['mime-type'], 717 'guid' => $uploads['url'] . "/$filename", 718 'post_title' => $image_name, 719 'post_content' => '', 720 ); 721 722 // Copy post_content, post_excerpt, and post_title from the edited image's attachment post. 723 $attachment_post = get_post( $attachment_id ); 724 725 if ( $attachment_post ) { 726 $new_attachment_post['post_content'] = $attachment_post->post_content; 727 $new_attachment_post['post_excerpt'] = $attachment_post->post_excerpt; 728 $new_attachment_post['post_title'] = $attachment_post->post_title; 729 } 730 744 // Grab original attachment post so we can use it to set defaults. 745 $original_attachment_post = get_post( $attachment_id ); 746 747 // Check request fields and assign default values. 748 $new_attachment_post = $this->prepare_item_for_database( $request ); 749 $new_attachment_post->post_mime_type = $saved['mime-type']; 750 $new_attachment_post->guid = $uploads['url'] . "/$filename"; 751 752 // Unset ID so wp_insert_attachment generates a new ID. 753 unset( $new_attachment_post->ID ); 754 755 // Set new attachment post title with fallbacks. 756 $new_attachment_post->post_title = $new_attachment_post->post_title ?? $original_attachment_post->post_title ?? $image_name; 757 758 // Set new attachment post caption (post_excerpt). 759 $new_attachment_post->post_excerpt = $new_attachment_post->post_excerpt ?? $original_attachment_post->post_excerpt ?? ''; 760 761 // Set new attachment post description (post_content) with fallbacks. 762 $new_attachment_post->post_content = $new_attachment_post->post_content ?? $original_attachment_post->post_content ?? ''; 763 764 // Set post parent if set in request, else the default of `0` (no parent). 765 $new_attachment_post->post_parent = $new_attachment_post->post_parent ?? 0; 766 767 // Insert the new attachment post. 731 768 $new_attachment_id = wp_insert_attachment( wp_slash( $new_attachment_post ), $saved['path'], 0, true ); 732 769 … … 741 778 } 742 779 743 // Copy the image alt text from the edited image.744 $image_alt = get_post_meta( $attachment_id, '_wp_attachment_image_alt', true );780 // First, try to use the alt text from the request. If not set, copy the image alt text from the original attachment. 781 $image_alt = isset( $request['alt_text'] ) ? sanitize_text_field( $request['alt_text'] ) : get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ); 745 782 746 783 if ( ! empty( $image_alt ) ) { … … 1481 1518 * 1482 1519 * @since 5.5.0 1520 * @since 6.9.0 Adds flips capability and editable fields for the newly-created attachment post. 1483 1521 * 1484 1522 * @return array 1485 1523 */ 1486 1524 protected function get_edit_media_item_args() { 1487 returnarray(1525 $args = array( 1488 1526 'src' => array( 1489 1527 'description' => __( 'URL to the edited image file.' ), … … 1492 1530 'required' => true, 1493 1531 ), 1532 // The `modifiers` param takes precedence over the older format. 1494 1533 'modifiers' => array( 1495 1534 'description' => __( 'Array of image edits.' ), … … 1504 1543 ), 1505 1544 'oneOf' => array( 1545 array( 1546 'title' => __( 'Flip' ), 1547 'properties' => array( 1548 'type' => array( 1549 'description' => __( 'Flip type.' ), 1550 'type' => 'string', 1551 'enum' => array( 'flip' ), 1552 ), 1553 'args' => array( 1554 'description' => __( 'Flip arguments.' ), 1555 'type' => 'object', 1556 'required' => array( 1557 'flip', 1558 ), 1559 'properties' => array( 1560 'flip' => array( 1561 'description' => __( 'Flip direction.' ), 1562 'type' => 'object', 1563 'required' => array( 1564 'horizontal', 1565 'vertical', 1566 ), 1567 'properties' => array( 1568 'horizontal' => array( 1569 'description' => __( 'Whether to flip in the horizontal direction.' ), 1570 'type' => 'boolean', 1571 ), 1572 'vertical' => array( 1573 'description' => __( 'Whether to flip in the vertical direction.' ), 1574 'type' => 'boolean', 1575 ), 1576 ), 1577 ), 1578 ), 1579 ), 1580 ), 1581 ), 1506 1582 array( 1507 1583 'title' => __( 'Rotation' ), … … 1601 1677 ), 1602 1678 ); 1679 1680 /* 1681 * Get the args based on the post schema. This calls `rest_get_endpoint_args_for_schema()`, 1682 * which also takes care of sanitization and validation. 1683 */ 1684 $update_item_args = $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ); 1685 1686 if ( isset( $update_item_args['caption'] ) ) { 1687 $args['caption'] = $update_item_args['caption']; 1688 } 1689 1690 if ( isset( $update_item_args['description'] ) ) { 1691 $args['description'] = $update_item_args['description']; 1692 } 1693 1694 if ( isset( $update_item_args['title'] ) ) { 1695 $args['title'] = $update_item_args['title']; 1696 } 1697 1698 if ( isset( $update_item_args['post'] ) ) { 1699 $args['post'] = $update_item_args['post']; 1700 } 1701 1702 if ( isset( $update_item_args['alt_text'] ) ) { 1703 $args['alt_text'] = $update_item_args['alt_text']; 1704 } 1705 1706 return $args; 1603 1707 } 1604 1708 } -
trunk/tests/phpunit/tests/rest-api/rest-attachments-controller.php
r60893 r60908 2683 2683 $this->assertTrue( $result ); 2684 2684 } 2685 2686 /** 2687 * Tests that the attachment fields caption, description, and title, post and alt_text are updated correctly. 2688 * @ticket 64035 2689 * @requires function imagejpeg 2690 */ 2691 public function test_edit_image_updates_attachment_fields() { 2692 wp_set_current_user( self::$superadmin_id ); 2693 $attachment = self::factory()->attachment->create_upload_object( self::$test_file ); 2694 2695 // In order to test the edit endpoint editable fields, we need to create a new attachment. 2696 $params = array( 2697 'src' => wp_get_attachment_image_url( $attachment, 'full' ), 2698 'modifiers' => array( 2699 array( 2700 'type' => 'crop', 2701 'args' => array( 2702 'left' => 10, 2703 'top' => 10, 2704 'width' => 80, 2705 'height' => 80, 2706 ), 2707 ), 2708 ), 2709 'caption' => 'Test Caption', 2710 'description' => 'Test Description', 2711 'title' => 'Test Title', 2712 'post' => 1, 2713 'alt_text' => 'Test Alt Text', 2714 ); 2715 2716 $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment}/edit" ); 2717 $request->set_body_params( $params ); 2718 $response = rest_do_request( $request ); 2719 2720 // The edit endpoint creates a new attachment, so we expect a 201 status. 2721 $this->assertEquals( 201, $response->get_status() ); 2722 2723 $data = $response->get_data(); 2724 $new_attachment_id = $data['id']; 2725 2726 $updated_attachment = get_post( $new_attachment_id ); 2727 2728 $this->assertSame( 'Test Title', $updated_attachment->post_title, 'Title of the updated attachment is not identical.' ); 2729 2730 $this->assertSame( 'Test Caption', $updated_attachment->post_excerpt, 'Caption of the updated attachment is not identical.' ); 2731 2732 $this->assertSame( 'Test Description', $updated_attachment->post_content, 'Description of the updated attachment is not identical.' ); 2733 2734 $this->assertSame( 1, $updated_attachment->post_parent, 'Post parent of the updated attachment is not identical.' ); 2735 2736 $this->assertSame( 'Test Alt Text', get_post_meta( $new_attachment_id, '_wp_attachment_image_alt', true ), 'Alt text of the updated attachment is not identical.' ); 2737 } 2738 2739 /** 2740 * Tests that the image is flipped correctly vertically and horizontally. 2741 * 2742 * @ticket 64035 2743 * @requires function imagejpeg 2744 */ 2745 public function test_edit_image_vertical_and_horizontal_flip() { 2746 wp_set_current_user( self::$superadmin_id ); 2747 $attachment = self::factory()->attachment->create_upload_object( self::$test_file ); 2748 2749 $this->setup_mock_editor(); 2750 WP_Image_Editor_Mock::$edit_return['flip'] = new WP_Error(); 2751 2752 $params = array( 2753 'flip' => array( 2754 'vertical' => true, 2755 'horizontal' => true, 2756 ), 2757 'src' => wp_get_attachment_image_url( $attachment, 'full' ), 2758 ); 2759 2760 $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment}/edit" ); 2761 $request->set_body_params( $params ); 2762 $response = rest_do_request( $request ); 2763 $this->assertErrorResponse( 'rest_image_flip_failed', $response, 500 ); 2764 2765 $this->assertCount( 1, WP_Image_Editor_Mock::$spy['flip'] ); 2766 // The controller converts the integer values to booleans: 0 !== (int) 1 = true. 2767 $this->assertSame( array( true, true ), WP_Image_Editor_Mock::$spy['flip'][0], 'Vertical and horizontal flip of the image is not identical.' ); 2768 } 2769 2770 /** 2771 * Tests that the image is flipped correctly vertically only. 2772 * 2773 * @ticket 64035 2774 * @requires function imagejpeg 2775 */ 2776 public function test_edit_image_vertical_flip_with_horizontal_false() { 2777 wp_set_current_user( self::$superadmin_id ); 2778 $attachment = self::factory()->attachment->create_upload_object( self::$test_file ); 2779 2780 $this->setup_mock_editor(); 2781 WP_Image_Editor_Mock::$edit_return['flip'] = new WP_Error(); 2782 2783 $params = array( 2784 'flip' => array( 2785 'vertical' => true, 2786 'horizontal' => false, 2787 ), 2788 'src' => wp_get_attachment_image_url( $attachment, 'full' ), 2789 ); 2790 2791 $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment}/edit" ); 2792 $request->set_body_params( $params ); 2793 $response = rest_do_request( $request ); 2794 $this->assertErrorResponse( 'rest_image_flip_failed', $response, 500 ); 2795 2796 $this->assertCount( 1, WP_Image_Editor_Mock::$spy['flip'] ); 2797 // The controller converts the integer values to booleans: 0 !== (int) 1 = true. 2798 $this->assertSame( array( true, false ), WP_Image_Editor_Mock::$spy['flip'][0], 'Vertical flip of the image is not identical.' ); 2799 } 2800 2801 /** 2802 * Tests that the image is flipped correctly with only vertical flip in arguments. 2803 * 2804 * @ticket 64035 2805 * @requires function imagejpeg 2806 */ 2807 public function test_edit_image_vertical_flip_only() { 2808 wp_set_current_user( self::$superadmin_id ); 2809 $attachment = self::factory()->attachment->create_upload_object( self::$test_file ); 2810 2811 $this->setup_mock_editor(); 2812 WP_Image_Editor_Mock::$edit_return['flip'] = new WP_Error(); 2813 2814 $params = array( 2815 'flip' => array( 2816 'vertical' => true, 2817 ), 2818 'src' => wp_get_attachment_image_url( $attachment, 'full' ), 2819 ); 2820 2821 $request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment}/edit" ); 2822 $request->set_body_params( $params ); 2823 $response = rest_do_request( $request ); 2824 $this->assertErrorResponse( 'rest_image_flip_failed', $response, 500 ); 2825 2826 $this->assertCount( 1, WP_Image_Editor_Mock::$spy['flip'] ); 2827 // The controller converts the integer values to booleans: 0 !== (int) 1 = true. 2828 $this->assertSame( array( true, false ), WP_Image_Editor_Mock::$spy['flip'][0], 'Vertical flip of the image is not identical.' ); 2829 } 2685 2830 } -
trunk/tests/qunit/fixtures/wp-api-generated.js
r60404 r60908 3428 3428 ], 3429 3429 "oneOf": [ 3430 { 3431 "title": "Flip", 3432 "properties": { 3433 "type": { 3434 "description": "Flip type.", 3435 "type": "string", 3436 "enum": [ 3437 "flip" 3438 ] 3439 }, 3440 "args": { 3441 "description": "Flip arguments.", 3442 "type": "object", 3443 "required": [ 3444 "flip" 3445 ], 3446 "properties": { 3447 "flip": { 3448 "description": "Flip direction.", 3449 "type": "object", 3450 "required": [ 3451 "horizontal", 3452 "vertical" 3453 ], 3454 "properties": { 3455 "horizontal": { 3456 "description": "Whether to flip in the horizontal direction.", 3457 "type": "boolean" 3458 }, 3459 "vertical": { 3460 "description": "Whether to flip in the vertical direction.", 3461 "type": "boolean" 3462 } 3463 } 3464 } 3465 } 3466 } 3467 } 3468 }, 3430 3469 { 3431 3470 "title": "Rotation", … … 3532 3571 "minimum": 0, 3533 3572 "maximum": 100, 3573 "required": false 3574 }, 3575 "caption": { 3576 "description": "The attachment caption.", 3577 "type": "object", 3578 "properties": { 3579 "raw": { 3580 "description": "Caption for the attachment, as it exists in the database.", 3581 "type": "string", 3582 "context": [ 3583 "edit" 3584 ] 3585 }, 3586 "rendered": { 3587 "description": "HTML caption for the attachment, transformed for display.", 3588 "type": "string", 3589 "context": [ 3590 "view", 3591 "edit", 3592 "embed" 3593 ], 3594 "readonly": true 3595 } 3596 }, 3597 "required": false 3598 }, 3599 "description": { 3600 "description": "The attachment description.", 3601 "type": "object", 3602 "properties": { 3603 "raw": { 3604 "description": "Description for the attachment, as it exists in the database.", 3605 "type": "string", 3606 "context": [ 3607 "edit" 3608 ] 3609 }, 3610 "rendered": { 3611 "description": "HTML description for the attachment, transformed for display.", 3612 "type": "string", 3613 "context": [ 3614 "view", 3615 "edit" 3616 ], 3617 "readonly": true 3618 } 3619 }, 3620 "required": false 3621 }, 3622 "title": { 3623 "description": "The title for the post.", 3624 "type": "object", 3625 "properties": { 3626 "raw": { 3627 "description": "Title for the post, as it exists in the database.", 3628 "type": "string", 3629 "context": [ 3630 "edit" 3631 ] 3632 }, 3633 "rendered": { 3634 "description": "HTML title for the post, transformed for display.", 3635 "type": "string", 3636 "context": [ 3637 "view", 3638 "edit", 3639 "embed" 3640 ], 3641 "readonly": true 3642 } 3643 }, 3644 "required": false 3645 }, 3646 "post": { 3647 "description": "The ID for the associated post of the attachment.", 3648 "type": "integer", 3649 "required": false 3650 }, 3651 "alt_text": { 3652 "description": "Alternative text to display when attachment is not displayed.", 3653 "type": "string", 3534 3654 "required": false 3535 3655 }
Note: See TracChangeset
for help on using the changeset viewer.