| 1 |
<?php |
| 2 |
/** |
| 3 |
* Registers Image Transformation functionality in the container. |
| 4 |
* |
| 5 |
* @package SolidWP\Performance |
| 6 |
*/ |
| 7 |
|
| 8 |
declare( strict_types=1 ); |
| 9 |
|
| 10 |
namespace SolidWP\Performance\Image_Transformation; |
| 11 |
|
| 12 |
use SolidWP\Performance\Config\Config; |
| 13 |
use SolidWP\Performance\Contracts\Service_Provider; |
| 14 |
use SolidWP\Performance\Image_Transformation\Contracts\Processor; |
| 15 |
use SolidWP\Performance\Image_Transformation\Decorators\Memoized; |
| 16 |
use SolidWP\Performance\Image_Transformation\Processors\Bypass; |
| 17 |
use SolidWP\Performance\Image_Transformation\Processors\Cloudflare; |
| 18 |
|
| 19 |
/** |
| 20 |
* Registers Image Transformation functionality in the container. |
| 21 |
* |
| 22 |
* @package SolidWP\Performance |
| 23 |
*/ |
| 24 |
final class Provider extends Service_Provider { |
| 25 |
|
| 26 |
/** |
| 27 |
* @inheritDoc |
| 28 |
*/ |
| 29 |
public function register(): void { |
| 30 |
$this->register_settings_listeners(); |
| 31 |
$this->register_processors(); |
| 32 |
$this->register_transformer(); |
| 33 |
} |
| 34 |
|
| 35 |
/** |
| 36 |
* Register a settings listener to purge the cache on image transformation changes and |
| 37 |
* to validate an image processor works before it gets enabled. |
| 38 |
* |
| 39 |
* @return void |
| 40 |
*/ |
| 41 |
private function register_settings_listeners(): void { |
| 42 |
add_action( |
| 43 |
'solidwp/performance/settings/changed', |
| 44 |
$this->container->callback( Settings_Listener::class, 'on_settings_change' ), |
| 45 |
10, |
| 46 |
2, |
| 47 |
); |
| 48 |
|
| 49 |
/** |
| 50 |
* Filters whether Settings Image Transformation Validation is enabled. |
| 51 |
* |
| 52 |
* @param bool $should_validate Whether we should validate. |
| 53 |
*/ |
| 54 |
$should_validate = apply_filters( 'solidwp/performance/image_transformation/should_validate', true ); |
| 55 |
|
| 56 |
if ( $should_validate ) { |
| 57 |
add_filter( |
| 58 |
'solidwp/performance/settings/before_save', |
| 59 |
$this->container->callback( Settings_Validator::class, 'validate' ), |
| 60 |
10, |
| 61 |
2 |
| 62 |
); |
| 63 |
} |
| 64 |
} |
| 65 |
/** |
| 66 |
* Register image transformation processors container definitions. |
| 67 |
* |
| 68 |
* @return void |
| 69 |
*/ |
| 70 |
private function register_processors(): void { |
| 71 |
$this->container->when( Cloudflare::class ) |
| 72 |
->needs( '$options' ) |
| 73 |
->give( |
| 74 |
static fn(): array => |
| 75 |
/** |
| 76 |
* The default options to use for Cloudflare's Transform via URL. |
| 77 |
* |
| 78 |
* @link https://developers.cloudflare.com/images/transform-images/transform-via-url/#options |
| 79 |
* |
| 80 |
* @param array<string, int|string> $options The Cloudflare options. |
| 81 |
*/ |
| 82 |
apply_filters( |
| 83 |
'solidwp/performance/image_transformation/processor/cloudflare/options', |
| 84 |
[ |
| 85 |
'w' => 0, |
| 86 |
'h' => 0, |
| 87 |
'dpr' => 1, |
| 88 |
'fit' => 'cover', |
| 89 |
'f' => 'auto', |
| 90 |
'q' => 85, |
| 91 |
] |
| 92 |
) |
| 93 |
); |
| 94 |
} |
| 95 |
|
| 96 |
/** |
| 97 |
* Registers the Image Transformer definitions in the container. |
| 98 |
* |
| 99 |
* @return void |
| 100 |
*/ |
| 101 |
private function register_transformer(): void { |
| 102 |
$config = $this->container->get( Config::class ); |
| 103 |
|
| 104 |
// Fallback to the Bypass processor in the event we are unable to find a processor. |
| 105 |
$processor_class = Processor_Type::tryFrom( (string) $config->get( 'page_cache.image_transformation.processor' ) ) ?? Bypass::class; |
| 106 |
|
| 107 |
// Wrap the processor in the Memoized decorator for an in-memory cache. |
| 108 |
$this->container->bindDecorators( |
| 109 |
Processor::class, |
| 110 |
[ |
| 111 |
Memoized::class, |
| 112 |
$processor_class, |
| 113 |
] |
| 114 |
); |
| 115 |
|
| 116 |
$this->container->when( Transformer::class ) |
| 117 |
->needs( '$mime_types' ) |
| 118 |
->give( |
| 119 |
static fn(): array => |
| 120 |
/** |
| 121 |
* Filter the allowed mime types an attachment must have in order to be transformed |
| 122 |
* by the image transformer. |
| 123 |
* |
| 124 |
* @param string[] $mime_types The mime types. |
| 125 |
*/ |
| 126 |
apply_filters( |
| 127 |
'solidwp/performance/image_transformation/mime_types', |
| 128 |
[ |
| 129 |
'image/jpeg', |
| 130 |
'image/png', |
| 131 |
'image/gif', |
| 132 |
'image/webp', |
| 133 |
] |
| 134 |
) |
| 135 |
); |
| 136 |
|
| 137 |
$this->container->singleton( Transformer::class, Transformer::class ); |
| 138 |
|
| 139 |
// Note we still need the definitions in case any other classes use Transformer as a dependency. |
| 140 |
// If this isn't enabled, bail here to prevent it from running. |
| 141 |
if ( ! $config->get( 'page_cache.image_transformation.enabled' ) ) { |
| 142 |
return; |
| 143 |
} |
| 144 |
|
| 145 |
// Run on template_redirect to only transform image URLs on the front-end. |
| 146 |
add_action( |
| 147 |
'template_redirect', |
| 148 |
function () { |
| 149 |
add_filter( |
| 150 |
'wp_get_attachment_url', |
| 151 |
function ( $url, $attachment_id ) { |
| 152 |
return $this->container->get( Transformer::class ) |
| 153 |
->filter_attachment_url( (string) $url, (int) $attachment_id ); |
| 154 |
}, |
| 155 |
60, |
| 156 |
2 |
| 157 |
); |
| 158 |
|
| 159 |
add_filter( |
| 160 |
'image_downsize', |
| 161 |
function ( $downsize, $attachment_id, $size ) { |
| 162 |
return $this->container->get( Transformer::class )->filter_image_downsize( $downsize, (int) $attachment_id, $size ); |
| 163 |
}, |
| 164 |
60, |
| 165 |
3 |
| 166 |
); |
| 167 |
|
| 168 |
add_filter( |
| 169 |
'wp_calculate_image_srcset', |
| 170 |
function ( $sources, $sizes, $image_src, $image_meta, $attachment_id ): array { |
| 171 |
return $this->container->get( Transformer::class )->filter_srcset( (array) $sources, (int) $attachment_id ); |
| 172 |
}, |
| 173 |
60, |
| 174 |
5 |
| 175 |
); |
| 176 |
|
| 177 |
add_filter( |
| 178 |
'wp_content_img_tag', |
| 179 |
function ( $image_markup, $context, $attachment_id ) { |
| 180 |
return $this->container->get( Transformer::class )->filter_img_tag_markup( (string) $image_markup, (int) $attachment_id ); |
| 181 |
}, |
| 182 |
60, |
| 183 |
3 |
| 184 |
); |
| 185 |
}, |
| 186 |
20 |
| 187 |
); |
| 188 |
} |
| 189 |
} |
| 190 |
|