Make WordPress Core

Ticket #22356: 22356.5.diff

File 22356.5.diff, 30.7 KB (added by scribu, 12 years ago)

WP_Image_Editor_Base

  • wp-admin/includes/media.php

    diff --git wp-admin/includes/media.php wp-admin/includes/media.php
    index 6cc1b63..185b096 100644
    function get_media_item( $attachment_id, $args = null ) { 
    11221122        $media_dims = apply_filters( 'media_meta', $media_dims, $post );
    11231123
    11241124        $image_edit_button = '';
    1125         if ( gd_edit_image_support( $post->post_mime_type ) ) {
     1125        if ( WP_Image_Editor::supports( array( 'mime_type' => $post->post_mime_type ) ) ) {
    11261126                $nonce = wp_create_nonce( "image_editor-$post->ID" );
    11271127                $image_edit_button = "<input type='button' id='imgedit-open-btn-$post->ID' onclick='imageEdit.open( $post->ID, \"$nonce\" )' class='button' value='" . esc_attr__( 'Edit Image' ) . "' /> <span class='spinner'></span>";
    11281128        }
    function edit_form_image_editor() { 
    22542254        $att_url = wp_get_attachment_url( $post->ID );
    22552255
    22562256        $image_edit_button = '';
    2257         if ( gd_edit_image_support( $post->post_mime_type ) ) {
     2257        if ( WP_Image_Editor::supports( array( 'mime_type' => $post->post_mime_type ) ) ) {
    22582258                $nonce = wp_create_nonce( "image_editor-$post->ID" );
    22592259                $image_edit_button = "<input type='button' id='imgedit-open-btn-$post->ID' onclick='imageEdit.open( $post->ID, \"$nonce\" )' class='button' value='" . esc_attr__( 'Edit Image' ) . "' /> <span class='spinner'></span>";
    22602260        }
  • new file wp-includes/class-wp-image-editor-base.php

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

    diff --git wp-includes/class-wp-image-editor-gd.php wp-includes/class-wp-image-editor-gd.php
    index ca76006..f28527c 100644
     
    1414 * @subpackage Image_Editor
    1515 * @uses WP_Image_Editor Extends class
    1616 */
    17 class WP_Image_Editor_GD extends WP_Image_Editor {
     17class WP_Image_Editor_GD extends WP_Image_Editor_Base {
    1818        protected $image = false; // GD Resource
    1919
    2020        function __destruct() {
    class WP_Image_Editor_GD extends WP_Image_Editor { 
    3232         *
    3333         * @return boolean
    3434         */
    35         public static function test( $args = null ) {
     35        public static function test() {
    3636                if ( ! extension_loaded('gd') || ! function_exists('gd_info') )
    3737                        return false;
    3838
    class WP_Image_Editor_GD extends WP_Image_Editor { 
    4747         *
    4848         * @return boolean|\WP_Error
    4949         */
    50         protected function load() {
     50        public function load() {
    5151                if ( $this->image )
    5252                        return true;
    5353
    class WP_Image_Editor_GD extends WP_Image_Editor { 
    100100         * @return boolean
    101101         */
    102102        public static function supports_mime_type( $mime_type ) {
    103                 $allowed_mime_types = array( 'image/gif', 'image/png', 'image/jpeg' );
     103                $image_types = imagetypes();
     104                switch( $mime_type ) {
     105                        case 'image/jpeg':
     106                                return ($image_types & IMG_JPG) != 0;
     107                        case 'image/png':
     108                                return ($image_types & IMG_PNG) != 0;
     109                        case 'image/gif':
     110                                return ($image_types & IMG_GIF) != 0;
     111                }
    104112
    105                 return in_array( $mime_type, $allowed_mime_types );
     113                return false;
    106114        }
    107115
    108116        /**
    class WP_Image_Editor_GD extends WP_Image_Editor { 
    261269         * @since 3.5.0
    262270         * @access public
    263271         *
    264          * @param boolean $horz Horizonal Flip
     272         * @param boolean $horz Horizontal Flip
    265273         * @param boolean $vert Vertical Flip
    266274         * @returns boolean|WP_Error
    267275         */
    class WP_Image_Editor_GD extends WP_Image_Editor { 
    369377                                return imagejpeg( $this->image, null, $this->quality );
    370378                }
    371379        }
    372 }
    373  No newline at end of file
     380}
  • wp-includes/class-wp-image-editor-imagick.php

    diff --git wp-includes/class-wp-image-editor-imagick.php wp-includes/class-wp-image-editor-imagick.php
    index 601b99b..d02e2be 100644
     
    1414 * @subpackage Image_Editor
    1515 * @uses WP_Image_Editor Extends class
    1616 */
    17 class WP_Image_Editor_Imagick extends WP_Image_Editor {
     17class WP_Image_Editor_Imagick extends WP_Image_Editor_Base {
    1818        protected $image = null; // Imagick Object
    1919
    2020        function __destruct() {
    class WP_Image_Editor_Imagick extends WP_Image_Editor { 
    3636         *
    3737         * @return boolean
    3838         */
    39         public static function test( $args = null ) {
     39        public static function test() {
    4040                if ( ! extension_loaded( 'imagick' ) || ! is_callable( 'Imagick', 'queryFormats' ) )
    4141                        return false;
    4242
    class WP_Image_Editor_Imagick extends WP_Image_Editor { 
    5151         *
    5252         * @return boolean|WP_Error True if loaded; WP_Error on failure.
    5353         */
    54         protected function load() {
     54        public function load() {
    5555                if ( $this->image )
    5656                        return true;
    5757
    class WP_Image_Editor_Imagick extends WP_Image_Editor { 
    147147         * @return boolean
    148148         */
    149149        public static function supports_mime_type( $mime_type ) {
    150                 if ( ! $mime_type )
    151                         return false;
    152 
    153150                $imagick_extension = strtoupper( self::get_extension( $mime_type ) );
    154151
     152                if ( ! $imagick_extension )
     153                        return false;
     154
    155155                try {
    156156                        return ( (bool) Imagick::queryFormats( $imagick_extension ) );
    157157                }
    class WP_Image_Editor_Imagick extends WP_Image_Editor { 
    312312         * @since 3.5.0
    313313         * @access public
    314314         *
    315          * @param boolean $horz Horizonal Flip
     315         * @param boolean $horz Horizontal Flip
    316316         * @param boolean $vert Vertical Flip
    317317         * @returns boolean|WP_Error
    318318         */
  • wp-includes/class-wp-image-editor.php

    diff --git wp-includes/class-wp-image-editor.php wp-includes/class-wp-image-editor.php
    index 920e4a4..391c8e1 100644
     
    11<?php
    22/**
    3  * Base WordPress Image Editor
    4  *
    5  * @package WordPress
    6  * @subpackage Image_Editor
    7  */
    8 
    9 /**
    10  * Base WordPress Image Editor class for which Editor implementations extend
     3 * Class for choosing image editor implementations
    114 *
    125 * @since 3.5.0
    136 */
    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         protected function __construct( $filename ) {
    22                 $this->file = $filename;
    23         }
     7class WP_Image_Editor {
    248
    259        /**
    2610         * Returns a WP_Image_Editor instance and loads file into it.
    abstract class WP_Image_Editor { 
    2812         * @since 3.5.0
    2913         * @access public
    3014         *
    31          * @param string $path Path to File to Load
    32          * @param array $required_methods Methods to require in implementation
     15         * @param string $path Path to file to load
     16         * @param array $args Additional data. Accepts { 'mime_type'=>string, 'methods'=>{string, string, ...} }
    3317         * @return WP_Image_Editor|WP_Error
    3418         */
    35         public final static function get_instance( $path = null, $required_methods = null ) {
    36                 $implementation = apply_filters( 'wp_image_editor_class', self::choose_implementation( $required_methods ), $path );
     19        public final static function get_instance( $path, $args = array() ) {
     20                if ( ! isset( $args['mime_type'] ) ) {
     21                        $file_info  = wp_check_filetype( $path );
     22
     23                        // If $file_info['type'] is false, then we let the editor attempt to
     24                        // figure out the file type, rather than forcing a failure based on extension.
     25                        if ( isset( $file_info ) && $file_info['type'] )
     26                                $args['mime_type'] = $file_info['type'];
     27                }
     28
     29                $implementation = apply_filters( 'wp_image_editor_class', self::choose_implementation( $args ) );
    3730
    3831                if ( $implementation ) {
    3932                        $editor = new $implementation( $path );
    abstract class WP_Image_Editor { 
    4538                        return $editor;
    4639                }
    4740
    48                 return new WP_Error( 'no_editor', __('No editor could be selected') );
    49         }
    50 
    51         /**
    52          * Tests which editors are capable of supporting the request.
    53          *
    54          * @since 3.5.0
    55          * @access private
    56          *
    57          * @param array $required_methods String array of all methods required for implementation returned.
    58          * @return string|bool Class name for the first editor that claims to support the request. False if no editor claims to support the request.
    59          */
    60         private final static function choose_implementation( $required_methods = null ) {
    61                 $request_order = apply_filters( 'wp_image_editors',
    62                         array( 'WP_Image_Editor_Imagick', 'WP_Image_Editor_GD' ) );
    63 
    64                 if ( ! $required_methods )
    65                         $required_methods = array();
    66 
    67                 // Loop over each editor on each request looking for one which will serve this request's needs
    68                 foreach ( $request_order as $editor ) {
    69                         // Check to see if this editor is a possibility, calls the editor statically
    70                         if ( ! call_user_func( array( $editor, 'test' ) ) )
    71                                 continue;
    72 
    73                         // Make sure that all methods are supported by editor.
    74                         if ( array_diff( $required_methods, get_class_methods( $editor ) ) )
    75                                 continue;
    76 
    77                         return $editor;
    78                 }
    79                 return false;
    80         }
    81 
    82         /**
    83          * Loads image from $this->file into editor.
    84          *
    85          * @since 3.5.0
    86          * @access protected
    87          * @abstract
    88          *
    89          * @return boolean|WP_Error True if loaded; WP_Error on failure.
    90          */
    91         abstract protected function load();
    92 
    93         /**
    94          * Saves current image to file.
    95          *
    96          * @since 3.5.0
    97          * @access public
    98          * @abstract
    99          *
    100          * @param string $destfilename
    101          * @param string $mime_type
    102          * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string}
    103          */
    104         abstract public function save( $destfilename = null, $mime_type = null );
    105 
    106         /**
    107          * Resizes current image.
    108          *
    109          * @since 3.5.0
    110          * @access public
    111          * @abstract
    112          *
    113          * @param int $max_w
    114          * @param int $max_h
    115          * @param boolean $crop
    116          * @return boolean|WP_Error
    117          */
    118         abstract public function resize( $max_w, $max_h, $crop = false );
    119 
    120         /**
    121          * Processes current image and saves to disk
    122          * multiple sizes from single source.
    123          *
    124          * @since 3.5.0
    125          * @access public
    126          * @abstract
    127          *
    128          * @param array $sizes
    129          * @return array
    130          */
    131         abstract public function multi_resize( $sizes );
    132 
    133         /**
    134          * Crops Image.
    135          *
    136          * @since 3.5.0
    137          * @access public
    138          * @abstract
    139          *
    140          * @param string|int $src The source file or Attachment ID.
    141          * @param int $src_x The start x position to crop from.
    142          * @param int $src_y The start y position to crop from.
    143          * @param int $src_w The width to crop.
    144          * @param int $src_h The height to crop.
    145          * @param int $dst_w Optional. The destination width.
    146          * @param int $dst_h Optional. The destination height.
    147          * @param boolean $src_abs Optional. If the source crop points are absolute.
    148          * @return boolean|WP_Error
    149          */
    150         abstract public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false );
    151 
    152         /**
    153          * Rotates current image counter-clockwise by $angle.
    154          *
    155          * @since 3.5.0
    156          * @access public
    157          * @abstract
    158          *
    159          * @param float $angle
    160          * @return boolean|WP_Error
    161          */
    162         abstract public function rotate( $angle );
    163 
    164         /**
    165          * Flips current image.
    166          *
    167          * @since 3.5.0
    168          * @access public
    169          * @abstract
    170          *
    171          * @param boolean $horz Horizonal Flip
    172          * @param boolean $vert Vertical Flip
    173          * @return boolean|WP_Error
    174          */
    175         abstract public function flip( $horz, $vert );
    176 
    177         /**
    178          * Streams current image to browser.
    179          *
    180          * @since 3.5.0
    181          * @access public
    182          * @abstract
    183          *
    184          * @param string $mime_type
    185          * @return boolean|WP_Error
    186          */
    187         abstract public function stream( $mime_type = null );
    188 
    189         /**
    190          * Checks to see if current environment supports the editor chosen.
    191          * Must be overridden in a sub-class.
    192          *
    193          * @since 3.5.0
    194          * @access public
    195          * @abstract
    196          *
    197          * @param array $args
    198          * @return boolean
    199          */
    200         public static function test( $args = null ) {
    201                 return false;
    202         }
    203 
    204         /**
    205          * Checks to see if editor supports the mime-type specified.
    206          * Must be overridden in a sub-class.
    207          *
    208          * @since 3.5.0
    209          * @access public
    210          * @abstract
    211          *
    212          * @param string $mime_type
    213          * @return boolean
    214          */
    215         public static function supports_mime_type( $mime_type ) {
    216                 return false;
    217         }
    218 
    219         /**
    220          * Gets dimensions of image.
    221          *
    222          * @since 3.5.0
    223          * @access public
    224          *
    225          * @return array {'width'=>int, 'height'=>int}
    226          */
    227         public function get_size() {
    228                 return $this->size;
    229         }
    230 
    231         /**
    232          * Sets current image size.
    233          *
    234          * @since 3.5.0
    235          * @access protected
    236          *
    237          * @param int $width
    238          * @param int $height
    239          */
    240         protected function update_size( $width = null, $height = null ) {
    241                 $this->size = array(
    242                         'width' => $width,
    243                         'height' => $height
    244                 );
    245                 return true;
    246         }
    247 
    248         /**
    249          * Sets Image Compression quality on a 1-100% scale.
    250          *
    251          * @since 3.5.0
    252          * @access public
    253          *
    254          * @param int $quality Compression Quality. Range: [1,100]
    255          * @return boolean
    256          */
    257         public function set_quality( $quality ) {
    258                 $this->quality = apply_filters( 'wp_editor_set_quality', $quality );
    259 
    260                 return ( (bool) $this->quality );
    261         }
    262 
    263         /**
    264          * Returns preferred mime-type and extension based on provided
    265          * file's extension and mime, or current file's extension and mime.
    266          *
    267          * Will default to $this->default_mime_type if requested is not supported.
    268          *
    269          * Provides corrected filename only if filename is provided.
    270          *
    271          * @since 3.5.0
    272          * @access protected
    273          *
    274          * @param string $filename
    275          * @param string $mime_type
    276          * @return array { filename|null, extension, mime-type }
    277          */
    278         protected function get_output_format( $filename = null, $mime_type = null ) {
    279                 $new_ext = $file_ext = null;
    280                 $file_mime = null;
    281 
    282                 // By default, assume specified type takes priority
    283                 if ( $mime_type ) {
    284                         $new_ext = $this->get_extension( $mime_type );
    285                 }
    286 
    287                 if ( $filename ) {
    288                         $file_ext = strtolower( pathinfo( $filename, PATHINFO_EXTENSION ) );
    289                         $file_mime = $this->get_mime_type( $file_ext );
    290                 }
    291                 else {
    292                         // If no file specified, grab editor's current extension and mime-type.
    293                         $file_ext = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) );
    294                         $file_mime = $this->mime_type;
    295                 }
    296 
    297                 // Check to see if specified mime-type is the same as type implied by
    298                 // file extension.  If so, prefer extension from file.
    299                 if ( ! $mime_type || ( $file_mime == $mime_type ) ) {
    300                         $mime_type = $file_mime;
    301                         $new_ext = $file_ext;
    302                 }
    303 
    304                 // Double-check that the mime-type selected is supported by the editor.
    305                 // If not, choose a default instead.
    306                 if ( ! $this->supports_mime_type( $mime_type ) ) {
    307                         $mime_type = apply_filters( 'image_editor_default_mime_type', $this->default_mime_type );
    308                         $new_ext = $this->get_extension( $mime_type );
    309                 }
    310 
    311                 if ( $filename ) {
    312                         $ext = '';
    313                         $info = pathinfo( $filename );
    314                         $dir  = $info['dirname'];
    315 
    316                         if( isset( $info['extension'] ) )
    317                                 $ext = $info['extension'];
    318 
    319                         $filename = trailingslashit( $dir ) . wp_basename( $filename, ".$ext" ) . ".{$new_ext}";
    320                 }
    321 
    322                 return array( $filename, $new_ext, $mime_type );
     41                return new WP_Error( 'image_no_editor', __('No editor could be selected.') );
    32342        }
    32443
    32544        /**
    326          * Builds an output filename based on current file, and adding proper suffix
     45         * Tests whether there is an editor that supports a given mime type or methods.
    32746         *
    32847         * @since 3.5.0
    32948         * @access public
    33049         *
    331          * @param string $suffix
    332          * @param string $dest_path
    333          * @param string $extension
    334          * @return string filename
     50         * @param string|array $args String path to image to check for support, or array of arguments.  Accepts { 'path'=>string, 'mime_type'=>string, 'methods'=>{string, string, ...} }
     51         * @return boolean true if an eligible editor is found; false otherwise
    33552         */
    336         public function generate_filename( $suffix = null, $dest_path = null, $extension = null ) {
    337                 // $suffix will be appended to the destination filename, just before the extension
    338                 if ( ! $suffix )
    339                         $suffix = $this->get_suffix();
    340 
    341                 $info = pathinfo( $this->file );
    342                 $dir  = $info['dirname'];
    343                 $ext  = $info['extension'];
    344 
    345                 $name = wp_basename( $this->file, ".$ext" );
    346                 $new_ext = strtolower( $extension ? $extension : $ext );
    347 
    348                 if ( ! is_null( $dest_path ) && $_dest_path = realpath( $dest_path ) )
    349                         $dir = $_dest_path;
    350 
    351                 return trailingslashit( $dir ) . "{$name}-{$suffix}.{$new_ext}";
    352         }
    353 
    354         /**
    355          * Builds and returns proper suffix for file based on height and width.
    356          *
    357          * @since 3.5.0
    358          * @access public
    359          *
    360          * @return string suffix
    361          */
    362         public function get_suffix() {
    363                 if ( ! $this->get_size() )
    364                         return false;
    365 
    366                 return "{$this->size['width']}x{$this->size['height']}";
     53        public static function supports( $args = array() ) {
     54                return (bool) self::choose_implementation( $args );
    36755        }
    36856
    36957        /**
    370          * Either calls editor's save function or handles file as a stream.
     58         * Tests which editors are capable of supporting the request.
    37159         *
    37260         * @since 3.5.0
    373          * @access protected
     61         * @access private
    37462         *
    375          * @param string|stream $filename
    376          * @param callable $function
    377          * @param array $arguments
    378          * @return boolean
     63         * @param array $args Additional data. Accepts { 'mime_type'=>string, 'methods'=>{string, string, ...} }
     64         * @return string|bool Class name for the first editor that claims to support the request. False if no editor claims to support the request.
    37965         */
    380         protected function make_image( $filename, $function, $arguments ) {
    381                 $dst_file = $filename;
    382 
    383                 if ( $stream = wp_is_stream( $filename ) ) {
    384                         $filename = null;
    385                         ob_start();
    386                 }
    387 
    388                 $result = call_user_func_array( $function, $arguments );
    389 
    390                 if ( $result && $stream ) {
    391                         $contents = ob_get_contents();
    392 
    393                         $fp = fopen( $dst_file, 'w' );
    394 
    395                         if ( ! $fp )
    396                                 return false;
    397 
    398                         fwrite( $fp, $contents );
    399                         fclose( $fp );
    400                 }
    401 
    402                 if ( $stream ) {
    403                         ob_end_clean();
    404                 }
    405 
    406                 return $result;
    407         }
     66        private static function choose_implementation( $args = array() ) {
     67                $implementations = apply_filters( 'wp_image_editors',
     68                        array( 'WP_Image_Editor_Imagick', 'WP_Image_Editor_GD' ) );
    40869
    409         /**
    410          * Returns first matched mime-type from extension,
    411          * as mapped from wp_get_mime_types()
    412          *
    413          * @since 3.5.0
    414          * @access protected
    415          *
    416          * @param string $extension
    417          * @return string|boolean
    418          */
    419         protected static function get_mime_type( $extension = null ) {
    420                 if ( ! $extension )
    421                         return false;
     70                foreach ( $implementations as $implementation ) {
     71                        if ( ! call_user_func( array( $implementation, 'test' ), $args ) )
     72                                continue;
    42273
    423                 $mime_types = wp_get_mime_types();
    424                 $extensions = array_keys( $mime_types );
     74                        if ( isset( $args['mime_type'] ) &&
     75                                ! call_user_func(
     76                                        array( $implementation, 'supports_mime_type' ),
     77                                        $args['mime_type'] ) ) {
     78                                continue;
     79                        }
    42580
    426                 foreach( $extensions as $_extension ) {
    427                         if ( preg_match( "/{$extension}/i", $_extension ) ) {
    428                                 return $mime_types[$_extension];
     81                        if ( isset( $args['methods'] ) &&
     82                                 array_diff( $args['methods'], get_class_methods( $implementation ) ) ) {
     83                                continue;
    42984                        }
     85
     86                        return $implementation;
    43087                }
    43188
    43289                return false;
    43390        }
    434 
    435         /**
    436          * Returns first matched extension from Mime-type,
    437          * as mapped from wp_get_mime_types()
    438          *
    439          * @since 3.5.0
    440          * @access protected
    441          *
    442          * @param string $mime_type
    443          * @return string|boolean
    444          */
    445         protected static function get_extension( $mime_type = null ) {
    446                 $extensions = explode( '|', array_search( $mime_type, wp_get_mime_types() ) );
    447 
    448                 if ( empty( $extensions[0] ) )
    449                         return false;
    450 
    451                 return $extensions[0];
    452         }
    45391}
     92
  • wp-includes/deprecated.php

    diff --git wp-includes/deprecated.php wp-includes/deprecated.php
    index 9e99614..5b841df 100644
    function user_pass_ok($user_login, $user_pass) { 
    33283328 * @since 2.3.0
    33293329 * @deprecated 3.5.0
    33303330 */
    3331 function _save_post_hook() {}
    3332  No newline at end of file
     3331function _save_post_hook() {}
     3332
     3333/**
     3334 * Check if the installed version of GD supports particular image type
     3335 *
     3336 * @since 2.9.0
     3337 * @deprecated 3.5.0
     3338 * @see WP_Image_Editor::supports()
     3339 *
     3340 * @param string $mime_type
     3341 * @return bool
     3342 */
     3343function gd_edit_image_support($mime_type) {
     3344        _deprecated_function( __FUNCTION__, '3.5', 'WP_Image_Editor::supports()' );
     3345        if ( function_exists('imagetypes') ) {
     3346                switch( $mime_type ) {
     3347                        case 'image/jpeg':
     3348                                return (imagetypes() & IMG_JPG) != 0;
     3349                        case 'image/png':
     3350                                return (imagetypes() & IMG_PNG) != 0;
     3351                        case 'image/gif':
     3352                                return (imagetypes() & IMG_GIF) != 0;
     3353                }
     3354        } else {
     3355                switch( $mime_type ) {
     3356                        case 'image/jpeg':
     3357                                return function_exists('imagecreatefromjpeg');
     3358                        case 'image/png':
     3359                                return function_exists('imagecreatefrompng');
     3360                        case 'image/gif':
     3361                                return function_exists('imagecreatefromgif');
     3362                }
     3363        }
     3364        return false;
     3365}
     3366 No newline at end of file
  • wp-includes/media.php

    diff --git wp-includes/media.php wp-includes/media.php
    index d8475f1..cfc7172 100644
    function get_taxonomies_for_attachments( $output = 'names' ) { 
    904904}
    905905
    906906/**
    907  * Check if the installed version of GD supports particular image type
    908  *
    909  * @since 2.9.0
    910  *
    911  * @param string $mime_type
    912  * @return bool
    913  */
    914 function gd_edit_image_support($mime_type) {
    915         if ( function_exists('imagetypes') ) {
    916                 switch( $mime_type ) {
    917                         case 'image/jpeg':
    918                                 return (imagetypes() & IMG_JPG) != 0;
    919                         case 'image/png':
    920                                 return (imagetypes() & IMG_PNG) != 0;
    921                         case 'image/gif':
    922                                 return (imagetypes() & IMG_GIF) != 0;
    923                 }
    924         } else {
    925                 switch( $mime_type ) {
    926                         case 'image/jpeg':
    927                                 return function_exists('imagecreatefromjpeg');
    928                         case 'image/png':
    929                                 return function_exists('imagecreatefrompng');
    930                         case 'image/gif':
    931                                 return function_exists('imagecreatefromgif');
    932                 }
    933         }
    934         return false;
    935 }
    936 
    937 /**
    938907 * Create new GD image resource with transparency support
    939908 * @TODO: Deprecate if possible.
    940909 *
  • wp-settings.php

    diff --git wp-settings.php wp-settings.php
    index ac331c2..bb15067 100644
    require( ABSPATH . WPINC . '/nav-menu-template.php' ); 
    144144require( ABSPATH . WPINC . '/admin-bar.php' );
    145145
    146146require( ABSPATH . WPINC . '/class-wp-image-editor.php' );
     147require( ABSPATH . WPINC . '/class-wp-image-editor-base.php' );
    147148require( ABSPATH . WPINC . '/class-wp-image-editor-gd.php' );
    148149require( ABSPATH . WPINC . '/class-wp-image-editor-imagick.php' );
    149150