From c18942333889581120d7d2e3b62925861aa99cd1 Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Sun, 15 Dec 2024 13:06:41 +0100 Subject: [PATCH] Add events to delegate the WebP/thumbnail generation This allows to bypass the image adapter when generating the WebP variant and the thumbnails. --- .../event/file/GenerateThumbnail.class.php | 28 ++++++ .../event/file/GenerateWebpVariant.class.php | 26 +++++ .../file/processor/FileProcessor.class.php | 99 +++++++++++-------- 3 files changed, 111 insertions(+), 42 deletions(-) create mode 100644 wcfsetup/install/files/lib/event/file/GenerateThumbnail.class.php create mode 100644 wcfsetup/install/files/lib/event/file/GenerateWebpVariant.class.php diff --git a/wcfsetup/install/files/lib/event/file/GenerateThumbnail.class.php b/wcfsetup/install/files/lib/event/file/GenerateThumbnail.class.php new file mode 100644 index 0000000000..3cdc58424a --- /dev/null +++ b/wcfsetup/install/files/lib/event/file/GenerateThumbnail.class.php @@ -0,0 +1,28 @@ + + * @since 6.1 + */ +final class GenerateThumbnail implements IPsr14Event +{ + /** + * The absolute path to the generated WebP image. + */ + public ?string $filename = null; + + public function __construct( + public readonly File $file, + public readonly ThumbnailFormat $thumbnailFormat, + ) {} +} diff --git a/wcfsetup/install/files/lib/event/file/GenerateWebpVariant.class.php b/wcfsetup/install/files/lib/event/file/GenerateWebpVariant.class.php new file mode 100644 index 0000000000..753e5300e9 --- /dev/null +++ b/wcfsetup/install/files/lib/event/file/GenerateWebpVariant.class.php @@ -0,0 +1,26 @@ + + * @since 6.1 + */ +final class GenerateWebpVariant implements IPsr14Event +{ + /** + * The absolute path to the generated WebP image. + */ + public ?string $filename = null; + + public function __construct( + public readonly File $file + ) {} +} diff --git a/wcfsetup/install/files/lib/system/file/processor/FileProcessor.class.php b/wcfsetup/install/files/lib/system/file/processor/FileProcessor.class.php index d9711d7d0c..09396023ef 100644 --- a/wcfsetup/install/files/lib/system/file/processor/FileProcessor.class.php +++ b/wcfsetup/install/files/lib/system/file/processor/FileProcessor.class.php @@ -9,7 +9,10 @@ use wcf\data\file\thumbnail\FileThumbnailEditor; use wcf\data\file\thumbnail\FileThumbnailList; use wcf\data\object\type\ObjectType; use wcf\data\object\type\ObjectTypeCache; +use wcf\event\file\GenerateThumbnail; +use wcf\event\file\GenerateWebpVariant; use wcf\system\database\util\PreparedStatementConditionBuilder; +use wcf\system\event\EventHandler; use wcf\system\exception\SystemException; use wcf\system\file\processor\exception\DamagedImage; use wcf\system\image\adapter\exception\ImageNotProcessable; @@ -159,32 +162,38 @@ final class FileProcessor extends SingletonFactory } } - $imageAdapter = ImageHandler::getInstance()->getAdapter(); - if (!$imageAdapter->checkMemoryLimit($file->width, $file->height, $file->mimeType)) { - return; - } + $event = new GenerateWebpVariant($file); + EventHandler::getInstance()->fire($event); - try { - $imageAdapter->loadSingleFrameFromFile($file->getPathname()); - } catch (SystemException | ImageNotReadable) { - throw new DamagedImage($file->fileID); - } catch (ImageNotProcessable $e) { - logThrowable($e); - - return; - } + $filename = $event->filename; + if ($filename === null) { + $imageAdapter = ImageHandler::getInstance()->getAdapter(); + if (!$imageAdapter->checkMemoryLimit($file->width, $file->height, $file->mimeType)) { + return; + } - $filename = FileUtil::getTemporaryFilename(extension: 'webp'); + try { + $imageAdapter->loadSingleFrameFromFile($file->getPathname()); + } catch (SystemException | ImageNotReadable) { + throw new DamagedImage($file->fileID); + } catch (ImageNotProcessable $e) { + logThrowable($e); - try { - $imageAdapter->saveImageAs($imageAdapter->getImage(), $filename, 'webp', 80); - } catch (\Throwable $e) { - // Ignore any errors trying to save the file unless in debug mode. - if (\ENABLE_DEBUG_MODE) { - throw $e; + return; } - return; + $filename = FileUtil::getTemporaryFilename(extension: 'webp'); + + try { + $imageAdapter->saveImageAs($imageAdapter->getImage(), $filename, 'webp', 80); + } catch (\Throwable $e) { + // Ignore any errors trying to save the file unless in debug mode. + if (\ENABLE_DEBUG_MODE) { + throw $e; + } + + return; + } } (new FileEditor($file))->update([ @@ -251,36 +260,42 @@ final class FileProcessor extends SingletonFactory } } - if ($imageAdapter === null) { - $imageAdapter = ImageHandler::getInstance()->getAdapter(); - if (!$imageAdapter->checkMemoryLimit($file->width, $file->height, $file->mimeType)) { - return; + $event = new GenerateThumbnail($file, $format); + EventHandler::getInstance()->fire($event); + + $filename = $event->filename; + if ($filename === null) { + if ($imageAdapter === null) { + $imageAdapter = ImageHandler::getInstance()->getAdapter(); + if (!$imageAdapter->checkMemoryLimit($file->width, $file->height, $file->mimeType)) { + return; + } + + try { + $imageAdapter->loadSingleFrameFromFile($file->getPathname()); + } catch (SystemException | ImageNotReadable $e) { + throw new DamagedImage($file->fileID, $e); + } catch (ImageNotProcessable $e) { + logThrowable($e); + + return; + } } + \assert($imageAdapter instanceof ImageAdapter); + try { - $imageAdapter->loadSingleFrameFromFile($file->getPathname()); - } catch (SystemException | ImageNotReadable $e) { - throw new DamagedImage($file->fileID, $e); - } catch (ImageNotProcessable $e) { + $image = $imageAdapter->createThumbnail($format->width, $format->height, $format->retainDimensions); + } catch (\Throwable $e) { logThrowable($e); - return; + continue; } - } - - \assert($imageAdapter instanceof ImageAdapter); - try { - $image = $imageAdapter->createThumbnail($format->width, $format->height, $format->retainDimensions); - } catch (\Throwable $e) { - logThrowable($e); - - continue; + $filename = FileUtil::getTemporaryFilename(extension: 'webp'); + $imageAdapter->saveImageAs($image, $filename, 'webp', 80); } - $filename = FileUtil::getTemporaryFilename(extension: 'webp'); - $imageAdapter->saveImageAs($image, $filename, 'webp', 80); - $fileThumbnail = FileThumbnailEditor::createFromTemporaryFile($file, $format, $filename); $processor->adoptThumbnail($fileThumbnail); } -- 2.20.1