Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
53 changes: 53 additions & 0 deletions wcfsetup/install/files/lib/event/file/GenerateThumbnail.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace wcf\event\file;

use wcf\data\file\File;
use wcf\event\IPsr14Event;
use wcf\system\file\processor\ThumbnailFormat;

/**
* Requests the generation of a thumbnail.
*
* @author Alexander Ebert
* @copyright 2001-2024 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @since 6.1
*/
final class GenerateThumbnail implements IPsr14Event
{
private string $pathname;

public function __construct(
public readonly File $file,
public readonly ThumbnailFormat $thumbnailFormat,
) {}

/**
* Returns true if a file has already been set and no further files are
* being accepted.
*/
public function hasFile(): bool
{
return isset($this->pathname);
}

/**
* Sets the pathname of the generated image unless it has already been set
* in which case the call will throw an exception. You must check the result
* of `hasFile()` first.
*/
public function setGeneratedFile(string $pathname): void
{
if (isset($this->pathname)) {
throw new \BadMethodCallException("Cannot set the generated file, a value has already been set.");
}

$this->pathname = $pathname;
}

public function getPathname(): ?string
{
return $this->pathname ?? null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace wcf\event\file;

use BadMethodCallException;
use wcf\data\file\File;
use wcf\event\IPsr14Event;

/**
* Requests the generation of a WebP variant for the provided image.
*
* @author Alexander Ebert
* @copyright 2001-2024 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @since 6.1
*/
final class GenerateWebpVariant implements IPsr14Event
{
private string $pathname;

public function __construct(
public readonly File $file
) {}

/**
* Returns true if a file has already been set and no further files are
* being accepted.
*/
public function hasFile(): bool
{
return isset($this->pathname);
}

/**
* Sets the pathname of the generated image unless it has already been set
* in which case the call will throw an exception. You must check the result
* of `hasFile()` first.
*/
public function setGeneratedFile(string $pathname): void
{
if (isset($this->pathname)) {
throw new \BadMethodCallException("Cannot set the generated file, a value has already been set.");
}

$this->pathname = $pathname;
}

public function getPathname(): ?string
{
return $this->pathname ?? null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
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;
Expand Down Expand Up @@ -159,32 +162,38 @@ public function generateWebpVariant(File $file): void
}
}

$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->getPathname();
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([
Expand Down Expand Up @@ -251,36 +260,42 @@ public function generateThumbnails(File $file): void
}
}

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->getPathname();
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);
}
Expand Down