Make WordPress Core


Ignore:
Timestamp:
10/20/2020 02:35:10 PM (4 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.