diff --git a/config/vuefilemanager.php b/config/vuefilemanager.php index 11b9afe0..b484ac4e 100644 --- a/config/vuefilemanager.php +++ b/config/vuefilemanager.php @@ -29,25 +29,33 @@ return [ ], 'image_sizes' => [ - [ - 'size' => 1440, - 'name' => 'xl', - ], - [ - 'size' => 960, - 'name' => 'lg', - ], - [ - 'size' => 480, - 'name' => 'md', - ], - [ - 'size' => 240, - 'name' => 'sm', - ], - [ - 'size' => 120, - 'name' => 'xs', + + 'immediately' => [ + [ + 'size' => 120, + 'name' => 'xs', + ], + [ + 'size' => 240, + 'name' => 'sm', + ], ], + + 'later' => [ + [ + 'size' => 480, + 'name' => 'md', + ], + [ + 'size' => 960, + 'name' => 'lg', + ], + [ + 'size' => 1440, + 'name' => 'xl', + ], + + ] + ], ]; diff --git a/src/App/Console/Commands/SetupDevEnvironment.php b/src/App/Console/Commands/SetupDevEnvironment.php index 9440281c..55b3f424 100644 --- a/src/App/Console/Commands/SetupDevEnvironment.php +++ b/src/App/Console/Commands/SetupDevEnvironment.php @@ -1180,7 +1180,10 @@ class SetupDevEnvironment extends Command $this->info("Generating thumbnails for $file..."); // Generate avatar sizes - collect(config('vuefilemanager.image_sizes')) + collect([ + config('vuefilemanager.image_sizes.later'), + config('vuefilemanager.image_sizes.immediately'), + ])->collapse() ->each(function ($size) use ($intervention, $file_name, $user) { // Create thumbnail only if image is larger than predefined image sizes if ($intervention->getWidth() > $size['size']) { diff --git a/src/Domain/Files/Actions/CreateImageThumbnailAction.php b/src/Domain/Files/Actions/CreateImageThumbnailAction.php deleted file mode 100644 index 814756f0..00000000 --- a/src/Domain/Files/Actions/CreateImageThumbnailAction.php +++ /dev/null @@ -1,44 +0,0 @@ -getClientMimeType(), $this->availableFormats)) { - // Create intervention image - $intervention = Image::make($file)->orientate(); - - // Generate avatar sizes - collect(config('vuefilemanager.image_sizes')) - ->each(function ($size) use ($intervention, $file_name, $user_id) { - // Create thumbnail only if image is larger than predefined image sizes - if ($intervention->getWidth() > $size['size']) { - // Generate thumbnail - $intervention->resize($size['size'], null, fn ($constraint) => $constraint->aspectRatio())->stream(); - - // Store thumbnail to disk - Storage::put("files/$user_id/{$size['name']}-{$file_name}", $intervention); - } - }); - } - } -} diff --git a/src/Domain/Files/Actions/GenerateImageThumbnailAction.php b/src/Domain/Files/Actions/GenerateImageThumbnailAction.php new file mode 100644 index 00000000..4b13dcc8 --- /dev/null +++ b/src/Domain/Files/Actions/GenerateImageThumbnailAction.php @@ -0,0 +1,44 @@ +get("temp/$userId/$fileName"); + + // Get image width + $imageWidth = getimagesize($localDisk->path("temp/$userId/$fileName"))[0]; + + collect(config("vuefilemanager.image_sizes.$execution")) + ->each(function ($size) use ($image, $userId, $fileName, $imageWidth) { + + if ($imageWidth > $size['size']) { + + // Create intervention image + $intervention = Image::make($image)->orientate(); + + // Generate thumbnail + $intervention->resize($size['size'], null, fn ($constraint) => $constraint->aspectRatio())->stream(); + + // Store thumbnail to disk + Storage::put("files/$userId/{$size['name']}-$fileName", $intervention); + } + }); + + // Delete file after generate a thumbnail + if ($execution === 'later') { + Storage::disk('local')->delete("temp/$userId/$fileName"); + } + } +} diff --git a/src/Domain/Files/Actions/ProcessImageThumbnailAction.php b/src/Domain/Files/Actions/ProcessImageThumbnailAction.php new file mode 100644 index 00000000..5f1ca027 --- /dev/null +++ b/src/Domain/Files/Actions/ProcessImageThumbnailAction.php @@ -0,0 +1,52 @@ +getClientMimeType(), $this->availableFormats)) { + + // Make copy of file for the thumbnail generation + Storage::disk('local')->copy("files/$userId/{$fileName}", "temp/$userId/{$fileName}"); + + // Create thumbnail instantly + ($this->generateImageThumbnail)( + fileName: $fileName, + userId: $userId, + execution: 'immediately' + ); + + // Create thumbnail later + ($this->generateImageThumbnail)->onQueue()->execute( + fileName: $fileName, + userId: $userId, + execution: 'later' + ); + } + } +} diff --git a/src/Domain/Files/Actions/UploadFileAction.php b/src/Domain/Files/Actions/UploadFileAction.php index 72e0ebdf..fc67b0a1 100644 --- a/src/Domain/Files/Actions/UploadFileAction.php +++ b/src/Domain/Files/Actions/UploadFileAction.php @@ -14,9 +14,9 @@ use App\Users\Actions\CheckStorageCapacityAction; class UploadFileAction { public function __construct( - public RecordUploadAction $recordUpload, - public CheckStorageCapacityAction $checkStorageCapacity, - public CreateImageThumbnailAction $createImageThumbnail, + public RecordUploadAction $recordUpload, + public CheckStorageCapacityAction $checkStorageCapacity, + public ProcessImageThumbnailAction $createImageThumbnail, public MoveFileToExternalStorageAction $moveFileToExternalStorage, ) { } @@ -69,12 +69,13 @@ class UploadFileAction // Check if user has enough space to upload file ($this->checkStorageCapacity)($user_id, $fileSize, $chunkName); - // Create multiple image thumbnails - ($this->createImageThumbnail)($fileName, $file, $user_id); // Move finished file from chunk to file-manager directory $disk_local->move("chunks/$chunkName", "files/$user_id/$fileName"); + // Create multiple image thumbnails + ($this->createImageThumbnail)($fileName, $file, $user_id); + // Move files to external storage if (! is_storage_driver('local')) { ($this->moveFileToExternalStorage)($fileName, $user_id); diff --git a/src/Domain/Files/Models/File.php b/src/Domain/Files/Models/File.php index 1fe95920..c7250b82 100644 --- a/src/Domain/Files/Models/File.php +++ b/src/Domain/Files/Models/File.php @@ -91,10 +91,11 @@ class File extends Model public function getThumbnailAttribute(): array | null { $links = []; + $thumbnail_sizes = collect(config('vuefilemanager.image_sizes'))->collapse()->all(); // Generate thumbnail link for external storage service - if ($this->type === 'image' && ! is_storage_driver('local')) { - foreach (config('vuefilemanager.image_sizes') as $item) { + if ($this->type === 'image' && ! is_storage_driver(['local'])) { + foreach ($thumbnail_sizes as $item) { $filePath = "files/{$this->user_id}/{$item['name']}-{$this->basename}"; $links[$item['name']] = Storage::temporaryUrl($filePath, now()->addHour()); @@ -105,7 +106,7 @@ class File extends Model // Generate thumbnail link for local storage if ($this->type === 'image') { - foreach (config('vuefilemanager.image_sizes') as $item) { + foreach ($thumbnail_sizes as $item) { $route = route('thumbnail', ['name' => $item['name'] . '-' . $this->basename]); if ($this->public_access) { diff --git a/src/Domain/Trash/Controllers/DumpTrashController.php b/src/Domain/Trash/Controllers/DumpTrashController.php index 4c438dee..1c3071b5 100644 --- a/src/Domain/Trash/Controllers/DumpTrashController.php +++ b/src/Domain/Trash/Controllers/DumpTrashController.php @@ -39,8 +39,16 @@ class DumpTrashController extends Controller // Delete thumbnail if exist if ($file->thumbnail) { - Storage::delete("/files/$user_id/{$file->getRawOriginal('thumbnail')}"); - } + + collect([ + config('vuefilemanager.image_sizes.later'), + config('vuefilemanager.image_sizes.immediately'), + ])->collapse() + ->each(function ($size) use ($file) { + + Storage::delete("/files/$file->user_id/{$size['name']}-{$file->basename}"); + }); + } // Delete file permanently $file->forceDelete(); diff --git a/src/Support/helpers.php b/src/Support/helpers.php index 2f0ce754..1d5610f8 100644 --- a/src/Support/helpers.php +++ b/src/Support/helpers.php @@ -601,8 +601,11 @@ if (! function_exists('get_thumbnail_file_list')) { */ function get_thumbnail_file_list(string $basename): Collection { - return collect(config('vuefilemanager.image_sizes')) - ->map(fn ($item) => $item['name'] . '-' . $basename); + return collect([ + config('vuefilemanager.image_sizes.later'), + config('vuefilemanager.image_sizes.immediately'), + ])->collapse() + ->map(fn ($item) => $item['name'] . '-' . $basename); } } diff --git a/tests/Domain/Files/FileTest.php b/tests/Domain/Files/FileTest.php index 59c17a4a..f3a2cabd 100644 --- a/tests/Domain/Files/FileTest.php +++ b/tests/Domain/Files/FileTest.php @@ -53,10 +53,13 @@ class FileTest extends TestCase "chunks/$file->basename" ); - collect(config('vuefilemanager.image_sizes')) + collect([ + config('vuefilemanager.image_sizes.later'), + config('vuefilemanager.image_sizes.immediately'), + ]) + ->collapse() ->each( - fn ($item) => - $disk->assertExists( + fn($item) => $disk->assertExists( "files/{$user->id}/{$item['name']}-{$file->basename}" ) ); diff --git a/tests/Domain/Teams/TeamManagementTest.php b/tests/Domain/Teams/TeamManagementTest.php index 61d6b305..0a329160 100644 --- a/tests/Domain/Teams/TeamManagementTest.php +++ b/tests/Domain/Teams/TeamManagementTest.php @@ -622,8 +622,10 @@ class TeamManagementTest extends TestCase // Put fake image into correct directory Storage::putFileAs("files/$member->id", $fakeFile, $fakeFile->name); + $thumbnail_sizes = collect([config('vuefilemanager.image_sizes.later'), config('vuefilemanager.image_sizes.immediately')])->collapse(); + // Create fake image thumbnails - collect(config('vuefilemanager.image_sizes')) + $thumbnail_sizes ->each(function ($item) use ($member) { $fakeFile = UploadedFile::fake() ->create("{$item['name']}-fake-image.jpeg", 2000, 'image/jpeg'); @@ -651,7 +653,7 @@ class TeamManagementTest extends TestCase Storage::assertExists("files/$user->id/fake-file.zip"); // Assert if image thumbnails was moved correctly to the new destination - collect(config('vuefilemanager.image_sizes')) + $thumbnail_sizes ->each(function ($item) use ($user) { Storage::assertExists("files/$user->id/{$item['name']}-fake-image.jpeg"); }); diff --git a/tests/Domain/Trash/TrashTest.php b/tests/Domain/Trash/TrashTest.php index 6ccb22b8..108f25bf 100644 --- a/tests/Domain/Trash/TrashTest.php +++ b/tests/Domain/Trash/TrashTest.php @@ -109,12 +109,17 @@ class TrashTest extends TestCase $disk = Storage::disk('local'); + $thumbnail_sizes = collect(config('vuefilemanager.image_sizes'))->collapse()->all(); + $disk->assertMissing( "files/$user->id/fake-image.jpg" ); - $disk->assertMissing( - "files/$user->id/thumbnail-fake-image.jpg" - ); + foreach($thumbnail_sizes as $size) { + $disk->assertMissing( + "files/$user->id/{$size['name']}-fake-image.jpg" + ); + } + } }