more fixes
This commit is contained in:
@@ -18,6 +18,18 @@ class AvatarService
|
||||
|
||||
private const ALLOWED_MIME_TYPES = ['image/jpeg', 'image/png', 'image/webp'];
|
||||
|
||||
private const ALLOWED_POSITIONS = [
|
||||
'top-left',
|
||||
'top',
|
||||
'top-right',
|
||||
'left',
|
||||
'center',
|
||||
'right',
|
||||
'bottom-left',
|
||||
'bottom',
|
||||
'bottom-right',
|
||||
];
|
||||
|
||||
protected $sizes = [
|
||||
'xs' => 32,
|
||||
'sm' => 64,
|
||||
@@ -50,13 +62,13 @@ class AvatarService
|
||||
}
|
||||
}
|
||||
|
||||
public function storeFromUploadedFile(int $userId, UploadedFile $file): string
|
||||
public function storeFromUploadedFile(int $userId, UploadedFile $file, string $position = 'center'): string
|
||||
{
|
||||
$this->assertImageManagerAvailable();
|
||||
$this->assertStorageIsAllowed();
|
||||
$binary = $this->assertSecureImageUpload($file);
|
||||
|
||||
return $this->storeFromBinary($userId, $binary);
|
||||
return $this->storeFromBinary($userId, $binary, $position);
|
||||
}
|
||||
|
||||
public function storeFromLegacyFile(int $userId, string $path): ?string
|
||||
@@ -76,10 +88,26 @@ class AvatarService
|
||||
return $this->storeFromBinary($userId, $binary);
|
||||
}
|
||||
|
||||
private function storeFromBinary(int $userId, string $binary): string
|
||||
public function removeAvatar(int $userId): void
|
||||
{
|
||||
$diskName = (string) config('avatars.disk', 's3');
|
||||
Storage::disk($diskName)->deleteDirectory("avatars/{$userId}");
|
||||
|
||||
UserProfile::query()->updateOrCreate(
|
||||
['user_id' => $userId],
|
||||
[
|
||||
'avatar_hash' => null,
|
||||
'avatar_mime' => null,
|
||||
'avatar_updated_at' => Carbon::now(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
private function storeFromBinary(int $userId, string $binary, string $position = 'center'): string
|
||||
{
|
||||
$image = $this->readImageFromBinary($binary);
|
||||
$image = $this->normalizeImage($image);
|
||||
$cropPosition = $this->normalizePosition($position);
|
||||
|
||||
$diskName = (string) config('avatars.disk', 's3');
|
||||
$disk = Storage::disk($diskName);
|
||||
@@ -87,7 +115,7 @@ class AvatarService
|
||||
|
||||
$hashSeed = '';
|
||||
foreach ($this->sizes as $size) {
|
||||
$variant = $image->cover($size, $size);
|
||||
$variant = $image->cover($size, $size, $cropPosition);
|
||||
$encoded = (string) $variant->encode(new WebpEncoder($this->quality));
|
||||
$disk->put("{$basePath}/{$size}.webp", $encoded, [
|
||||
'visibility' => 'public',
|
||||
@@ -110,6 +138,17 @@ class AvatarService
|
||||
return $hash;
|
||||
}
|
||||
|
||||
private function normalizePosition(string $position): string
|
||||
{
|
||||
$normalized = strtolower(trim($position));
|
||||
|
||||
if (in_array($normalized, self::ALLOWED_POSITIONS, true)) {
|
||||
return $normalized;
|
||||
}
|
||||
|
||||
return 'center';
|
||||
}
|
||||
|
||||
private function normalizeImage($image)
|
||||
{
|
||||
try {
|
||||
|
||||
@@ -18,21 +18,22 @@ class ThumbnailService
|
||||
}
|
||||
|
||||
/**
|
||||
* Canonical size keys (upload-agent spec §8): thumb · sq · md · lg · xl
|
||||
* 'sm' is kept as a backwards-compatible alias for 'thumb'.
|
||||
* Canonical size keys: xs · sm · md · lg · xl (+ legacy thumb/sq support).
|
||||
*/
|
||||
protected const VALID_SIZES = ['thumb', 'sq', 'sm', 'md', 'lg', 'xl'];
|
||||
protected const VALID_SIZES = ['xs', 'sm', 'md', 'lg', 'xl', 'thumb', 'sq'];
|
||||
|
||||
/** Size aliases: legacy 'sm' maps to the 'thumb' CDN directory. */
|
||||
protected const SIZE_ALIAS = ['sm' => 'thumb'];
|
||||
/** Size aliases for backwards compatibility with old callers. */
|
||||
protected const SIZE_ALIAS = [];
|
||||
|
||||
protected const THUMB_SIZES = [
|
||||
'thumb' => ['height' => 320, 'quality' => 78, 'dir' => 'thumb'],
|
||||
'xs' => ['height' => 160, 'quality' => 74, 'dir' => 'xs'],
|
||||
'sm' => ['height' => 320, 'quality' => 78, 'dir' => 'sm'],
|
||||
'sq' => ['height' => 512, 'quality' => 82, 'dir' => 'sq', 'square' => true],
|
||||
'sm' => ['height' => 320, 'quality' => 78, 'dir' => 'thumb'], // alias for thumb
|
||||
'md' => ['height' => 1024, 'quality' => 82, 'dir' => 'md'],
|
||||
'lg' => ['height' => 1920, 'quality' => 85, 'dir' => 'lg'],
|
||||
'xl' => ['height' => 2560, 'quality' => 90, 'dir' => 'xl'],
|
||||
// Legacy compatibility for older paths still expecting /thumb/.
|
||||
'thumb' => ['height' => 320, 'quality' => 78, 'dir' => 'thumb'],
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -129,8 +129,25 @@ final class UploadPipelineService
|
||||
$height = is_array($dimensions) && isset($dimensions[1]) ? (int) $dimensions[1] : 1;
|
||||
|
||||
$origExt = strtolower(pathinfo($originalPath, PATHINFO_EXTENSION) ?: '');
|
||||
$downloadFileName = $origFilename;
|
||||
|
||||
if (is_string($originalFileName) && trim($originalFileName) !== '') {
|
||||
$candidate = basename(str_replace('\\', '/', $originalFileName));
|
||||
$candidate = preg_replace('/[\x00-\x1F\x7F]/', '', (string) $candidate) ?? '';
|
||||
$candidate = trim((string) $candidate);
|
||||
|
||||
if ($candidate !== '') {
|
||||
$candidateExt = strtolower((string) pathinfo($candidate, PATHINFO_EXTENSION));
|
||||
if ($candidateExt === '' && $origExt !== '') {
|
||||
$candidate .= '.' . $origExt;
|
||||
}
|
||||
|
||||
$downloadFileName = $candidate;
|
||||
}
|
||||
}
|
||||
|
||||
Artwork::query()->whereKey($artworkId)->update([
|
||||
'file_name' => $origFilename,
|
||||
'file_name' => $downloadFileName,
|
||||
'file_path' => '',
|
||||
'file_size' => (int) filesize($originalPath),
|
||||
'mime_type' => $origMime,
|
||||
|
||||
Reference in New Issue
Block a user