Make WordPress Core

Ticket #22356: 22356.7.diff

File 22356.7.diff, 32.0 KB (added by scribu, 12 years ago)

optional supports_mime_type()

  • 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..99023a2
    - +  
     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
     9        protected $file = null;
     10        protected $size = null;
     11        protected $mime_type = null;
     12        protected $default_mime_type = 'image/jpeg';
     13        protected $quality = 90;
     14
     15        /**
     16         * Checks to see if current environment supports the editor chosen.
     17         * Must be overridden in a sub-class.
     18         *
     19         * @since 3.5.0
     20         * @access public
     21         * @abstract
     22         *
     23         * @param array $args
     24         * @return boolean
     25         */
     26        public static function test( $args = array() ) {
     27                return false;
     28        }
     29
     30        /**
     31         * Each instance handles a single file.
     32         */
     33        public function __construct( $file ) {
     34                $this->file = $file;
     35        }
     36
     37        /**
     38         * Loads image from $this->file into editor.
     39         *
     40         * @since 3.5.0
     41         * @access protected
     42         * @abstract
     43         *
     44         * @return boolean|WP_Error True if loaded; WP_Error on failure.
     45         */
     46        abstract public function load();
     47
     48        /**
     49         * Saves current image to file.
     50         *
     51         * @since 3.5.0
     52         * @access public
     53         * @abstract
     54         *
     55         * @param string $destfilename
     56         * @param string $mime_type
     57         * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string}
     58         */
     59        abstract public function save( $destfilename = null, $mime_type = null );
     60
     61        /**
     62         * Resizes current image.
     63         *
     64         * @since 3.5.0
     65         * @access public
     66         * @abstract
     67         *
     68         * @param int $max_w
     69         * @param int $max_h
     70         * @param boolean $crop
     71         * @return boolean|WP_Error
     72         */
     73        abstract public function resize( $max_w, $max_h, $crop = false );
     74
     75        /**
     76         * Processes current image and saves to disk
     77         * multiple sizes from single source.
     78         *
     79         * @since 3.5.0
     80         * @access public
     81         * @abstract
     82         *
     83         * @param array $sizes
     84         * @return array
     85         */
     86        abstract public function multi_resize( $sizes );
     87
     88        /**
     89         * Crops Image.
     90         *
     91         * @since 3.5.0
     92         * @access public
     93         * @abstract
     94         *
     95         * @param string|int $src The source file or Attachment ID.
     96         * @param int $src_x The start x position to crop from.
     97         * @param int $src_y The start y position to crop from.
     98         * @param int $src_w The width to crop.
     99         * @param int $src_h The height to crop.
     100         * @param int $dst_w Optional. The destination width.
     101         * @param int $dst_h Optional. The destination height.
     102         * @param boolean $src_abs Optional. If the source crop points are absolute.
     103         * @return boolean|WP_Error
     104         */
     105        abstract public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false );
     106
     107        /**
     108         * Rotates current image counter-clockwise by $angle.
     109         *
     110         * @since 3.5.0
     111         * @access public
     112         * @abstract
     113         *
     114         * @param float $angle
     115         * @return boolean|WP_Error
     116         */
     117        abstract public function rotate( $angle );
     118
     119        /**
     120         * Flips current image.
     121         *
     122         * @since 3.5.0
     123         * @access public
     124         * @abstract
     125         *
     126         * @param boolean $horz Horizontal Flip
     127         * @param boolean $vert Vertical Flip
     128         * @return boolean|WP_Error
     129         */
     130        abstract public function flip( $horz, $vert );
     131
     132        /**
     133         * Streams current image to browser.
     134         *
     135         * @since 3.5.0
     136         * @access public
     137         * @abstract
     138         *
     139         * @param string $mime_type
     140         * @return boolean|WP_Error
     141         */
     142        abstract public function stream( $mime_type = null );
     143
     144        /**
     145         * Gets dimensions of image.
     146         *
     147         * @since 3.5.0
     148         * @access public
     149         *
     150         * @return array {'width'=>int, 'height'=>int}
     151         */
     152        public function get_size() {
     153                return $this->size;
     154        }
     155
     156        /**
     157         * Sets current image size.
     158         *
     159         * @since 3.5.0
     160         * @access protected
     161         *
     162         * @param int $width
     163         * @param int $height
     164         */
     165        protected function update_size( $width = null, $height = null ) {
     166                $this->size = array(
     167                        'width' => $width,
     168                        'height' => $height
     169                );
     170                return true;
     171        }
     172
     173        /**
     174         * Sets Image Compression quality on a 1-100% scale.
     175         *
     176         * @since 3.5.0
     177         * @access public
     178         *
     179         * @param int $quality Compression Quality. Range: [1,100]
     180         * @return boolean
     181         */
     182        public function set_quality( $quality ) {
     183                $this->quality = apply_filters( 'wp_editor_set_quality', $quality );
     184
     185                return ( (bool) $this->quality );
     186        }
     187
     188        /**
     189         * Returns preferred mime-type and extension based on provided
     190         * file's extension and mime, or current file's extension and mime.
     191         *
     192         * Will default to $this->default_mime_type if requested is not supported.
     193         *
     194         * Provides corrected filename only if filename is provided.
     195         *
     196         * @since 3.5.0
     197         * @access protected
     198         *
     199         * @param string $filename
     200         * @param string $mime_type
     201         * @return array { filename|null, extension, mime-type }
     202         */
     203        protected function get_output_format( $filename = null, $mime_type = null ) {
     204                $new_ext = $file_ext = null;
     205                $file_mime = null;
     206
     207                // By default, assume specified type takes priority
     208                if ( $mime_type ) {
     209                        $new_ext = $this->get_extension( $mime_type );
     210                }
     211
     212                if ( $filename ) {
     213                        $file_ext = strtolower( pathinfo( $filename, PATHINFO_EXTENSION ) );
     214                        $file_mime = $this->get_mime_type( $file_ext );
     215                }
     216                else {
     217                        // If no file specified, grab editor's current extension and mime-type.
     218                        $file_ext = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) );
     219                        $file_mime = $this->mime_type;
     220                }
     221
     222                // Check to see if specified mime-type is the same as type implied by
     223                // file extension.  If so, prefer extension from file.
     224                if ( ! $mime_type || ( $file_mime == $mime_type ) ) {
     225                        $mime_type = $file_mime;
     226                        $new_ext = $file_ext;
     227                }
     228
     229                // Double-check that the mime-type selected is supported by the editor.
     230                // If not, choose a default instead.
     231                if ( ! $this->supports_mime_type( $mime_type ) ) {
     232                        $mime_type = apply_filters( 'image_editor_default_mime_type', $this->default_mime_type );
     233                        $new_ext = $this->get_extension( $mime_type );
     234                }
     235
     236                if ( $filename ) {
     237                        $ext = '';
     238                        $info = pathinfo( $filename );
     239                        $dir  = $info['dirname'];
     240
     241                        if( isset( $info['extension'] ) )
     242                                $ext = $info['extension'];
     243
     244                        $filename = trailingslashit( $dir ) . wp_basename( $filename, ".$ext" ) . ".{$new_ext}";
     245                }
     246
     247                return array( $filename, $new_ext, $mime_type );
     248        }
     249
     250        /**
     251         * Builds an output filename based on current file, and adding proper suffix
     252         *
     253         * @since 3.5.0
     254         * @access public
     255         *
     256         * @param string $suffix
     257         * @param string $dest_path
     258         * @param string $extension
     259         * @return string filename
     260         */
     261        public function generate_filename( $suffix = null, $dest_path = null, $extension = null ) {
     262                // $suffix will be appended to the destination filename, just before the extension
     263                if ( ! $suffix )
     264                        $suffix = $this->get_suffix();
     265
     266                $info = pathinfo( $this->file );
     267                $dir  = $info['dirname'];
     268                $ext  = $info['extension'];
     269
     270                $name = wp_basename( $this->file, ".$ext" );
     271                $new_ext = strtolower( $extension ? $extension : $ext );
     272
     273                if ( ! is_null( $dest_path ) && $_dest_path = realpath( $dest_path ) )
     274                        $dir = $_dest_path;
     275
     276                return trailingslashit( $dir ) . "{$name}-{$suffix}.{$new_ext}";
     277        }
     278
     279        /**
     280         * Builds and returns proper suffix for file based on height and width.
     281         *
     282         * @since 3.5.0
     283         * @access public
     284         *
     285         * @return string suffix
     286         */
     287        public function get_suffix() {
     288                if ( ! $this->get_size() )
     289                        return false;
     290
     291                return "{$this->size['width']}x{$this->size['height']}";
     292        }
     293
     294        /**
     295         * Either calls editor's save function or handles file as a stream.
     296         *
     297         * @since 3.5.0
     298         * @access protected
     299         *
     300         * @param string|stream $filename
     301         * @param callable $function
     302         * @param array $arguments
     303         * @return boolean
     304         */
     305        protected function make_image( $filename, $function, $arguments ) {
     306                $dst_file = $filename;
     307
     308                if ( $stream = wp_is_stream( $filename ) ) {
     309                        $filename = null;
     310                        ob_start();
     311                }
     312
     313                $result = call_user_func_array( $function, $arguments );
     314
     315                if ( $result && $stream ) {
     316                        $contents = ob_get_contents();
     317
     318                        $fp = fopen( $dst_file, 'w' );
     319
     320                        if ( ! $fp )
     321                                return false;
     322
     323                        fwrite( $fp, $contents );
     324                        fclose( $fp );
     325                }
     326
     327                if ( $stream ) {
     328                        ob_end_clean();
     329                }
     330
     331                return $result;
     332        }
     333
     334        /**
     335         * Returns first matched mime-type from extension,
     336         * as mapped from wp_get_mime_types()
     337         *
     338         * @since 3.5.0
     339         * @access protected
     340         *
     341         * @param string $extension
     342         * @return string|boolean
     343         */
     344        protected static function get_mime_type( $extension = null ) {
     345                if ( ! $extension )
     346                        return false;
     347
     348                $mime_types = wp_get_mime_types();
     349                $extensions = array_keys( $mime_types );
     350
     351                foreach( $extensions as $_extension ) {
     352                        if ( preg_match( "/{$extension}/i", $_extension ) ) {
     353                                return $mime_types[$_extension];
     354                        }
     355                }
     356
     357                return false;
     358        }
     359
     360        /**
     361         * Returns first matched extension from Mime-type,
     362         * as mapped from wp_get_mime_types()
     363         *
     364         * @since 3.5.0
     365         * @access protected
     366         *
     367         * @param string $mime_type
     368         * @return string|boolean
     369         */
     370        protected static function get_extension( $mime_type = null ) {
     371                $extensions = explode( '|', array_search( $mime_type, wp_get_mime_types() ) );
     372
     373                if ( empty( $extensions[0] ) )
     374                        return false;
     375
     376                return $extensions[0];
     377        }
     378}
     379
  • 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..7239207 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 {
     18
    1819        protected $image = false; // GD Resource
    1920
    2021        function __destruct() {
    class WP_Image_Editor_GD extends WP_Image_Editor { 
    3233         *
    3334         * @return boolean
    3435         */
    35         public static function test( $args = null ) {
     36        public static function test( $args = array() ) {
    3637                if ( ! extension_loaded('gd') || ! function_exists('gd_info') )
    3738                        return false;
    3839
     40                if ( isset( $args['mime_type'] ) && !self::supports_mime_type( $args['mime_type'] ) )
     41                        return false;
     42
    3943                return true;
    4044        }
    4145
    4246        /**
     47         * Checks to see if editor supports the mime-type specified.
     48         *
     49         * @since 3.5.0
     50         * @access public
     51         *
     52         * @param string $mime_type
     53         * @return boolean
     54         */
     55        protected static function supports_mime_type( $mime_type ) {
     56                $image_types = imagetypes();
     57                switch( $mime_type ) {
     58                        case 'image/jpeg':
     59                                return ($image_types & IMG_JPG) != 0;
     60                        case 'image/png':
     61                                return ($image_types & IMG_PNG) != 0;
     62                        case 'image/gif':
     63                                return ($image_types & IMG_GIF) != 0;
     64                }
     65
     66                return false;
     67        }
     68
     69        /**
    4370         * Loads image from $this->file into new GD Resource.
    4471         *
    4572         * @since 3.5.0
    class WP_Image_Editor_GD extends WP_Image_Editor { 
    4774         *
    4875         * @return boolean|\WP_Error
    4976         */
    50         protected function load() {
     77        public function load() {
    5178                if ( $this->image )
    5279                        return true;
    5380
    class WP_Image_Editor_GD extends WP_Image_Editor { 
    91118        }
    92119
    93120        /**
    94          * Checks to see if editor supports the mime-type specified.
    95          *
    96          * @since 3.5.0
    97          * @access public
    98          *
    99          * @param string $mime_type
    100          * @return boolean
    101          */
    102         public static function supports_mime_type( $mime_type ) {
    103                 $allowed_mime_types = array( 'image/gif', 'image/png', 'image/jpeg' );
    104 
    105                 return in_array( $mime_type, $allowed_mime_types );
    106         }
    107 
    108         /**
    109121         * Resizes current image.
    110122         * Wraps _resize, since _resize returns a GD Resource.
    111123         *
    class WP_Image_Editor_GD extends WP_Image_Editor { 
    261273         * @since 3.5.0
    262274         * @access public
    263275         *
    264          * @param boolean $horz Horizonal Flip
     276         * @param boolean $horz Horizontal Flip
    265277         * @param boolean $vert Vertical Flip
    266278         * @returns boolean|WP_Error
    267279         */
    class WP_Image_Editor_GD extends WP_Image_Editor { 
    369381                                return imagejpeg( $this->image, null, $this->quality );
    370382                }
    371383        }
    372 }
    373  No newline at end of file
     384}
  • 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..b7aa955 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 {
     18
    1819        protected $image = null; // Imagick Object
    1920
    2021        function __destruct() {
    class WP_Image_Editor_Imagick extends WP_Image_Editor { 
    3637         *
    3738         * @return boolean
    3839         */
    39         public static function test( $args = null ) {
     40        public static function test( $args = array() ) {
    4041                if ( ! extension_loaded( 'imagick' ) || ! is_callable( 'Imagick', 'queryFormats' ) )
    4142                        return false;
    4243
     44                if ( isset( $args['mime_type'] ) && !self::supports_mime_type( $args['mime_type'] ) )
     45                        return false;
     46
    4347                return true;
    4448        }
    4549
    4650        /**
     51         * Checks to see if editor supports the mime-type specified.
     52         *
     53         * @since 3.5.0
     54         * @access public
     55         *
     56         * @param string $mime_type
     57         * @return boolean
     58         */
     59        protected static function supports_mime_type( $mime_type ) {
     60                $imagick_extension = strtoupper( self::get_extension( $mime_type ) );
     61
     62                if ( ! $imagick_extension )
     63                        return false;
     64
     65                try {
     66                        return ( (bool) Imagick::queryFormats( $imagick_extension ) );
     67                }
     68                catch ( Exception $e ) {
     69                        return false;
     70                }
     71        }
     72
     73        /**
    4774         * Loads image from $this->file into new Imagick Object.
    4875         *
    4976         * @since 3.5.0
    class WP_Image_Editor_Imagick extends WP_Image_Editor { 
    5178         *
    5279         * @return boolean|WP_Error True if loaded; WP_Error on failure.
    5380         */
    54         protected function load() {
     81        public function load() {
    5582                if ( $this->image )
    5683                        return true;
    5784
    class WP_Image_Editor_Imagick extends WP_Image_Editor { 
    138165        }
    139166
    140167        /**
    141          * Checks to see if editor supports the mime-type specified.
    142          *
    143          * @since 3.5.0
    144          * @access public
    145          *
    146          * @param string $mime_type
    147          * @return boolean
    148          */
    149         public static function supports_mime_type( $mime_type ) {
    150                 if ( ! $mime_type )
    151                         return false;
    152 
    153                 $imagick_extension = strtoupper( self::get_extension( $mime_type ) );
    154 
    155                 try {
    156                         return ( (bool) Imagick::queryFormats( $imagick_extension ) );
    157                 }
    158                 catch ( Exception $e ) {
    159                         return false;
    160                 }
    161         }
    162 
    163         /**
    164168         * Resizes current image.
    165169         *
    166170         * @since 3.5.0
    class WP_Image_Editor_Imagick extends WP_Image_Editor { 
    312316         * @since 3.5.0
    313317         * @access public
    314318         *
    315          * @param boolean $horz Horizonal Flip
     319         * @param boolean $horz Horizontal Flip
    316320         * @param boolean $vert Vertical Flip
    317321         * @returns boolean|WP_Error
    318322         */
  • 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..8fccf53 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                $args['path'] = $path;
     21
     22                $implementation = apply_filters( 'wp_image_editor_class', self::choose_implementation( $args ) );
    3723
    3824                if ( $implementation ) {
    3925                        $editor = new $implementation( $path );
    abstract class WP_Image_Editor { 
    4531                        return $editor;
    4632                }
    4733
    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 );
    323         }
    324 
    325         /**
    326          * Builds an output filename based on current file, and adding proper suffix
    327          *
    328          * @since 3.5.0
    329          * @access public
    330          *
    331          * @param string $suffix
    332          * @param string $dest_path
    333          * @param string $extension
    334          * @return string filename
    335          */
    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}";
     34                return new WP_Error( 'image_no_editor', __('No editor could be selected.') );
    35235        }
    35336
    35437        /**
    355          * Builds and returns proper suffix for file based on height and width.
     38         * Tests whether there is an editor that supports a given mime type or methods.
    35639         *
    35740         * @since 3.5.0
    35841         * @access public
    35942         *
    360          * @return string suffix
     43         * @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, ...} }
     44         * @return boolean true if an eligible editor is found; false otherwise
    36145         */
    362         public function get_suffix() {
    363                 if ( ! $this->get_size() )
    364                         return false;
    365 
    366                 return "{$this->size['width']}x{$this->size['height']}";
     46        public static function supports( $args = array() ) {
     47                return (bool) self::choose_implementation( $args );
    36748        }
    36849
    36950        /**
    370          * Either calls editor's save function or handles file as a stream.
     51         * Tests which editors are capable of supporting the request.
    37152         *
    37253         * @since 3.5.0
    373          * @access protected
     54         * @access private
    37455         *
    375          * @param string|stream $filename
    376          * @param callable $function
    377          * @param array $arguments
    378          * @return boolean
     56         * @param array $args Additional data. Accepts { 'mime_type'=>string, 'methods'=>{string, string, ...} }
     57         * @return string|bool Class name for the first editor that claims to support the request. False if no editor claims to support the request.
    37958         */
    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' );
     59        private static function choose_implementation( $args = array() ) {
     60                if ( !isset( $args['mime_type'] ) && isset( $args['path'] ) ) {
     61                        $file_info  = wp_check_filetype( $args['path'] );
    39462
    395                         if ( ! $fp )
    396                                 return false;
    397 
    398                         fwrite( $fp, $contents );
    399                         fclose( $fp );
    400                 }
    401 
    402                 if ( $stream ) {
    403                         ob_end_clean();
     63                        // If $file_info['type'] is false, then we let the editor attempt to
     64                        // figure out the file type, rather than forcing a failure based on extension.
     65                        if ( isset( $file_info ) && $file_info['type'] )
     66                                $args['mime_type'] = $file_info['type'];
    40467                }
    40568
    406                 return $result;
    407         }
    408 
    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;
     69                $implementations = apply_filters( 'wp_image_editors',
     70                        array( 'WP_Image_Editor_Imagick', 'WP_Image_Editor_GD' ) );
    42271
    423                 $mime_types = wp_get_mime_types();
    424                 $extensions = array_keys( $mime_types );
     72                foreach ( $implementations as $implementation ) {
     73                        if ( ! call_user_func( array( $implementation, 'test' ), $args ) )
     74                                continue;
    42575
    426                 foreach( $extensions as $_extension ) {
    427                         if ( preg_match( "/{$extension}/i", $_extension ) ) {
    428                                 return $mime_types[$_extension];
     76                        if ( isset( $args['methods'] ) &&
     77                                 array_diff( $args['methods'], get_class_methods( $implementation ) ) ) {
     78                                continue;
    42979                        }
     80
     81                        return $implementation;
    43082                }
    43183
    43284                return false;
    43385        }
    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         }
    45386}
     87
  • 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