Skip to content

Commit

Permalink
Squash
Browse files Browse the repository at this point in the history
  • Loading branch information
aSouchereau committed Nov 9, 2024
1 parent 2001c44 commit 757cefe
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 757cefe

Please sign in to comment.