- Issue created by @Chris Burge
When an image style converts an image to another format, Drupal\image\Entity\ImageStyle::addExtension()
adds the converted extension instead of replacing it:
/**
* Adds an extension to a path.
*
* If this image style changes the extension of the derivative, this method
* adds the new extension to the given path. This way we avoid filename
* clashes while still allowing us to find the source image.
*
* @param string $path
* The path to add the extension to.
*
* @return string
* The given path if this image style doesn't change its extension, or the
* path with the added extension if it does.
*/
protected function addExtension($path) {
$original_extension = pathinfo($path, PATHINFO_EXTENSION);
$extension = $this->getDerivativeExtension($original_extension);
if ($original_extension !== $extension) {
$path .= '.' . $extension;
}
return $path;
}
This strategy is designed to avoid namespace conflicts. (See comments #27 and #28 in π Allow image effects to change the MIME type + extension, add a "convert" image effect Fixed .)
In an instance where an image style converts an image to another format (e.g. png to webp), Drupal\image\Controller\ImageStyleDownloadController::deliver()
attempts to infer the source image:
// Don't try to generate file if source is missing.
if (!$this->sourceImageExists($image_uri, $token_is_valid)) {
// If the image style converted the extension, it has been added to the
// original file, resulting in filenames like image.png.jpeg. So to find
// the actual source image, we remove the extension and check if that
// image exists.
$path_info = pathinfo(StreamWrapperManager::getTarget($image_uri));
$converted_image_uri = sprintf('%s://%s%s%s', $this->streamWrapperManager->getScheme($derivative_uri), $path_info['dirname'], DIRECTORY_SEPARATOR, $path_info['filename']);
if (!$this->sourceImageExists($converted_image_uri, $token_is_valid)) {
$this->logger->notice('Source image at %source_image_path not found while trying to generate derivative image at %derivative_path.', ['%source_image_path' => $image_uri, '%derivative_path' => $derivative_uri]);
return new Response($this->t('Error generating image, missing source file.'), 404);
}
else {
// The converted file does exist, use it as the source.
$image_uri = $converted_image_uri;
}
}
In the end, the ::deliver()
method is making a best guess. If image.png.jpeg already exists, ::deliver()
will return an incorrect image derivative.
When ::deliver()
receives an inbound request, all it has is the requested image URL. It has no way to definitively determine the source image, because that isn't tracked anywhere.
TBD.
TBD.
TBD.
TBD.
TBD.
TBD.
Active
11.0 π₯