Make WordPress Core


Ignore:
Timestamp:
10/06/2025 11:50:00 PM (11 months ago)
Author:
ramonopoly
Message:

Attachments REST API endpoint: update attachments controller to support flip and to customize attachment fields

This commit enhances media editor capabilities pursuant to the Phase 3: Collaboration > Media Library. See https://make.wordpress.org/core/2023/07/07/media-library/

It adds the following functionality:

  • the ability to flip an image horizontally and vertically
  • the ability to send arguments to update the new image's captiondescription, and titlepost and alt_text fields.

Props ramonopoly, mukesh27, isabel_brison, andrewserong.
Fixes #64035.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php

    r60893 r60908  
    544544         *
    545545         * @since 5.5.0
     546         * @since 6.9.0 Adds flips capability and editable fields for the newly-created attachment post.
    546547         *
    547548         * @param WP_REST_Request $request Full details about the request.
     
    584585                } else {
    585586                        $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                        }
    586601
    587602                        if ( ! empty( $request['rotation'] ) ) {
     
    638653                        $args = $modifier['args'];
    639654                        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;
    640670                                case 'rotate':
    641671                                        // Rotation direction: clockwise vs. counterclockwise.
     
    712742                }
    713743
    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.
    731768                $new_attachment_id = wp_insert_attachment( wp_slash( $new_attachment_post ), $saved['path'], 0, true );
    732769
     
    741778                }
    742779
    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 );
    745782
    746783                if ( ! empty( $image_alt ) ) {
     
    14811518         *
    14821519         * @since 5.5.0
     1520         * @since 6.9.0 Adds flips capability and editable fields for the newly-created attachment post.
    14831521         *
    14841522         * @return array
    14851523         */
    14861524        protected function get_edit_media_item_args() {
    1487                 return array(
     1525                $args = array(
    14881526                        'src'       => array(
    14891527                                'description' => __( 'URL to the edited image file.' ),
     
    14921530                                'required'    => true,
    14931531                        ),
     1532                        // The `modifiers` param takes precedence over the older format.
    14941533                        'modifiers' => array(
    14951534                                'description' => __( 'Array of image edits.' ),
     
    15041543                                        ),
    15051544                                        '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                                                ),
    15061582                                                array(
    15071583                                                        'title'      => __( 'Rotation' ),
     
    16011677                        ),
    16021678                );
     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;
    16031707        }
    16041708}
Note: See TracChangeset for help on using the changeset viewer.