[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-admin/includes/ -> image-edit.php (source)

   1  <?php
   2  /**
   3   * WordPress Image Editor
   4   *
   5   * @package WordPress
   6   * @subpackage Administration
   7   */
   8  
   9  /**
  10   * Loads the WP image-editing interface.
  11   *
  12   * @since 2.9.0
  13   *
  14   * @param int          $post_id Attachment post ID.
  15   * @param false|object $msg     Optional. Message to display for image editor updates or errors.
  16   *                              Default false.
  17   */
  18  function wp_image_editor( $post_id, $msg = false ) {
  19      $nonce     = wp_create_nonce( "image_editor-$post_id" );
  20      $meta      = wp_get_attachment_metadata( $post_id );
  21      $thumb     = image_get_intermediate_size( $post_id, 'thumbnail' );
  22      $sub_sizes = isset( $meta['sizes'] ) && is_array( $meta['sizes'] );
  23      $note      = '';
  24  
  25      if ( isset( $meta['width'], $meta['height'] ) ) {
  26          $big = max( $meta['width'], $meta['height'] );
  27      } else {
  28          die( __( 'Image data does not exist. Please re-upload the image.' ) );
  29      }
  30  
  31      $sizer = $big > 400 ? 400 / $big : 1;
  32  
  33      $backup_sizes = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
  34      $can_restore  = false;
  35      if ( ! empty( $backup_sizes ) && isset( $backup_sizes['full-orig'], $meta['file'] ) ) {
  36          $can_restore = wp_basename( $meta['file'] ) !== $backup_sizes['full-orig']['file'];
  37      }
  38  
  39      if ( $msg ) {
  40          if ( isset( $msg->error ) ) {
  41              $note = "<div class='notice notice-error' tabindex='-1' role='alert'><p>$msg->error</p></div>";
  42          } elseif ( isset( $msg->msg ) ) {
  43              $note = "<div class='notice notice-success' tabindex='-1' role='alert'><p>$msg->msg</p></div>";
  44          }
  45      }
  46      $edit_custom_sizes = false;
  47      /**
  48       * Filters whether custom sizes are available options for image editing.
  49       *
  50       * @since 6.0.0
  51       *
  52       * @param bool|string[] $edit_custom_sizes True if custom sizes can be edited or array of custom size names.
  53       */
  54      $edit_custom_sizes = apply_filters( 'edit_custom_thumbnail_sizes', $edit_custom_sizes );
  55      ?>
  56      <div class="imgedit-wrap wp-clearfix">
  57      <div id="imgedit-panel-<?php echo $post_id; ?>">
  58  
  59      <div class="imgedit-panel-content wp-clearfix">
  60          <?php echo $note; ?>
  61          <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              <?php
  64  
  65              // On some setups GD library does not provide imagerotate() - Ticket #11536.
  66              if ( wp_image_editor_supports(
  67                  array(
  68                      'mime_type' => get_post_mime_type( $post_id ),
  69                      'methods'   => array( 'rotate' ),
  70                  )
  71              ) ) {
  72                  $note_no_rotate = '';
  73                  ?>
  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>
  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>
  76                  <?php
  77              } else {
  78                  $note_no_rotate = '<p class="note-no-rotate"><em>' . __( 'Image rotation is not supported by your web host.' ) . '</em></p>';
  79                  ?>
  80                  <button type="button" class="imgedit-rleft button disabled" disabled></button>
  81                  <button type="button" class="imgedit-rright button disabled" disabled></button>
  82              <?php } ?>
  83  
  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>
  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>
  86  
  87              <br class="imgedit-undo-redo-separator" />
  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>
  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>
  90              <?php echo $note_no_rotate; ?>
  91          </div>
  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>
 109      </div>
 110  
 111      <div class="imgedit-settings">
 112      <div class="imgedit-group">
 113      <div class="imgedit-group-top">
 114          <h2><?php _e( 'Scale Image' ); ?></h2>
 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>
 116          <div class="imgedit-help">
 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>
 118          </div>
 119          <?php if ( isset( $meta['width'], $meta['height'] ) ) : ?>
 120          <p>
 121              <?php
 122              printf(
 123                  /* translators: %s: Image width and height in pixels. */
 124                  __( 'Original dimensions %s' ),
 125                  '<span class="imgedit-original-dimensions">' . $meta['width'] . ' &times; ' . $meta['height'] . '</span>'
 126              );
 127              ?>
 128          </p>
 129          <?php endif; ?>
 130          <div class="imgedit-submit">
 131  
 132          <fieldset class="imgedit-scale">
 133          <legend><?php _e( 'New dimensions:' ); ?></legend>
 134          <div class="nowrap">
 135          <label for="imgedit-scale-width-<?php echo $post_id; ?>" class="screen-reader-text"><?php _e( 'scale width' ); ?></label>
 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; ?>" />
 137          <span class="imgedit-separator" aria-hidden="true">&times;</span>
 138          <label for="imgedit-scale-height-<?php echo $post_id; ?>" class="screen-reader-text"><?php _e( 'scale height' ); ?></label>
 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; ?>" />
 140          <span class="imgedit-scale-warn" id="imgedit-scale-warn-<?php echo $post_id; ?>">!</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>
 142          </div>
 143          </fieldset>
 144  
 145          </div>
 146      </div>
 147      </div>
 148  
 149      <?php if ( $can_restore ) { ?>
 150  
 151      <div class="imgedit-group">
 152      <div class="imgedit-group-top">
 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>
 154          <div class="imgedit-help imgedit-restore">
 155          <p>
 156              <?php
 157              _e( 'Discard any changes and restore the original image.' );
 158  
 159              if ( ! defined( 'IMAGE_EDIT_OVERWRITE' ) || ! IMAGE_EDIT_OVERWRITE ) {
 160                  echo ' ' . __( 'Previously edited copies of the image will not be deleted.' );
 161              }
 162              ?>
 163          </p>
 164          <div class="imgedit-submit">
 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; ?> />
 166          </div>
 167          </div>
 168      </div>
 169      </div>
 170  
 171      <?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>
 187      </div>
 188  
 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>
 212  
 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>
 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>
 281      </div>
 282      <?php
 283  }
 284  
 285  /**
 286   * Streams image in WP_Image_Editor to browser.
 287   *
 288   * @since 2.9.0
 289   *
 290   * @param WP_Image_Editor $image         The image editor instance.
 291   * @param string          $mime_type     The mime type of the image.
 292   * @param int             $attachment_id The image's attachment post ID.
 293   * @return bool True on success, false on failure.
 294   */
 295  function wp_stream_image( $image, $mime_type, $attachment_id ) {
 296      if ( $image instanceof WP_Image_Editor ) {
 297  
 298          /**
 299           * Filters the WP_Image_Editor instance for the image to be streamed to the browser.
 300           *
 301           * @since 3.5.0
 302           *
 303           * @param WP_Image_Editor $image         The image editor instance.
 304           * @param int             $attachment_id The attachment post ID.
 305           */
 306          $image = apply_filters( 'image_editor_save_pre', $image, $attachment_id );
 307  
 308          if ( is_wp_error( $image->stream( $mime_type ) ) ) {
 309              return false;
 310          }
 311  
 312          return true;
 313      } else {
 314          /* translators: 1: $image, 2: WP_Image_Editor */
 315          _deprecated_argument( __FUNCTION__, '3.5.0', sprintf( __( '%1$s needs to be a %2$s object.' ), '$image', 'WP_Image_Editor' ) );
 316  
 317          /**
 318           * Filters the GD image resource to be streamed to the browser.
 319           *
 320           * @since 2.9.0
 321           * @deprecated 3.5.0 Use {@see 'image_editor_save_pre'} instead.
 322           *
 323           * @param resource|GdImage $image         Image resource to be streamed.
 324           * @param int              $attachment_id The attachment post ID.
 325           */
 326          $image = apply_filters_deprecated( 'image_save_pre', array( $image, $attachment_id ), '3.5.0', 'image_editor_save_pre' );
 327  
 328          switch ( $mime_type ) {
 329              case 'image/jpeg':
 330                  header( 'Content-Type: image/jpeg' );
 331                  return imagejpeg( $image, null, 90 );
 332              case 'image/png':
 333                  header( 'Content-Type: image/png' );
 334                  return imagepng( $image );
 335              case 'image/gif':
 336                  header( 'Content-Type: image/gif' );
 337                  return imagegif( $image );
 338              case 'image/webp':
 339                  if ( function_exists( 'imagewebp' ) ) {
 340                      header( 'Content-Type: image/webp' );
 341                      return imagewebp( $image, null, 90 );
 342                  }
 343                  return false;
 344              default:
 345                  return false;
 346          }
 347      }
 348  }
 349  
 350  /**
 351   * Saves image to file.
 352   *
 353   * @since 2.9.0
 354   *
 355   * @param string          $filename  Name of the file to be saved.
 356   * @param WP_Image_Editor $image     The image editor instance.
 357   * @param string          $mime_type The mime type of the image.
 358   * @param int             $post_id   Attachment post ID.
 359   * @return bool True on success, false on failure.
 360   */
 361  function wp_save_image_file( $filename, $image, $mime_type, $post_id ) {
 362      if ( $image instanceof WP_Image_Editor ) {
 363  
 364          /** This filter is documented in wp-admin/includes/image-edit.php */
 365          $image = apply_filters( 'image_editor_save_pre', $image, $post_id );
 366  
 367          /**
 368           * Filters whether to skip saving the image file.
 369           *
 370           * Returning a non-null value will short-circuit the save method,
 371           * returning that value instead.
 372           *
 373           * @since 3.5.0
 374           *
 375           * @param bool|null       $override  Value to return instead of saving. Default null.
 376           * @param string          $filename  Name of the file to be saved.
 377           * @param WP_Image_Editor $image     The image editor instance.
 378           * @param string          $mime_type The mime type of the image.
 379           * @param int             $post_id   Attachment post ID.
 380           */
 381          $saved = apply_filters( 'wp_save_image_editor_file', null, $filename, $image, $mime_type, $post_id );
 382  
 383          if ( null !== $saved ) {
 384              return $saved;
 385          }
 386  
 387          return $image->save( $filename, $mime_type );
 388      } else {
 389          /* translators: 1: $image, 2: WP_Image_Editor */
 390          _deprecated_argument( __FUNCTION__, '3.5.0', sprintf( __( '%1$s needs to be a %2$s object.' ), '$image', 'WP_Image_Editor' ) );
 391  
 392          /** This filter is documented in wp-admin/includes/image-edit.php */
 393          $image = apply_filters_deprecated( 'image_save_pre', array( $image, $post_id ), '3.5.0', 'image_editor_save_pre' );
 394  
 395          /**
 396           * Filters whether to skip saving the image file.
 397           *
 398           * Returning a non-null value will short-circuit the save method,
 399           * returning that value instead.
 400           *
 401           * @since 2.9.0
 402           * @deprecated 3.5.0 Use {@see 'wp_save_image_editor_file'} instead.
 403           *
 404           * @param bool|null        $override  Value to return instead of saving. Default null.
 405           * @param string           $filename  Name of the file to be saved.
 406           * @param resource|GdImage $image     Image resource or GdImage instance.
 407           * @param string           $mime_type The mime type of the image.
 408           * @param int              $post_id   Attachment post ID.
 409           */
 410          $saved = apply_filters_deprecated(
 411              'wp_save_image_file',
 412              array( null, $filename, $image, $mime_type, $post_id ),
 413              '3.5.0',
 414              'wp_save_image_editor_file'
 415          );
 416  
 417          if ( null !== $saved ) {
 418              return $saved;
 419          }
 420  
 421          switch ( $mime_type ) {
 422              case 'image/jpeg':
 423                  /** This filter is documented in wp-includes/class-wp-image-editor.php */
 424                  return imagejpeg( $image, $filename, apply_filters( 'jpeg_quality', 90, 'edit_image' ) );
 425              case 'image/png':
 426                  return imagepng( $image, $filename );
 427              case 'image/gif':
 428                  return imagegif( $image, $filename );
 429              case 'image/webp':
 430                  if ( function_exists( 'imagewebp' ) ) {
 431                      return imagewebp( $image, $filename );
 432                  }
 433                  return false;
 434              default:
 435                  return false;
 436          }
 437      }
 438  }
 439  
 440  /**
 441   * Image preview ratio. Internal use only.
 442   *
 443   * @since 2.9.0
 444   *
 445   * @ignore
 446   * @param int $w Image width in pixels.
 447   * @param int $h Image height in pixels.
 448   * @return float|int Image preview ratio.
 449   */
 450  function _image_get_preview_ratio( $w, $h ) {
 451      $max = max( $w, $h );
 452      return $max > 400 ? ( 400 / $max ) : 1;
 453  }
 454  
 455  /**
 456   * Returns an image resource. Internal use only.
 457   *
 458   * @since 2.9.0
 459   * @deprecated 3.5.0 Use WP_Image_Editor::rotate()
 460   * @see WP_Image_Editor::rotate()
 461   *
 462   * @ignore
 463   * @param resource|GdImage  $img   Image resource.
 464   * @param float|int         $angle Image rotation angle, in degrees.
 465   * @return resource|GdImage|false GD image resource or GdImage instance, false otherwise.
 466   */
 467  function _rotate_image_resource( $img, $angle ) {
 468      _deprecated_function( __FUNCTION__, '3.5.0', 'WP_Image_Editor::rotate()' );
 469  
 470      if ( function_exists( 'imagerotate' ) ) {
 471          $rotated = imagerotate( $img, $angle, 0 );
 472  
 473          if ( is_gd_image( $rotated ) ) {
 474              imagedestroy( $img );
 475              $img = $rotated;
 476          }
 477      }
 478  
 479      return $img;
 480  }
 481  
 482  /**
 483   * Flips an image resource. Internal use only.
 484   *
 485   * @since 2.9.0
 486   * @deprecated 3.5.0 Use WP_Image_Editor::flip()
 487   * @see WP_Image_Editor::flip()
 488   *
 489   * @ignore
 490   * @param resource|GdImage $img  Image resource or GdImage instance.
 491   * @param bool             $horz Whether to flip horizontally.
 492   * @param bool             $vert Whether to flip vertically.
 493   * @return resource|GdImage (maybe) flipped image resource or GdImage instance.
 494   */
 495  function _flip_image_resource( $img, $horz, $vert ) {
 496      _deprecated_function( __FUNCTION__, '3.5.0', 'WP_Image_Editor::flip()' );
 497  
 498      $w   = imagesx( $img );
 499      $h   = imagesy( $img );
 500      $dst = wp_imagecreatetruecolor( $w, $h );
 501  
 502      if ( is_gd_image( $dst ) ) {
 503          $sx = $vert ? ( $w - 1 ) : 0;
 504          $sy = $horz ? ( $h - 1 ) : 0;
 505          $sw = $vert ? -$w : $w;
 506          $sh = $horz ? -$h : $h;
 507  
 508          if ( imagecopyresampled( $dst, $img, 0, 0, $sx, $sy, $w, $h, $sw, $sh ) ) {
 509              imagedestroy( $img );
 510              $img = $dst;
 511          }
 512      }
 513  
 514      return $img;
 515  }
 516  
 517  /**
 518   * Crops an image resource. Internal use only.
 519   *
 520   * @since 2.9.0
 521   *
 522   * @ignore
 523   * @param resource|GdImage $img Image resource or GdImage instance.
 524   * @param float            $x   Source point x-coordinate.
 525   * @param float            $y   Source point y-coordinate.
 526   * @param float            $w   Source width.
 527   * @param float            $h   Source height.
 528   * @return resource|GdImage (maybe) cropped image resource or GdImage instance.
 529   */
 530  function _crop_image_resource( $img, $x, $y, $w, $h ) {
 531      $dst = wp_imagecreatetruecolor( $w, $h );
 532  
 533      if ( is_gd_image( $dst ) ) {
 534          if ( imagecopy( $dst, $img, 0, 0, $x, $y, $w, $h ) ) {
 535              imagedestroy( $img );
 536              $img = $dst;
 537          }
 538      }
 539  
 540      return $img;
 541  }
 542  
 543  /**
 544   * Performs group of changes on Editor specified.
 545   *
 546   * @since 2.9.0
 547   *
 548   * @param WP_Image_Editor $image   WP_Image_Editor instance.
 549   * @param array           $changes Array of change operations.
 550   * @return WP_Image_Editor WP_Image_Editor instance with changes applied.
 551   */
 552  function image_edit_apply_changes( $image, $changes ) {
 553      if ( is_gd_image( $image ) ) {
 554          /* translators: 1: $image, 2: WP_Image_Editor */
 555          _deprecated_argument( __FUNCTION__, '3.5.0', sprintf( __( '%1$s needs to be a %2$s object.' ), '$image', 'WP_Image_Editor' ) );
 556      }
 557  
 558      if ( ! is_array( $changes ) ) {
 559          return $image;
 560      }
 561  
 562      // Expand change operations.
 563      foreach ( $changes as $key => $obj ) {
 564          if ( isset( $obj->r ) ) {
 565              $obj->type  = 'rotate';
 566              $obj->angle = $obj->r;
 567              unset( $obj->r );
 568          } elseif ( isset( $obj->f ) ) {
 569              $obj->type = 'flip';
 570              $obj->axis = $obj->f;
 571              unset( $obj->f );
 572          } elseif ( isset( $obj->c ) ) {
 573              $obj->type = 'crop';
 574              $obj->sel  = $obj->c;
 575              unset( $obj->c );
 576          }
 577          $changes[ $key ] = $obj;
 578      }
 579  
 580      // Combine operations.
 581      if ( count( $changes ) > 1 ) {
 582          $filtered = array( $changes[0] );
 583          for ( $i = 0, $j = 1, $c = count( $changes ); $j < $c; $j++ ) {
 584              $combined = false;
 585              if ( $filtered[ $i ]->type == $changes[ $j ]->type ) {
 586                  switch ( $filtered[ $i ]->type ) {
 587                      case 'rotate':
 588                          $filtered[ $i ]->angle += $changes[ $j ]->angle;
 589                          $combined               = true;
 590                          break;
 591                      case 'flip':
 592                          $filtered[ $i ]->axis ^= $changes[ $j ]->axis;
 593                          $combined              = true;
 594                          break;
 595                  }
 596              }
 597              if ( ! $combined ) {
 598                  $filtered[ ++$i ] = $changes[ $j ];
 599              }
 600          }
 601          $changes = $filtered;
 602          unset( $filtered );
 603      }
 604  
 605      // Image resource before applying the changes.
 606      if ( $image instanceof WP_Image_Editor ) {
 607  
 608          /**
 609           * Filters the WP_Image_Editor instance before applying changes to the image.
 610           *
 611           * @since 3.5.0
 612           *
 613           * @param WP_Image_Editor $image   WP_Image_Editor instance.
 614           * @param array           $changes Array of change operations.
 615           */
 616          $image = apply_filters( 'wp_image_editor_before_change', $image, $changes );
 617      } elseif ( is_gd_image( $image ) ) {
 618  
 619          /**
 620           * Filters the GD image resource before applying changes to the image.
 621           *
 622           * @since 2.9.0
 623           * @deprecated 3.5.0 Use {@see 'wp_image_editor_before_change'} instead.
 624           *
 625           * @param resource|GdImage $image   GD image resource or GdImage instance.
 626           * @param array            $changes Array of change operations.
 627           */
 628          $image = apply_filters_deprecated( 'image_edit_before_change', array( $image, $changes ), '3.5.0', 'wp_image_editor_before_change' );
 629      }
 630  
 631      foreach ( $changes as $operation ) {
 632          switch ( $operation->type ) {
 633              case 'rotate':
 634                  if ( 0 != $operation->angle ) {
 635                      if ( $image instanceof WP_Image_Editor ) {
 636                          $image->rotate( $operation->angle );
 637                      } else {
 638                          $image = _rotate_image_resource( $image, $operation->angle );
 639                      }
 640                  }
 641                  break;
 642              case 'flip':
 643                  if ( 0 != $operation->axis ) {
 644                      if ( $image instanceof WP_Image_Editor ) {
 645                          $image->flip( ( $operation->axis & 1 ) != 0, ( $operation->axis & 2 ) != 0 );
 646                      } else {
 647                          $image = _flip_image_resource( $image, ( $operation->axis & 1 ) != 0, ( $operation->axis & 2 ) != 0 );
 648                      }
 649                  }
 650                  break;
 651              case 'crop':
 652                  $sel = $operation->sel;
 653  
 654                  if ( $image instanceof WP_Image_Editor ) {
 655                      $size = $image->get_size();
 656                      $w    = $size['width'];
 657                      $h    = $size['height'];
 658  
 659                      $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 );
 661                  } else {
 662                      $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 );
 664                  }
 665                  break;
 666          }
 667      }
 668  
 669      return $image;
 670  }
 671  
 672  
 673  /**
 674   * Streams image in post to browser, along with enqueued changes
 675   * in `$_REQUEST['history']`.
 676   *
 677   * @since 2.9.0
 678   *
 679   * @param int $post_id Attachment post ID.
 680   * @return bool True on success, false on failure.
 681   */
 682  function stream_preview_image( $post_id ) {
 683      $post = get_post( $post_id );
 684  
 685      wp_raise_memory_limit( 'admin' );
 686  
 687      $img = wp_get_image_editor( _load_image_to_edit_path( $post_id ) );
 688  
 689      if ( is_wp_error( $img ) ) {
 690          return false;
 691      }
 692  
 693      $changes = ! empty( $_REQUEST['history'] ) ? json_decode( wp_unslash( $_REQUEST['history'] ) ) : null;
 694      if ( $changes ) {
 695          $img = image_edit_apply_changes( $img, $changes );
 696      }
 697  
 698      // Scale the image.
 699      $size = $img->get_size();
 700      $w    = $size['width'];
 701      $h    = $size['height'];
 702  
 703      $ratio = _image_get_preview_ratio( $w, $h );
 704      $w2    = max( 1, $w * $ratio );
 705      $h2    = max( 1, $h * $ratio );
 706  
 707      if ( is_wp_error( $img->resize( $w2, $h2 ) ) ) {
 708          return false;
 709      }
 710  
 711      return wp_stream_image( $img, $post->post_mime_type, $post_id );
 712  }
 713  
 714  /**
 715   * Restores the metadata for a given attachment.
 716   *
 717   * @since 2.9.0
 718   *
 719   * @param int $post_id Attachment post ID.
 720   * @return stdClass Image restoration message object.
 721   */
 722  function wp_restore_image( $post_id ) {
 723      $meta             = wp_get_attachment_metadata( $post_id );
 724      $file             = get_attached_file( $post_id );
 725      $backup_sizes     = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
 726      $old_backup_sizes = $backup_sizes;
 727      $restored         = false;
 728      $msg              = new stdClass;
 729  
 730      if ( ! is_array( $backup_sizes ) ) {
 731          $msg->error = __( 'Cannot load image metadata.' );
 732          return $msg;
 733      }
 734  
 735      $parts         = pathinfo( $file );
 736      $suffix        = time() . rand( 100, 999 );
 737      $default_sizes = get_intermediate_image_sizes();
 738  
 739      if ( isset( $backup_sizes['full-orig'] ) && is_array( $backup_sizes['full-orig'] ) ) {
 740          $data = $backup_sizes['full-orig'];
 741  
 742          if ( $parts['basename'] != $data['file'] ) {
 743              if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE ) {
 744  
 745                  // Delete only if it's an edited image.
 746                  if ( preg_match( '/-e[0-9]{13}\./', $parts['basename'] ) ) {
 747                      wp_delete_file( $file );
 748                  }
 749              } elseif ( isset( $meta['width'], $meta['height'] ) ) {
 750                  $backup_sizes[ "full-$suffix" ] = array(
 751                      'width'  => $meta['width'],
 752                      'height' => $meta['height'],
 753                      'file'   => $parts['basename'],
 754                  );
 755              }
 756          }
 757  
 758          $restored_file = path_join( $parts['dirname'], $data['file'] );
 759          $restored      = update_attached_file( $post_id, $restored_file );
 760  
 761          $meta['file']   = _wp_relative_upload_path( $restored_file );
 762          $meta['width']  = $data['width'];
 763          $meta['height'] = $data['height'];
 764      }
 765  
 766      foreach ( $default_sizes as $default_size ) {
 767          if ( isset( $backup_sizes[ "$default_size-orig" ] ) ) {
 768              $data = $backup_sizes[ "$default_size-orig" ];
 769              if ( isset( $meta['sizes'][ $default_size ] ) && $meta['sizes'][ $default_size ]['file'] != $data['file'] ) {
 770                  if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE ) {
 771  
 772                      // Delete only if it's an edited image.
 773                      if ( preg_match( '/-e[0-9]{13}-/', $meta['sizes'][ $default_size ]['file'] ) ) {
 774                          $delete_file = path_join( $parts['dirname'], $meta['sizes'][ $default_size ]['file'] );
 775                          wp_delete_file( $delete_file );
 776                      }
 777                  } else {
 778                      $backup_sizes[ "$default_size-{$suffix}" ] = $meta['sizes'][ $default_size ];
 779                  }
 780              }
 781  
 782              $meta['sizes'][ $default_size ] = $data;
 783          } else {
 784              unset( $meta['sizes'][ $default_size ] );
 785          }
 786      }
 787  
 788      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 ) ) ) {
 790  
 791          $msg->error = __( 'Cannot save image metadata.' );
 792          return $msg;
 793      }
 794  
 795      if ( ! $restored ) {
 796          $msg->error = __( 'Image metadata is inconsistent.' );
 797      } else {
 798          $msg->msg = __( 'Image restored successfully.' );
 799      }
 800  
 801      return $msg;
 802  }
 803  
 804  /**
 805   * Saves image to post, along with enqueued changes
 806   * in `$_REQUEST['history']`.
 807   *
 808   * @since 2.9.0
 809   *
 810   * @param int $post_id Attachment post ID.
 811   * @return stdClass
 812   */
 813  function wp_save_image( $post_id ) {
 814      $_wp_additional_image_sizes = wp_get_additional_image_sizes();
 815  
 816      $return  = new stdClass;
 817      $success = false;
 818      $delete  = false;
 819      $scaled  = false;
 820      $nocrop  = false;
 821      $post    = get_post( $post_id );
 822  
 823      $img = wp_get_image_editor( _load_image_to_edit_path( $post_id, 'full' ) );
 824      if ( is_wp_error( $img ) ) {
 825          $return->error = esc_js( __( 'Unable to create new image.' ) );
 826          return $return;
 827      }
 828  
 829      $fwidth  = ! empty( $_REQUEST['fwidth'] ) ? (int) $_REQUEST['fwidth'] : 0;
 830      $fheight = ! empty( $_REQUEST['fheight'] ) ? (int) $_REQUEST['fheight'] : 0;
 831      $target  = ! empty( $_REQUEST['target'] ) ? preg_replace( '/[^a-z0-9_-]+/i', '', $_REQUEST['target'] ) : '';
 832      $scale   = ! empty( $_REQUEST['do'] ) && 'scale' === $_REQUEST['do'];
 833  
 834      if ( $scale && $fwidth > 0 && $fheight > 0 ) {
 835          $size = $img->get_size();
 836          $sX   = $size['width'];
 837          $sY   = $size['height'];
 838  
 839          // Check if it has roughly the same w / h ratio.
 840          $diff = round( $sX / $sY, 2 ) - round( $fwidth / $fheight, 2 );
 841          if ( -0.1 < $diff && $diff < 0.1 ) {
 842              // Scale the full size image.
 843              if ( $img->resize( $fwidth, $fheight ) ) {
 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;
 851          }
 852      } elseif ( ! empty( $_REQUEST['history'] ) ) {
 853          $changes = json_decode( wp_unslash( $_REQUEST['history'] ) );
 854          if ( $changes ) {
 855              $img = image_edit_apply_changes( $img, $changes );
 856          }
 857      } else {
 858          $return->error = esc_js( __( 'Nothing to save, the image has not changed.' ) );
 859          return $return;
 860      }
 861  
 862      $meta         = wp_get_attachment_metadata( $post_id );
 863      $backup_sizes = get_post_meta( $post->ID, '_wp_attachment_backup_sizes', true );
 864  
 865      if ( ! is_array( $meta ) ) {
 866          $return->error = esc_js( __( 'Image data does not exist. Please re-upload the image.' ) );
 867          return $return;
 868      }
 869  
 870      if ( ! is_array( $backup_sizes ) ) {
 871          $backup_sizes = array();
 872      }
 873  
 874      // Generate new filename.
 875      $path = get_attached_file( $post_id );
 876  
 877      $basename = pathinfo( $path, PATHINFO_BASENAME );
 878      $dirname  = pathinfo( $path, PATHINFO_DIRNAME );
 879      $ext      = pathinfo( $path, PATHINFO_EXTENSION );
 880      $filename = pathinfo( $path, PATHINFO_FILENAME );
 881      $suffix   = time() . rand( 100, 999 );
 882  
 883      if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE &&
 884          isset( $backup_sizes['full-orig'] ) && $backup_sizes['full-orig']['file'] != $basename ) {
 885  
 886          if ( 'thumbnail' === $target ) {
 887              $new_path = "{$dirname}/{$filename}-temp.{$ext}";
 888          } else {
 889              $new_path = $path;
 890          }
 891      } else {
 892          while ( true ) {
 893              $filename     = preg_replace( '/-e([0-9]+)$/', '', $filename );
 894              $filename    .= "-e{$suffix}";
 895              $new_filename = "{$filename}.{$ext}";
 896              $new_path     = "{$dirname}/$new_filename";
 897              if ( file_exists( $new_path ) ) {
 898                  $suffix++;
 899              } else {
 900                  break;
 901              }
 902          }
 903      }
 904  
 905      // Save the full-size file, also needed to create sub-sizes.
 906      if ( ! wp_save_image_file( $new_path, $img, $post->post_mime_type, $post_id ) ) {
 907          $return->error = esc_js( __( 'Unable to save the image.' ) );
 908          return $return;
 909      }
 910  
 911      if ( 'nothumb' === $target || 'all' === $target || 'full' === $target || $scaled ) {
 912          $tag = false;
 913          if ( isset( $backup_sizes['full-orig'] ) ) {
 914              if ( ( ! defined( 'IMAGE_EDIT_OVERWRITE' ) || ! IMAGE_EDIT_OVERWRITE ) && $backup_sizes['full-orig']['file'] !== $basename ) {
 915                  $tag = "full-$suffix";
 916              }
 917          } else {
 918              $tag = 'full-orig';
 919          }
 920  
 921          if ( $tag ) {
 922              $backup_sizes[ $tag ] = array(
 923                  'width'  => $meta['width'],
 924                  'height' => $meta['height'],
 925                  'file'   => $basename,
 926              );
 927          }
 928          $success = ( $path === $new_path ) || update_attached_file( $post_id, $new_path );
 929  
 930          $meta['file'] = _wp_relative_upload_path( $new_path );
 931  
 932          $size           = $img->get_size();
 933          $meta['width']  = $size['width'];
 934          $meta['height'] = $size['height'];
 935  
 936          if ( $success ) {
 937              $sizes = get_intermediate_image_sizes();
 938              if ( 'nothumb' === $target || 'all' === $target ) {
 939                  if ( 'nothumb' === $target ) {
 940                      $sizes = array_diff( $sizes, array( 'thumbnail' ) );
 941                  }
 942              } elseif ( 'thumbnail' !== $target ) {
 943                  $sizes = array_diff( $sizes, array( $target ) );
 944              }
 945          }
 946  
 947          $return->fw = $meta['width'];
 948          $return->fh = $meta['height'];
 949      } elseif ( 'thumbnail' === $target ) {
 950          $sizes   = array( 'thumbnail' );
 951          $success = true;
 952          $delete  = true;
 953          $nocrop  = true;
 954      } else {
 955          $sizes   = array( $target );
 956          $success = true;
 957          $delete  = true;
 958          $nocrop  = $_wp_additional_image_sizes[ $size ]['crop'];
 959      }
 960  
 961      /*
 962       * We need to remove any existing resized image files because
 963       * a new crop or rotate could generate different sizes (and hence, filenames),
 964       * keeping the new resized images from overwriting the existing image files.
 965       * https://core.trac.wordpress.org/ticket/32171
 966       */
 967      if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE && ! empty( $meta['sizes'] ) ) {
 968          foreach ( $meta['sizes'] as $size ) {
 969              if ( ! empty( $size['file'] ) && preg_match( '/-e[0-9]{13}-/', $size['file'] ) ) {
 970                  $delete_file = path_join( $dirname, $size['file'] );
 971                  wp_delete_file( $delete_file );
 972              }
 973          }
 974      }
 975  
 976      if ( isset( $sizes ) ) {
 977          $_sizes = array();
 978  
 979          foreach ( $sizes as $size ) {
 980              $tag = false;
 981              if ( isset( $meta['sizes'][ $size ] ) ) {
 982                  if ( isset( $backup_sizes[ "$size-orig" ] ) ) {
 983                      if ( ( ! defined( 'IMAGE_EDIT_OVERWRITE' ) || ! IMAGE_EDIT_OVERWRITE ) && $backup_sizes[ "$size-orig" ]['file'] != $meta['sizes'][ $size ]['file'] ) {
 984                          $tag = "$size-$suffix";
 985                      }
 986                  } else {
 987                      $tag = "$size-orig";
 988                  }
 989  
 990                  if ( $tag ) {
 991                      $backup_sizes[ $tag ] = $meta['sizes'][ $size ];
 992                  }
 993              }
 994  
 995              if ( isset( $_wp_additional_image_sizes[ $size ] ) ) {
 996                  $width  = (int) $_wp_additional_image_sizes[ $size ]['width'];
 997                  $height = (int) $_wp_additional_image_sizes[ $size ]['height'];
 998                  $crop   = ( $nocrop ) ? false : $_wp_additional_image_sizes[ $size ]['crop'];
 999              } else {
1000                  $height = get_option( "{$size}_size_h" );
1001                  $width  = get_option( "{$size}_size_w" );
1002                  $crop   = ( $nocrop ) ? false : get_option( "{$size}_crop" );
1003              }
1004  
1005              $_sizes[ $size ] = array(
1006                  'width'  => $width,
1007                  'height' => $height,
1008                  'crop'   => $crop,
1009              );
1010          }
1011  
1012          $meta['sizes'] = array_merge( $meta['sizes'], $img->multi_resize( $_sizes ) );
1013      }
1014  
1015      unset( $img );
1016  
1017      if ( $success ) {
1018          wp_update_attachment_metadata( $post_id, $meta );
1019          update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes );
1020  
1021          if ( 'thumbnail' === $target || 'all' === $target || 'full' === $target ) {
1022              // Check if it's an image edit from attachment edit screen.
1023              if ( ! empty( $_REQUEST['context'] ) && 'edit-attachment' === $_REQUEST['context'] ) {
1024                  $thumb_url         = wp_get_attachment_image_src( $post_id, array( 900, 600 ), true );
1025                  $return->thumbnail = $thumb_url[0];
1026              } else {
1027                  $file_url = wp_get_attachment_url( $post_id );
1028                  if ( ! empty( $meta['sizes']['thumbnail'] ) ) {
1029                      $thumb             = $meta['sizes']['thumbnail'];
1030                      $return->thumbnail = path_join( dirname( $file_url ), $thumb['file'] );
1031                  } else {
1032                      $return->thumbnail = "$file_url?w=128&h=128";
1033                  }
1034              }
1035          }
1036      } else {
1037          $delete = true;
1038      }
1039  
1040      if ( $delete ) {
1041          wp_delete_file( $new_path );
1042      }
1043  
1044      $return->msg = esc_js( __( 'Image saved' ) );
1045      return $return;
1046  }


Generated: Mon May 16 01:00:02 2022 Cross-referenced by PHPXref 0.7.1