Make WordPress Core


Ignore:
Timestamp:
10/20/2020 02:35:10 PM (6 years ago)
Author:
mikeschroder
Message:

Media: Support Stream Wrappers In WP_Image_Editor_Imagick

Since WP_Image_Editor's introduction, stream wrappers have functioned in WP_Image_Editor_GD, but haven't been properly supported in WP_Image_Editor_Imagick.

  • Detects stream wrappers and uses file_put_contents() along with Imagick::read/getImageBlob() for handling when necessary.
  • Introduces private method, WP_Image_Editor_Imagick::write_image to handle detection and proper saving.
  • Introduces WP_Test_Stream class for testing stream wrappers, along with new tests for Imagick's stream handling and a stream filename test.

Adds requirement for Imagick::readImageBlob(), available in Imagick >= 2.0.0, which aligns with the current requirement of Imagick >= 2.2.0.

Props p00ya, calin, joemcgill, pputzer, jimyaghi, mikeschroder.
Fixes #42663.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-image-editor-imagick.php

    r49174 r49230  
    7272                        'flopimage',
    7373                        'readimage',
     74                        'readimageblob',
    7475                );
    7576
    … …  
    128129                }
    129130
    130                 if ( ! is_file( $this->file ) && ! preg_match( '|^https?://|', $this->file ) ) {
     131                if ( ! is_file( $this->file ) && ! wp_is_stream( $this->file ) ) {
    131132                        return new WP_Error( 'error_loading_image', __( 'File doesn’t exist?' ), $this->file );
    132133                }
    … …  
    149150                                }
    150151                        } else {
    151                                 $this->image->readImage( $this->file );
     152                                if ( wp_is_stream( $this->file ) ) {
     153                                        // Due to reports of issues with streams with `Imagick::readImageFile()`, uses `Imagick::readImageBlob()` instead.
     154                                        $this->image->readImageBlob( file_get_contents( $this->file ), $this->file );
     155                                } else {
     156                                        $this->image->readImage( $this->file );
     157                                }
    152158                        }
    153159
    … …  
    683689
    684690                        $this->image->setImageFormat( strtoupper( $this->get_extension( $mime_type ) ) );
    685                         $this->make_image( $filename, array( $image, 'writeImage' ), array( $filename ) );
    686 
     691                } catch ( Exception $e ) {
     692                        return new WP_Error( 'image_save_error', $e->getMessage(), $filename );
     693                }
     694
     695                $write_image_result = $this->write_image( $this->image, $filename );
     696                if ( is_wp_error( $write_image_result ) ) {
     697                        return $write_image_result;
     698                }
     699
     700                try {
    687701                        // Reset original format.
    688702                        $this->image->setImageFormat( $orig_format );
    … …  
    704718                        'mime-type' => $mime_type,
    705719                );
     720        }
     721
     722        /**
     723         * Writes an image to a file or stream.
     724         *
     725         * @since 5.6
     726         *
     727         * @param Imagick $image
     728         * @param string  $filename The destination filename or stream URL.
     729         *
     730         * @return true|WP_Error
     731         */
     732        private function write_image( $image, $filename ) {
     733                if ( wp_is_stream( $filename ) ) {
     734                        /*
     735                         * Due to reports of issues with streams with `Imagick::writeImageFile()` and `Imagick::writeImage()`, copies the blob instead.
     736                         * Checks for exact type due to: https://www.php.net/manual/en/function.file-put-contents.php
     737                         */
     738                        if ( file_put_contents( $filename, $image->getImageBlob() ) === false ) {
     739                                /* translators: %s: PHP function name. */
     740                                return new WP_Error( 'image_save_error', sprintf( __( '%s failed while writing image to stream.' ), '<code>file_put_contents()</code>' ), $filename );
     741                        } else {
     742                                return true;
     743                        }
     744                } else {
     745                        try {
     746                                return $image->writeImage( $filename );
     747                        } catch ( Exception $e ) {
     748                                return new WP_Error( 'image_save_error', $e->getMessage(), $filename );
     749                        }
     750                }
    706751        }
    707752
Note: See TracChangeset for help on using the changeset viewer.