Make WordPress Core

Changeset 50124

Timestamp:
02/01/2021 06:35:38 PM (3 years ago)
Author:
antpb
Message:

REST API, Media: Add batch image editing endpoints.

Introduces new endpoints to allow for batch image editing using the REST API.

The new endpoints can take an array of modifiers that will be applied in the order they appear.

Props ajlende, TimothyBlynJacobs, hellofromTonya, Mista-Flo.
Fixes #52192.

Location:
trunk
Files:
2 edited

Legend:

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

    r49731 r50124  
    449449        }
    450450
    451         // Check if we need to do anything.
    452         $rotate = 0;
    453         $crop   = false;
    454 
    455         if ( ! empty( $request['rotation'] ) ) {
    456             // Rotation direction: clockwise vs. counter clockwise.
    457             $rotate = 0 - (int) $request['rotation'];
    458         }
    459 
    460         if ( isset( $request['x'], $request['y'], $request['width'], $request['height'] ) ) {
    461             $crop = true;
    462         }
    463 
    464         if ( ! $rotate && ! $crop ) {
    465             return new WP_Error(
    466                 'rest_image_not_edited',
    467                 __( 'The image was not edited. Edit the image before applying the changes.' ),
    468                 array( 'status' => 400 )
    469             );
     451        // The `modifiers` param takes precedence over the older format.
     452        if ( isset( $request['modifiers'] ) ) {
     453            $modifiers = $request['modifiers'];
     454        } else {
     455            $modifiers = array();
     456
     457            if ( ! empty( $request['rotation'] ) ) {
     458                $modifiers[] = array(
     459                    'type' => 'rotate',
     460                    'args' => array(
     461                        'angle' => $request['rotation'],
     462                    ),
     463                );
     464            }
     465
     466            if ( isset( $request['x'], $request['y'], $request['width'], $request['height'] ) ) {
     467                $modifiers[] = array(
     468                    'type' => 'crop',
     469                    'args' => array(
     470                        'left'   => $request['x'],
     471                        'top'    => $request['y'],
     472                        'width'  => $request['width'],
     473                        'height' => $request['height'],
     474                    ),
     475                );
     476            }
     477
     478            if ( 0 === count( $modifiers ) ) {
     479                return new WP_Error(
     480                    'rest_image_not_edited',
     481                    __( 'The image was not edited. Edit the image before applying the changes.' ),
     482                    array( 'status' => 400 )
     483                );
     484            }
    470485        }
    471486
     
    490505        }
    491506
    492         if ( 0 !== $rotate ) {
    493             $result = $image_editor->rotate( $rotate );
    494 
    495             if ( is_wp_error( $result ) ) {
    496                 return new WP_Error(
    497                     'rest_image_rotation_failed',
    498                     __( 'Unable to rotate this image.' ),
    499                     array( 'status' => 500 )
    500                 );
    501             }
    502         }
    503 
    504         if ( $crop ) {
    505             $size = $image_editor->get_size();
    506 
    507             $crop_x = round( ( $size['width'] * (float) $request['x'] ) / 100.0 );
    508             $crop_y = round( ( $size['height'] * (float) $request['y'] ) / 100.0 );
    509             $width  = round( ( $size['width'] * (float) $request['width'] ) / 100.0 );
    510             $height = round( ( $size['height'] * (float) $request['height'] ) / 100.0 );
    511 
    512             $result = $image_editor->crop( $crop_x, $crop_y, $width, $height );
    513 
    514             if ( is_wp_error( $result ) ) {
    515                 return new WP_Error(
    516                     'rest_image_crop_failed',
    517                     __( 'Unable to crop this image.' ),
    518                     array( 'status' => 500 )
    519                 );
     507        foreach ( $modifiers as $modifier ) {
     508            $args = $modifier['args'];
     509            switch ( $modifier['type'] ) {
     510                case 'rotate':
     511                    // Rotation direction: clockwise vs. counter clockwise.
     512                    $rotate = 0 - $args['angle'];
     513
     514                    if ( 0 !== $rotate ) {
     515                        $result = $image_editor->rotate( $rotate );
     516
     517                        if ( is_wp_error( $result ) ) {
     518                            return new WP_Error(
     519                                'rest_image_rotation_failed',
     520                                __( 'Unable to rotate this image.' ),
     521                                array( 'status' => 500 )
     522                            );
     523                        }
     524                    }
     525
     526                    break;
     527
     528                case 'crop':
     529                    $size = $image_editor->get_size();
     530
     531                    $crop_x = round( ( $size['width'] * $args['left'] ) / 100.0 );
     532                    $crop_y = round( ( $size['height'] * $args['top'] ) / 100.0 );
     533                    $width  = round( ( $size['width'] * $args['width'] ) / 100.0 );
     534                    $height = round( ( $size['height'] * $args['height'] ) / 100.0 );
     535
     536                    if ( $size['width'] !== $width && $size['height'] !== $height ) {
     537                        $result = $image_editor->crop( $crop_x, $crop_y, $width, $height );
     538
     539                        if ( is_wp_error( $result ) ) {
     540                            return new WP_Error(
     541                                'rest_image_crop_failed',
     542                                __( 'Unable to crop this image.' ),
     543                                array( 'status' => 500 )
     544                            );
     545                        }
     546                    }
     547
     548                    break;
     549
    520550            }
    521551        }
     
    12871317    protected function get_edit_media_item_args() {
    12881318        return array(
    1289             'rotation' => array(
    1290                 'description'      => __( 'The amount to rotate the image clockwise in degrees.' ),
     1319            'src'       => array(
     1320                'description' => __( 'URL to the edited image file.' ),
     1321                'type'        => 'string',
     1322                'format'      => 'uri',
     1323                'required'    => true,
     1324            ),
     1325            'modifiers' => array(
     1326                'description' => __( 'Array of image edits.' ),
     1327                'type'        => 'array',
     1328                'minItems'    => 1,
     1329                'items'       => array(
     1330                    'description' => __( 'Image edit.' ),
     1331                    'type'        => 'object',
     1332                    'required'    => array(
     1333                        'type',
     1334                        'args',
     1335                    ),
     1336                    'oneOf'       => array(
     1337                        array(
     1338                            'title'       => __( 'Rotation' ),
     1339                            'properties'  => array(
     1340                                'type' => array(
     1341                                    'description' => __( 'Rotation type.' ),
     1342                                    'type'        => 'string',
     1343                                    'enum'        => array( 'rotate' ),
     1344                                ),
     1345                                'args' => array(
     1346                                    'description' => __( 'Rotation arguments.' ),
     1347                                    'type'        => 'object',
     1348                                    'required'    => array(
     1349                                        'angle',
     1350                                    ),
     1351                                    'properties'  => array(
     1352                                        'angle' => array(
     1353                                            'description' => __( 'Angle to rotate clockwise in degrees.' ),
     1354                                            'type'        => 'number',
     1355                                        ),
     1356                                    ),
     1357                                ),
     1358                            ),
     1359                        ),
     1360                        array(
     1361                            'title'       => __( 'Crop' ),
     1362                            'properties'  => array(
     1363                                'type' => array(
     1364                                    'description' => __( 'Crop type.' ),
     1365                                    'type'        => 'string',
     1366                                    'enum'        => array( 'crop' ),
     1367                                ),
     1368                                'args' => array(
     1369                                    'description' => __( 'Crop arguments.' ),
     1370                                    'type'        => 'object',
     1371                                    'required'    => array(
     1372                                        'left',
     1373                                        'top',
     1374                                        'width',
     1375                                        'height',
     1376                                    ),
     1377                                    'properties'  => array(
     1378                                        'left'   => array(
     1379                                            'description' => __( 'Horizontal position from the left to begin the crop as a percentage of the image width.' ),
     1380                                            'type'        => 'number',
     1381                                        ),
     1382                                        'top'    => array(
     1383                                            'description' => __( 'Vertical position from the top to begin the crop as a percentage of the image height.' ),
     1384                                            'type'        => 'number',
     1385                                        ),
     1386                                        'width'  => array(
     1387                                            'description' => __( 'Width of the crop as a percentage of the image width.' ),
     1388                                            'type'        => 'number',
     1389                                        ),
     1390                                        'height' => array(
     1391                                            'description' => __( 'Height of the crop as a percentage of the image height.' ),
     1392                                            'type'        => 'number',
     1393                                        ),
     1394                                    ),
     1395                                ),
     1396                            ),
     1397                        ),
     1398                    ),
     1399                ),
     1400            ),
     1401            'rotation'  => array(
     1402                'description'      => __( 'The amount to rotate the image clockwise in degrees. DEPRECATED: Use `modifiers` instead.' ),
    12911403                'type'             => 'integer',
    12921404                'minimum'          => 0,
     
    12951407                'exclusiveMaximum' => true,
    12961408            ),
    1297             'x'        => array(
    1298                 'description' => __( 'As a percentage of the image, the x position to start the crop from.' ),
     1409            'x'        => array(
     1410                'description' => __( 'As a percentage of the image, the x position to start the crop from.' ),
    12991411                'type'        => 'number',
    13001412                'minimum'     => 0,
    13011413                'maximum'     => 100,
    13021414            ),
    1303             'y'        => array(
    1304                 'description' => __( 'As a percentage of the image, the y position to start the crop from.' ),
     1415            'y'        => array(
     1416                'description' => __( 'As a percentage of the image, the y position to start the crop from.' ),
    13051417                'type'        => 'number',
    13061418                'minimum'     => 0,
    13071419                'maximum'     => 100,
    13081420            ),
    1309             'width'    => array(
    1310                 'description' => __( 'As a percentage of the image, the width to crop the image to.' ),
     1421            'width'    => array(
     1422                'description' => __( 'As a percentage of the image, the width to crop the image to.' ),
    13111423                'type'        => 'number',
    13121424                'minimum'     => 0,
    13131425                'maximum'     => 100,
    13141426            ),
    1315             'height'   => array(
    1316                 'description' => __( 'As a percentage of the image, the height to crop the image to.' ),
     1427            'height'   => array(
     1428                'description' => __( 'As a percentage of the image, the height to crop the image to.' ),
    13171429                'type'        => 'number',
    13181430                'minimum'     => 0,
    13191431                'maximum'     => 100,
    13201432            ),
    1321             'src'      => array(
    1322                 'description' => __( 'URL to the edited image file.' ),
    1323                 'type'        => 'string',
    1324                 'format'      => 'uri',
    1325                 'required'    => true,
    1326             ),
    13271433        );
    13281434    }
  • trunk/tests/phpunit/tests/rest-api/rest-attachments-controller.php

    r50024 r50124  
    20802080
    20812081    /**
     2082
     2083
     2084
     2085
     2086
     2087
     2088
     2089
     2090
     2091
     2092
     2093
     2094
     2095
     2096
     2097
     2098
     2099
     2100
     2101
     2102
     2103
     2104
     2105
     2106
     2107
     2108
     2109
     2110
     2111
     2112
     2113
     2114
     2115
     2116
     2117
     2118
     2119
     2120
     2121
     2122
     2123
     2124
    20822125     * @ticket 50565
    20832126     */
Note: See TracChangeset for help on using the changeset viewer.