]> scripts.mit.edu Git - autoinstalls/wordpress.git/blobdiff - wp-admin/includes/image-edit.php
WordPress 4.6.3
[autoinstalls/wordpress.git] / wp-admin / includes / image-edit.php
index 9e0f38448ab6a3a3116bb3d2ac9ab7de1be391f6..928cd1357f7b39831c6d251b546b018573ea0fa0 100644 (file)
@@ -6,6 +6,13 @@
  * @subpackage Administration
  */
 
+/**
+ * Loads the WP image-editing interface.
+ *
+ * @param int         $post_id Post ID.
+ * @param bool|object $msg     Optional. Message to display for image editor updates or errors.
+ *                             Default false.
+ */
 function wp_image_editor($post_id, $msg = false) {
        $nonce = wp_create_nonce("image_editor-$post_id");
        $meta = wp_get_attachment_metadata($post_id);
@@ -33,13 +40,14 @@ function wp_image_editor($post_id, $msg = false) {
        }
 
        ?>
-       <div class="imgedit-wrap">
+       <div class="imgedit-wrap wp-clearfix">
        <div id="imgedit-panel-<?php echo $post_id; ?>">
 
        <div class="imgedit-settings">
        <div class="imgedit-group">
        <div class="imgedit-group-top">
-               <h3><?php _e( 'Scale Image' ); ?> <a href="#" class="dashicons dashicons-editor-help imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;"></a></h3>
+               <h2><?php _e( 'Scale Image' ); ?></h2>
+               <button type="button" class="dashicons dashicons-editor-help imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;" aria-expanded="false"><span class="screen-reader-text"><?php esc_html_e( 'Scale Image Help' ); ?></span></button>
                <div class="imgedit-help">
                <p><?php _e('You can proportionally scale the original image. For best results, scaling should be done before you crop, flip, or rotate. Images can only be scaled down, not up.'); ?></p>
                </div>
@@ -47,9 +55,22 @@ function wp_image_editor($post_id, $msg = false) {
                <p><?php printf( __('Original dimensions %s'), $meta['width'] . ' &times; ' . $meta['height'] ); ?></p>
                <?php endif ?>
                <div class="imgedit-submit">
-               <span class="nowrap"><input type="text" id="imgedit-scale-width-<?php echo $post_id; ?>" onkeyup="imageEdit.scaleChanged(<?php echo $post_id; ?>, 1)" onblur="imageEdit.scaleChanged(<?php echo $post_id; ?>, 1)" style="width:4em;" value="<?php echo isset( $meta['width'] ) ? $meta['width'] : 0; ?>" /> &times; <input type="text" id="imgedit-scale-height-<?php echo $post_id; ?>" onkeyup="imageEdit.scaleChanged(<?php echo $post_id; ?>, 0)" onblur="imageEdit.scaleChanged(<?php echo $post_id; ?>, 0)" style="width:4em;" value="<?php echo isset( $meta['height'] ) ? $meta['height'] : 0; ?>" />
-               <span class="imgedit-scale-warn" id="imgedit-scale-warn-<?php echo $post_id; ?>">!</span></span>
-               <input type="button" onclick="imageEdit.action(<?php echo "$post_id, '$nonce'"; ?>, 'scale')" class="button button-primary" value="<?php esc_attr_e( 'Scale' ); ?>" />
+
+               <fieldset class="imgedit-scale">
+               <legend><?php _e( 'New dimensions:' ); ?></legend>
+               <div class="nowrap">
+               <label><span class="screen-reader-text"><?php _e( 'scale width' ); ?></span>
+               <input type="text" id="imgedit-scale-width-<?php echo $post_id; ?>" onkeyup="imageEdit.scaleChanged(<?php echo $post_id; ?>, 1, this)" onblur="imageEdit.scaleChanged(<?php echo $post_id; ?>, 1, this)" value="<?php echo isset( $meta['width'] ) ? $meta['width'] : 0; ?>" />
+               </label>
+               <span class="imgedit-separator">&times;</span>
+               <label><span class="screen-reader-text"><?php _e( 'scale height' ); ?></span>
+               <input type="text" id="imgedit-scale-height-<?php echo $post_id; ?>" onkeyup="imageEdit.scaleChanged(<?php echo $post_id; ?>, 0, this)" onblur="imageEdit.scaleChanged(<?php echo $post_id; ?>, 0, this)" value="<?php echo isset( $meta['height'] ) ? $meta['height'] : 0; ?>" />
+               </label>
+               <span class="imgedit-scale-warn" id="imgedit-scale-warn-<?php echo $post_id; ?>">!</span>
+               <input id="imgedit-scale-button" type="button" onclick="imageEdit.action(<?php echo "$post_id, '$nonce'"; ?>, 'scale')" class="button button-primary" value="<?php esc_attr_e( 'Scale' ); ?>" />
+               </div>
+               </fieldset>
+
                </div>
        </div>
        </div>
@@ -58,7 +79,7 @@ function wp_image_editor($post_id, $msg = false) {
 
        <div class="imgedit-group">
        <div class="imgedit-group-top">
-               <h3><a onclick="imageEdit.toggleHelp(this);return false;" href="#"><?php _e('Restore Original Image'); ?> <span class="dashicons dashicons-arrow-down imgedit-help-toggle"></span></a></h3>
+               <h2><button type="button" onclick="imageEdit.toggleHelp(this);" class="button-link"><?php _e( 'Restore Original Image' ); ?> <span class="dashicons dashicons-arrow-down imgedit-help-toggle"></span></button></h2>
                <div class="imgedit-help">
                <p><?php _e('Discard any changes and restore the original image.');
 
@@ -77,7 +98,8 @@ function wp_image_editor($post_id, $msg = false) {
 
        <div class="imgedit-group">
        <div class="imgedit-group-top">
-               <h3><?php _e('Image Crop'); ?> <a href="#" class="dashicons dashicons-editor-help imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;"></a></h3>
+               <h2><?php _e( 'Image Crop' ); ?></h2>
+               <button type="button" class="dashicons dashicons-editor-help imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;" aria-expanded="false"><span class="screen-reader-text"><?php esc_html_e( 'Image Crop Help' ); ?></span></button>
 
                <div class="imgedit-help">
                <p><?php _e('To crop the image, click on it and drag to make your selection.'); ?></p>
@@ -90,23 +112,32 @@ function wp_image_editor($post_id, $msg = false) {
                </div>
        </div>
 
-       <p>
-               <?php _e('Aspect ratio:'); ?>
-               <span  class="nowrap">
-               <input type="text" id="imgedit-crop-width-<?php echo $post_id; ?>" onkeyup="imageEdit.setRatioSelection(<?php echo $post_id; ?>, 0, this)" style="width:3em;" />
-               :
-               <input type="text" id="imgedit-crop-height-<?php echo $post_id; ?>" onkeyup="imageEdit.setRatioSelection(<?php echo $post_id; ?>, 1, this)" style="width:3em;" />
-               </span>
-       </p>
-
-       <p id="imgedit-crop-sel-<?php echo $post_id; ?>">
-               <?php _e('Selection:'); ?>
-               <span  class="nowrap">
-               <input type="text" id="imgedit-sel-width-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>)" style="width:4em;" />
-               &times;
-               <input type="text" id="imgedit-sel-height-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>)" style="width:4em;" />
-               </span>
-       </p>
+       <fieldset class="imgedit-crop-ratio">
+               <legend><?php _e( 'Aspect ratio:' ); ?></legend>
+               <div class="nowrap">
+               <label><span class="screen-reader-text"><?php _e( 'crop ratio width' ); ?></span>
+               <input type="text" id="imgedit-crop-width-<?php echo $post_id; ?>" onkeyup="imageEdit.setRatioSelection(<?php echo $post_id; ?>, 0, this)" onblur="imageEdit.setRatioSelection(<?php echo $post_id; ?>, 0, this)" />
+               </label>
+               <span class="imgedit-separator">:</span>
+               <label><span class="screen-reader-text"><?php _e( 'crop ratio height' ); ?></span>
+               <input type="text" id="imgedit-crop-height-<?php echo $post_id; ?>" onkeyup="imageEdit.setRatioSelection(<?php echo $post_id; ?>, 1, this)" onblur="imageEdit.setRatioSelection(<?php echo $post_id; ?>, 1, this)" />
+               </label>
+               </div>
+       </fieldset>
+
+       <fieldset id="imgedit-crop-sel-<?php echo $post_id; ?>" class="imgedit-crop-sel">
+               <legend><?php _e( 'Selection:' ); ?></legend>
+               <div class="nowrap">
+               <label><span class="screen-reader-text"><?php _e( 'selection width' ); ?></span>
+               <input type="text" id="imgedit-sel-width-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" onblur="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" />
+               </label>
+               <span class="imgedit-separator">&times;</span>
+               <label><span class="screen-reader-text"><?php _e( 'selection height' ); ?></span>
+               <input type="text" id="imgedit-sel-height-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" onblur="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" />
+               </label>
+               </div>
+       </fieldset>
+
        </div>
 
        <?php if ( $thumb && $sub_sizes ) {
@@ -115,17 +146,19 @@ function wp_image_editor($post_id, $msg = false) {
 
        <div class="imgedit-group imgedit-applyto">
        <div class="imgedit-group-top">
-               <h3><?php _e('Thumbnail Settings'); ?> <a href="#" class="dashicons dashicons-editor-help imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;"></a></h3>
+               <h2><?php _e( 'Thumbnail Settings' ); ?></h2>
+               <button type="button" class="dashicons dashicons-editor-help imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);return false;" aria-expanded="false"><span class="screen-reader-text"><?php esc_html_e( 'Thumbnail Settings Help' ); ?></span></button>
                <p class="imgedit-help"><?php _e('You can edit the image while preserving the thumbnail. For example, you may wish to have a square thumbnail that displays just a section of the image.'); ?></p>
        </div>
 
-       <p>
+       <figure class="imgedit-thumbnail-preview">
                <img src="<?php echo $thumb['url']; ?>" width="<?php echo $thumb_img[0]; ?>" height="<?php echo $thumb_img[1]; ?>" class="imgedit-size-preview" alt="" draggable="false" />
-               <br /><?php _e('Current thumbnail'); ?>
-       </p>
+               <figcaption class="imgedit-thumbnail-preview-caption"><?php _e( 'Current thumbnail' ); ?></figcaption>
+       </figure>
 
-       <p id="imgedit-save-target-<?php echo $post_id; ?>">
-               <strong><?php _e('Apply changes to:'); ?></strong><br />
+       <div id="imgedit-save-target-<?php echo $post_id; ?>" class="imgedit-save-target">
+       <fieldset>
+               <legend><strong><?php _e( 'Apply changes to:' ); ?></strong></legend>
 
                <label class="imgedit-label">
                <input type="radio" name="imgedit-target-<?php echo $post_id; ?>" value="all" checked="checked" />
@@ -138,58 +171,59 @@ function wp_image_editor($post_id, $msg = false) {
                <label class="imgedit-label">
                <input type="radio" name="imgedit-target-<?php echo $post_id; ?>" value="nothumb" />
                <?php _e('All sizes except thumbnail'); ?></label>
-       </p>
+       </fieldset>
+       </div>
        </div>
 
        <?php } ?>
 
        </div>
-       
-       <div class="imgedit-panel-content">
+
+       <div class="imgedit-panel-content wp-clearfix">
                <?php echo $note; ?>
-               <div class="imgedit-menu">
-                       <div onclick="imageEdit.crop(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-crop disabled" title="<?php esc_attr_e( 'Crop' ); ?>"></div><?php
-       
+               <div class="imgedit-menu wp-clearfix">
+                       <button type="button" onclick="imageEdit.crop(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-crop button disabled" disabled><span class="screen-reader-text"><?php esc_html_e( 'Crop' ); ?></span></button><?php
+
                // On some setups GD library does not provide imagerotate() - Ticket #11536
-               if ( wp_image_editor_supports( array( 'mime_type' => get_post_mime_type( $post_id ), 'methods' => array( 'rotate' ) ) ) ) { ?>
-                       <div class="imgedit-rleft"  onclick="imageEdit.rotate( 90, <?php echo "$post_id, '$nonce'"; ?>, this)" title="<?php esc_attr_e( 'Rotate counter-clockwise' ); ?>"></div>
-                       <div class="imgedit-rright" onclick="imageEdit.rotate(-90, <?php echo "$post_id, '$nonce'"; ?>, this)" title="<?php esc_attr_e( 'Rotate clockwise' ); ?>"></div>
+               if ( wp_image_editor_supports( array( 'mime_type' => get_post_mime_type( $post_id ), 'methods' => array( 'rotate' ) ) ) ) {
+                       $note_no_rotate = '';
+       ?>
+                       <button type="button" class="imgedit-rleft button" onclick="imageEdit.rotate( 90, <?php echo "$post_id, '$nonce'"; ?>, this)"><span class="screen-reader-text"><?php esc_html_e( 'Rotate counter-clockwise' ); ?></span></button>
+                       <button type="button" class="imgedit-rright button" onclick="imageEdit.rotate(-90, <?php echo "$post_id, '$nonce'"; ?>, this)"><span class="screen-reader-text"><?php esc_html_e( 'Rotate clockwise' ); ?></span></button>
        <?php } else {
-                       $note_no_rotate = esc_attr__('Image rotation is not supported by your web host.');
+                       $note_no_rotate = '<p class="note-no-rotate"><em>' . __( 'Image rotation is not supported by your web host.' ) . '</em></p>';
        ?>
-                   <div class="imgedit-rleft disabled"  title="<?php echo $note_no_rotate; ?>"></div>
-                   <div class="imgedit-rright disabled" title="<?php echo $note_no_rotate; ?>"></div>
+                       <button type="button" class="imgedit-rleft button disabled" disabled></button>
+                       <button type="button" class="imgedit-rright button disabled" disabled></button>
        <?php } ?>
-       
-                       <div onclick="imageEdit.flip(1, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-flipv" title="<?php esc_attr_e( 'Flip vertically' ); ?>"></div>
-                       <div onclick="imageEdit.flip(2, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-fliph" title="<?php esc_attr_e( 'Flip horizontally' ); ?>"></div>
-       
-                       <div id="image-undo-<?php echo $post_id; ?>" onclick="imageEdit.undo(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-undo disabled" title="<?php esc_attr_e( 'Undo' ); ?>"></div>
-                       <div id="image-redo-<?php echo $post_id; ?>" onclick="imageEdit.redo(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-redo disabled" title="<?php esc_attr_e( 'Redo' ); ?>"></div>
-                       <br class="clear" />
+
+                       <button type="button" onclick="imageEdit.flip(1, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-flipv button"><span class="screen-reader-text"><?php esc_html_e( 'Flip vertically' ); ?></span></button>
+                       <button type="button" onclick="imageEdit.flip(2, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-fliph button"><span class="screen-reader-text"><?php esc_html_e( 'Flip horizontally' ); ?></span></button>
+
+                       <button type="button" id="image-undo-<?php echo $post_id; ?>" onclick="imageEdit.undo(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-undo button disabled" disabled><span class="screen-reader-text"><?php esc_html_e( 'Undo' ); ?></span></button>
+                       <button type="button" id="image-redo-<?php echo $post_id; ?>" onclick="imageEdit.redo(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-redo button disabled" disabled><span class="screen-reader-text"><?php esc_html_e( 'Redo' ); ?></span></button>
+                       <?php echo $note_no_rotate; ?>
                </div>
-       
+
                <input type="hidden" id="imgedit-sizer-<?php echo $post_id; ?>" value="<?php echo $sizer; ?>" />
-               <input type="hidden" id="imgedit-minthumb-<?php echo $post_id; ?>" value="<?php echo ( get_option('thumbnail_size_w') . ':' . get_option('thumbnail_size_h') ); ?>" />
                <input type="hidden" id="imgedit-history-<?php echo $post_id; ?>" value="" />
                <input type="hidden" id="imgedit-undone-<?php echo $post_id; ?>" value="0" />
                <input type="hidden" id="imgedit-selection-<?php echo $post_id; ?>" value="" />
                <input type="hidden" id="imgedit-x-<?php echo $post_id; ?>" value="<?php echo isset( $meta['width'] ) ? $meta['width'] : 0; ?>" />
                <input type="hidden" id="imgedit-y-<?php echo $post_id; ?>" value="<?php echo isset( $meta['height'] ) ? $meta['height'] : 0; ?>" />
-       
+
                <div id="imgedit-crop-<?php echo $post_id; ?>" class="imgedit-crop-wrap">
-               <img id="image-preview-<?php echo $post_id; ?>" onload="imageEdit.imgLoaded('<?php echo $post_id; ?>')" src="<?php echo admin_url( 'admin-ajax.php', 'relative' ); ?>?action=imgedit-preview&amp;_ajax_nonce=<?php echo $nonce; ?>&amp;postid=<?php echo $post_id; ?>&amp;rand=<?php echo rand(1, 99999); ?>" />
+               <img id="image-preview-<?php echo $post_id; ?>" onload="imageEdit.imgLoaded('<?php echo $post_id; ?>')" src="<?php echo admin_url( 'admin-ajax.php', 'relative' ); ?>?action=imgedit-preview&amp;_ajax_nonce=<?php echo $nonce; ?>&amp;postid=<?php echo $post_id; ?>&amp;rand=<?php echo rand(1, 99999); ?>" alt="" />
                </div>
-       
+
                <div class="imgedit-submit">
-                       <input type="button" onclick="imageEdit.close(<?php echo $post_id; ?>, 1)" class="button" value="<?php esc_attr_e( 'Cancel' ); ?>" />
+                       <input type="button" onclick="imageEdit.close(<?php echo $post_id; ?>, 1)" class="button imgedit-cancel-btn" value="<?php esc_attr_e( 'Cancel' ); ?>" />
                        <input type="button" onclick="imageEdit.save(<?php echo "$post_id, '$nonce'"; ?>)" disabled="disabled" class="button button-primary imgedit-submit-btn" value="<?php esc_attr_e( 'Save' ); ?>" />
                </div>
        </div>
-       
+
        </div>
        <div class="imgedit-wait" id="imgedit-wait-<?php echo $post_id; ?>"></div>
-       <script type="text/javascript">jQuery( function() { imageEdit.init(<?php echo $post_id; ?>); });</script>
        <div class="hidden" id="imgedit-leaving-<?php echo $post_id; ?>"><?php _e("There are unsaved changes that will be lost. 'OK' to continue, 'Cancel' to return to the Image Editor."); ?></div>
        </div>
 <?php
@@ -202,13 +236,13 @@ function wp_image_editor($post_id, $msg = false) {
  * @param WP_Image_Editor $image
  * @param string $mime_type
  * @param int $post_id
- * @return boolean
+ * @return bool
  */
 function wp_stream_image( $image, $mime_type, $post_id ) {
        if ( $image instanceof WP_Image_Editor ) {
 
                /**
-                * Filter the WP_Image_Editor instance for the image to be streamed to the browser.
+                * Filters the WP_Image_Editor instance for the image to be streamed to the browser.
                 *
                 * @since 3.5.0
                 *
@@ -222,10 +256,10 @@ function wp_stream_image( $image, $mime_type, $post_id ) {
 
                return true;
        } else {
-               _deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
+               _deprecated_argument( __FUNCTION__, '3.5.0', __( '$image needs to be an WP_Image_Editor object' ) );
 
                /**
-                * Filter the GD image resource to be streamed to the browser.
+                * Filters the GD image resource to be streamed to the browser.
                 *
                 * @since 2.9.0
                 * @deprecated 3.5.0 Use image_editor_save_pre instead.
@@ -258,7 +292,7 @@ function wp_stream_image( $image, $mime_type, $post_id ) {
  * @param WP_Image_Editor $image
  * @param string $mime_type
  * @param int $post_id
- * @return boolean
+ * @return bool
  */
 function wp_save_image_file( $filename, $image, $mime_type, $post_id ) {
        if ( $image instanceof WP_Image_Editor ) {
@@ -267,7 +301,7 @@ function wp_save_image_file( $filename, $image, $mime_type, $post_id ) {
                $image = apply_filters( 'image_editor_save_pre', $image, $post_id );
 
                /**
-                * Filter whether to skip saving the image file.
+                * Filters whether to skip saving the image file.
                 *
                 * Returning a non-null value will short-circuit the save method,
                 * returning that value instead.
@@ -287,13 +321,13 @@ function wp_save_image_file( $filename, $image, $mime_type, $post_id ) {
 
                return $image->save( $filename, $mime_type );
        } else {
-               _deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
+               _deprecated_argument( __FUNCTION__, '3.5.0', __( '$image needs to be an WP_Image_Editor object' ) );
 
                /** This filter is documented in wp-admin/includes/image-edit.php */
                $image = apply_filters( 'image_save_pre', $image, $post_id );
 
                /**
-                * Filter whether to skip saving the image file.
+                * Filters whether to skip saving the image file.
                 *
                 * Returning a non-null value will short-circuit the save method,
                 * returning that value instead.
@@ -327,14 +361,33 @@ function wp_save_image_file( $filename, $image, $mime_type, $post_id ) {
        }
 }
 
+/**
+ * Image preview ratio. Internal use only.
+ *
+ * @since 2.9.0
+ *
+ * @ignore
+ * @param int $w Image width in pixels.
+ * @param int $h Image height in pixels.
+ * @return float|int Image preview ratio.
+ */
 function _image_get_preview_ratio($w, $h) {
        $max = max($w, $h);
        return $max > 400 ? (400 / $max) : 1;
 }
 
-// @TODO: Returns GD resource, but is NOT public
+/**
+ * Returns an image resource. Internal use only.
+ *
+ * @since 2.9.0
+ *
+ * @ignore
+ * @param resource  $img   Image resource.
+ * @param float|int $angle Image rotation angle, in degrees.
+ * @return resource|false GD image resource, false otherwise.
+ */
 function _rotate_image_resource($img, $angle) {
-       _deprecated_function( __FUNCTION__, '3.5', __( 'Use WP_Image_Editor::rotate' ) );
+       _deprecated_function( __FUNCTION__, '3.5.0', __( 'Use WP_Image_Editor::rotate' ) );
        if ( function_exists('imagerotate') ) {
                $rotated = imagerotate($img, $angle, 0);
                if ( is_resource($rotated) ) {
@@ -346,17 +399,18 @@ function _rotate_image_resource($img, $angle) {
 }
 
 /**
- * @TODO: Only used within image_edit_apply_changes
- *               and receives/returns GD Resource.
- *               Consider removal.
+ * Flips an image resource. Internal use only.
+ *
+ * @since 2.9.0
  *
- * @param GD_Resource $img
- * @param boolean $horz
- * @param boolean $vert
- * @return GD_Resource
+ * @ignore
+ * @param resource $img  Image resource.
+ * @param bool     $horz Whether to flip horizontally.
+ * @param bool     $vert Whether to flip vertically.
+ * @return resource (maybe) flipped image resource.
  */
 function _flip_image_resource($img, $horz, $vert) {
-       _deprecated_function( __FUNCTION__, '3.5', __( 'Use WP_Image_Editor::flip' ) );
+       _deprecated_function( __FUNCTION__, '3.5.0', __( 'Use WP_Image_Editor::flip' ) );
        $w = imagesx($img);
        $h = imagesy($img);
        $dst = wp_imagecreatetruecolor($w, $h);
@@ -375,16 +429,17 @@ function _flip_image_resource($img, $horz, $vert) {
 }
 
 /**
- * @TODO: Only used within image_edit_apply_changes
- *               and receives/returns GD Resource.
- *               Consider removal.
+ * Crops an image resource. Internal use only.
  *
- * @param GD_Resource $img
- * @param float $x
- * @param float $y
- * @param float $w
- * @param float $h
- * @return GD_Resource
+ * @since 2.9.0
+ *
+ * @ignore
+ * @param resource $img Image resource.
+ * @param float    $x   Source point x-coordinate.
+ * @param float    $y   Source point y-cooredinate.
+ * @param float    $w   Source width.
+ * @param float    $h   Source height.
+ * @return resource (maybe) cropped image resource.
  */
 function _crop_image_resource($img, $x, $y, $w, $h) {
        $dst = wp_imagecreatetruecolor($w, $h);
@@ -400,18 +455,20 @@ function _crop_image_resource($img, $x, $y, $w, $h) {
 /**
  * Performs group of changes on Editor specified.
  *
- * @param WP_Image_Editor $image
- * @param type $changes
- * @return WP_Image_Editor
+ * @since 2.9.0
+ *
+ * @param WP_Image_Editor $image   WP_Image_Editor instance.
+ * @param array           $changes Array of change operations.
+ * @return WP_Image_Editor WP_Image_Editor instance with changes applied.
  */
 function image_edit_apply_changes( $image, $changes ) {
        if ( is_resource( $image ) )
-               _deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) );
+               _deprecated_argument( __FUNCTION__, '3.5.0', __( '$image needs to be an WP_Image_Editor object' ) );
 
        if ( !is_array($changes) )
                return $image;
 
-       // expand change operations
+       // Expand change operations.
        foreach ( $changes as $key => $obj ) {
                if ( isset($obj->r) ) {
                        $obj->type = 'rotate';
@@ -429,10 +486,10 @@ function image_edit_apply_changes( $image, $changes ) {
                $changes[$key] = $obj;
        }
 
-       // combine operations
+       // Combine operations.
        if ( count($changes) > 1 ) {
                $filtered = array($changes[0]);
-               for ( $i = 0, $j = 1; $j < count($changes); $j++ ) {
+               for ( $i = 0, $j = 1, $c = count( $changes ); $j < $c; $j++ ) {
                        $combined = false;
                        if ( $filtered[$i]->type == $changes[$j]->type ) {
                                switch ( $filtered[$i]->type ) {
@@ -453,11 +510,11 @@ function image_edit_apply_changes( $image, $changes ) {
                unset($filtered);
        }
 
-       // image resource before applying the changes
+       // Image resource before applying the changes.
        if ( $image instanceof WP_Image_Editor ) {
 
                /**
-                * Filter the WP_Image_Editor instance before applying changes to the image.
+                * Filters the WP_Image_Editor instance before applying changes to the image.
                 *
                 * @since 3.5.0
                 *
@@ -468,7 +525,7 @@ function image_edit_apply_changes( $image, $changes ) {
        } elseif ( is_resource( $image ) ) {
 
                /**
-                * Filter the GD image resource before applying changes to the image.
+                * Filters the GD image resource before applying changes to the image.
                 *
                 * @since 2.9.0
                 * @deprecated 3.5.0 Use wp_image_editor_before_change instead.
@@ -523,24 +580,24 @@ function image_edit_apply_changes( $image, $changes ) {
  * in $_REQUEST['history']
  *
  * @param int $post_id
- * @return boolean
+ * @return bool
  */
 function stream_preview_image( $post_id ) {
        $post = get_post( $post_id );
 
-       /** This filter is documented in wp-admin/admin.php */
-       @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
+       wp_raise_memory_limit( 'admin' );
 
        $img = wp_get_image_editor( _load_image_to_edit_path( $post_id ) );
 
-    if ( is_wp_error( $img ) )
-        return false;
+       if ( is_wp_error( $img ) ) {
+               return false;
+       }
 
        $changes = !empty($_REQUEST['history']) ? json_decode( wp_unslash($_REQUEST['history']) ) : null;
        if ( $changes )
                $img = image_edit_apply_changes( $img, $changes );
 
-       // scale the image
+       // Scale the image.
        $size = $img->get_size();
        $w = $size['width'];
        $h = $size['height'];
@@ -555,10 +612,18 @@ function stream_preview_image( $post_id ) {
        return wp_stream_image( $img, $post->post_mime_type, $post_id );
 }
 
+/**
+ * Restores the metadata for a given attachment.
+ *
+ * @since 2.9.0
+ *
+ * @param int $post_id Attachment post ID.
+ * @return stdClass Image restoration message object.
+ */
 function wp_restore_image($post_id) {
        $meta = wp_get_attachment_metadata($post_id);
        $file = get_attached_file($post_id);
-       $backup_sizes = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
+       $backup_sizes = $old_backup_sizes = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
        $restored = false;
        $msg = new stdClass;
 
@@ -576,12 +641,10 @@ function wp_restore_image($post_id) {
 
                if ( $parts['basename'] != $data['file'] ) {
                        if ( defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE ) {
-                               // delete only if it's edited image
-                               if ( preg_match('/-e[0-9]{13}\./', $parts['basename']) ) {
 
-                                       /** This filter is documented in wp-admin/custom-header.php */
-                                       $delpath = apply_filters( 'wp_delete_file', $file );
-                                       @unlink($delpath);
+                               // Delete only if it's an edited image.
+                               if ( preg_match('/-e[0-9]{13}\./', $parts['basename']) ) {
+                                       wp_delete_file( $file );
                                }
                        } elseif ( isset( $meta['width'], $meta['height'] ) ) {
                                $backup_sizes["full-$suffix"] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $parts['basename']);
@@ -601,11 +664,11 @@ function wp_restore_image($post_id) {
                        $data = $backup_sizes["$default_size-orig"];
                        if ( isset($meta['sizes'][$default_size]) && $meta['sizes'][$default_size]['file'] != $data['file'] ) {
                                if ( defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE ) {
-                                       // delete only if it's edited image
+
+                                       // Delete only if it's an edited image.
                                        if ( preg_match('/-e[0-9]{13}-/', $meta['sizes'][$default_size]['file']) ) {
-                                               /** This filter is documented in wp-admin/custom-header.php */
-                                               $delpath = apply_filters( 'wp_delete_file', path_join($parts['dirname'], $meta['sizes'][$default_size]['file']) );
-                                               @unlink($delpath);
+                                               $delete_file = path_join( $parts['dirname'], $meta['sizes'][$default_size]['file'] );
+                                               wp_delete_file( $delete_file );
                                        }
                                } else {
                                        $backup_sizes["$default_size-{$suffix}"] = $meta['sizes'][$default_size];
@@ -618,7 +681,9 @@ function wp_restore_image($post_id) {
                }
        }
 
-       if ( !wp_update_attachment_metadata($post_id, $meta) || !update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes) ) {
+       if ( ! wp_update_attachment_metadata( $post_id, $meta ) ||
+               ( $old_backup_sizes !== $backup_sizes && ! update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes ) ) ) {
+
                $msg->error = __('Cannot save image metadata.');
                return $msg;
        }
@@ -635,6 +700,8 @@ function wp_restore_image($post_id) {
  * Saves image to post along with enqueued changes
  * in $_REQUEST['history']
  *
+ * @global array $_wp_additional_image_sizes
+ *
  * @param int $post_id
  * @return \stdClass
  */
@@ -661,10 +728,10 @@ function wp_save_image( $post_id ) {
                $sX = $size['width'];
                $sY = $size['height'];
 
-               // check if it has roughly the same w / h ratio
+               // Check if it has roughly the same w / h ratio.
                $diff = round($sX / $sY, 2) - round($fwidth / $fheight, 2);
                if ( -0.1 < $diff && $diff < 0.1 ) {
-                       // scale the full size image
+                       // Scale the full size image.
                        if ( $img->resize( $fwidth, $fheight ) )
                                $scaled = true;
                }
@@ -693,7 +760,7 @@ function wp_save_image( $post_id ) {
        if ( !is_array($backup_sizes) )
                $backup_sizes = array();
 
-       // generate new filename
+       // Generate new filename.
        $path = get_attached_file($post_id);
        $path_parts = pathinfo( $path );
        $filename = $path_parts['filename'];
@@ -719,7 +786,7 @@ function wp_save_image( $post_id ) {
                }
        }
 
-       // save the full-size file, also needed to create sub-sizes
+       // Save the full-size file, also needed to create sub-sizes.
        if ( !wp_save_image_file($new_path, $img, $post->post_mime_type, $post_id) ) {
                $return->error = esc_js( __('Unable to save the image.') );
                return $return;
@@ -737,7 +804,7 @@ function wp_save_image( $post_id ) {
                if ( $tag )
                        $backup_sizes[$tag] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $path_parts['basename']);
 
-               $success = update_attached_file( $post_id, $new_path );
+               $success = ( $path === $new_path ) || update_attached_file( $post_id, $new_path );
 
                $meta['file'] = _wp_relative_upload_path( $new_path );
 
@@ -758,6 +825,21 @@ function wp_save_image( $post_id ) {
                $success = $delete = $nocrop = true;
        }
 
+       /*
+        * We need to remove any existing resized image files because
+        * a new crop or rotate could generate different sizes (and hence, filenames),
+        * keeping the new resized images from overwriting the existing image files.
+        * https://core.trac.wordpress.org/ticket/32171
+        */
+       if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE && ! empty( $meta['sizes'] ) ) {
+               foreach ( $meta['sizes'] as $size ) {
+                       if ( ! empty( $size['file'] ) && preg_match( '/-e[0-9]{13}-/', $size['file'] ) ) {
+                               $delete_file = path_join( $path_parts['dirname'], $size['file'] );
+                               wp_delete_file( $delete_file );
+                       }
+               }
+       }
+
        if ( isset( $sizes ) ) {
                $_sizes = array();
 
@@ -804,10 +886,11 @@ function wp_save_image( $post_id ) {
                                $return->thumbnail = $thumb_url[0];
                        } else {
                                $file_url = wp_get_attachment_url($post_id);
-                               if ( $thumb = $meta['sizes']['thumbnail'] )
+                               if ( ! empty( $meta['sizes']['thumbnail'] ) && $thumb = $meta['sizes']['thumbnail'] ) {
                                        $return->thumbnail = path_join( dirname($file_url), $thumb['file'] );
-                               else
+                               } else {
                                        $return->thumbnail = "$file_url?w=128&h=128";
+                               }
                        }
                }
        } else {
@@ -815,10 +898,7 @@ function wp_save_image( $post_id ) {
        }
 
        if ( $delete ) {
-
-               /** This filter is documented in wp-admin/custom-header.php */
-               $delpath = apply_filters( 'wp_delete_file', $new_path );
-               @unlink( $delpath );
+               wp_delete_file( $new_path );
        }
 
        $return->msg = esc_js( __('Image saved') );