wp/wp-admin/includes/image-edit.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
child 22 8c2e4d02f4ef
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
    26 		$big = max( $meta['width'], $meta['height'] );
    26 		$big = max( $meta['width'], $meta['height'] );
    27 	} else {
    27 	} else {
    28 		die( __( 'Image data does not exist. Please re-upload the image.' ) );
    28 		die( __( 'Image data does not exist. Please re-upload the image.' ) );
    29 	}
    29 	}
    30 
    30 
    31 	$sizer = $big > 400 ? 400 / $big : 1;
    31 	$sizer = $big > 600 ? 600 / $big : 1;
    32 
    32 
    33 	$backup_sizes = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
    33 	$backup_sizes = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
    34 	$can_restore  = false;
    34 	$can_restore  = false;
       
    35 
    35 	if ( ! empty( $backup_sizes ) && isset( $backup_sizes['full-orig'], $meta['file'] ) ) {
    36 	if ( ! empty( $backup_sizes ) && isset( $backup_sizes['full-orig'], $meta['file'] ) ) {
    36 		$can_restore = wp_basename( $meta['file'] ) !== $backup_sizes['full-orig']['file'];
    37 		$can_restore = wp_basename( $meta['file'] ) !== $backup_sizes['full-orig']['file'];
    37 	}
    38 	}
    38 
    39 
    39 	if ( $msg ) {
    40 	if ( $msg ) {
    40 		if ( isset( $msg->error ) ) {
    41 		if ( isset( $msg->error ) ) {
    41 			$note = "<div class='notice notice-error' tabindex='-1' role='alert'><p>$msg->error</p></div>";
    42 			$note = "<div class='notice notice-error' role='alert'><p>$msg->error</p></div>";
    42 		} elseif ( isset( $msg->msg ) ) {
    43 		} elseif ( isset( $msg->msg ) ) {
    43 			$note = "<div class='notice notice-success' tabindex='-1' role='alert'><p>$msg->msg</p></div>";
    44 			$note = "<div class='notice notice-success' role='alert'><p>$msg->msg</p></div>";
    44 		}
    45 		}
    45 	}
    46 	}
    46 	$edit_custom_sizes = false;
    47 
    47 	/**
    48 	/**
    48 	 * Filters whether custom sizes are available options for image editing.
    49 	 * Shows the settings in the Image Editor that allow selecting to edit only the thumbnail of an image.
    49 	 *
    50 	 *
    50 	 * @since 6.0.0
    51 	 * @since 6.3.0
    51 	 *
    52 	 *
    52 	 * @param bool|string[] $edit_custom_sizes True if custom sizes can be edited or array of custom size names.
    53 	 * @param bool $show Whether to show the settings in the Image Editor. Default false.
    53 	 */
    54 	 */
    54 	$edit_custom_sizes = apply_filters( 'edit_custom_thumbnail_sizes', $edit_custom_sizes );
    55 	$edit_thumbnails_separately = (bool) apply_filters( 'image_edit_thumbnails_separately', false );
       
    56 
    55 	?>
    57 	?>
    56 	<div class="imgedit-wrap wp-clearfix">
    58 	<div class="imgedit-wrap wp-clearfix">
    57 	<div id="imgedit-panel-<?php echo $post_id; ?>">
    59 	<div id="imgedit-panel-<?php echo $post_id; ?>">
    58 
    60 	<?php echo $note; ?>
    59 	<div class="imgedit-panel-content wp-clearfix">
    61 	<div class="imgedit-panel-content imgedit-panel-tools wp-clearfix">
    60 		<?php echo $note; ?>
       
    61 		<div class="imgedit-menu wp-clearfix">
    62 		<div class="imgedit-menu wp-clearfix">
    62 			<button type="button" onclick="imageEdit.handleCropToolClick( <?php echo "$post_id, '$nonce'"; ?>, this )" class="imgedit-crop button disabled" disabled><?php esc_html_e( 'Crop' ); ?></button>
    63 			<button type="button" onclick="imageEdit.toggleCropTool( <?php echo "$post_id, '$nonce'"; ?>, this );" aria-expanded="false" aria-controls="imgedit-crop" class="imgedit-crop button disabled" disabled><?php esc_html_e( 'Crop' ); ?></button>
       
    64 			<button type="button" class="imgedit-scale button" onclick="imageEdit.toggleControls(this);" aria-expanded="false" aria-controls="imgedit-scale"><?php esc_html_e( 'Scale' ); ?></button>
       
    65 			<div class="imgedit-rotate-menu-container">
       
    66 				<button type="button" aria-controls="imgedit-rotate-menu" class="imgedit-rotate button" aria-expanded="false" onclick="imageEdit.togglePopup(this)" onblur="imageEdit.monitorPopup()"><?php esc_html_e( 'Image Rotation' ); ?></button>
       
    67 				<div id="imgedit-rotate-menu" class="imgedit-popup-menu">
    63 			<?php
    68 			<?php
    64 
       
    65 			// On some setups GD library does not provide imagerotate() - Ticket #11536.
    69 			// On some setups GD library does not provide imagerotate() - Ticket #11536.
    66 			if ( wp_image_editor_supports(
    70 			if ( wp_image_editor_supports(
    67 				array(
    71 				array(
    68 					'mime_type' => get_post_mime_type( $post_id ),
    72 					'mime_type' => get_post_mime_type( $post_id ),
    69 					'methods'   => array( 'rotate' ),
    73 					'methods'   => array( 'rotate' ),
    70 				)
    74 				)
    71 			) ) {
    75 			) ) {
    72 				$note_no_rotate = '';
    76 				$note_no_rotate = '';
    73 				?>
    77 				?>
    74 				<button type="button" class="imgedit-rleft button" onclick="imageEdit.rotate( 90, <?php echo "$post_id, '$nonce'"; ?>, this)"><?php esc_html_e( 'Rotate left' ); ?></button>
    78 					<button type="button" class="imgedit-rleft button" onkeyup="imageEdit.browsePopup(this)" onclick="imageEdit.rotate( 90, <?php echo "$post_id, '$nonce'"; ?>, this)" onblur="imageEdit.monitorPopup()"><?php esc_html_e( 'Rotate 90&deg; left' ); ?></button>
    75 				<button type="button" class="imgedit-rright button" onclick="imageEdit.rotate(-90, <?php echo "$post_id, '$nonce'"; ?>, this)"><?php esc_html_e( 'Rotate right' ); ?></button>
    79 					<button type="button" class="imgedit-rright button" onkeyup="imageEdit.browsePopup(this)" onclick="imageEdit.rotate(-90, <?php echo "$post_id, '$nonce'"; ?>, this)" onblur="imageEdit.monitorPopup()"><?php esc_html_e( 'Rotate 90&deg; right' ); ?></button>
       
    80 					<button type="button" class="imgedit-rfull button" onkeyup="imageEdit.browsePopup(this)" onclick="imageEdit.rotate(180, <?php echo "$post_id, '$nonce'"; ?>, this)" onblur="imageEdit.monitorPopup()"><?php esc_html_e( 'Rotate 180&deg;' ); ?></button>
    76 				<?php
    81 				<?php
    77 			} else {
    82 			} else {
    78 				$note_no_rotate = '<p class="note-no-rotate"><em>' . __( 'Image rotation is not supported by your web host.' ) . '</em></p>';
    83 				$note_no_rotate = '<p class="note-no-rotate"><em>' . __( 'Image rotation is not supported by your web host.' ) . '</em></p>';
    79 				?>
    84 				?>
    80 				<button type="button" class="imgedit-rleft button disabled" disabled></button>
    85 					<button type="button" class="imgedit-rleft button disabled" disabled></button>
    81 				<button type="button" class="imgedit-rright button disabled" disabled></button>
    86 					<button type="button" class="imgedit-rright button disabled" disabled></button>
    82 			<?php } ?>
    87 				<?php
    83 
    88 			}
    84 			<button type="button" onclick="imageEdit.flip(1, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-flipv button"><?php esc_html_e( 'Flip vertical' ); ?></button>
    89 			?>
    85 			<button type="button" onclick="imageEdit.flip(2, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-fliph button"><?php esc_html_e( 'Flip horizontal' ); ?></button>
    90 					<hr />
    86 
    91 					<button type="button" onkeyup="imageEdit.browsePopup(this)" onclick="imageEdit.flip(1, <?php echo "$post_id, '$nonce'"; ?>, this)" onblur="imageEdit.monitorPopup()" class="imgedit-flipv button"><?php esc_html_e( 'Flip vertical' ); ?></button>
    87 			<br class="imgedit-undo-redo-separator" />
    92 					<button type="button" onkeyup="imageEdit.browsePopup(this)" onclick="imageEdit.flip(2, <?php echo "$post_id, '$nonce'"; ?>, this)" onblur="imageEdit.monitorPopup()" class="imgedit-fliph button"><?php esc_html_e( 'Flip horizontal' ); ?></button>
       
    93 					<?php echo $note_no_rotate; ?>
       
    94 				</div>
       
    95 			</div>
       
    96 		</div>
       
    97 		<div class="imgedit-submit imgedit-menu">
    88 			<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><?php esc_html_e( 'Undo' ); ?></button>
    98 			<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><?php esc_html_e( 'Undo' ); ?></button>
    89 			<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><?php esc_html_e( 'Redo' ); ?></button>
    99 			<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><?php esc_html_e( 'Redo' ); ?></button>
    90 			<?php echo $note_no_rotate; ?>
   100 			<button type="button" onclick="imageEdit.close(<?php echo $post_id; ?>, 1)" class="button imgedit-cancel-btn"><?php esc_html_e( 'Cancel Editing' ); ?></button>
    91 		</div>
   101 			<button type="button" onclick="imageEdit.save(<?php echo "$post_id, '$nonce'"; ?>)" disabled="disabled" class="button button-primary imgedit-submit-btn"><?php esc_html_e( 'Save Edits' ); ?></button>
    92 
       
    93 		<input type="hidden" id="imgedit-sizer-<?php echo $post_id; ?>" value="<?php echo $sizer; ?>" />
       
    94 		<input type="hidden" id="imgedit-history-<?php echo $post_id; ?>" value="" />
       
    95 		<input type="hidden" id="imgedit-undone-<?php echo $post_id; ?>" value="0" />
       
    96 		<input type="hidden" id="imgedit-selection-<?php echo $post_id; ?>" value="" />
       
    97 		<input type="hidden" id="imgedit-x-<?php echo $post_id; ?>" value="<?php echo isset( $meta['width'] ) ? $meta['width'] : 0; ?>" />
       
    98 		<input type="hidden" id="imgedit-y-<?php echo $post_id; ?>" value="<?php echo isset( $meta['height'] ) ? $meta['height'] : 0; ?>" />
       
    99 
       
   100 		<div id="imgedit-crop-<?php echo $post_id; ?>" class="imgedit-crop-wrap">
       
   101 		<img id="image-preview-<?php echo $post_id; ?>" onload="imageEdit.imgLoaded('<?php echo $post_id; ?>')"
       
   102 			src="<?php echo esc_url( admin_url( 'admin-ajax.php', 'relative' ) ) . '?action=imgedit-preview&amp;_ajax_nonce=' . $nonce . '&amp;postid=' . $post_id . '&amp;rand=' . rand( 1, 99999 ); ?>" alt="" />
       
   103 		</div>
       
   104 
       
   105 		<div class="imgedit-submit">
       
   106 			<input type="button" onclick="imageEdit.close(<?php echo $post_id; ?>, 1)" class="button imgedit-cancel-btn" value="<?php esc_attr_e( 'Cancel' ); ?>" />
       
   107 			<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' ); ?>" />
       
   108 		</div>
   102 		</div>
   109 	</div>
   103 	</div>
   110 
   104 
   111 	<div class="imgedit-settings">
   105 	<div class="imgedit-panel-content wp-clearfix">
   112 	<div class="imgedit-group">
   106 		<div class="imgedit-tools">
   113 	<div class="imgedit-group-top">
   107 			<input type="hidden" id="imgedit-nonce-<?php echo $post_id; ?>" value="<?php echo $nonce; ?>" />
   114 		<h2><?php _e( 'Scale Image' ); ?></h2>
   108 			<input type="hidden" id="imgedit-sizer-<?php echo $post_id; ?>" value="<?php echo $sizer; ?>" />
   115 		<button type="button" class="dashicons dashicons-editor-help imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);" aria-expanded="false"><span class="screen-reader-text"><?php esc_html_e( 'Scale Image Help' ); ?></span></button>
   109 			<input type="hidden" id="imgedit-history-<?php echo $post_id; ?>" value="" />
   116 		<div class="imgedit-help">
   110 			<input type="hidden" id="imgedit-undone-<?php echo $post_id; ?>" value="0" />
   117 		<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>
   111 			<input type="hidden" id="imgedit-selection-<?php echo $post_id; ?>" value="" />
       
   112 			<input type="hidden" id="imgedit-x-<?php echo $post_id; ?>" value="<?php echo isset( $meta['width'] ) ? $meta['width'] : 0; ?>" />
       
   113 			<input type="hidden" id="imgedit-y-<?php echo $post_id; ?>" value="<?php echo isset( $meta['height'] ) ? $meta['height'] : 0; ?>" />
       
   114 
       
   115 			<div id="imgedit-crop-<?php echo $post_id; ?>" class="imgedit-crop-wrap">
       
   116 			<div class="imgedit-crop-grid"></div>
       
   117 			<img id="image-preview-<?php echo $post_id; ?>" onload="imageEdit.imgLoaded('<?php echo $post_id; ?>')"
       
   118 				src="<?php echo esc_url( admin_url( 'admin-ajax.php', 'relative' ) ) . '?action=imgedit-preview&amp;_ajax_nonce=' . $nonce . '&amp;postid=' . $post_id . '&amp;rand=' . rand( 1, 99999 ); ?>" alt="" />
       
   119 			</div>
   118 		</div>
   120 		</div>
   119 		<?php if ( isset( $meta['width'], $meta['height'] ) ) : ?>
   121 		<div class="imgedit-settings">
   120 		<p>
   122 			<div class="imgedit-tool-active">
   121 			<?php
   123 				<div class="imgedit-group">
   122 			printf(
   124 				<div id="imgedit-scale" tabindex="-1" class="imgedit-group-controls">
   123 				/* translators: %s: Image width and height in pixels. */
   125 					<div class="imgedit-group-top">
   124 				__( 'Original dimensions %s' ),
   126 						<h2><?php _e( 'Scale Image' ); ?></h2>
   125 				'<span class="imgedit-original-dimensions">' . $meta['width'] . ' &times; ' . $meta['height'] . '</span>'
   127 						<button type="button" class="dashicons dashicons-editor-help imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);" aria-expanded="false"><span class="screen-reader-text">
   126 			);
   128 						<?php
   127 			?>
   129 						/* translators: Hidden accessibility text. */
   128 		</p>
   130 						esc_html_e( 'Scale Image Help' );
   129 		<?php endif; ?>
   131 						?>
   130 		<div class="imgedit-submit">
   132 						</span></button>
   131 
   133 						<div class="imgedit-help">
   132 		<fieldset class="imgedit-scale">
   134 						<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>
   133 		<legend><?php _e( 'New dimensions:' ); ?></legend>
   135 						</div>
   134 		<div class="nowrap">
   136 						<?php if ( isset( $meta['width'], $meta['height'] ) ) : ?>
   135 		<label for="imgedit-scale-width-<?php echo $post_id; ?>" class="screen-reader-text"><?php _e( 'scale width' ); ?></label>
   137 						<p>
   136 		<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; ?>" />
   138 							<?php
   137 		<span class="imgedit-separator" aria-hidden="true">&times;</span>
   139 							printf(
   138 		<label for="imgedit-scale-height-<?php echo $post_id; ?>" class="screen-reader-text"><?php _e( 'scale height' ); ?></label>
   140 								/* translators: %s: Image width and height in pixels. */
   139 		<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; ?>" />
   141 								__( 'Original dimensions %s' ),
   140 		<span class="imgedit-scale-warn" id="imgedit-scale-warn-<?php echo $post_id; ?>">!</span>
   142 								'<span class="imgedit-original-dimensions">' . $meta['width'] . ' &times; ' . $meta['height'] . '</span>'
   141 		<div class="imgedit-scale-button-wrapper"><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>
   143 							);
   142 		</div>
   144 							?>
   143 		</fieldset>
   145 						</p>
   144 
   146 						<?php endif; ?>
       
   147 						<div class="imgedit-submit">
       
   148 						<fieldset class="imgedit-scale-controls">
       
   149 							<legend><?php _e( 'New dimensions:' ); ?></legend>
       
   150 							<div class="nowrap">
       
   151 							<label for="imgedit-scale-width-<?php echo $post_id; ?>" class="screen-reader-text">
       
   152 							<?php
       
   153 							/* translators: Hidden accessibility text. */
       
   154 							_e( 'scale height' );
       
   155 							?>
       
   156 							</label>
       
   157 							<input type="number" step="1" min="0" max="<?php echo isset( $meta['width'] ) ? $meta['width'] : ''; ?>" aria-describedby="imgedit-scale-warn-<?php echo $post_id; ?>"  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; ?>" />
       
   158 							<span class="imgedit-separator" aria-hidden="true">&times;</span>
       
   159 							<label for="imgedit-scale-height-<?php echo $post_id; ?>" class="screen-reader-text"><?php _e( 'scale height' ); ?></label>
       
   160 							<input type="number" step="1" min="0" max="<?php echo isset( $meta['height'] ) ? $meta['height'] : ''; ?>" aria-describedby="imgedit-scale-warn-<?php echo $post_id; ?>" 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; ?>" />
       
   161 							<button id="imgedit-scale-button" type="button" onclick="imageEdit.action(<?php echo "$post_id, '$nonce'"; ?>, 'scale')" class="button button-primary"><?php esc_html_e( 'Scale' ); ?></button>
       
   162 							</div>
       
   163 							<span class="imgedit-scale-warn" id="imgedit-scale-warn-<?php echo $post_id; ?>"><span class="dashicons dashicons-warning" aria-hidden="true"></span><?php esc_html_e( 'Images cannot be scaled to a size larger than the original.' ); ?></span>
       
   164 						</fieldset>
       
   165 						</div>
       
   166 					</div>
       
   167 				</div>
       
   168 			</div>
       
   169 
       
   170 		<?php if ( $can_restore ) { ?>
       
   171 				<div class="imgedit-group">
       
   172 				<div class="imgedit-group-top">
       
   173 					<h2><button type="button" onclick="imageEdit.toggleHelp(this);" class="button-link" aria-expanded="false"><?php _e( 'Restore original image' ); ?> <span class="dashicons dashicons-arrow-down imgedit-help-toggle"></span></button></h2>
       
   174 					<div class="imgedit-help imgedit-restore">
       
   175 					<p>
       
   176 					<?php
       
   177 					_e( 'Discard any changes and restore the original image.' );
       
   178 					if ( ! defined( 'IMAGE_EDIT_OVERWRITE' ) || ! IMAGE_EDIT_OVERWRITE ) {
       
   179 						echo ' ' . __( 'Previously edited copies of the image will not be deleted.' );
       
   180 					}
       
   181 					?>
       
   182 					</p>
       
   183 					<div class="imgedit-submit">
       
   184 						<input type="button" onclick="imageEdit.action(<?php echo "$post_id, '$nonce'"; ?>, 'restore')" class="button button-primary" value="<?php esc_attr_e( 'Restore image' ); ?>" <?php echo $can_restore; ?> />
       
   185 					</div>
       
   186 				</div>
       
   187 			</div>
       
   188 			</div>
       
   189 		<?php } ?>
       
   190 			<div class="imgedit-group">
       
   191 				<div id="imgedit-crop" tabindex="-1" class="imgedit-group-controls">
       
   192 				<div class="imgedit-group-top">
       
   193 					<h2><?php _e( 'Crop Image' ); ?></h2>
       
   194 					<button type="button" class="dashicons dashicons-editor-help imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);" aria-expanded="false"><span class="screen-reader-text">
       
   195 					<?php
       
   196 					/* translators: Hidden accessibility text. */
       
   197 					_e( 'Image Crop Help' );
       
   198 					?>
       
   199 					</span></button>
       
   200 					<div class="imgedit-help">
       
   201 						<p><?php _e( 'To crop the image, click on it and drag to make your selection.' ); ?></p>
       
   202 						<p><strong><?php _e( 'Crop Aspect Ratio' ); ?></strong><br />
       
   203 						<?php _e( 'The aspect ratio is the relationship between the width and height. You can preserve the aspect ratio by holding down the shift key while resizing your selection. Use the input box to specify the aspect ratio, e.g. 1:1 (square), 4:3, 16:9, etc.' ); ?></p>
       
   204 
       
   205 						<p><strong><?php _e( 'Crop Selection' ); ?></strong><br />
       
   206 						<?php _e( 'Once you have made your selection, you can adjust it by entering the size in pixels. The minimum selection size is the thumbnail size as set in the Media settings.' ); ?></p>
       
   207 					</div>
       
   208 				</div>
       
   209 				<fieldset class="imgedit-crop-ratio">
       
   210 					<legend><?php _e( 'Aspect ratio:' ); ?></legend>
       
   211 					<div class="nowrap">
       
   212 					<label for="imgedit-crop-width-<?php echo $post_id; ?>" class="screen-reader-text">
       
   213 					<?php
       
   214 					/* translators: Hidden accessibility text. */
       
   215 					_e( 'crop ratio width' );
       
   216 					?>
       
   217 					</label>
       
   218 					<input type="number" step="1" min="1" 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)" />
       
   219 					<span class="imgedit-separator" aria-hidden="true">:</span>
       
   220 					<label for="imgedit-crop-height-<?php echo $post_id; ?>" class="screen-reader-text">
       
   221 					<?php
       
   222 					/* translators: Hidden accessibility text. */
       
   223 					_e( 'crop ratio height' );
       
   224 					?>
       
   225 					</label>
       
   226 					<input  type="number" step="1" min="0" 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)" />
       
   227 					</div>
       
   228 				</fieldset>
       
   229 				<fieldset id="imgedit-crop-sel-<?php echo $post_id; ?>" class="imgedit-crop-sel">
       
   230 					<legend><?php _e( 'Selection:' ); ?></legend>
       
   231 					<div class="nowrap">
       
   232 					<label for="imgedit-sel-width-<?php echo $post_id; ?>" class="screen-reader-text">
       
   233 					<?php
       
   234 					/* translators: Hidden accessibility text. */
       
   235 					_e( 'selection width' );
       
   236 					?>
       
   237 					</label>
       
   238 					<input  type="number" step="1" min="0" id="imgedit-sel-width-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" onblur="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" />
       
   239 					<span class="imgedit-separator" aria-hidden="true">&times;</span>
       
   240 					<label for="imgedit-sel-height-<?php echo $post_id; ?>" class="screen-reader-text">
       
   241 					<?php
       
   242 					/* translators: Hidden accessibility text. */
       
   243 					_e( 'selection height' );
       
   244 					?>
       
   245 					</label>
       
   246 					<input  type="number" step="1" min="0" id="imgedit-sel-height-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" onblur="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" />
       
   247 					</div>
       
   248 				</fieldset>
       
   249 				<fieldset id="imgedit-crop-sel-<?php echo $post_id; ?>" class="imgedit-crop-sel">
       
   250 					<legend><?php _e( 'Starting Coordinates:' ); ?></legend>
       
   251 					<div class="nowrap">
       
   252 					<label for="imgedit-start-x-<?php echo $post_id; ?>" class="screen-reader-text">
       
   253 					<?php
       
   254 					/* translators: Hidden accessibility text. */
       
   255 					_e( 'horizontal start position' );
       
   256 					?>
       
   257 					</label>
       
   258 					<input  type="number" step="1" min="0" id="imgedit-start-x-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" onblur="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" value="0" />
       
   259 					<span class="imgedit-separator" aria-hidden="true">&times;</span>
       
   260 					<label for="imgedit-start-y-<?php echo $post_id; ?>" class="screen-reader-text">
       
   261 					<?php
       
   262 					/* translators: Hidden accessibility text. */
       
   263 					_e( 'vertical start position' );
       
   264 					?>
       
   265 					</label>
       
   266 					<input  type="number" step="1" min="0" id="imgedit-start-y-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" onblur="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" value="0" />
       
   267 					</div>
       
   268 				</fieldset>
       
   269 				<div class="imgedit-crop-apply imgedit-menu container">
       
   270 					<button class="button-primary" type="button" onclick="imageEdit.handleCropToolClick( <?php echo "$post_id, '$nonce'"; ?>, this );" class="imgedit-crop-apply button"><?php esc_html_e( 'Apply Crop' ); ?></button> <button type="button" onclick="imageEdit.handleCropToolClick( <?php echo "$post_id, '$nonce'"; ?>, this );" class="imgedit-crop-clear button" disabled="disabled"><?php esc_html_e( 'Clear Crop' ); ?></button>
       
   271 				</div>
       
   272 			</div>
   145 		</div>
   273 		</div>
   146 	</div>
   274 	</div>
   147 	</div>
   275 
   148 
   276 	<?php
   149 	<?php if ( $can_restore ) { ?>
   277 	if ( $edit_thumbnails_separately && $thumb && $sub_sizes ) {
   150 
   278 		$thumb_img = wp_constrain_dimensions( $thumb['width'], $thumb['height'], 160, 120 );
   151 	<div class="imgedit-group">
   279 		?>
   152 	<div class="imgedit-group-top">
   280 
   153 		<h2><button type="button" onclick="imageEdit.toggleHelp(this);" class="button-link" aria-expanded="false"><?php _e( 'Restore original image' ); ?> <span class="dashicons dashicons-arrow-down imgedit-help-toggle"></span></button></h2>
   281 	<div class="imgedit-group imgedit-applyto">
   154 		<div class="imgedit-help imgedit-restore">
   282 		<div class="imgedit-group-top">
   155 		<p>
   283 			<h2><?php _e( 'Thumbnail Settings' ); ?></h2>
       
   284 			<button type="button" class="dashicons dashicons-editor-help imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);" aria-expanded="false"><span class="screen-reader-text">
   156 			<?php
   285 			<?php
   157 			_e( 'Discard any changes and restore the original image.' );
   286 			/* translators: Hidden accessibility text. */
   158 
   287 			esc_html_e( 'Thumbnail Settings Help' );
   159 			if ( ! defined( 'IMAGE_EDIT_OVERWRITE' ) || ! IMAGE_EDIT_OVERWRITE ) {
       
   160 				echo ' ' . __( 'Previously edited copies of the image will not be deleted.' );
       
   161 			}
       
   162 			?>
   288 			?>
   163 		</p>
   289 			</span></button>
   164 		<div class="imgedit-submit">
   290 			<div class="imgedit-help">
   165 		<input type="button" onclick="imageEdit.action(<?php echo "$post_id, '$nonce'"; ?>, 'restore')" class="button button-primary" value="<?php esc_attr_e( 'Restore image' ); ?>" <?php echo $can_restore; ?> />
   291 			<p><?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>
       
   292 			</div>
   166 		</div>
   293 		</div>
       
   294 		<div class="imgedit-thumbnail-preview-group">
       
   295 			<figure class="imgedit-thumbnail-preview">
       
   296 				<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" />
       
   297 				<figcaption class="imgedit-thumbnail-preview-caption"><?php _e( 'Current thumbnail' ); ?></figcaption>
       
   298 			</figure>
       
   299 			<div id="imgedit-save-target-<?php echo $post_id; ?>" class="imgedit-save-target">
       
   300 			<fieldset>
       
   301 				<legend><?php _e( 'Apply changes to:' ); ?></legend>
       
   302 
       
   303 				<span class="imgedit-label">
       
   304 					<input type="radio" id="imgedit-target-all" name="imgedit-target-<?php echo $post_id; ?>" value="all" checked="checked" />
       
   305 					<label for="imgedit-target-all"><?php _e( 'All image sizes' ); ?></label>
       
   306 				</span>
       
   307 
       
   308 				<span class="imgedit-label">
       
   309 					<input type="radio" id="imgedit-target-thumbnail" name="imgedit-target-<?php echo $post_id; ?>" value="thumbnail" />
       
   310 					<label for="imgedit-target-thumbnail"><?php _e( 'Thumbnail' ); ?></label>
       
   311 				</span>
       
   312 
       
   313 				<span class="imgedit-label">
       
   314 					<input type="radio" id="imgedit-target-nothumb" name="imgedit-target-<?php echo $post_id; ?>" value="nothumb" />
       
   315 					<label for="imgedit-target-nothumb"><?php _e( 'All sizes except thumbnail' ); ?></label>
       
   316 				</span>
       
   317 
       
   318 				</fieldset>
       
   319 			</div>
   167 		</div>
   320 		</div>
   168 	</div>
   321 	</div>
   169 	</div>
       
   170 
       
   171 	<?php } ?>
   322 	<?php } ?>
   172 
       
   173 	<div class="imgedit-group">
       
   174 	<div class="imgedit-group-top">
       
   175 		<h2><?php _e( 'Image Crop' ); ?></h2>
       
   176 		<button type="button" class="dashicons dashicons-editor-help imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);" aria-expanded="false"><span class="screen-reader-text"><?php esc_html_e( 'Image Crop Help' ); ?></span></button>
       
   177 
       
   178 		<div class="imgedit-help">
       
   179 		<p><?php _e( 'To crop the image, click on it and drag to make your selection.' ); ?></p>
       
   180 
       
   181 		<p><strong><?php _e( 'Crop Aspect Ratio' ); ?></strong><br />
       
   182 		<?php _e( 'The aspect ratio is the relationship between the width and height. You can preserve the aspect ratio by holding down the shift key while resizing your selection. Use the input box to specify the aspect ratio, e.g. 1:1 (square), 4:3, 16:9, etc.' ); ?></p>
       
   183 
       
   184 		<p><strong><?php _e( 'Crop Selection' ); ?></strong><br />
       
   185 		<?php _e( 'Once you have made your selection, you can adjust it by entering the size in pixels. The minimum selection size is the thumbnail size as set in the Media settings.' ); ?></p>
       
   186 		</div>
   323 		</div>
   187 	</div>
   324 	</div>
   188 
   325 
   189 	<fieldset class="imgedit-crop-ratio">
       
   190 		<legend><?php _e( 'Aspect ratio:' ); ?></legend>
       
   191 		<div class="nowrap">
       
   192 		<label for="imgedit-crop-width-<?php echo $post_id; ?>" class="screen-reader-text"><?php _e( 'crop ratio width' ); ?></label>
       
   193 		<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)" />
       
   194 		<span class="imgedit-separator" aria-hidden="true">:</span>
       
   195 		<label for="imgedit-crop-height-<?php echo $post_id; ?>" class="screen-reader-text"><?php _e( 'crop ratio height' ); ?></label>
       
   196 		<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)" />
       
   197 		</div>
       
   198 	</fieldset>
       
   199 
       
   200 	<fieldset id="imgedit-crop-sel-<?php echo $post_id; ?>" class="imgedit-crop-sel">
       
   201 		<legend><?php _e( 'Selection:' ); ?></legend>
       
   202 		<div class="nowrap">
       
   203 		<label for="imgedit-sel-width-<?php echo $post_id; ?>" class="screen-reader-text"><?php _e( 'selection width' ); ?></label>
       
   204 		<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)" />
       
   205 		<span class="imgedit-separator" aria-hidden="true">&times;</span>
       
   206 		<label for="imgedit-sel-height-<?php echo $post_id; ?>" class="screen-reader-text"><?php _e( 'selection height' ); ?></label>
       
   207 		<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)" />
       
   208 		</div>
       
   209 	</fieldset>
       
   210 
       
   211 	</div>
   326 	</div>
   212 
   327 
   213 	<?php
       
   214 	if ( $thumb && $sub_sizes ) {
       
   215 		$thumb_img = wp_constrain_dimensions( $thumb['width'], $thumb['height'], 160, 120 );
       
   216 		?>
       
   217 
       
   218 	<div class="imgedit-group imgedit-applyto">
       
   219 	<div class="imgedit-group-top">
       
   220 		<h2><?php _e( 'Thumbnail Settings' ); ?></h2>
       
   221 		<button type="button" class="dashicons dashicons-editor-help imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);" aria-expanded="false"><span class="screen-reader-text"><?php esc_html_e( 'Thumbnail Settings Help' ); ?></span></button>
       
   222 		<div class="imgedit-help">
       
   223 		<p><?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>
       
   224 		</div>
       
   225 	</div>
       
   226 
       
   227 	<figure class="imgedit-thumbnail-preview">
       
   228 		<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" />
       
   229 		<figcaption class="imgedit-thumbnail-preview-caption"><?php _e( 'Current thumbnail' ); ?></figcaption>
       
   230 	</figure>
       
   231 
       
   232 	<div id="imgedit-save-target-<?php echo $post_id; ?>" class="imgedit-save-target">
       
   233 	<fieldset>
       
   234 		<legend><?php _e( 'Apply changes to:' ); ?></legend>
       
   235 
       
   236 		<span class="imgedit-label">
       
   237 			<input type="radio" id="imgedit-target-all" name="imgedit-target-<?php echo $post_id; ?>" value="all" checked="checked" />
       
   238 			<label for="imgedit-target-all"><?php _e( 'All image sizes' ); ?></label>
       
   239 		</span>
       
   240 
       
   241 		<span class="imgedit-label">
       
   242 			<input type="radio" id="imgedit-target-thumbnail" name="imgedit-target-<?php echo $post_id; ?>" value="thumbnail" />
       
   243 			<label for="imgedit-target-thumbnail"><?php _e( 'Thumbnail' ); ?></label>
       
   244 		</span>
       
   245 
       
   246 		<span class="imgedit-label">
       
   247 			<input type="radio" id="imgedit-target-nothumb" name="imgedit-target-<?php echo $post_id; ?>" value="nothumb" />
       
   248 			<label for="imgedit-target-nothumb"><?php _e( 'All sizes except thumbnail' ); ?></label>
       
   249 		</span>
       
   250 		<?php
       
   251 		if ( $edit_custom_sizes ) {
       
   252 			if ( ! is_array( $edit_custom_sizes ) ) {
       
   253 				$edit_custom_sizes = get_intermediate_image_sizes();
       
   254 			}
       
   255 			foreach ( array_unique( $edit_custom_sizes ) as $key => $size ) {
       
   256 				if ( array_key_exists( $size, $meta['sizes'] ) ) {
       
   257 					if ( 'thumbnail' === $size ) {
       
   258 						continue;
       
   259 					}
       
   260 					?>
       
   261 					<span class="imgedit-label">
       
   262 						<input type="radio" id="imgedit-target-custom<?php echo esc_attr( $key ); ?>" name="imgedit-target-<?php echo $post_id; ?>" value="<?php echo esc_attr( $size ); ?>" />
       
   263 						<label for="imgedit-target-custom<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $size ); ?></label>
       
   264 					</span>
       
   265 					<?php
       
   266 				}
       
   267 			}
       
   268 		}
       
   269 		?>
       
   270 	</fieldset>
       
   271 	</div>
       
   272 	</div>
       
   273 
       
   274 	<?php } ?>
       
   275 
       
   276 	</div>
       
   277 
       
   278 	</div>
       
   279 	<div class="imgedit-wait" id="imgedit-wait-<?php echo $post_id; ?>"></div>
   328 	<div class="imgedit-wait" id="imgedit-wait-<?php echo $post_id; ?>"></div>
   280 	<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>
   329 	<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>
   281 	</div>
   330 	</div>
   282 	<?php
   331 	<?php
   283 }
   332 }
   339 				if ( function_exists( 'imagewebp' ) ) {
   388 				if ( function_exists( 'imagewebp' ) ) {
   340 					header( 'Content-Type: image/webp' );
   389 					header( 'Content-Type: image/webp' );
   341 					return imagewebp( $image, null, 90 );
   390 					return imagewebp( $image, null, 90 );
   342 				}
   391 				}
   343 				return false;
   392 				return false;
       
   393 			case 'image/avif':
       
   394 				if ( function_exists( 'imageavif' ) ) {
       
   395 					header( 'Content-Type: image/avif' );
       
   396 					return imageavif( $image, null, 90 );
       
   397 				}
       
   398 				return false;
   344 			default:
   399 			default:
   345 				return false;
   400 				return false;
   346 		}
   401 		}
   347 	}
   402 	}
   348 }
   403 }
   349 
   404 
   350 /**
   405 /**
   351  * Saves image to file.
   406  * Saves image to file.
   352  *
   407  *
   353  * @since 2.9.0
   408  * @since 2.9.0
       
   409  * @since 3.5.0 The `$image` parameter expects a `WP_Image_Editor` instance.
       
   410  * @since 6.0.0 The `$filesize` value was added to the returned array.
   354  *
   411  *
   355  * @param string          $filename  Name of the file to be saved.
   412  * @param string          $filename  Name of the file to be saved.
   356  * @param WP_Image_Editor $image     The image editor instance.
   413  * @param WP_Image_Editor $image     The image editor instance.
   357  * @param string          $mime_type The mime type of the image.
   414  * @param string          $mime_type The mime type of the image.
   358  * @param int             $post_id   Attachment post ID.
   415  * @param int             $post_id   Attachment post ID.
   359  * @return bool True on success, false on failure.
   416  * @return array|WP_Error|bool {
       
   417  *     Array on success or WP_Error if the file failed to save.
       
   418  *     When called with a deprecated value for the `$image` parameter,
       
   419  *     i.e. a non-`WP_Image_Editor` image resource or `GdImage` instance,
       
   420  *     the function will return true on success, false on failure.
       
   421  *
       
   422  *     @type string $path      Path to the image file.
       
   423  *     @type string $file      Name of the image file.
       
   424  *     @type int    $width     Image width.
       
   425  *     @type int    $height    Image height.
       
   426  *     @type string $mime-type The mime type of the image.
       
   427  *     @type int    $filesize  File size of the image.
       
   428  * }
   360  */
   429  */
   361 function wp_save_image_file( $filename, $image, $mime_type, $post_id ) {
   430 function wp_save_image_file( $filename, $image, $mime_type, $post_id ) {
   362 	if ( $image instanceof WP_Image_Editor ) {
   431 	if ( $image instanceof WP_Image_Editor ) {
   363 
   432 
   364 		/** This filter is documented in wp-admin/includes/image-edit.php */
   433 		/** This filter is documented in wp-admin/includes/image-edit.php */
   429 			case 'image/webp':
   498 			case 'image/webp':
   430 				if ( function_exists( 'imagewebp' ) ) {
   499 				if ( function_exists( 'imagewebp' ) ) {
   431 					return imagewebp( $image, $filename );
   500 					return imagewebp( $image, $filename );
   432 				}
   501 				}
   433 				return false;
   502 				return false;
       
   503 			case 'image/avif':
       
   504 				if ( function_exists( 'imageavif' ) ) {
       
   505 					return imageavif( $image, $filename );
       
   506 				}
       
   507 				return false;
   434 			default:
   508 			default:
   435 				return false;
   509 				return false;
   436 		}
   510 		}
   437 	}
   511 	}
   438 }
   512 }
   447  * @param int $h Image height in pixels.
   521  * @param int $h Image height in pixels.
   448  * @return float|int Image preview ratio.
   522  * @return float|int Image preview ratio.
   449  */
   523  */
   450 function _image_get_preview_ratio( $w, $h ) {
   524 function _image_get_preview_ratio( $w, $h ) {
   451 	$max = max( $w, $h );
   525 	$max = max( $w, $h );
   452 	return $max > 400 ? ( 400 / $max ) : 1;
   526 	return $max > 600 ? ( 600 / $max ) : 1;
   453 }
   527 }
   454 
   528 
   455 /**
   529 /**
   456  * Returns an image resource. Internal use only.
   530  * Returns an image resource. Internal use only.
   457  *
   531  *
   572 		} elseif ( isset( $obj->c ) ) {
   646 		} elseif ( isset( $obj->c ) ) {
   573 			$obj->type = 'crop';
   647 			$obj->type = 'crop';
   574 			$obj->sel  = $obj->c;
   648 			$obj->sel  = $obj->c;
   575 			unset( $obj->c );
   649 			unset( $obj->c );
   576 		}
   650 		}
       
   651 
   577 		$changes[ $key ] = $obj;
   652 		$changes[ $key ] = $obj;
   578 	}
   653 	}
   579 
   654 
   580 	// Combine operations.
   655 	// Combine operations.
   581 	if ( count( $changes ) > 1 ) {
   656 	if ( count( $changes ) > 1 ) {
   582 		$filtered = array( $changes[0] );
   657 		$filtered = array( $changes[0] );
       
   658 
   583 		for ( $i = 0, $j = 1, $c = count( $changes ); $j < $c; $j++ ) {
   659 		for ( $i = 0, $j = 1, $c = count( $changes ); $j < $c; $j++ ) {
   584 			$combined = false;
   660 			$combined = false;
   585 			if ( $filtered[ $i ]->type == $changes[ $j ]->type ) {
   661 
       
   662 			if ( $filtered[ $i ]->type === $changes[ $j ]->type ) {
   586 				switch ( $filtered[ $i ]->type ) {
   663 				switch ( $filtered[ $i ]->type ) {
   587 					case 'rotate':
   664 					case 'rotate':
   588 						$filtered[ $i ]->angle += $changes[ $j ]->angle;
   665 						$filtered[ $i ]->angle += $changes[ $j ]->angle;
   589 						$combined               = true;
   666 						$combined               = true;
   590 						break;
   667 						break;
   592 						$filtered[ $i ]->axis ^= $changes[ $j ]->axis;
   669 						$filtered[ $i ]->axis ^= $changes[ $j ]->axis;
   593 						$combined              = true;
   670 						$combined              = true;
   594 						break;
   671 						break;
   595 				}
   672 				}
   596 			}
   673 			}
       
   674 
   597 			if ( ! $combined ) {
   675 			if ( ! $combined ) {
   598 				$filtered[ ++$i ] = $changes[ $j ];
   676 				$filtered[ ++$i ] = $changes[ $j ];
   599 			}
   677 			}
   600 		}
   678 		}
       
   679 
   601 		$changes = $filtered;
   680 		$changes = $filtered;
   602 		unset( $filtered );
   681 		unset( $filtered );
   603 	}
   682 	}
   604 
   683 
   605 	// Image resource before applying the changes.
   684 	// Image resource before applying the changes.
   629 	}
   708 	}
   630 
   709 
   631 	foreach ( $changes as $operation ) {
   710 	foreach ( $changes as $operation ) {
   632 		switch ( $operation->type ) {
   711 		switch ( $operation->type ) {
   633 			case 'rotate':
   712 			case 'rotate':
   634 				if ( 0 != $operation->angle ) {
   713 				if ( 0 !== $operation->angle ) {
   635 					if ( $image instanceof WP_Image_Editor ) {
   714 					if ( $image instanceof WP_Image_Editor ) {
   636 						$image->rotate( $operation->angle );
   715 						$image->rotate( $operation->angle );
   637 					} else {
   716 					} else {
   638 						$image = _rotate_image_resource( $image, $operation->angle );
   717 						$image = _rotate_image_resource( $image, $operation->angle );
   639 					}
   718 					}
   640 				}
   719 				}
   641 				break;
   720 				break;
   642 			case 'flip':
   721 			case 'flip':
   643 				if ( 0 != $operation->axis ) {
   722 				if ( 0 !== $operation->axis ) {
   644 					if ( $image instanceof WP_Image_Editor ) {
   723 					if ( $image instanceof WP_Image_Editor ) {
   645 						$image->flip( ( $operation->axis & 1 ) != 0, ( $operation->axis & 2 ) != 0 );
   724 						$image->flip( ( $operation->axis & 1 ) !== 0, ( $operation->axis & 2 ) !== 0 );
   646 					} else {
   725 					} else {
   647 						$image = _flip_image_resource( $image, ( $operation->axis & 1 ) != 0, ( $operation->axis & 2 ) != 0 );
   726 						$image = _flip_image_resource( $image, ( $operation->axis & 1 ) !== 0, ( $operation->axis & 2 ) !== 0 );
   648 					}
   727 					}
   649 				}
   728 				}
   650 				break;
   729 				break;
   651 			case 'crop':
   730 			case 'crop':
   652 				$sel = $operation->sel;
   731 				$sel = $operation->sel;
   655 					$size = $image->get_size();
   734 					$size = $image->get_size();
   656 					$w    = $size['width'];
   735 					$w    = $size['width'];
   657 					$h    = $size['height'];
   736 					$h    = $size['height'];
   658 
   737 
   659 					$scale = 1 / _image_get_preview_ratio( $w, $h ); // Discard preview scaling.
   738 					$scale = 1 / _image_get_preview_ratio( $w, $h ); // Discard preview scaling.
   660 					$image->crop( $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale );
   739 					$image->crop( (int) ( $sel->x * $scale ), (int) ( $sel->y * $scale ), (int) ( $sel->w * $scale ), (int) ( $sel->h * $scale ) );
   661 				} else {
   740 				} else {
   662 					$scale = 1 / _image_get_preview_ratio( imagesx( $image ), imagesy( $image ) ); // Discard preview scaling.
   741 					$scale = 1 / _image_get_preview_ratio( imagesx( $image ), imagesy( $image ) ); // Discard preview scaling.
   663 					$image = _crop_image_resource( $image, $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale );
   742 					$image = _crop_image_resource( $image, $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale );
   664 				}
   743 				}
   665 				break;
   744 				break;
   723 	$meta             = wp_get_attachment_metadata( $post_id );
   802 	$meta             = wp_get_attachment_metadata( $post_id );
   724 	$file             = get_attached_file( $post_id );
   803 	$file             = get_attached_file( $post_id );
   725 	$backup_sizes     = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
   804 	$backup_sizes     = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
   726 	$old_backup_sizes = $backup_sizes;
   805 	$old_backup_sizes = $backup_sizes;
   727 	$restored         = false;
   806 	$restored         = false;
   728 	$msg              = new stdClass;
   807 	$msg              = new stdClass();
   729 
   808 
   730 	if ( ! is_array( $backup_sizes ) ) {
   809 	if ( ! is_array( $backup_sizes ) ) {
   731 		$msg->error = __( 'Cannot load image metadata.' );
   810 		$msg->error = __( 'Cannot load image metadata.' );
   732 		return $msg;
   811 		return $msg;
   733 	}
   812 	}
   737 	$default_sizes = get_intermediate_image_sizes();
   816 	$default_sizes = get_intermediate_image_sizes();
   738 
   817 
   739 	if ( isset( $backup_sizes['full-orig'] ) && is_array( $backup_sizes['full-orig'] ) ) {
   818 	if ( isset( $backup_sizes['full-orig'] ) && is_array( $backup_sizes['full-orig'] ) ) {
   740 		$data = $backup_sizes['full-orig'];
   819 		$data = $backup_sizes['full-orig'];
   741 
   820 
   742 		if ( $parts['basename'] != $data['file'] ) {
   821 		if ( $parts['basename'] !== $data['file'] ) {
   743 			if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE ) {
   822 			if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE ) {
   744 
       
   745 				// Delete only if it's an edited image.
   823 				// Delete only if it's an edited image.
   746 				if ( preg_match( '/-e[0-9]{13}\./', $parts['basename'] ) ) {
   824 				if ( preg_match( '/-e[0-9]{13}\./', $parts['basename'] ) ) {
   747 					wp_delete_file( $file );
   825 					wp_delete_file( $file );
   748 				}
   826 				}
   749 			} elseif ( isset( $meta['width'], $meta['height'] ) ) {
   827 			} elseif ( isset( $meta['width'], $meta['height'] ) ) {
   764 	}
   842 	}
   765 
   843 
   766 	foreach ( $default_sizes as $default_size ) {
   844 	foreach ( $default_sizes as $default_size ) {
   767 		if ( isset( $backup_sizes[ "$default_size-orig" ] ) ) {
   845 		if ( isset( $backup_sizes[ "$default_size-orig" ] ) ) {
   768 			$data = $backup_sizes[ "$default_size-orig" ];
   846 			$data = $backup_sizes[ "$default_size-orig" ];
   769 			if ( isset( $meta['sizes'][ $default_size ] ) && $meta['sizes'][ $default_size ]['file'] != $data['file'] ) {
   847 
       
   848 			if ( isset( $meta['sizes'][ $default_size ] ) && $meta['sizes'][ $default_size ]['file'] !== $data['file'] ) {
   770 				if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE ) {
   849 				if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE ) {
   771 
       
   772 					// Delete only if it's an edited image.
   850 					// Delete only if it's an edited image.
   773 					if ( preg_match( '/-e[0-9]{13}-/', $meta['sizes'][ $default_size ]['file'] ) ) {
   851 					if ( preg_match( '/-e[0-9]{13}-/', $meta['sizes'][ $default_size ]['file'] ) ) {
   774 						$delete_file = path_join( $parts['dirname'], $meta['sizes'][ $default_size ]['file'] );
   852 						$delete_file = path_join( $parts['dirname'], $meta['sizes'][ $default_size ]['file'] );
   775 						wp_delete_file( $delete_file );
   853 						wp_delete_file( $delete_file );
   776 					}
   854 					}
   783 		} else {
   861 		} else {
   784 			unset( $meta['sizes'][ $default_size ] );
   862 			unset( $meta['sizes'][ $default_size ] );
   785 		}
   863 		}
   786 	}
   864 	}
   787 
   865 
   788 	if ( ! wp_update_attachment_metadata( $post_id, $meta ) ||
   866 	if ( ! wp_update_attachment_metadata( $post_id, $meta )
   789 		( $old_backup_sizes !== $backup_sizes && ! update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes ) ) ) {
   867 		|| ( $old_backup_sizes !== $backup_sizes && ! update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes ) )
   790 
   868 	) {
   791 		$msg->error = __( 'Cannot save image metadata.' );
   869 		$msg->error = __( 'Cannot save image metadata.' );
   792 		return $msg;
   870 		return $msg;
   793 	}
   871 	}
   794 
   872 
   795 	if ( ! $restored ) {
   873 	if ( ! $restored ) {
   796 		$msg->error = __( 'Image metadata is inconsistent.' );
   874 		$msg->error = __( 'Image metadata is inconsistent.' );
   797 	} else {
   875 	} else {
   798 		$msg->msg = __( 'Image restored successfully.' );
   876 		$msg->msg = __( 'Image restored successfully.' );
       
   877 
       
   878 		if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE ) {
       
   879 			delete_post_meta( $post_id, '_wp_attachment_backup_sizes' );
       
   880 		}
   799 	}
   881 	}
   800 
   882 
   801 	return $msg;
   883 	return $msg;
   802 }
   884 }
   803 
   885 
   811  * @return stdClass
   893  * @return stdClass
   812  */
   894  */
   813 function wp_save_image( $post_id ) {
   895 function wp_save_image( $post_id ) {
   814 	$_wp_additional_image_sizes = wp_get_additional_image_sizes();
   896 	$_wp_additional_image_sizes = wp_get_additional_image_sizes();
   815 
   897 
   816 	$return  = new stdClass;
   898 	$return  = new stdClass();
   817 	$success = false;
   899 	$success = false;
   818 	$delete  = false;
   900 	$delete  = false;
   819 	$scaled  = false;
   901 	$scaled  = false;
   820 	$nocrop  = false;
   902 	$nocrop  = false;
   821 	$post    = get_post( $post_id );
   903 	$post    = get_post( $post_id );
   822 
   904 
   823 	$img = wp_get_image_editor( _load_image_to_edit_path( $post_id, 'full' ) );
   905 	$img = wp_get_image_editor( _load_image_to_edit_path( $post_id, 'full' ) );
       
   906 
   824 	if ( is_wp_error( $img ) ) {
   907 	if ( is_wp_error( $img ) ) {
   825 		$return->error = esc_js( __( 'Unable to create new image.' ) );
   908 		$return->error = esc_js( __( 'Unable to create new image.' ) );
   826 		return $return;
   909 		return $return;
   827 	}
   910 	}
   828 
   911 
   829 	$fwidth  = ! empty( $_REQUEST['fwidth'] ) ? (int) $_REQUEST['fwidth'] : 0;
   912 	$full_width  = ! empty( $_REQUEST['fwidth'] ) ? (int) $_REQUEST['fwidth'] : 0;
   830 	$fheight = ! empty( $_REQUEST['fheight'] ) ? (int) $_REQUEST['fheight'] : 0;
   913 	$full_height = ! empty( $_REQUEST['fheight'] ) ? (int) $_REQUEST['fheight'] : 0;
   831 	$target  = ! empty( $_REQUEST['target'] ) ? preg_replace( '/[^a-z0-9_-]+/i', '', $_REQUEST['target'] ) : '';
   914 	$target      = ! empty( $_REQUEST['target'] ) ? preg_replace( '/[^a-z0-9_-]+/i', '', $_REQUEST['target'] ) : '';
   832 	$scale   = ! empty( $_REQUEST['do'] ) && 'scale' === $_REQUEST['do'];
   915 	$scale       = ! empty( $_REQUEST['do'] ) && 'scale' === $_REQUEST['do'];
   833 
   916 
   834 	if ( $scale && $fwidth > 0 && $fheight > 0 ) {
   917 	/** This filter is documented in wp-admin/includes/image-edit.php */
   835 		$size = $img->get_size();
   918 	$edit_thumbnails_separately = (bool) apply_filters( 'image_edit_thumbnails_separately', false );
   836 		$sX   = $size['width'];
   919 
   837 		$sY   = $size['height'];
   920 	if ( $scale ) {
   838 
   921 		$size            = $img->get_size();
   839 		// Check if it has roughly the same w / h ratio.
   922 		$original_width  = $size['width'];
   840 		$diff = round( $sX / $sY, 2 ) - round( $fwidth / $fheight, 2 );
   923 		$original_height = $size['height'];
   841 		if ( -0.1 < $diff && $diff < 0.1 ) {
   924 
   842 			// Scale the full size image.
   925 		if ( $full_width > $original_width || $full_height > $original_height ) {
   843 			if ( $img->resize( $fwidth, $fheight ) ) {
   926 			$return->error = esc_js( __( 'Images cannot be scaled to a size larger than the original.' ) );
   844 				$scaled = true;
       
   845 			}
       
   846 		}
       
   847 
       
   848 		if ( ! $scaled ) {
       
   849 			$return->error = esc_js( __( 'Error while saving the scaled image. Please reload the page and try again.' ) );
       
   850 			return $return;
   927 			return $return;
       
   928 		}
       
   929 
       
   930 		if ( $full_width > 0 && $full_height > 0 ) {
       
   931 			// Check if it has roughly the same w / h ratio.
       
   932 			$diff = round( $original_width / $original_height, 2 ) - round( $full_width / $full_height, 2 );
       
   933 			if ( -0.1 < $diff && $diff < 0.1 ) {
       
   934 				// Scale the full size image.
       
   935 				if ( $img->resize( $full_width, $full_height ) ) {
       
   936 					$scaled = true;
       
   937 				}
       
   938 			}
       
   939 
       
   940 			if ( ! $scaled ) {
       
   941 				$return->error = esc_js( __( 'Error while saving the scaled image. Please reload the page and try again.' ) );
       
   942 				return $return;
       
   943 			}
   851 		}
   944 		}
   852 	} elseif ( ! empty( $_REQUEST['history'] ) ) {
   945 	} elseif ( ! empty( $_REQUEST['history'] ) ) {
   853 		$changes = json_decode( wp_unslash( $_REQUEST['history'] ) );
   946 		$changes = json_decode( wp_unslash( $_REQUEST['history'] ) );
   854 		if ( $changes ) {
   947 		if ( $changes ) {
   855 			$img = image_edit_apply_changes( $img, $changes );
   948 			$img = image_edit_apply_changes( $img, $changes );
   878 	$dirname  = pathinfo( $path, PATHINFO_DIRNAME );
   971 	$dirname  = pathinfo( $path, PATHINFO_DIRNAME );
   879 	$ext      = pathinfo( $path, PATHINFO_EXTENSION );
   972 	$ext      = pathinfo( $path, PATHINFO_EXTENSION );
   880 	$filename = pathinfo( $path, PATHINFO_FILENAME );
   973 	$filename = pathinfo( $path, PATHINFO_FILENAME );
   881 	$suffix   = time() . rand( 100, 999 );
   974 	$suffix   = time() . rand( 100, 999 );
   882 
   975 
   883 	if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE &&
   976 	if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE
   884 		isset( $backup_sizes['full-orig'] ) && $backup_sizes['full-orig']['file'] != $basename ) {
   977 		&& isset( $backup_sizes['full-orig'] ) && $backup_sizes['full-orig']['file'] !== $basename
   885 
   978 	) {
   886 		if ( 'thumbnail' === $target ) {
   979 
       
   980 		if ( $edit_thumbnails_separately && 'thumbnail' === $target ) {
   887 			$new_path = "{$dirname}/{$filename}-temp.{$ext}";
   981 			$new_path = "{$dirname}/{$filename}-temp.{$ext}";
   888 		} else {
   982 		} else {
   889 			$new_path = $path;
   983 			$new_path = $path;
   890 		}
   984 		}
   891 	} else {
   985 	} else {
   892 		while ( true ) {
   986 		while ( true ) {
   893 			$filename     = preg_replace( '/-e([0-9]+)$/', '', $filename );
   987 			$filename     = preg_replace( '/-e([0-9]+)$/', '', $filename );
   894 			$filename    .= "-e{$suffix}";
   988 			$filename    .= "-e{$suffix}";
   895 			$new_filename = "{$filename}.{$ext}";
   989 			$new_filename = "{$filename}.{$ext}";
   896 			$new_path     = "{$dirname}/$new_filename";
   990 			$new_path     = "{$dirname}/$new_filename";
       
   991 
   897 			if ( file_exists( $new_path ) ) {
   992 			if ( file_exists( $new_path ) ) {
   898 				$suffix++;
   993 				++$suffix;
   899 			} else {
   994 			} else {
   900 				break;
   995 				break;
   901 			}
   996 			}
   902 		}
   997 		}
   903 	}
   998 	}
   908 		return $return;
  1003 		return $return;
   909 	}
  1004 	}
   910 
  1005 
   911 	if ( 'nothumb' === $target || 'all' === $target || 'full' === $target || $scaled ) {
  1006 	if ( 'nothumb' === $target || 'all' === $target || 'full' === $target || $scaled ) {
   912 		$tag = false;
  1007 		$tag = false;
       
  1008 
   913 		if ( isset( $backup_sizes['full-orig'] ) ) {
  1009 		if ( isset( $backup_sizes['full-orig'] ) ) {
   914 			if ( ( ! defined( 'IMAGE_EDIT_OVERWRITE' ) || ! IMAGE_EDIT_OVERWRITE ) && $backup_sizes['full-orig']['file'] !== $basename ) {
  1010 			if ( ( ! defined( 'IMAGE_EDIT_OVERWRITE' ) || ! IMAGE_EDIT_OVERWRITE )
       
  1011 				&& $backup_sizes['full-orig']['file'] !== $basename
       
  1012 			) {
   915 				$tag = "full-$suffix";
  1013 				$tag = "full-$suffix";
   916 			}
  1014 			}
   917 		} else {
  1015 		} else {
   918 			$tag = 'full-orig';
  1016 			$tag = 'full-orig';
   919 		}
  1017 		}
   923 				'width'  => $meta['width'],
  1021 				'width'  => $meta['width'],
   924 				'height' => $meta['height'],
  1022 				'height' => $meta['height'],
   925 				'file'   => $basename,
  1023 				'file'   => $basename,
   926 			);
  1024 			);
   927 		}
  1025 		}
       
  1026 
   928 		$success = ( $path === $new_path ) || update_attached_file( $post_id, $new_path );
  1027 		$success = ( $path === $new_path ) || update_attached_file( $post_id, $new_path );
   929 
  1028 
   930 		$meta['file'] = _wp_relative_upload_path( $new_path );
  1029 		$meta['file'] = _wp_relative_upload_path( $new_path );
   931 
  1030 
   932 		$size           = $img->get_size();
  1031 		$size           = $img->get_size();
   933 		$meta['width']  = $size['width'];
  1032 		$meta['width']  = $size['width'];
   934 		$meta['height'] = $size['height'];
  1033 		$meta['height'] = $size['height'];
   935 
  1034 
   936 		if ( $success ) {
  1035 		if ( $success && ( 'nothumb' === $target || 'all' === $target ) ) {
   937 			$sizes = get_intermediate_image_sizes();
  1036 			$sizes = get_intermediate_image_sizes();
   938 			if ( 'nothumb' === $target || 'all' === $target ) {
  1037 
   939 				if ( 'nothumb' === $target ) {
  1038 			if ( $edit_thumbnails_separately && 'nothumb' === $target ) {
   940 					$sizes = array_diff( $sizes, array( 'thumbnail' ) );
  1039 				$sizes = array_diff( $sizes, array( 'thumbnail' ) );
   941 				}
       
   942 			} elseif ( 'thumbnail' !== $target ) {
       
   943 				$sizes = array_diff( $sizes, array( $target ) );
       
   944 			}
  1040 			}
   945 		}
  1041 		}
   946 
  1042 
   947 		$return->fw = $meta['width'];
  1043 		$return->fw = $meta['width'];
   948 		$return->fh = $meta['height'];
  1044 		$return->fh = $meta['height'];
   949 	} elseif ( 'thumbnail' === $target ) {
  1045 	} elseif ( $edit_thumbnails_separately && 'thumbnail' === $target ) {
   950 		$sizes   = array( 'thumbnail' );
  1046 		$sizes   = array( 'thumbnail' );
   951 		$success = true;
  1047 		$success = true;
   952 		$delete  = true;
  1048 		$delete  = true;
   953 		$nocrop  = true;
  1049 		$nocrop  = true;
   954 	} else {
       
   955 		$sizes   = array( $target );
       
   956 		$success = true;
       
   957 		$delete  = true;
       
   958 		$nocrop  = $_wp_additional_image_sizes[ $size ]['crop'];
       
   959 	}
  1050 	}
   960 
  1051 
   961 	/*
  1052 	/*
   962 	 * We need to remove any existing resized image files because
  1053 	 * We need to remove any existing resized image files because
   963 	 * a new crop or rotate could generate different sizes (and hence, filenames),
  1054 	 * a new crop or rotate could generate different sizes (and hence, filenames),
   976 	if ( isset( $sizes ) ) {
  1067 	if ( isset( $sizes ) ) {
   977 		$_sizes = array();
  1068 		$_sizes = array();
   978 
  1069 
   979 		foreach ( $sizes as $size ) {
  1070 		foreach ( $sizes as $size ) {
   980 			$tag = false;
  1071 			$tag = false;
       
  1072 
   981 			if ( isset( $meta['sizes'][ $size ] ) ) {
  1073 			if ( isset( $meta['sizes'][ $size ] ) ) {
   982 				if ( isset( $backup_sizes[ "$size-orig" ] ) ) {
  1074 				if ( isset( $backup_sizes[ "$size-orig" ] ) ) {
   983 					if ( ( ! defined( 'IMAGE_EDIT_OVERWRITE' ) || ! IMAGE_EDIT_OVERWRITE ) && $backup_sizes[ "$size-orig" ]['file'] != $meta['sizes'][ $size ]['file'] ) {
  1075 					if ( ( ! defined( 'IMAGE_EDIT_OVERWRITE' ) || ! IMAGE_EDIT_OVERWRITE )
       
  1076 						&& $backup_sizes[ "$size-orig" ]['file'] !== $meta['sizes'][ $size ]['file']
       
  1077 					) {
   984 						$tag = "$size-$suffix";
  1078 						$tag = "$size-$suffix";
   985 					}
  1079 					}
   986 				} else {
  1080 				} else {
   987 					$tag = "$size-orig";
  1081 					$tag = "$size-orig";
   988 				}
  1082 				}
  1019 		update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes );
  1113 		update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes );
  1020 
  1114 
  1021 		if ( 'thumbnail' === $target || 'all' === $target || 'full' === $target ) {
  1115 		if ( 'thumbnail' === $target || 'all' === $target || 'full' === $target ) {
  1022 			// Check if it's an image edit from attachment edit screen.
  1116 			// Check if it's an image edit from attachment edit screen.
  1023 			if ( ! empty( $_REQUEST['context'] ) && 'edit-attachment' === $_REQUEST['context'] ) {
  1117 			if ( ! empty( $_REQUEST['context'] ) && 'edit-attachment' === $_REQUEST['context'] ) {
  1024 				$thumb_url         = wp_get_attachment_image_src( $post_id, array( 900, 600 ), true );
  1118 				$thumb_url = wp_get_attachment_image_src( $post_id, array( 900, 600 ), true );
       
  1119 
  1025 				$return->thumbnail = $thumb_url[0];
  1120 				$return->thumbnail = $thumb_url[0];
  1026 			} else {
  1121 			} else {
  1027 				$file_url = wp_get_attachment_url( $post_id );
  1122 				$file_url = wp_get_attachment_url( $post_id );
       
  1123 
  1028 				if ( ! empty( $meta['sizes']['thumbnail'] ) ) {
  1124 				if ( ! empty( $meta['sizes']['thumbnail'] ) ) {
  1029 					$thumb             = $meta['sizes']['thumbnail'];
  1125 					$thumb             = $meta['sizes']['thumbnail'];
  1030 					$return->thumbnail = path_join( dirname( $file_url ), $thumb['file'] );
  1126 					$return->thumbnail = path_join( dirname( $file_url ), $thumb['file'] );
  1031 				} else {
  1127 				} else {
  1032 					$return->thumbnail = "$file_url?w=128&h=128";
  1128 					$return->thumbnail = "$file_url?w=128&h=128";
  1040 	if ( $delete ) {
  1136 	if ( $delete ) {
  1041 		wp_delete_file( $new_path );
  1137 		wp_delete_file( $new_path );
  1042 	}
  1138 	}
  1043 
  1139 
  1044 	$return->msg = esc_js( __( 'Image saved' ) );
  1140 	$return->msg = esc_js( __( 'Image saved' ) );
       
  1141 
  1045 	return $return;
  1142 	return $return;
  1046 }
  1143 }