[ENTITY][AttachmentThumbnail] Uncache when deleting, cleanup code and ensure the biggest thumbnail is used when the original is not avaliable
This commit is contained in:
parent
a3074662b8
commit
c509692102
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
// {{{ License
|
// {{{ License
|
||||||
|
|
||||||
// This file is part of GNU social - https://www.gnu.org/software/social
|
// This file is part of GNU social - https://www.gnu.org/software/social
|
||||||
@ -59,6 +61,12 @@ class AttachmentThumbnail extends Entity
|
|||||||
public const SIZE_MEDIUM = 1;
|
public const SIZE_MEDIUM = 1;
|
||||||
public const SIZE_BIG = 2;
|
public const SIZE_BIG = 2;
|
||||||
|
|
||||||
|
public const SIZE_MAP = [
|
||||||
|
'small' => self::SIZE_SMALL,
|
||||||
|
'medium' => self::SIZE_MEDIUM,
|
||||||
|
'big' => self::SIZE_BIG,
|
||||||
|
];
|
||||||
|
|
||||||
// {{{ Autocode
|
// {{{ Autocode
|
||||||
// @codeCoverageIgnoreStart
|
// @codeCoverageIgnoreStart
|
||||||
private int $attachment_id;
|
private int $attachment_id;
|
||||||
@ -67,7 +75,7 @@ class AttachmentThumbnail extends Entity
|
|||||||
private string $filename;
|
private string $filename;
|
||||||
private int $width;
|
private int $width;
|
||||||
private int $height;
|
private int $height;
|
||||||
private \DateTimeInterface $modified;
|
private DateTimeInterface $modified;
|
||||||
|
|
||||||
public function setAttachmentId(int $attachment_id): self
|
public function setAttachmentId(int $attachment_id): self
|
||||||
{
|
{
|
||||||
@ -149,6 +157,17 @@ class AttachmentThumbnail extends Entity
|
|||||||
// @codeCoverageIgnoreEnd
|
// @codeCoverageIgnoreEnd
|
||||||
// }}} Autocode
|
// }}} Autocode
|
||||||
|
|
||||||
|
public static function sizeIntToStr(?int $size): string
|
||||||
|
{
|
||||||
|
$map = array_flip(self::SIZE_MAP);
|
||||||
|
return $map[$size] ?? $map[self::SIZE_SMALL];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function sizeStrToInt(string $size)
|
||||||
|
{
|
||||||
|
return self::SIZE_MAP[$size] ?? self::SIZE_MAP[self::SIZE_SMALL];
|
||||||
|
}
|
||||||
|
|
||||||
private ?Attachment $attachment = null;
|
private ?Attachment $attachment = null;
|
||||||
|
|
||||||
public function setAttachment(?Attachment $attachment)
|
public function setAttachment(?Attachment $attachment)
|
||||||
@ -158,17 +177,20 @@ class AttachmentThumbnail extends Entity
|
|||||||
|
|
||||||
public function getAttachment()
|
public function getAttachment()
|
||||||
{
|
{
|
||||||
if (isset($this->attachment) && !is_null($this->attachment)) {
|
if (isset($this->attachment) && !\is_null($this->attachment)) {
|
||||||
return $this->attachment;
|
return $this->attachment;
|
||||||
} else {
|
} else {
|
||||||
return $this->attachment = DB::findOneBy('attachment', ['id' => $this->attachment_id]);
|
return $this->attachment = DB::findOneBy('attachment', ['id' => $this->attachment_id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getCacheKey(int $id, int $size)
|
||||||
|
{
|
||||||
|
return "thumb-{$id}-{$size}";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Attachment $attachment
|
* @param ?string $size 'small'|'medium'|'big'
|
||||||
* @param ?string $size 'small'|'medium'|'big'
|
|
||||||
* @param bool $crop
|
|
||||||
*
|
*
|
||||||
* @throws ClientException
|
* @throws ClientException
|
||||||
* @throws NotFoundException
|
* @throws NotFoundException
|
||||||
@ -178,26 +200,23 @@ class AttachmentThumbnail extends Entity
|
|||||||
*/
|
*/
|
||||||
public static function getOrCreate(Attachment $attachment, ?string $size = null, bool $crop = false): ?self
|
public static function getOrCreate(Attachment $attachment, ?string $size = null, bool $crop = false): ?self
|
||||||
{
|
{
|
||||||
$size = $size ?? Common::config('thumbnail', 'default_size');
|
$size ??= Common::config('thumbnail', 'default_size');
|
||||||
$size_int = match ($size) {
|
$size_int = self::sizeStrToInt($size);
|
||||||
'medium' => self::SIZE_MEDIUM,
|
|
||||||
'big' => self::SIZE_BIG,
|
|
||||||
default => self::SIZE_SMALL,
|
|
||||||
};
|
|
||||||
try {
|
try {
|
||||||
return Cache::get('thumb-' . $attachment->getId() . "-{$size}",
|
return Cache::get(
|
||||||
function () use ($attachment, $size_int) {
|
self::getCacheKey($attachment->getId(), $size_int),
|
||||||
return DB::findOneBy('attachment_thumbnail', ['attachment_id' => $attachment->getId(), 'size' => $size_int]);
|
fn () => DB::findOneBy('attachment_thumbnail', ['attachment_id' => $attachment->getId(), 'size' => $size_int]),
|
||||||
});
|
);
|
||||||
} catch (NotFoundException) {
|
} catch (NotFoundException) {
|
||||||
if (is_null($attachment->getWidth()) || is_null($attachment->getHeight())) {
|
if (\is_null($attachment->getWidth()) || \is_null($attachment->getHeight())) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
[$predicted_width, $predicted_height] = self::predictScalingValues($attachment->getWidth(), $attachment->getHeight(), $size, $crop);
|
[$predicted_width, $predicted_height] = self::predictScalingValues($attachment->getWidth(), $attachment->getHeight(), $size, $crop);
|
||||||
if (!file_exists($attachment->getPath())) {
|
if (!file_exists($attachment->getPath())) {
|
||||||
// Before we quit, check if there's any other thumb
|
// Before we quit, check if there's any other thumb
|
||||||
$alternative_thumbs = DB::findBy('attachment_thumbnail', ['attachment_id' => $attachment->getId()]);
|
$alternative_thumbs = DB::findBy('attachment_thumbnail', ['attachment_id' => $attachment->getId()]);
|
||||||
if ($alternative_thumbs === []) {
|
usort($alternative_thumbs, fn ($l, $r) => $r->getSize() <=> $l->getSize());
|
||||||
|
if (empty($alternative_thumbs)) {
|
||||||
throw new NotStoredLocallyException();
|
throw new NotStoredLocallyException();
|
||||||
} else {
|
} else {
|
||||||
return $alternative_thumbs[0];
|
return $alternative_thumbs[0];
|
||||||
@ -237,12 +256,12 @@ class AttachmentThumbnail extends Entity
|
|||||||
|
|
||||||
public function getPath()
|
public function getPath()
|
||||||
{
|
{
|
||||||
return Common::config('thumbnail', 'dir') . DIRECTORY_SEPARATOR . $this->getFilename();
|
return Common::config('thumbnail', 'dir') . \DIRECTORY_SEPARATOR . $this->getFilename();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getUrl()
|
public function getUrl()
|
||||||
{
|
{
|
||||||
return Router::url('attachment_thumbnail', ['id' => $this->getAttachmentId(), 'size' => $this->getSize()]);
|
return Router::url('attachment_thumbnail', ['id' => $this->getAttachmentId(), 'size' => self::sizeIntToStr($this->getSize())]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -258,6 +277,7 @@ class AttachmentThumbnail extends Entity
|
|||||||
// @codeCoverageIgnoreEnd
|
// @codeCoverageIgnoreEnd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Cache::delete(self::getCacheKey($this->getAttachmentId(), $this->getSize()));
|
||||||
DB::remove($this);
|
DB::remove($this);
|
||||||
if ($flush) {
|
if ($flush) {
|
||||||
DB::flush();
|
DB::flush();
|
||||||
@ -270,10 +290,8 @@ class AttachmentThumbnail extends Entity
|
|||||||
* Values will scale _up_ to fit max values if cropping is enabled!
|
* Values will scale _up_ to fit max values if cropping is enabled!
|
||||||
* With cropping disabled, the max value of each axis will be respected.
|
* With cropping disabled, the max value of each axis will be respected.
|
||||||
*
|
*
|
||||||
* @param int $existing_width Original width
|
* @param int $existing_width Original width
|
||||||
* @param int $existing_height Original height
|
* @param int $existing_height Original height
|
||||||
* @param string $requested_size
|
|
||||||
* @param bool $crop
|
|
||||||
*
|
*
|
||||||
* @return array [predicted width, predicted height]
|
* @return array [predicted width, predicted height]
|
||||||
*/
|
*/
|
||||||
@ -281,7 +299,7 @@ class AttachmentThumbnail extends Entity
|
|||||||
int $existing_width,
|
int $existing_width,
|
||||||
int $existing_height,
|
int $existing_height,
|
||||||
string $requested_size,
|
string $requested_size,
|
||||||
bool $crop
|
bool $crop,
|
||||||
): array {
|
): array {
|
||||||
/**
|
/**
|
||||||
* 1:1 => Square
|
* 1:1 => Square
|
||||||
@ -318,7 +336,7 @@ class AttachmentThumbnail extends Entity
|
|||||||
|
|
||||||
// Binary search the closer allowed aspect ratio
|
// Binary search the closer allowed aspect ratio
|
||||||
$left = 0;
|
$left = 0;
|
||||||
$right = count($allowed_aspect_ratios) - 1;
|
$right = \count($allowed_aspect_ratios) - 1;
|
||||||
while ($left < $right) {
|
while ($left < $right) {
|
||||||
$mid = floor($left + ($right - $left) / 2);
|
$mid = floor($left + ($right - $left) / 2);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user