Skip to content

Commit

Permalink
Squash
Browse files Browse the repository at this point in the history
Add placeholder uri to thumb resource

Add placeholder image rendering

Update types

Add maintenance placeholder generation

Add encoding to placeholder generation

remove phpstan ignore with type indication

fixes

add soft transition effect
  • Loading branch information
ildyria authored and aSouchereau committed Nov 9, 2024
1 parent b156ec4 commit 6d39ae5
Show file tree
Hide file tree
Showing 53 changed files with 604 additions and 25 deletions.
2 changes: 2 additions & 0 deletions app/Actions/Diagnostics/Errors.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use App\Actions\Diagnostics\Pipes\Checks\IniSettingsCheck;
use App\Actions\Diagnostics\Pipes\Checks\MigrationCheck;
use App\Actions\Diagnostics\Pipes\Checks\PHPVersionCheck;
use App\Actions\Diagnostics\Pipes\Checks\PlaceholderExistsCheck;
use App\Actions\Diagnostics\Pipes\Checks\SmallMediumExistsCheck;
use App\Actions\Diagnostics\Pipes\Checks\SupporterCheck;
use App\Actions\Diagnostics\Pipes\Checks\TimezoneCheck;
Expand Down Expand Up @@ -44,6 +45,7 @@ class Errors
ForeignKeyListInfo::class,
DBIntegrityCheck::class,
SmallMediumExistsCheck::class,
PlaceholderExistsCheck::class,
CountSizeVariantsCheck::class,
SupporterCheck::class,
];
Expand Down
74 changes: 74 additions & 0 deletions app/Actions/Diagnostics/Pipes/Checks/PlaceholderExistsCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

namespace App\Actions\Diagnostics\Pipes\Checks;

use App\Contracts\DiagnosticPipe;
use App\Enum\SizeVariantType;
use App\Image\SizeVariantDimensionHelpers;
use App\Models\SizeVariant;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

/**
* Check if there are placeholders that can be generated or encoded.
*/
class PlaceholderExistsCheck implements DiagnosticPipe
{
public const INFO_MSG_MISSING = 'Info: Found %d placeholders that could be generated.';
public const INFO_LINE_MISSING = ' You can use `php artisan lychee:generate_thumbs placeholder %d` to generate them.';
public const INFO_MSG_UNENCODED = 'Info: Found %d placeholder images that have not been encoded.';
public const INFO_LINE_UNENCODED = ' You can use `php artisan lychee:encode_placeholders %d` to encode them.';

/**
* {@inheritDoc}
*/
public function handle(array &$data, \Closure $next): array
{
if (!Schema::hasTable('configs') || !Schema::hasTable('size_variants')) {
// @codeCoverageIgnoreStart
return $next($data);
// @codeCoverageIgnoreEnd
}

$svHelpers = new SizeVariantDimensionHelpers();
if (!$svHelpers->isEnabledByConfiguration(SizeVariantType::PLACEHOLDER)) {
return $next($data);
}

/** @var object{num_placeholder:int,max_num_placeholder:int,num_unencoded_placeholder:int}> $result */
$result = DB::query()
->selectSub(
SizeVariant::query()
->selectRaw('COUNT(*)')
->where('type', '=', SizeVariantType::PLACEHOLDER),
'num_placeholder'
)
->selectSub(
SizeVariant::query()
->selectRaw('COUNT(*)')
->where('type', '=', SizeVariantType::ORIGINAL),
'max_num_placeholder'
)
->selectSub(
SizeVariant::query()
->selectRaw('COUNT(*)')
->where('short_path', 'LIKE', '%placeholder/%'),
'num_unencoded_placeholder'
)
->first();

$num = $result->num_unencoded_placeholder;
if ($num > 0) {
$data[] = sprintf(self::INFO_MSG_UNENCODED, $num);
$data[] = sprintf(self::INFO_LINE_UNENCODED, $num);
}

$num = $result->max_num_placeholder - $result->num_placeholder;
if ($num > 0) {
$data[] = sprintf(self::INFO_MSG_MISSING, $num);
$data[] = sprintf(self::INFO_LINE_MISSING, $num);
}

return $next($data);
}
}
2 changes: 2 additions & 0 deletions app/Actions/Photo/Create.php
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ private function handleStandalone(InitDTO $initDTO): Photo
Shared\Save::class,
Standalone\CreateOriginalSizeVariant::class,
Standalone\CreateSizeVariants::class,
Standalone\EncodePlaceholder::class,
Standalone\ReplaceOriginalWithBackup::class,
Shared\UploadSizeVariantsToS3::class,
];
Expand Down Expand Up @@ -253,6 +254,7 @@ private function handlePhotoLivePartner(InitDTO $initDTO): Photo
Shared\Save::class,
Standalone\CreateOriginalSizeVariant::class,
Standalone\CreateSizeVariants::class,
Standalone\EncodePlaceholder::class,
Standalone\ReplaceOriginalWithBackup::class,
Shared\UploadSizeVariantsToS3::class,
];
Expand Down
26 changes: 26 additions & 0 deletions app/Actions/Photo/Pipes/Standalone/EncodePlaceholder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace App\Actions\Photo\Pipes\Standalone;

use App\Contracts\PhotoCreate\StandalonePipe;
use App\DTO\PhotoCreate\StandaloneDTO;
use App\Exceptions\MediaFileOperationException;
use App\Image\PlaceholderEncoder;

class EncodePlaceholder implements StandalonePipe
{
public function handle(StandaloneDTO $state, \Closure $next): StandaloneDTO
{
try {
$placeholderEncoder = new PlaceholderEncoder();
$placeholder = $state->getPhoto()->size_variants->getPlaceholder();
if ($placeholder !== null) {
$placeholderEncoder->do($placeholder);
}

return $next($state);
} catch (\ErrorException $e) {
throw new MediaFileOperationException('Failed to encode placeholder to base64', $e);
}
}
}
9 changes: 9 additions & 0 deletions app/Assets/BaseSizeVariantNamingStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ abstract class BaseSizeVariantNamingStrategy extends AbstractSizeVariantNamingSt
*/
public const THUMB_EXTENSION = '.jpeg';

/**
* The file extension which is always used by placeholder variants.
*/
public const PLACEHOLDER_EXTENSION = '.webp';

/**
* Returns the file extension incl. the preceding dot.
*
Expand All @@ -32,6 +37,10 @@ protected function generateExtension(SizeVariantType $sizeVariant): string
return self::THUMB_EXTENSION;
}

if ($sizeVariant === SizeVariantType::PLACEHOLDER) {
return self::PLACEHOLDER_EXTENSION;
}

if ($this->extension === '') {
throw new MissingValueException('extension');
}
Expand Down
63 changes: 63 additions & 0 deletions app/Console/Commands/ImageProcessing/EncodePlaceholders.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

namespace App\Console\Commands\ImageProcessing;

use App\Exceptions\UnexpectedException;
use App\Image\PlaceholderEncoder;
use App\Models\SizeVariant;
use Illuminate\Console\Command;
use Safe\Exceptions\InfoException;
use function Safe\set_time_limit;

class EncodePlaceholders extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'lychee:encode_placeholders {limit=5 : number of photos to encode placeholders for} {tm=600 : timeout time requirement}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Encode placeholders if size variant exists and image has not been encoded';

/**
* Execute the console command.
*/
public function handle(): int
{
try {
$limit = (int) $this->argument('limit');
$timeout = (int) $this->argument('tm');

try {
set_time_limit($timeout);
} catch (InfoException) {
// Silently do nothing, if `set_time_limit` is denied.
}

$placeholders = SizeVariant::query()
->where('short_path', 'LIKE', '%placeholder/%')
->limit($limit)
->get();
if (count($placeholders) === 0) {
$this->line('No placeholders require encoding.');

return 0;
}

$placeholderEncoder = new PlaceholderEncoder();
foreach ($placeholders as $placeholder) {
$placeholderEncoder->do($placeholder);
}

return 0;
} catch (\Throwable $e) {
throw new UnexpectedException($e);
}
}
}
1 change: 1 addition & 0 deletions app/Console/Commands/ImageProcessing/GenerateThumbs.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class GenerateThumbs extends Command
* @var array<string,SizeVariantType>
*/
public const SIZE_VARIANTS = [
'placeholder' => SizeVariantType::PLACEHOLDER,
'thumb' => SizeVariantType::THUMB,
'thumb2x' => SizeVariantType::THUMB2X,
'small' => SizeVariantType::SMALL,
Expand Down
3 changes: 3 additions & 0 deletions app/Enum/SizeVariantType.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ enum SizeVariantType: int
case SMALL = 4;
case THUMB2X = 5;
case THUMB = 6;
case PLACEHOLDER = 7;

/**
* Given a sizeVariantType return the associated name.
Expand All @@ -25,6 +26,7 @@ enum SizeVariantType: int
public function name(): string
{
return match ($this) {
self::PLACEHOLDER => 'placeholder',
self::THUMB => 'thumb',
self::THUMB2X => 'thumb2x',
self::SMALL => 'small',
Expand All @@ -43,6 +45,7 @@ public function name(): string
public function localization(): string
{
return match ($this) {
self::PLACEHOLDER => __('lychee.PHOTO_PLACEHOLDER'),
self::THUMB => __('lychee.PHOTO_THUMB'),
self::THUMB2X => __('lychee.PHOTO_THUMB_HIDPI'),
self::SMALL => __('lychee.PHOTO_SMALL'),
Expand Down
6 changes: 5 additions & 1 deletion app/Http/Controllers/Admin/Maintenance/GenSizeVariants.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use App\Contracts\Models\SizeVariantFactory;
use App\Enum\SizeVariantType;
use App\Http\Requests\Maintenance\CreateThumbsRequest;
use App\Image\PlaceholderEncoder;
use App\Image\SizeVariantDimensionHelpers;
use App\Models\Photo;
use App\Models\SizeVariant;
Expand All @@ -24,7 +25,7 @@ class GenSizeVariants extends Controller
*
* @return void
*/
public function do(CreateThumbsRequest $request, SizeVariantFactory $sizeVariantFactory): void
public function do(CreateThumbsRequest $request, SizeVariantFactory $sizeVariantFactory, PlaceholderEncoder $placeholderEncoder): void
{
$photos = Photo::query()
->where('type', 'like', 'image/%')
Expand All @@ -41,6 +42,9 @@ public function do(CreateThumbsRequest $request, SizeVariantFactory $sizeVariant
// @codeCoverageIgnoreStart
$sizeVariantFactory->init($photo);
$sizeVariant = $sizeVariantFactory->createSizeVariantCond($request->kind());
if ($request->kind() === SizeVariantType::PLACEHOLDER && $sizeVariant !== null) {
$placeholderEncoder->do($sizeVariant);
}
if ($sizeVariant !== null) {
$generated++;
Log::notice($request->kind()->value . ' (' . $sizeVariant->width . 'x' . $sizeVariant->height . ') for ' . $photo->title . ' created.');
Expand Down
1 change: 1 addition & 0 deletions app/Http/Requests/Maintenance/CreateThumbsRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public function rules(): array
RequestAttribute::SIZE_VARIANT_ATTRIBUTE => [
'required',
Rule::in([
SizeVariantType::PLACEHOLDER,
SizeVariantType::SMALL->value,
SizeVariantType::SMALL2X->value,
SizeVariantType::MEDIUM->value,
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Resources/Models/AlbumResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public function __construct(Album $album)

// thumb
$this->cover_id = $album->cover_id;
$this->thumb = ThumbResource::make($album->thumb?->id, $album->thumb?->type, $album->thumb?->thumbUrl, $album->thumb?->thumb2xUrl);
$this->thumb = ThumbResource::make($album->thumb?->id, $album->thumb?->type, $album->thumb?->thumbUrl, $album->thumb?->thumb2xUrl, $album->thumb?->placeholderUrl);

// security
$this->policy = AlbumProtectionPolicy::ofBaseAlbum($album);
Expand Down
3 changes: 3 additions & 0 deletions app/Http/Resources/Models/SizeVariantsResouce.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class SizeVariantsResouce extends Data
public ?SizeVariantResource $small;
public ?SizeVariantResource $thumb2x;
public ?SizeVariantResource $thumb;
public ?SizeVariantResource $placeholder;

public function __construct(Photo $photo)
{
Expand All @@ -34,6 +35,7 @@ public function __construct(Photo $photo)
$small2x = $size_variants?->getSizeVariant(SizeVariantType::SMALL2X);
$thumb = $size_variants?->getSizeVariant(SizeVariantType::THUMB);
$thumb2x = $size_variants?->getSizeVariant(SizeVariantType::THUMB2X);
$placeholder = $size_variants?->getSizeVariant(SizeVariantType::PLACEHOLDER);

$this->medium = $medium?->toResource();
$this->medium2x = $medium2x?->toResource();
Expand All @@ -42,5 +44,6 @@ public function __construct(Photo $photo)
$this->small2x = $small2x?->toResource();
$this->thumb = $thumb?->toResource();
$this->thumb2x = $thumb2x?->toResource();
$this->placeholder = $placeholder?->toResource();
}
}
2 changes: 1 addition & 1 deletion app/Http/Resources/Models/SmartAlbumResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function __construct(BaseSmartAlbum $smartAlbum)
$this->photos = $smartAlbum->relationLoaded('photos') ? PhotoResource::collect($smartAlbum->getPhotos()) : null;
$this->prepPhotosCollection();

$this->thumb = ThumbResource::make($smartAlbum->thumb?->id, $smartAlbum->thumb?->type, $smartAlbum->thumb?->thumbUrl, $smartAlbum->thumb?->thumb2xUrl);
$this->thumb = ThumbResource::make($smartAlbum->thumb?->id, $smartAlbum->thumb?->type, $smartAlbum->thumb?->thumbUrl, $smartAlbum->thumb?->thumb2xUrl, $smartAlbum->thumb?->placeholderUrl);
$this->policy = AlbumProtectionPolicy::ofSmartAlbum($smartAlbum);
$this->rights = new AlbumRightsResource($smartAlbum);
$url = $this->getHeaderUrl($smartAlbum);
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Resources/Models/TagAlbumResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public function __construct(TagAlbum $tagAlbum)
$this->prepPhotosCollection();

// thumb
$this->thumb = ThumbResource::make($tagAlbum->thumb?->id, $tagAlbum->thumb?->type, $tagAlbum->thumb?->thumbUrl, $tagAlbum->thumb?->thumb2xUrl);
$this->thumb = ThumbResource::make($tagAlbum->thumb?->id, $tagAlbum->thumb?->type, $tagAlbum->thumb?->thumbUrl, $tagAlbum->thumb?->thumb2xUrl, $tagAlbum->thumb?->placeholderUrl);

// security
$this->policy = AlbumProtectionPolicy::ofBaseAlbum($tagAlbum);
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Resources/Models/ThumbAlbumResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public function __construct(AbstractAlbum $data)
$date_format = Configs::getValueAsString('date_format_album_thumb');

$this->id = $data->id;
$this->thumb = $data->thumb === null ? null : new ThumbResource($data->thumb->id, $data->thumb->type, $data->thumb->thumbUrl, $data->thumb->thumb2xUrl);
$this->thumb = $data->thumb === null ? null : new ThumbResource($data->thumb->id, $data->thumb->type, $data->thumb->thumbUrl, $data->thumb->thumb2xUrl, $data->thumb->placeholderUrl);
$this->title = $data->title;

if ($data instanceof BaseSmartAlbum) {
Expand Down
10 changes: 7 additions & 3 deletions app/Http/Resources/Models/ThumbResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,27 @@ class ThumbResource extends Data
public string $type;
public ?string $thumb;
public ?string $thumb2x;
public ?string $placeholder;

public function __construct(string $id, string $type, string $thumbUrl, ?string $thumb2xUrl = null)
public function __construct(string $id, string $type, string $thumbUrl, ?string $thumb2xUrl = null, ?string $placeholderUrl = null)
{
$this->id = $id;
$this->type = $type;
$this->thumb = $thumbUrl;
$this->thumb2x = $thumb2xUrl;
$this->placeholder = $placeholderUrl;
}

/**
* @param string|null $id
* @param string|null $type
* @param string|null $thumbUrl
* @param string|null $thumb2xUrl
* @param string|null $placeholderUrl
*
* @return ($id is null ? null : ThumbResource)
*/
public static function make(?string $id, ?string $type, ?string $thumbUrl, ?string $thumb2xUrl = null): ?self
public static function make(?string $id, ?string $type, ?string $thumbUrl, ?string $thumb2xUrl = null, ?string $placeholderUrl = null): ?self
{
if ($id === null) {
return null;
Expand All @@ -38,6 +41,7 @@ public static function make(?string $id, ?string $type, ?string $thumbUrl, ?stri
/** @var string $id */
/** @var string $type */
/** @var string $thumbUrl */
return new self($id, $type, $thumbUrl, $thumb2xUrl);
/** @var string $placeholderUrl */
return new self($id, $type, $thumbUrl, $thumb2xUrl, $placeholderUrl);
}
}
Loading

0 comments on commit 6d39ae5

Please sign in to comment.