[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-core/classes/ -> class-bp-attachment.php (source)

   1  <?php
   2  /**
   3   * Core attachment class.
   4   *
   5   * @package BuddyPress
   6   * @subpackage Core
   7   * @since 2.3.0
   8   */
   9  
  10  // Exit if accessed directly.
  11  defined( 'ABSPATH' ) || exit;
  12  
  13  /**
  14   * BP Attachment class.
  15   *
  16   * Extend it to manage your component's uploads.
  17   *
  18   * @since 2.3.0
  19   */
  20  abstract class BP_Attachment {
  21  
  22      /** Upload properties *****************************************************/
  23  
  24      /**
  25       * The file being uploaded.
  26       *
  27       * @var array
  28       */
  29      public $attachment = array();
  30  
  31      /**
  32       * The default args to be merged with the
  33       * ones passed by the child class.
  34       *
  35       * @var array
  36       */
  37      protected $default_args = array(
  38          'original_max_filesize'  => 0,
  39          'allowed_mime_types'     => array(),
  40          'base_dir'               => '',
  41          'action'                 => '',
  42          'file_input'             => '',
  43          'upload_error_strings'   => array(),
  44          'required_wp_files'      => array( 'file' ),
  45          'upload_dir_filter_args' => 0,
  46      );
  47  
  48      /**
  49       * Construct Upload parameters.
  50       *
  51       * @since 2.3.0
  52       * @since 2.4.0 Add the $upload_dir_filter_args argument to the $arguments array
  53       *
  54       * @param array|string $args {
  55       *     @type int    $original_max_filesize  Maximum file size in kilobytes. Defaults to php.ini settings.
  56       *     @type array  $allowed_mime_types     List of allowed file extensions (eg: array( 'jpg', 'gif', 'png' ) ).
  57       *                                          Defaults to WordPress allowed mime types.
  58       *     @type string $base_dir               Component's upload base directory. Defaults to WordPress 'uploads'.
  59       *     @type string $action                 The upload action used when uploading a file, $_POST['action'] must be set
  60       *                                          and its value must equal $action {@link wp_handle_upload()} (required).
  61       *     @type string $file_input             The name attribute used in the file input. (required).
  62       *     @type array  $upload_error_strings   A list of specific error messages (optional).
  63       *     @type array  $required_wp_files      The list of required WordPress core files. Default: array( 'file' ).
  64       *     @type int    $upload_dir_filter_args 1 to receive the original Upload dir array in the Upload dir filter, 0 otherwise.
  65       *                                          Defaults to 0 (optional).
  66       * }
  67       */
  68  	public function __construct( $args = '' ) {
  69          // Upload action and the file input name are required parameters.
  70          if ( empty( $args['action'] ) || empty( $args['file_input'] ) ) {
  71              return false;
  72          }
  73  
  74          // Sanitize the action ID and the file input name.
  75          $this->action     = sanitize_key( $args['action'] );
  76          $this->file_input = sanitize_key( $args['file_input'] );
  77  
  78          /**
  79           * Max file size defaults to php ini settings or, in the case of
  80           * a multisite config, the root site fileupload_maxk option.
  81           */
  82          $this->default_args['original_max_filesize'] = (int) wp_max_upload_size();
  83  
  84          $params = bp_parse_args(
  85              $args,
  86              $this->default_args,
  87              $this->action . '_upload_params'
  88          );
  89  
  90          foreach ( $params as $key => $param ) {
  91              if ( 'upload_error_strings' === $key ) {
  92                  $this->{$key} = $this->set_upload_error_strings( $param );
  93  
  94              // Sanitize the base dir.
  95              } elseif ( 'base_dir' === $key ) {
  96                  $this->{$key} = sanitize_title( $param );
  97  
  98              // Sanitize the upload dir filter arg to pass.
  99              } elseif ( 'upload_dir_filter_args' === $key ) {
 100                  $this->{$key} = (int) $param;
 101  
 102              // Action & File input are already set and sanitized.
 103              } elseif ( 'action' !== $key && 'file_input' !== $key ) {
 104                  $this->{$key} = $param;
 105              }
 106          }
 107  
 108          // Set the path/url and base dir for uploads.
 109          $this->set_upload_dir();
 110      }
 111  
 112      /**
 113       * Set upload path and url for the component.
 114       *
 115       * @since 2.3.0
 116       *
 117       */
 118  	public function set_upload_dir() {
 119          // Set the directory, path, & url variables.
 120          $this->upload_dir  = bp_upload_dir();
 121  
 122          if ( empty( $this->upload_dir ) ) {
 123              return false;
 124          }
 125  
 126          $this->upload_path = $this->upload_dir['basedir'];
 127          $this->url         = $this->upload_dir['baseurl'];
 128  
 129          // Ensure URL is https if SSL is set/forced.
 130          if ( is_ssl() ) {
 131              $this->url = str_replace( 'http://', 'https://', $this->url );
 132          }
 133  
 134          /**
 135           * Custom base dir.
 136           *
 137           * If the component set this property, set the specific path, url and create the dir
 138           */
 139          if ( ! empty( $this->base_dir ) ) {
 140              $this->upload_path = trailingslashit( $this->upload_path ) . $this->base_dir;
 141              $this->url         = trailingslashit( $this->url  ) . $this->base_dir;
 142  
 143              // Finally create the base dir.
 144              $this->create_dir();
 145          }
 146      }
 147  
 148      /**
 149       * Set Upload error messages.
 150       *
 151       * Used into the $overrides argument of BP_Attachment->upload()
 152       *
 153       * @since 2.3.0
 154       *
 155       * @param array $param A list of error messages to add to BuddyPress core ones.
 156       * @return array $upload_errors The list of upload errors.
 157       */
 158  	public function set_upload_error_strings( $param = array() ) {
 159          /**
 160           * Index of the array is the error code
 161           * Custom errors will start at 9 code
 162           */
 163          $upload_errors = array(
 164              0 => __( 'The file was uploaded successfully', 'buddypress' ),
 165              1 => __( 'The uploaded file exceeds the maximum allowed file size for this site', 'buddypress' ),
 166  
 167              /* translators: %s: Max file size for the file */
 168              2 => sprintf( __( 'The uploaded file exceeds the maximum allowed file size of: %s', 'buddypress' ), size_format( $this->original_max_filesize ) ),
 169              3 => __( 'The uploaded file was only partially uploaded.', 'buddypress' ),
 170              4 => __( 'No file was uploaded.', 'buddypress' ),
 171              5 => '',
 172              6 => __( 'Missing a temporary folder.', 'buddypress' ),
 173              7 => __( 'Failed to write file to disk.', 'buddypress' ),
 174              8 => __( 'File upload stopped by extension.', 'buddypress' ),
 175          );
 176  
 177          if ( ! array_intersect_key( $upload_errors, (array) $param ) ) {
 178              foreach ( $param as $key_error => $error_message ) {
 179                  $upload_errors[ $key_error ] = $error_message;
 180              }
 181          }
 182  
 183          return $upload_errors;
 184      }
 185  
 186      /**
 187       * Include the WordPress core needed files.
 188       *
 189       * @since 2.3.0
 190       */
 191  	public function includes() {
 192          foreach ( array_unique( $this->required_wp_files ) as $wp_file ) {
 193              if ( ! file_exists( ABSPATH . "/wp-admin/includes/{$wp_file}.php" ) ) {
 194                  continue;
 195              }
 196  
 197              require_once( ABSPATH . "/wp-admin/includes/{$wp_file}.php" );
 198          }
 199      }
 200  
 201      /**
 202       * Upload the attachment.
 203       *
 204       * @since 2.3.0
 205       *
 206       * @param array       $file              The appropriate entry the from $_FILES superglobal.
 207       * @param string      $upload_dir_filter A specific filter to be applied to 'upload_dir' (optional).
 208       * @param string|null $time              Optional. Time formatted in 'yyyy/mm'. Default null.
 209       * @return array On success, returns an associative array of file attributes.
 210       *               On failure, returns an array containing the error message
 211       *               (eg: array( 'error' => $message ) )
 212       */
 213  	public function upload( $file, $upload_dir_filter = '', $time = null ) {
 214          /**
 215           * Upload action and the file input name are required parameters.
 216           *
 217           * @see BP_Attachment:__construct()
 218           */
 219          if ( empty( $this->action ) || empty( $this->file_input ) ) {
 220              return false;
 221          }
 222  
 223          /**
 224           * Add custom rules before enabling the file upload
 225           */
 226          add_filter( "{$this->action}_prefilter", array( $this, 'validate_upload' ), 10, 1 );
 227  
 228          // Set Default overrides.
 229          $overrides = array(
 230              'action'               => $this->action,
 231              'upload_error_strings' => $this->upload_error_strings,
 232          );
 233  
 234          /**
 235           * Add a mime override if needed
 236           * Used to restrict uploads by extensions
 237           */
 238          if ( ! empty( $this->allowed_mime_types ) ) {
 239              $mime_types = $this->validate_mime_types();
 240  
 241              if ( ! empty( $mime_types ) ) {
 242                  $overrides['mimes'] = $mime_types;
 243              }
 244          }
 245  
 246          /**
 247           * If you need to add some overrides we haven't thought of.
 248           *
 249           * @param array $overrides The wp_handle_upload overrides
 250           */
 251          $overrides = apply_filters( 'bp_attachment_upload_overrides', $overrides );
 252  
 253          $this->includes();
 254  
 255          /**
 256           * If the $base_dir was set when constructing the class,
 257           * and no specific filter has been requested, use a default
 258           * filter to create the specific $base dir
 259           * @see  BP_Attachment->upload_dir_filter()
 260           */
 261          if ( empty( $upload_dir_filter ) && ! empty( $this->base_dir ) ) {
 262              $upload_dir_filter = array( $this, 'upload_dir_filter' );
 263          }
 264  
 265          // Make sure the file will be uploaded in the attachment directory.
 266          if ( ! empty( $upload_dir_filter ) ) {
 267              add_filter( 'upload_dir', $upload_dir_filter, 10, $this->upload_dir_filter_args );
 268          }
 269  
 270          // Helper for utf-8 filenames.
 271          add_filter( 'sanitize_file_name', array( $this, 'sanitize_utf8_filename' ) );
 272  
 273          // Upload the attachment.
 274          $this->attachment = wp_handle_upload( $file[ $this->file_input ], $overrides, $time );
 275  
 276          remove_filter( 'sanitize_file_name', array( $this, 'sanitize_utf8_filename' ) );
 277  
 278          // Restore WordPress Uploads data.
 279          if ( ! empty( $upload_dir_filter ) ) {
 280              remove_filter( 'upload_dir', $upload_dir_filter, 10 );
 281          }
 282  
 283          // Finally return the uploaded file or the error.
 284          return $this->attachment;
 285      }
 286  
 287      /**
 288       * Helper to convert utf-8 characters in filenames to their ASCII equivalent.
 289       *
 290       * @since 2.9.0
 291       *
 292       * @param  string $retval Filename.
 293       * @return string
 294       */
 295  	public function sanitize_utf8_filename( $retval ) {
 296          // PHP 5.4+ or with PECL intl 2.0+
 297          if ( function_exists( 'transliterator_transliterate' ) && seems_utf8( $retval ) ) {
 298              $retval = transliterator_transliterate( 'Any-Latin; Latin-ASCII; [\u0080-\u7fff] remove', $retval );
 299  
 300          // Older.
 301          } else {
 302              // Use WP's built-in function to convert accents to their ASCII equivalent.
 303              $retval = remove_accents( $retval );
 304  
 305              // Still here? use iconv().
 306              if ( function_exists( 'iconv' ) && seems_utf8( $retval ) ) {
 307                  $retval = iconv( 'UTF-8', 'ASCII//TRANSLIT//IGNORE', $retval );
 308              }
 309          }
 310  
 311          return $retval;
 312      }
 313  
 314      /**
 315       * Validate the allowed mime types using WordPress allowed mime types.
 316       *
 317       * In case of a multisite, the mime types are already restricted by
 318       * the 'upload_filetypes' setting. BuddyPress will respect this setting.
 319       *
 320       * @see check_upload_mimes()
 321       *
 322       * @since 2.3.0
 323       *
 324       */
 325  	protected function validate_mime_types() {
 326          $wp_mimes = get_allowed_mime_types();
 327          $valid_mimes = array();
 328  
 329          // Set the allowed mimes for the upload.
 330          foreach ( (array) $this->allowed_mime_types as $ext ) {
 331              foreach ( $wp_mimes as $ext_pattern => $mime ) {
 332                  if ( $ext !== '' && strpos( $ext_pattern, $ext ) !== false ) {
 333                      $valid_mimes[$ext_pattern] = $mime;
 334                  }
 335              }
 336          }
 337          return $valid_mimes;
 338      }
 339  
 340      /**
 341       * Specific upload rules.
 342       *
 343       * Override this function from your child class to build your specific rules
 344       * By default, if an original_max_filesize is provided, a check will be done
 345       * on the file size.
 346       *
 347       * @see BP_Attachment_Avatar->validate_upload() for an example of use
 348       *
 349       * @since 2.3.0
 350       *
 351       * @param array $file The temporary file attributes (before it has been moved).
 352       * @return array The file.
 353       */
 354  	public function validate_upload( $file = array() ) {
 355          // Bail if already an error.
 356          if ( ! empty( $file['error'] ) ) {
 357              return $file;
 358          }
 359  
 360          if ( ! empty( $this->original_max_filesize ) && $file['size'] > $this->original_max_filesize ) {
 361              $file['error'] = 2;
 362          }
 363  
 364          // Return the file.
 365          return $file;
 366      }
 367  
 368      /**
 369       * Default filter to save the attachments.
 370       *
 371       * @since 2.3.0
 372       * @since 2.4.0 Add the $upload_dir parameter to the method
 373       *
 374       *       regarding to context
 375       *
 376       * @param array $upload_dir The original Uploads dir.
 377       * @return array The upload directory data.
 378       */
 379  	public function upload_dir_filter( $upload_dir = array() ) {
 380  
 381          /**
 382           * Filters the component's upload directory.
 383           *
 384           * @since 2.3.0
 385           * @since 2.4.0 Include the original Upload directory as the second parameter of the filter.
 386           *
 387           * @param array $value          Array containing the path, URL, and other helpful settings.
 388           * @param array $upload_dir     The original Uploads dir.
 389           */
 390          return apply_filters( 'bp_attachment_upload_dir', array(
 391              'path'    => $this->upload_path,
 392              'url'     => $this->url,
 393              'subdir'  => false,
 394              'basedir' => $this->upload_path,
 395              'baseurl' => $this->url,
 396              'error'   => false
 397          ), $upload_dir );
 398      }
 399  
 400      /**
 401       * Create the custom base directory for the component uploads.
 402       *
 403       * Override this function in your child class to run specific actions.
 404       * (eg: add an .htaccess file)
 405       *
 406       * @since 2.3.0
 407       *
 408       */
 409  	public function create_dir() {
 410          // Bail if no specific base dir is set.
 411          if ( empty( $this->base_dir ) ) {
 412              return false;
 413          }
 414  
 415          // Check if upload path already exists.
 416          if ( ! is_dir( $this->upload_path ) ) {
 417  
 418              // If path does not exist, attempt to create it.
 419              if ( ! wp_mkdir_p( $this->upload_path ) ) {
 420                  return false;
 421              }
 422          }
 423  
 424          // Directory exists.
 425          return true;
 426      }
 427  
 428      /**
 429       * Crop an image file.
 430       *
 431       * @since 2.3.0
 432       *
 433       * @param array $args {
 434       *     @type string $original_file The source file (absolute path) for the Attachment.
 435       *     @type int    $crop_x        The start x position to crop from.
 436       *     @type int    $crop_y        The start y position to crop from.
 437       *     @type int    $crop_w        The width to crop.
 438       *     @type int    $crop_h        The height to crop.
 439       *     @type int    $dst_w         The destination width.
 440       *     @type int    $dst_h         The destination height.
 441       *     @type int    $src_abs       Optional. If the source crop points are absolute.
 442       *     @type string $dst_file      Optional. The destination file to write to.
 443       * }
 444       *
 445       * @return string|WP_Error New filepath on success, WP_Error on failure.
 446       */
 447  	public function crop( $args = array() ) {
 448          $wp_error = new WP_Error();
 449  
 450          $r = bp_parse_args(
 451              $args,
 452              array(
 453                  'original_file' => '',
 454                  'crop_x'        => 0,
 455                  'crop_y'        => 0,
 456                  'crop_w'        => 0,
 457                  'crop_h'        => 0,
 458                  'dst_w'         => 0,
 459                  'dst_h'         => 0,
 460                  'src_abs'       => false,
 461                  'dst_file'      => false,
 462              ),
 463              'bp_attachment_crop_args'
 464          );
 465  
 466          if ( empty( $r['original_file'] ) || ! file_exists( $r['original_file'] ) ) {
 467              $wp_error->add( 'crop_error', __( 'Cropping the file failed: missing source file.', 'buddypress' ) );
 468              return $wp_error;
 469          }
 470  
 471          // Check image file pathes.
 472          $path_error = __( 'Cropping the file failed: the file path is not allowed.', 'buddypress' );
 473  
 474          // Make sure it's coming from an uploaded file.
 475          if ( false === strpos( $r['original_file'], $this->upload_path ) ) {
 476              $wp_error->add( 'crop_error', $path_error );
 477              return $wp_error;
 478          }
 479  
 480          /**
 481           * If no destination file is provided, WordPress will use a default name
 482           * and will write the file in the source file's folder.
 483           * If a destination file is provided, we need to make sure it's going into uploads.
 484           */
 485          if ( ! empty( $r['dst_file'] ) && false === strpos( $r['dst_file'], $this->upload_path ) ) {
 486              $wp_error->add( 'crop_error', $path_error );
 487              return $wp_error;
 488          }
 489  
 490          // Check image file types.
 491          $check_types = array( 'src_file' => array( 'file' => $r['original_file'], 'error' => _x( 'source file', 'Attachment source file', 'buddypress' ) ) );
 492          if ( ! empty( $r['dst_file'] ) ) {
 493              $check_types['dst_file'] = array( 'file' => $r['dst_file'], 'error' => _x( 'destination file', 'Attachment destination file', 'buddypress' ) );
 494          }
 495  
 496          /**
 497           * WordPress image supported types.
 498           * @see wp_attachment_is()
 499           */
 500          $supported_image_types = array(
 501              'jpg'  => 1,
 502              'jpeg' => 1,
 503              'jpe'  => 1,
 504              'gif'  => 1,
 505              'png'  => 1,
 506          );
 507  
 508          foreach ( $check_types as $file ) {
 509              $is_image      = wp_check_filetype( $file['file'] );
 510              $ext           = $is_image['ext'];
 511  
 512              if ( empty( $ext ) || empty( $supported_image_types[ $ext ] ) ) {
 513                  $wp_error->add(
 514                      'crop_error',
 515                      sprintf(
 516                          /* translators: %s: image file extension */
 517                          __( 'Cropping the file failed: %s is not a supported image file.', 'buddypress' ),
 518                          $file['error']
 519                      )
 520                  );
 521  
 522                  return $wp_error;
 523              }
 524          }
 525  
 526          // Add the image.php to the required WordPress files, if it's not already the case.
 527          $required_files = array_flip( $this->required_wp_files );
 528          if ( ! isset( $required_files['image'] ) ) {
 529              $this->required_wp_files[] = 'image';
 530          }
 531  
 532          // Load the files.
 533          $this->includes();
 534  
 535          // Finally crop the image.
 536          return wp_crop_image( $r['original_file'], (int) $r['crop_x'], (int) $r['crop_y'], (int) $r['crop_w'], (int) $r['crop_h'], (int) $r['dst_w'], (int) $r['dst_h'], $r['src_abs'], $r['dst_file'] );
 537      }
 538  
 539      /**
 540       * Build script datas for the Uploader UI.
 541       *
 542       * Override this method from your child class to build the script datas.
 543       *
 544       * @since 2.3.0
 545       *
 546       * @return array The javascript localization data.
 547       */
 548  	public function script_data() {
 549          $script_data = array(
 550              'action'            => $this->action,
 551              'file_data_name'    => $this->file_input,
 552              'max_file_size'     => $this->original_max_filesize,
 553              'feedback_messages' => array(
 554                  1 => __( 'Sorry, uploading the file failed.', 'buddypress' ),
 555                  2 => __( 'File successfully uploaded.', 'buddypress' ),
 556              ),
 557          );
 558  
 559          return $script_data;
 560      }
 561  
 562      /**
 563       * Get full data for an image
 564       *
 565       * @since 2.4.0
 566       *
 567       * @param string $file Absolute path to the uploaded image.
 568       * @return bool|array   An associate array containing the width, height and metadatas.
 569       *                      False in case an important image attribute is missing.
 570       */
 571  	public static function get_image_data( $file ) {
 572          // Try to get image basic data.
 573          list( $width, $height, $sourceImageType ) = @getimagesize( $file );
 574  
 575          // No need to carry on if we couldn't get image's basic data.
 576          if ( is_null( $width ) || is_null( $height ) || is_null( $sourceImageType ) ) {
 577              return false;
 578          }
 579  
 580          // Initialize the image data.
 581          $image_data = array(
 582              'width'  => $width,
 583              'height' => $height,
 584          );
 585  
 586          /**
 587           * Make sure the wp_read_image_metadata function is reachable for the old Avatar UI
 588           * or if WordPress < 3.9 (New Avatar UI is not available in this case)
 589           */
 590          if ( ! function_exists( 'wp_read_image_metadata' ) ) {
 591              require_once( ABSPATH . 'wp-admin/includes/image.php' );
 592          }
 593  
 594          // Now try to get image's meta data.
 595          $meta = wp_read_image_metadata( $file );
 596          if ( ! empty( $meta ) ) {
 597              $image_data['meta'] = $meta;
 598          }
 599  
 600          /**
 601           * Filter here to add/remove/edit data to the image full data
 602           *
 603           * @since 2.4.0
 604           *
 605           * @param array $image_data An associate array containing the width, height and metadatas.
 606           */
 607          return apply_filters( 'bp_attachments_get_image_data', $image_data );
 608      }
 609  
 610      /**
 611       * Edit an image file to resize it or rotate it
 612       *
 613       * @since 2.4.0
 614       *
 615       * @param string $attachment_type The attachment type (eg: avatar or cover_image). Required.
 616       * @param array  $args {
 617       *     @type string $file     Absolute path to the image file (required).
 618       *     @type int    $max_w    Max width attribute for the editor's resize method (optional).
 619       *     @type int    $max_h    Max height attribute for the editor's resize method (optional).
 620       *     @type bool   $crop     Crop attribute for the editor's resize method (optional).
 621       *     @type float  $rotate   Angle for the editor's rotate method (optional).
 622       *     @type int    $quality  Compression quality on a 1-100% scale (optional).
 623       *     @type bool   $save     Whether to use the editor's save method or not (optional).
 624       * }
 625       * @return string|WP_Image_Editor|WP_Error The edited image path or the WP_Image_Editor object in case of success,
 626       *                                         an WP_Error object otherwise.
 627       */
 628  	public static function edit_image( $attachment_type, $args = array() ) {
 629          if ( empty( $attachment_type ) ) {
 630              return new WP_Error( 'missing_parameter' );
 631          }
 632  
 633          $r = bp_parse_args(
 634              $args,
 635              array(
 636                  'file'    => '',
 637                  'max_w'   => 0,
 638                  'max_h'   => 0,
 639                  'crop'    => false,
 640                  'rotate'  => 0,
 641                  'quality' => 90,
 642                  'save'    => true,
 643              ),
 644              'attachment_' . $attachment_type . '_edit_image'
 645          );
 646  
 647          // Make sure we have to edit the image.
 648          if ( empty( $r['max_w'] ) && empty( $r['max_h'] ) && empty( $r['rotate'] ) && empty( $r['file'] ) ) {
 649              return new WP_Error( 'missing_parameter' );
 650          }
 651  
 652          // Get the image editor.
 653          $editor = wp_get_image_editor( $r['file'] );
 654  
 655          if ( is_wp_error( $editor ) ) {
 656              return $editor;
 657          }
 658  
 659          $editor->set_quality( $r['quality'] );
 660  
 661          if ( ! empty( $r['rotate'] ) ) {
 662              $rotated = $editor->rotate( $r['rotate'] );
 663  
 664              // Stop in case of error.
 665              if ( is_wp_error( $rotated ) ) {
 666                  return $rotated;
 667              }
 668          }
 669  
 670          if ( ! empty( $r['max_w'] ) || ! empty( $r['max_h'] ) ) {
 671              $resized = $editor->resize( $r['max_w'], $r['max_h'], $r['crop'] );
 672  
 673              // Stop in case of error.
 674              if ( is_wp_error( $resized ) ) {
 675                  return $resized;
 676              }
 677          }
 678  
 679          // Use the editor save method to get a path to the edited image.
 680          if ( true === $r['save'] ) {
 681              return $editor->save( $editor->generate_filename() );
 682  
 683          // Need to do some other edit actions or use a specific method to save file.
 684          } else {
 685              return $editor;
 686          }
 687      }
 688  }


Generated: Thu Sep 23 01:01:38 2021 Cross-referenced by PHPXref 0.7.1