web/wp-includes/class-wp-image-editor.php
changeset 204 09a1c134465b
equal deleted inserted replaced
203:f507feede89a 204:09a1c134465b
       
     1 <?php
       
     2 /**
       
     3  * Base WordPress Image Editor
       
     4  *
       
     5  * @package WordPress
       
     6  * @subpackage Image_Editor
       
     7  */
       
     8 
       
     9 /**
       
    10  * Base image editor class from which implementations extend
       
    11  *
       
    12  * @since 3.5.0
       
    13  */
       
    14 abstract class WP_Image_Editor {
       
    15 	protected $file = null;
       
    16 	protected $size = null;
       
    17 	protected $mime_type = null;
       
    18 	protected $default_mime_type = 'image/jpeg';
       
    19 	protected $quality = 90;
       
    20 
       
    21 	/**
       
    22 	 * Each instance handles a single file.
       
    23 	 */
       
    24 	public function __construct( $file ) {
       
    25 		$this->file = $file;
       
    26 	}
       
    27 
       
    28 	/**
       
    29 	 * Checks to see if current environment supports the editor chosen.
       
    30 	 * Must be overridden in a sub-class.
       
    31 	 *
       
    32 	 * @since 3.5.0
       
    33 	 * @access public
       
    34 	 * @abstract
       
    35 	 *
       
    36 	 * @param array $args
       
    37 	 * @return boolean
       
    38 	 */
       
    39 	public static function test( $args = array() ) {
       
    40 		return false;
       
    41 	}
       
    42 
       
    43 	/**
       
    44 	 * Checks to see if editor supports the mime-type specified.
       
    45 	 * Must be overridden in a sub-class.
       
    46 	 *
       
    47 	 * @since 3.5.0
       
    48 	 * @access public
       
    49 	 * @abstract
       
    50 	 *
       
    51 	 * @param string $mime_type
       
    52 	 * @return boolean
       
    53 	 */
       
    54 	public static function supports_mime_type( $mime_type ) {
       
    55 		return false;
       
    56 	}
       
    57 
       
    58 	/**
       
    59 	 * Loads image from $this->file into editor.
       
    60 	 *
       
    61 	 * @since 3.5.0
       
    62 	 * @access protected
       
    63 	 * @abstract
       
    64 	 *
       
    65 	 * @return boolean|WP_Error True if loaded; WP_Error on failure.
       
    66 	 */
       
    67 	abstract public function load();
       
    68 
       
    69 	/**
       
    70 	 * Saves current image to file.
       
    71 	 *
       
    72 	 * @since 3.5.0
       
    73 	 * @access public
       
    74 	 * @abstract
       
    75 	 *
       
    76 	 * @param string $destfilename
       
    77 	 * @param string $mime_type
       
    78 	 * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string}
       
    79 	 */
       
    80 	abstract public function save( $destfilename = null, $mime_type = null );
       
    81 
       
    82 	/**
       
    83 	 * Resizes current image.
       
    84 	 *
       
    85 	 * @since 3.5.0
       
    86 	 * @access public
       
    87 	 * @abstract
       
    88 	 *
       
    89 	 * @param int $max_w
       
    90 	 * @param int $max_h
       
    91 	 * @param boolean $crop
       
    92 	 * @return boolean|WP_Error
       
    93 	 */
       
    94 	abstract public function resize( $max_w, $max_h, $crop = false );
       
    95 
       
    96 	/**
       
    97 	 * Processes current image and saves to disk
       
    98 	 * multiple sizes from single source.
       
    99 	 *
       
   100 	 * @since 3.5.0
       
   101 	 * @access public
       
   102 	 * @abstract
       
   103 	 *
       
   104 	 * @param array $sizes { {'width'=>int, 'height'=>int, 'crop'=>bool}, ... }
       
   105 	 * @return array
       
   106 	 */
       
   107 	abstract public function multi_resize( $sizes );
       
   108 
       
   109 	/**
       
   110 	 * Crops Image.
       
   111 	 *
       
   112 	 * @since 3.5.0
       
   113 	 * @access public
       
   114 	 * @abstract
       
   115 	 *
       
   116 	 * @param string|int $src The source file or Attachment ID.
       
   117 	 * @param int $src_x The start x position to crop from.
       
   118 	 * @param int $src_y The start y position to crop from.
       
   119 	 * @param int $src_w The width to crop.
       
   120 	 * @param int $src_h The height to crop.
       
   121 	 * @param int $dst_w Optional. The destination width.
       
   122 	 * @param int $dst_h Optional. The destination height.
       
   123 	 * @param boolean $src_abs Optional. If the source crop points are absolute.
       
   124 	 * @return boolean|WP_Error
       
   125 	 */
       
   126 	abstract public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false );
       
   127 
       
   128 	/**
       
   129 	 * Rotates current image counter-clockwise by $angle.
       
   130 	 *
       
   131 	 * @since 3.5.0
       
   132 	 * @access public
       
   133 	 * @abstract
       
   134 	 *
       
   135 	 * @param float $angle
       
   136 	 * @return boolean|WP_Error
       
   137 	 */
       
   138 	abstract public function rotate( $angle );
       
   139 
       
   140 	/**
       
   141 	 * Flips current image.
       
   142 	 *
       
   143 	 * @since 3.5.0
       
   144 	 * @access public
       
   145 	 * @abstract
       
   146 	 *
       
   147 	 * @param boolean $horz Horizontal Flip
       
   148 	 * @param boolean $vert Vertical Flip
       
   149 	 * @return boolean|WP_Error
       
   150 	 */
       
   151 	abstract public function flip( $horz, $vert );
       
   152 
       
   153 	/**
       
   154 	 * Streams current image to browser.
       
   155 	 *
       
   156 	 * @since 3.5.0
       
   157 	 * @access public
       
   158 	 * @abstract
       
   159 	 *
       
   160 	 * @param string $mime_type
       
   161 	 * @return boolean|WP_Error
       
   162 	 */
       
   163 	abstract public function stream( $mime_type = null );
       
   164 
       
   165 	/**
       
   166 	 * Gets dimensions of image.
       
   167 	 *
       
   168 	 * @since 3.5.0
       
   169 	 * @access public
       
   170 	 *
       
   171 	 * @return array {'width'=>int, 'height'=>int}
       
   172 	 */
       
   173 	public function get_size() {
       
   174 		return $this->size;
       
   175 	}
       
   176 
       
   177 	/**
       
   178 	 * Sets current image size.
       
   179 	 *
       
   180 	 * @since 3.5.0
       
   181 	 * @access protected
       
   182 	 *
       
   183 	 * @param int $width
       
   184 	 * @param int $height
       
   185 	 */
       
   186 	protected function update_size( $width = null, $height = null ) {
       
   187 		$this->size = array(
       
   188 			'width' => (int) $width,
       
   189 			'height' => (int) $height
       
   190 		);
       
   191 		return true;
       
   192 	}
       
   193 
       
   194 	/**
       
   195 	 * Sets Image Compression quality on a 1-100% scale.
       
   196 	 *
       
   197 	 * @since 3.5.0
       
   198 	 * @access public
       
   199 	 *
       
   200 	 * @param int $quality Compression Quality. Range: [1,100]
       
   201 	 * @return boolean
       
   202 	 */
       
   203 	public function set_quality( $quality ) {
       
   204 		$this->quality = apply_filters( 'wp_editor_set_quality', $quality );
       
   205 
       
   206 		return ( (bool) $this->quality );
       
   207 	}
       
   208 
       
   209 	/**
       
   210 	 * Returns preferred mime-type and extension based on provided
       
   211 	 * file's extension and mime, or current file's extension and mime.
       
   212 	 *
       
   213 	 * Will default to $this->default_mime_type if requested is not supported.
       
   214 	 *
       
   215 	 * Provides corrected filename only if filename is provided.
       
   216 	 *
       
   217 	 * @since 3.5.0
       
   218 	 * @access protected
       
   219 	 *
       
   220 	 * @param string $filename
       
   221 	 * @param string $mime_type
       
   222 	 * @return array { filename|null, extension, mime-type }
       
   223 	 */
       
   224 	protected function get_output_format( $filename = null, $mime_type = null ) {
       
   225 		$new_ext = $file_ext = null;
       
   226 		$file_mime = null;
       
   227 
       
   228 		// By default, assume specified type takes priority
       
   229 		if ( $mime_type ) {
       
   230 			$new_ext = $this->get_extension( $mime_type );
       
   231 		}
       
   232 
       
   233 		if ( $filename ) {
       
   234 			$file_ext = strtolower( pathinfo( $filename, PATHINFO_EXTENSION ) );
       
   235 			$file_mime = $this->get_mime_type( $file_ext );
       
   236 		}
       
   237 		else {
       
   238 			// If no file specified, grab editor's current extension and mime-type.
       
   239 			$file_ext = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) );
       
   240 			$file_mime = $this->mime_type;
       
   241 		}
       
   242 
       
   243 		// Check to see if specified mime-type is the same as type implied by
       
   244 		// file extension.  If so, prefer extension from file.
       
   245 		if ( ! $mime_type || ( $file_mime == $mime_type ) ) {
       
   246 			$mime_type = $file_mime;
       
   247 			$new_ext = $file_ext;
       
   248 		}
       
   249 
       
   250 		// Double-check that the mime-type selected is supported by the editor.
       
   251 		// If not, choose a default instead.
       
   252 		if ( ! $this->supports_mime_type( $mime_type ) ) {
       
   253 			$mime_type = apply_filters( 'image_editor_default_mime_type', $this->default_mime_type );
       
   254 			$new_ext = $this->get_extension( $mime_type );
       
   255 		}
       
   256 
       
   257 		if ( $filename ) {
       
   258 			$ext = '';
       
   259 			$info = pathinfo( $filename );
       
   260 			$dir  = $info['dirname'];
       
   261 
       
   262 			if( isset( $info['extension'] ) )
       
   263 				$ext = $info['extension'];
       
   264 
       
   265 			$filename = trailingslashit( $dir ) . wp_basename( $filename, ".$ext" ) . ".{$new_ext}";
       
   266 		}
       
   267 
       
   268 		return array( $filename, $new_ext, $mime_type );
       
   269 	}
       
   270 
       
   271 	/**
       
   272 	 * Builds an output filename based on current file, and adding proper suffix
       
   273 	 *
       
   274 	 * @since 3.5.0
       
   275 	 * @access public
       
   276 	 *
       
   277 	 * @param string $suffix
       
   278 	 * @param string $dest_path
       
   279 	 * @param string $extension
       
   280 	 * @return string filename
       
   281 	 */
       
   282 	public function generate_filename( $suffix = null, $dest_path = null, $extension = null ) {
       
   283 		// $suffix will be appended to the destination filename, just before the extension
       
   284 		if ( ! $suffix )
       
   285 			$suffix = $this->get_suffix();
       
   286 
       
   287 		$info = pathinfo( $this->file );
       
   288 		$dir  = $info['dirname'];
       
   289 		$ext  = $info['extension'];
       
   290 
       
   291 		$name = wp_basename( $this->file, ".$ext" );
       
   292 		$new_ext = strtolower( $extension ? $extension : $ext );
       
   293 
       
   294 		if ( ! is_null( $dest_path ) && $_dest_path = realpath( $dest_path ) )
       
   295 			$dir = $_dest_path;
       
   296 
       
   297 		return trailingslashit( $dir ) . "{$name}-{$suffix}.{$new_ext}";
       
   298 	}
       
   299 
       
   300 	/**
       
   301 	 * Builds and returns proper suffix for file based on height and width.
       
   302 	 *
       
   303 	 * @since 3.5.0
       
   304 	 * @access public
       
   305 	 *
       
   306 	 * @return string suffix
       
   307 	 */
       
   308 	public function get_suffix() {
       
   309 		if ( ! $this->get_size() )
       
   310 			return false;
       
   311 
       
   312 		return "{$this->size['width']}x{$this->size['height']}";
       
   313 	}
       
   314 
       
   315 	/**
       
   316 	 * Either calls editor's save function or handles file as a stream.
       
   317 	 *
       
   318 	 * @since 3.5.0
       
   319 	 * @access protected
       
   320 	 *
       
   321 	 * @param string|stream $filename
       
   322 	 * @param callable $function
       
   323 	 * @param array $arguments
       
   324 	 * @return boolean
       
   325 	 */
       
   326 	protected function make_image( $filename, $function, $arguments ) {
       
   327 		$dst_file = $filename;
       
   328 
       
   329 		if ( $stream = wp_is_stream( $filename ) ) {
       
   330 			$filename = null;
       
   331 			ob_start();
       
   332 		}
       
   333 
       
   334 		$result = call_user_func_array( $function, $arguments );
       
   335 
       
   336 		if ( $result && $stream ) {
       
   337 			$contents = ob_get_contents();
       
   338 
       
   339 			$fp = fopen( $dst_file, 'w' );
       
   340 
       
   341 			if ( ! $fp )
       
   342 				return false;
       
   343 
       
   344 			fwrite( $fp, $contents );
       
   345 			fclose( $fp );
       
   346 		}
       
   347 
       
   348 		if ( $stream ) {
       
   349 			ob_end_clean();
       
   350 		}
       
   351 
       
   352 		return $result;
       
   353 	}
       
   354 
       
   355 	/**
       
   356 	 * Returns first matched mime-type from extension,
       
   357 	 * as mapped from wp_get_mime_types()
       
   358 	 *
       
   359 	 * @since 3.5.0
       
   360 	 * @access protected
       
   361 	 *
       
   362 	 * @param string $extension
       
   363 	 * @return string|boolean
       
   364 	 */
       
   365 	protected static function get_mime_type( $extension = null ) {
       
   366 		if ( ! $extension )
       
   367 			return false;
       
   368 
       
   369 		$mime_types = wp_get_mime_types();
       
   370 		$extensions = array_keys( $mime_types );
       
   371 
       
   372 		foreach( $extensions as $_extension ) {
       
   373 			if ( preg_match( "/{$extension}/i", $_extension ) ) {
       
   374 				return $mime_types[$_extension];
       
   375 			}
       
   376 		}
       
   377 
       
   378 		return false;
       
   379 	}
       
   380 
       
   381 	/**
       
   382 	 * Returns first matched extension from Mime-type,
       
   383 	 * as mapped from wp_get_mime_types()
       
   384 	 *
       
   385 	 * @since 3.5.0
       
   386 	 * @access protected
       
   387 	 *
       
   388 	 * @param string $mime_type
       
   389 	 * @return string|boolean
       
   390 	 */
       
   391 	protected static function get_extension( $mime_type = null ) {
       
   392 		$extensions = explode( '|', array_search( $mime_type, wp_get_mime_types() ) );
       
   393 
       
   394 		if ( empty( $extensions[0] ) )
       
   395 			return false;
       
   396 
       
   397 		return $extensions[0];
       
   398 	}
       
   399 }
       
   400