Skip to content

Commit

Permalink
feat: disable image subsize generation with cdn image processing
Browse files Browse the repository at this point in the history
  • Loading branch information
carlalexander committed Dec 9, 2022
1 parent feb2755 commit 4a757e0
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 79 deletions.
29 changes: 25 additions & 4 deletions src/Attachment/GDImageEditor.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ class GDImageEditor extends \WP_Image_Editor_GD
{
use ServiceLocatorTrait;

/**
* Flag whether to disable creating image subsizes or not.
*
* @var bool
*/
private $disableImageSubsizes;

/**
* The attachment file manager.
*
Expand All @@ -34,6 +41,7 @@ class GDImageEditor extends \WP_Image_Editor_GD
*/
public function __construct($file)
{
$this->disableImageSubsizes = (bool) self::getService('ymir_cdn_image_processing_enabled');
$this->fileManager = self::getService('file_manager');

if (!$this->fileManager instanceof AttachmentFileManager) {
Expand All @@ -50,9 +58,22 @@ public function __construct($file)
/**
* {@inheritdoc}
*/
public function save($destfilename = null, $mime_type = null)
public function make_subsize($size)
{
return !$this->disableImageSubsizes || !is_array($size) || (!isset($size['height']) && !isset($size['width'])) ? parent::make_subsize($size) : [
'file' => wp_basename($this->file),
'width' => $size['width'],
'height' => $size['height'],
'mime-type' => $this->mime_type,
];
}

/**
* {@inheritdoc}
*/
public function save($destFilename = null, $mimeType = null)
{
$savedImage = parent::save($destfilename, $mime_type);
$savedImage = parent::save($destFilename, $mimeType);

// The "save" method changes the "file" property which is an issue with "multi_resize"
// since we call the "save" method multiple times. So after the first save, the "file"
Expand All @@ -67,9 +88,9 @@ public function save($destfilename = null, $mime_type = null)
/**
* {@inheritdoc}
*/
protected function _save($image, $filename = null, $mime_type = null)
protected function _save($image, $filename = null, $mimeType = null)
{
$savedImage = parent::_save($image, $filename, $mime_type);
$savedImage = parent::_save($image, $filename, $mimeType);

if ($savedImage instanceof \WP_Error || empty($savedImage['path']) || !$this->fileManager->isInTempDirectory($savedImage['path'])) {
return $savedImage;
Expand Down
29 changes: 25 additions & 4 deletions src/Attachment/ImagickImageEditor.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ class ImagickImageEditor extends \WP_Image_Editor_Imagick
{
use ServiceLocatorTrait;

/**
* Flag whether to disable creating image subsizes or not.
*
* @var bool
*/
private $disableImageSubsizes;

/**
* The attachment file manager.
*
Expand All @@ -34,6 +41,7 @@ class ImagickImageEditor extends \WP_Image_Editor_Imagick
*/
public function __construct($file)
{
$this->disableImageSubsizes = (bool) self::getService('ymir_cdn_image_processing_enabled');
$this->fileManager = self::getService('file_manager');

if (!$this->fileManager instanceof AttachmentFileManager) {
Expand All @@ -50,9 +58,22 @@ public function __construct($file)
/**
* {@inheritdoc}
*/
public function save($destfilename = null, $mime_type = null)
public function make_subsize($size)
{
return !$this->disableImageSubsizes || !is_array($size) || (!isset($size['height']) && !isset($size['width'])) ? parent::make_subsize($size) : [
'file' => wp_basename($this->file),
'width' => $size['width'],
'height' => $size['height'],
'mime-type' => $this->mime_type,
];
}

/**
* {@inheritdoc}
*/
public function save($destFilename = null, $mimeType = null)
{
$savedImage = parent::save($destfilename, $mime_type);
$savedImage = parent::save($destFilename, $mimeType);

// The "save" method changes the "file" property which is an issue with "multi_resize"
// since we call the "save" method multiple times. So after the first save, the "file"
Expand All @@ -67,14 +88,14 @@ public function save($destfilename = null, $mime_type = null)
/**
* {@inheritdoc}
*/
protected function _save($image, $filename = null, $mime_type = null)
protected function _save($image, $filename = null, $mimeType = null)
{
// Imagick by default can't handle ymir-public:// paths so have it save the file locally.
if (is_string($filename) && $this->fileManager->isInUploadsDirectory($filename)) {
$filename = $this->fileManager->getTempFilePath($filename);
}

$savedImage = parent::_save($image, $filename, $mime_type);
$savedImage = parent::_save($image, $filename, $mimeType);

if ($savedImage instanceof \WP_Error || empty($savedImage['path']) || !$this->fileManager->isInTempDirectory($savedImage['path'])) {
return $savedImage;
Expand Down
83 changes: 65 additions & 18 deletions src/Subscriber/ContentDeliveryNetworkImageProcessingSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,22 +82,40 @@ public function __construct(array $baseImageSizes, bool $isMultisite, string $up
public static function getSubscribedEvents(): array
{
return [
'image_downsize' => ['generateScaledDownImage', 10, 3],
'the_content' => ['rewriteContentImageUrls', 999999],
'big_image_size_threshold' => 'disableScalingDownImages',
'get_post_galleries' => ['rewriteGalleryImageUrls', 999999],
'image_downsize' => ['generateScaledDownImage', 10, 3],
'rest_after_insert_attachment' => ['maybeDisableImageDownsizeFilterForInsertAttachmentRestRequest', 10, 2],
'rest_request_after_callbacks' => 'reEnableImageDownsizeFilter',
'rest_request_before_callbacks' => ['maybeDisableImageDownsizeFilterForRestRequest', 10, 3],
'the_content' => ['rewriteContentImageUrls', 999999],
'wp_calculate_image_srcset' => ['rewriteImageSrcset', 10, 5],
'wp_img_tag_add_width_and_height_attr' => ['disableAddingImageWidthAndHeightAttributes', 10, 2],
];
}

/**
* Prevent WordPress from adding width and height attributes to images that the content delivery network will process.
*/
public function disableAddingImageWidthAndHeightAttributes($value, string $image): bool
{
return preg_match('#src=["|\']([^\s]+?)["|\']#i', $image, $matches) ? !$this->isProcessableImageUrl($matches[1]) : (bool) $value;
}
/**
* Prevent WordPress from creating scaled down versions of images.
*/
public function disableScalingDownImages(): bool
{
return false;
}
/**
* Generate the scaled down image array for the given size.
*/
public function generateScaledDownImage($image, $attachmentId, $size)
{
if (!$this->imageDownsizeFilterEnabled || is_admin() || !$this->isValidImageSize($size)) {
if (!$this->imageDownsizeFilterEnabled || !$this->isValidImageSize($size)) {
return $image;
}
Expand Down Expand Up @@ -368,20 +386,27 @@ private function getImageAttachmentSizeMetadata(int $attachmentId, $size): ?arra
*/
private function getImageSize(array $image): array
{
$height = null;
$width = null;
/*
* Priority list for determining image size.
*
* 1. Parse width and height from the image source query string.
* 2. Parse width and height from the image tag attributes.
* 3. Parse width and height from the WordPress generated file name.
* 4. Determine width and height from the WordPress image metadata.
*/
list($width, $height, $cropped) = $this->parseImageDimensionsFromImageSourceQueryString($image['image_src']);

// Start by trying to parse the dimension from the <img> tag.
if (isset($image['image_tag'])) {
list($width, $height) = $this->parseImageDimensionsFromImgTagAttributes($image['image_tag']);
if (!$height && !$width) {
list($width, $height, $cropped) = $this->parseImageDimensionsFromImageTagAttributes($image['image_tag']);
}

// Next try to get the image dimensions using the filename.
if (isset($image['image_src']) && !$height && !$width) {
list($width, $height) = $this->parseImageDimensionsFromFilename($image['image_src']);
if (!$height && !$width) {
list($width, $height, $cropped) = $this->parseImageDimensionsFromFilename($image['image_src']);
}
if (!$height && !$width) {
list($width, $height, $cropped) = $this->determineImageSizeUsingWordPressImageSizes($image);
}

return ($height || $width) ? [$width, $height, $height && $width] : $this->determineImageSizeUsingWordPressImageSizes($image);
return [$width, $height, $cropped];
}

/**
Expand Down Expand Up @@ -449,35 +474,57 @@ private function isValidImageSize($size): bool
*/
private function parseImageDimensionsFromFilename(string $filename): array
{
$cropped = false;
$height = null;
$matches = [];
$width = null;

if (preg_match(sprintf('#-(\d+)x(\d+)\.(?:%s)$#i', implode('|', self::SUPPORTED_EXTENSIONS)), $filename, $matches)) {
$cropped = true;
$height = (int) $matches[2];
$width = (int) $matches[1];
}

return [$width, $height];
return [$width, $height, $cropped];
}

/**
* Parse the dimension of an image using the query strings in the image source.
*/
private function parseImageDimensionsFromImageSourceQueryString(string $imageSource): array
{
$cropped = (bool) preg_match('#\?.*cropped#i', $imageSource);
$height = null;
$matches = [];
$width = null;

if (preg_match('#\?.*height=(\d+)#i', $imageSource, $matches)) {
$height = (int) $matches[1];
}
if (preg_match('#\?.*width=(\d+)#i', $imageSource, $matches)) {
$width = (int) $matches[1];
}

return [$width, $height, $cropped];
}

/**
* Parse the dimension of an image using the <img> tag attributes.
*/
private function parseImageDimensionsFromImgTagAttributes(string $tag): array
private function parseImageDimensionsFromImageTagAttributes(string $tag): array
{
$height = null;
$matches = [];
$width = null;

if (preg_match('#\sheight=["|\']?([\d]+)["|\']?#i', $tag, $matches)) {
if (preg_match('#\sheight=["|\']?(\d+)["|\']?#i', $tag, $matches)) {
$height = (int) $matches[1];
}
if (preg_match('#\swidth=["|\']?([\d]+)["|\']?#i', $tag, $matches)) {
if (preg_match('#\swidth=["|\']?(\d+)["|\']?#i', $tag, $matches)) {
$width = (int) $matches[1];
}

return [$width, $height];
return [$width, $height, $width && $height];
}

/**
Expand Down
Loading

0 comments on commit 4a757e0

Please sign in to comment.