Skip to content

Add Image editor to prevent errors with offloaded images #910

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions inc/media_offload.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* @author Optimole <[email protected]>
*/

use OptimoleWP\Offload\Loader;
use Optimole\Sdk\Exception\InvalidArgumentException;
use Optimole\Sdk\Exception\InvalidUploadApiResponseException;
use Optimole\Sdk\Exception\RuntimeException;
Expand Down Expand Up @@ -186,6 +187,7 @@ public static function instance() {
if ( self::$is_legacy_install === null ) {
self::$is_legacy_install = get_option( 'optimole_wp_install', 0 ) > 1677171600;
}
( new Loader() )->register_hooks();
}
}

Expand Down
157 changes: 157 additions & 0 deletions inc/v2/Offload/ImageEditor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
<?php

namespace OptimoleWP\Offload;

use Optml_Config;
use Optml_Media_Offload;
use WP_Error;

/**
* Class ImageEditor
*
* Custom image editor implementation for Optimole offloaded images.
* This class extends WP_Image_Editor to handle images that have been offloaded
* to Optimole's servers, preventing local editing operations on remote images.
*
* @package OptimoleWP\Offload
*/
class ImageEditor extends \WP_Image_Editor {
/**
* Tests whether this editor can handle the given file.
*
* @param array $args Arguments to test the editor.
* @return bool True if the file is an offloaded image, false otherwise.
*/
public static function test( $args = [] ) {
if ( isset( $args['path'] ) && Optml_Media_Offload::is_uploaded_image( $args['path'] ) ) {
return true;
}

return false;
}

/**
* Checks if this editor supports the given MIME type.
*
* @param string $mime_type The MIME type to check.
* @return bool True if the MIME type is supported, false otherwise.
*/
public static function supports_mime_type( $mime_type ) {
return in_array( $mime_type, Optml_Config::$image_extensions, true );
}

/**
* Saves the image to a file.
*
* For offloaded images, this operation is not supported and always returns false.
*
* @param string $destfilename Optional. The destination filename.
* @param string $mime_type Optional. The MIME type of the image.
* @return array|WP_Error {
* Array on success or WP_Error if the file failed to save.
*
* @type string $path Path to the image file.
* @type string $file Name of the image file.
* @type int $width Image width.
* @type int $height Image height.
* @type string $mime-type The mime type of the image.
* @type int $filesize File size of the image.
* }
*/
public function save( $destfilename = null, $mime_type = null ) {
return false; // @phpstan-ignore-line
}

/**
* Loads the image file.
*
* @return bool True if the file is an offloaded image, false otherwise.
*/
public function load() {
if ( isset( $this->file ) && Optml_Media_Offload::is_uploaded_image( $this->file ) ) {
return true;
}
return false;
}

/**
* Resizes the image.
*
* For offloaded images, this operation is not performed locally and always returns true.
*
* @param int $max_w Maximum width.
* @param int $max_h Maximum height.
* @param bool $crop Optional. Whether to crop the image. Default false.
* @return bool Always returns true for offloaded images.
*/
public function resize( $max_w, $max_h, $crop = false ) {
return true;
}

/**
* Resizes the image to multiple sizes.
*
* For offloaded images, this operation is not performed locally and always returns an empty array.
*
* @param array $sizes Array of size arrays. Each size array must include width, height, crop.
* @return array Empty array for offloaded images.
*/
public function multi_resize( $sizes ) {
return [];
}

/**
* Crops the image.
*
* For offloaded images, this operation is not performed locally and always returns true.
*
* @param int $src_x The start x position to crop from.
* @param int $src_y The start y position to crop from.
* @param int $src_w The width to crop.
* @param int $src_h The height to crop.
* @param int $dst_w Optional. The destination width.
* @param int $dst_h Optional. The destination height.
* @param bool $src_abs Optional. If the source crop points are absolute.
* @return bool Always returns true for offloaded images.
*/
public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) {
return true;
}

/**
* Rotates the image.
*
* For offloaded images, this operation is not performed locally and always returns true.
*
* @param float $angle The angle of rotation.
* @return bool Always returns true for offloaded images.
*/
public function rotate( $angle ) {
return true;
}

/**
* Flips the image.
*
* For offloaded images, this operation is not performed locally and always returns true.
*
* @param bool $horz Whether to flip horizontally.
* @param bool $vert Whether to flip vertically.
* @return bool Always returns true for offloaded images.
*/
public function flip( $horz, $vert ) {
return true;
}

/**
* Streams the image to the browser.
*
* For offloaded images, this redirects to the remote image URL.
*
* @param string $mime_type Optional. The MIME type of the image.
*/
public function stream( $mime_type = null ) {
header( 'Location: ' . esc_url( $this->file ) );
return true;
}
}
44 changes: 44 additions & 0 deletions inc/v2/Offload/Loader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace OptimoleWP\Offload;

/**
* Class Loader
*
* Handles the registration of custom image editors for the Optimole WordPress plugin.
* This class is responsible for integrating Optimole's custom image processing
* capabilities into WordPress's image editing system.
*
* @package OptimoleWP\Offload
*/
class Loader {

/**
* Constructor for the Loader class.
*/
public function __construct() {
}

/**
* Register WordPress hooks needed for the image editor functionality.
*
* Adds filters to integrate the custom image editor into WordPress.
*/
public function register_hooks() {
add_filter( 'wp_image_editors', [ $this, 'register_image_editor' ] );
}

/**
* Register the custom ImageEditor class to WordPress's image editors list.
*
* Adds Optimole's custom ImageEditor to the beginning of WordPress's image editors array,
* giving it priority over the default editors.
*
* @param array $editors Array of image editor class names.
* @return array Modified array of image editor class names.
*/
public function register_image_editor( $editors ) {
array_unshift( $editors, ImageEditor::class );
return $editors;
}
}
Loading