From 975b902c277cf63941de62cf89a8fe509b8c8e49 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Fri, 13 May 2022 15:57:26 -0400 Subject: [PATCH 01/63] Extract this path logic to clean up `upload()` method. --- src/Assets/Asset.php | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/Assets/Asset.php b/src/Assets/Asset.php index 90eb346901..71ae67f63d 100644 --- a/src/Assets/Asset.php +++ b/src/Assets/Asset.php @@ -679,19 +679,7 @@ public function title() */ public function upload(UploadedFile $file) { - $ext = $file->getClientOriginalExtension(); - $filename = $this->getSafeFilename(pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME)); - - $directory = $this->folder(); - $directory = ($directory === '.') ? '/' : $directory; - $path = Path::tidy($directory.'/'.$filename.'.'.$ext); - $path = ltrim($path, '/'); - - // If the file exists, we'll append a timestamp to prevent overwriting. - if ($this->disk()->exists($path)) { - $basename = $filename.'-'.Carbon::now()->timestamp.'.'.$ext; - $path = Str::removeLeft(Path::assemble($directory, $basename), '/'); - } + $path = $this->getSafeUploadPath($file); $stream = fopen($file->getRealPath(), 'r'); $this->disk()->put($path, $stream); @@ -718,6 +706,31 @@ public function download(string $name = null, array $headers = []) return $this->disk()->filesystem()->download($this->path(), $name, $headers); } + /** + * Get safe upload path for UploadedFile. + * + * @param UploadedFile $file + * @return string + */ + private function getSafeUploadPath(UploadedFile $file) + { + $ext = $file->getClientOriginalExtension(); + $filename = $this->getSafeFilename(pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME)); + + $directory = $this->folder(); + $directory = ($directory === '.') ? '/' : $directory; + $path = Path::tidy($directory.'/'.$filename.'.'.$ext); + $path = ltrim($path, '/'); + + // If the file exists, we'll append a timestamp to prevent overwriting. + if ($this->disk()->exists($path)) { + $basename = $filename.'-'.Carbon::now()->timestamp.'.'.$ext; + $path = Str::removeLeft(Path::assemble($directory, $basename), '/'); + } + + return $path; + } + private function getSafeFilename($string) { $replacements = [ From f830cd0679493d155e9fbf8dc82f412ad612a2dd Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Fri, 13 May 2022 16:18:55 -0400 Subject: [PATCH 02/63] Extract `put()` disk logic for file uploads. --- src/Assets/Asset.php | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/Assets/Asset.php b/src/Assets/Asset.php index 71ae67f63d..4483a964ea 100644 --- a/src/Assets/Asset.php +++ b/src/Assets/Asset.php @@ -681,11 +681,7 @@ public function upload(UploadedFile $file) { $path = $this->getSafeUploadPath($file); - $stream = fopen($file->getRealPath(), 'r'); - $this->disk()->put($path, $stream); - if (is_resource($stream)) { - fclose($stream); - } + $this->putFileOnDisk($sourcePath, $path); $this->path($path)->syncOriginal(); @@ -747,6 +743,23 @@ private function getSafeFilename($string) return (string) $str; } + /** + * Put file on destination disk. + * + * @param string $sourcePath + * @param string $destinationPath + */ + private function putFileOnDisk($sourcePath, $destinationPath) + { + $stream = fopen($sourcePath, 'r'); + + $this->disk()->put($destinationPath, $stream); + + if (is_resource($stream)) { + fclose($stream); + } + } + /** * Get the asset file contents. * From 53816693234912865cc34e1e1688214c2d0de0d8 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Fri, 13 May 2022 16:19:49 -0400 Subject: [PATCH 03/63] Process images using glide on upload. --- src/Assets/Asset.php | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/Assets/Asset.php b/src/Assets/Asset.php index 4483a964ea..dfb45c70e5 100644 --- a/src/Assets/Asset.php +++ b/src/Assets/Asset.php @@ -5,6 +5,7 @@ use ArrayAccess; use Facades\Statamic\Assets\Attributes; use Illuminate\Contracts\Support\Arrayable; +use Illuminate\Filesystem\Filesystem; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Cache; use Statamic\Contracts\Assets\Asset as AssetContract; @@ -681,6 +682,13 @@ public function upload(UploadedFile $file) { $path = $this->getSafeUploadPath($file); + // TODO: Check container for glide params... + $glide = false; + + $sourcePath = $glide + ? $this->glideProcessUploadedFile($file, $glide) + : $file->getRealPath(); + $this->putFileOnDisk($sourcePath, $path); $this->path($path)->syncOriginal(); @@ -891,4 +899,41 @@ public function getQueryableValue(string $field) return $field->fieldtype()->toQueryableValue($value); } + + /** + * Get temporary glide cache path in storage for processing uploads. + * + * @return string + */ + private function glideTmpPath() + { + return storage_path('statamic/glide/tmp'); + } + + /** + * Process UploadedFile instance using glide and return cached path. + * + * @param UploadedFile $file + * @param array $params + * @param string + */ + private function glideProcessUploadedFile(UploadedFile $file, $params) + { + $glideTmpPath = $this->glideTmpPath(); + + $server = \League\Glide\ServerFactory::create([ + 'source' => $file->getPath(), + 'cache' => $glideTmpPath, + ]); + + $server->makeImage($file->getFilename(), $params); + + $local = app(Filesystem::class); + + $newFilePath = collect($local->files($glideTmpPath.'/'.$file->getFilename())) + ->first() + ->getRealPath(); + + return $newFilePath; + } } From 18e61c4450432f9ac34e74e5e9b91bd9a6dc7c80 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Fri, 13 May 2022 16:20:17 -0400 Subject: [PATCH 04/63] Ensure we delete tmp glide cache in storage after successful upload. --- src/Assets/Asset.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Assets/Asset.php b/src/Assets/Asset.php index dfb45c70e5..4072de84a0 100644 --- a/src/Assets/Asset.php +++ b/src/Assets/Asset.php @@ -691,6 +691,10 @@ public function upload(UploadedFile $file) $this->putFileOnDisk($sourcePath, $path); + if ($glide) { + $this->glideClearTmpCache(); + } + $this->path($path)->syncOriginal(); $this->save(); @@ -936,4 +940,18 @@ private function glideProcessUploadedFile(UploadedFile $file, $params) return $newFilePath; } + + /** + * Clear tmp glide cache. + */ + private function glideClearTmpCache() + { + $glideTmpPath = $this->glideTmpPath(); + + $local = app(Filesystem::class); + + if ($local->exists($glideTmpPath)) { + $local->deleteDirectory($glideTmpPath); + } + } } From 2919b304427cae164e352a43488cb2b527e9e7c5 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Fri, 13 May 2022 16:23:13 -0400 Subject: [PATCH 05/63] Move private methods to bottom and docblock. --- src/Assets/Asset.php | 122 +++++++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 58 deletions(-) diff --git a/src/Assets/Asset.php b/src/Assets/Asset.php index 4072de84a0..ad220c37d7 100644 --- a/src/Assets/Asset.php +++ b/src/Assets/Asset.php @@ -714,64 +714,6 @@ public function download(string $name = null, array $headers = []) return $this->disk()->filesystem()->download($this->path(), $name, $headers); } - /** - * Get safe upload path for UploadedFile. - * - * @param UploadedFile $file - * @return string - */ - private function getSafeUploadPath(UploadedFile $file) - { - $ext = $file->getClientOriginalExtension(); - $filename = $this->getSafeFilename(pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME)); - - $directory = $this->folder(); - $directory = ($directory === '.') ? '/' : $directory; - $path = Path::tidy($directory.'/'.$filename.'.'.$ext); - $path = ltrim($path, '/'); - - // If the file exists, we'll append a timestamp to prevent overwriting. - if ($this->disk()->exists($path)) { - $basename = $filename.'-'.Carbon::now()->timestamp.'.'.$ext; - $path = Str::removeLeft(Path::assemble($directory, $basename), '/'); - } - - return $path; - } - - private function getSafeFilename($string) - { - $replacements = [ - ' ' => '-', - '#' => '-', - ]; - - $str = Stringy::create(urldecode($string))->toAscii(); - - foreach ($replacements as $from => $to) { - $str = $str->replace($from, $to); - } - - return (string) $str; - } - - /** - * Put file on destination disk. - * - * @param string $sourcePath - * @param string $destinationPath - */ - private function putFileOnDisk($sourcePath, $destinationPath) - { - $stream = fopen($sourcePath, 'r'); - - $this->disk()->put($destinationPath, $stream); - - if (is_resource($stream)) { - fclose($stream); - } - } - /** * Get the asset file contents. * @@ -904,6 +846,70 @@ public function getQueryableValue(string $field) return $field->fieldtype()->toQueryableValue($value); } + /** + * Get safe upload path for UploadedFile. + * + * @param UploadedFile $file + * @return string + */ + private function getSafeUploadPath(UploadedFile $file) + { + $ext = $file->getClientOriginalExtension(); + $filename = $this->getSafeFilename(pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME)); + + $directory = $this->folder(); + $directory = ($directory === '.') ? '/' : $directory; + $path = Path::tidy($directory.'/'.$filename.'.'.$ext); + $path = ltrim($path, '/'); + + // If the file exists, we'll append a timestamp to prevent overwriting. + if ($this->disk()->exists($path)) { + $basename = $filename.'-'.Carbon::now()->timestamp.'.'.$ext; + $path = Str::removeLeft(Path::assemble($directory, $basename), '/'); + } + + return $path; + } + + /** + * Get safe filename. + * + * @param string $string + * @return string + */ + private function getSafeFilename($string) + { + $replacements = [ + ' ' => '-', + '#' => '-', + ]; + + $str = Stringy::create(urldecode($string))->toAscii(); + + foreach ($replacements as $from => $to) { + $str = $str->replace($from, $to); + } + + return (string) $str; + } + + /** + * Put file on destination disk. + * + * @param string $sourcePath + * @param string $destinationPath + */ + private function putFileOnDisk($sourcePath, $destinationPath) + { + $stream = fopen($sourcePath, 'r'); + + $this->disk()->put($destinationPath, $stream); + + if (is_resource($stream)) { + fclose($stream); + } + } + /** * Get temporary glide cache path in storage for processing uploads. * From 266ab5331d70a542c696c272bb3ae74cf63b7cc9 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Fri, 13 May 2022 17:12:00 -0400 Subject: [PATCH 06/63] Add `Glide Processing` config field to asset containers. --- .../Controllers/CP/Assets/AssetContainersController.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Http/Controllers/CP/Assets/AssetContainersController.php b/src/Http/Controllers/CP/Assets/AssetContainersController.php index dee32fb71a..69300cace7 100644 --- a/src/Http/Controllers/CP/Assets/AssetContainersController.php +++ b/src/Http/Controllers/CP/Assets/AssetContainersController.php @@ -257,6 +257,13 @@ protected function formBlueprint($container = null) 'instructions' => __('statamic::messages.asset_container_quick_download_instructions'), 'default' => true, ], + 'glide' => [ + 'type' => 'array', + 'display' => __('Glide Processing'), + 'instructions' => __('When enabled, images will be permanently processed with these glide parameters on upload.'), + 'key_header' => __('Param'), + 'add_button' => __('Add Param'), + ], ], ], ]); From eb9add345b025ee517a4e22b12d0c234cb7288fe Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Fri, 13 May 2022 17:13:01 -0400 Subject: [PATCH 07/63] Implement reading/writing of `glide` config on containers. --- src/Assets/AssetContainer.php | 18 ++++++++++++++++++ .../CP/Assets/AssetContainersController.php | 8 ++++++-- src/Stache/Stores/AssetContainersStore.php | 1 + 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/Assets/AssetContainer.php b/src/Assets/AssetContainer.php index 2b5ae06004..b2eece93dd 100644 --- a/src/Assets/AssetContainer.php +++ b/src/Assets/AssetContainer.php @@ -35,6 +35,7 @@ class AssetContainer implements AssetContainerContract, Augmentable, ArrayAccess protected $allowMoving; protected $allowRenaming; protected $createFolders; + protected $glide; protected $searchIndex; public function id($id = null) @@ -444,6 +445,22 @@ public function createFolders($createFolders = null) ->args(func_get_args()); } + /** + * The glide parameters to be applied on image upload. + * + * @param array|null $glide + * @return array|$this + */ + public function glide($glide = null) + { + return $this + ->fluentlyGetOrSet('glide') + ->getter(function ($glide) { + return (array) ($glide ?? []); + }) + ->args(func_get_args()); + } + public function fileData() { return [ @@ -455,6 +472,7 @@ public function fileData() 'allow_renaming' => $this->allowRenaming, 'allow_moving' => $this->allowMoving, 'create_folders' => $this->createFolders, + 'glide' => $this->glide, ]; } diff --git a/src/Http/Controllers/CP/Assets/AssetContainersController.php b/src/Http/Controllers/CP/Assets/AssetContainersController.php index 69300cace7..b75ecc86d2 100644 --- a/src/Http/Controllers/CP/Assets/AssetContainersController.php +++ b/src/Http/Controllers/CP/Assets/AssetContainersController.php @@ -29,6 +29,7 @@ public function index(Request $request) 'allow_renaming' => $container->allowRenaming(), 'allow_uploads' => $container->allowUploads(), 'create_folders' => $container->createFolders(), + 'glide' => $container->glide(), 'edit_url' => $container->editUrl(), 'delete_url' => $container->deleteUrl(), 'blueprint_url' => cp_route('asset-containers.blueprint.edit', $container->handle()), @@ -61,6 +62,7 @@ public function edit($container) 'allow_renaming' => $container->allowRenaming(), 'allow_moving' => $container->allowMoving(), 'create_folders' => $container->createFolders(), + 'glide' => $container->glide(), ]; $fields = ($blueprint = $this->formBlueprint($container)) @@ -93,7 +95,8 @@ public function update(Request $request, $container) ->allowRenaming($values['allow_renaming']) ->allowMoving($values['allow_moving']) ->allowUploads($values['allow_uploads']) - ->createFolders($values['create_folders']); + ->createFolders($values['create_folders']) + ->glide($values['glide']); $container->save(); @@ -139,7 +142,8 @@ public function store(Request $request) ->title($values['title']) ->disk($values['disk']) ->allowUploads($values['allow_uploads']) - ->createFolders($values['create_folders']); + ->createFolders($values['create_folders']) + ->glide($values['glide']); $container->save(); diff --git a/src/Stache/Stores/AssetContainersStore.php b/src/Stache/Stores/AssetContainersStore.php index d60040deb1..b3f98790a6 100644 --- a/src/Stache/Stores/AssetContainersStore.php +++ b/src/Stache/Stores/AssetContainersStore.php @@ -25,6 +25,7 @@ public function makeItemFromFile($path, $contents) ->allowRenaming(array_get($data, 'allow_renaming')) ->allowUploads(array_get($data, 'allow_uploads')) ->createFolders(array_get($data, 'create_folders')) + ->glide(array_get($data, 'glide')) ->searchIndex(array_get($data, 'search_index')); } } From 3bbfa7a132025e7892286e819284b4df2906c067 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Fri, 13 May 2022 17:13:22 -0400 Subject: [PATCH 08/63] Check container for glide params when uploading. --- src/Assets/Asset.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Assets/Asset.php b/src/Assets/Asset.php index ad220c37d7..42339c31f0 100644 --- a/src/Assets/Asset.php +++ b/src/Assets/Asset.php @@ -682,8 +682,7 @@ public function upload(UploadedFile $file) { $path = $this->getSafeUploadPath($file); - // TODO: Check container for glide params... - $glide = false; + $glide = $this->container()->glide(); $sourcePath = $glide ? $this->glideProcessUploadedFile($file, $glide) From 24ec7f1373cf578a918695ff3fd067b1d7194581 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Fri, 13 May 2022 17:17:31 -0400 Subject: [PATCH 09/63] Pass tests again. --- tests/Feature/AssetContainers/ListAssetContainersTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/Feature/AssetContainers/ListAssetContainersTest.php b/tests/Feature/AssetContainers/ListAssetContainersTest.php index bae094e710..9b4ee65597 100644 --- a/tests/Feature/AssetContainers/ListAssetContainersTest.php +++ b/tests/Feature/AssetContainers/ListAssetContainersTest.php @@ -57,6 +57,7 @@ public function containerArray() 'allow_renaming' => true, 'allow_uploads' => true, 'create_folders' => true, + 'glide' => [], 'edit_url' => 'http://localhost/cp/asset-containers/three/edit', 'delete_url' => 'http://localhost/cp/asset-containers/three', 'blueprint_url' => 'http://localhost/cp/asset-containers/three/blueprint', @@ -71,6 +72,7 @@ public function containerArray() 'allow_renaming' => true, 'allow_uploads' => true, 'create_folders' => true, + 'glide' => [], 'edit_url' => 'http://localhost/cp/asset-containers/two/edit', 'delete_url' => 'http://localhost/cp/asset-containers/two', 'blueprint_url' => 'http://localhost/cp/asset-containers/two/blueprint', From 7a2cf091cd126fa8d34f447b16ef6130e56b09fc Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Fri, 13 May 2022 21:17:56 +0000 Subject: [PATCH 10/63] Apply fixes from StyleCI --- src/Assets/Asset.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Assets/Asset.php b/src/Assets/Asset.php index 42339c31f0..93901fae64 100644 --- a/src/Assets/Asset.php +++ b/src/Assets/Asset.php @@ -848,7 +848,7 @@ public function getQueryableValue(string $field) /** * Get safe upload path for UploadedFile. * - * @param UploadedFile $file + * @param UploadedFile $file * @return string */ private function getSafeUploadPath(UploadedFile $file) @@ -873,7 +873,7 @@ private function getSafeUploadPath(UploadedFile $file) /** * Get safe filename. * - * @param string $string + * @param string $string * @return string */ private function getSafeFilename($string) @@ -895,8 +895,8 @@ private function getSafeFilename($string) /** * Put file on destination disk. * - * @param string $sourcePath - * @param string $destinationPath + * @param string $sourcePath + * @param string $destinationPath */ private function putFileOnDisk($sourcePath, $destinationPath) { @@ -922,8 +922,8 @@ private function glideTmpPath() /** * Process UploadedFile instance using glide and return cached path. * - * @param UploadedFile $file - * @param array $params + * @param UploadedFile $file + * @param array $params * @param string */ private function glideProcessUploadedFile(UploadedFile $file, $params) From 262bf0b2d20eb42ab1d22c4f50a9f79d7162a68f Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 19 May 2022 16:15:33 -0400 Subject: [PATCH 11/63] Copy driver and file extensions config from `GlideManager`. --- src/Assets/Asset.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Assets/Asset.php b/src/Assets/Asset.php index 93901fae64..5a4c82512d 100644 --- a/src/Assets/Asset.php +++ b/src/Assets/Asset.php @@ -933,6 +933,8 @@ private function glideProcessUploadedFile(UploadedFile $file, $params) $server = \League\Glide\ServerFactory::create([ 'source' => $file->getPath(), 'cache' => $glideTmpPath, + 'driver' => config('statamic.assets.image_manipulation.driver'), + 'cache_with_file_extensions' => true, ]); $server->makeImage($file->getFilename(), $params); From 52c3ed3b98fae2a050f074670abf5b28f1578f86 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 19 May 2022 16:16:11 -0400 Subject: [PATCH 12/63] Add some basic test coverage for glide on upload. --- tests/Assets/AssetTest.php | 56 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/tests/Assets/AssetTest.php b/tests/Assets/AssetTest.php index b962186047..6d843383cc 100644 --- a/tests/Assets/AssetTest.php +++ b/tests/Assets/AssetTest.php @@ -988,6 +988,62 @@ private function uploadFileTest() Event::assertDispatched(AssetSaved::class); } + /** @test */ + public function it_can_upload_an_image_into_a_container_with_glide_config() + { + Event::fake(); + + $this->container->glide([ + 'w' => '15', + 'h' => '15', + ]); + + $asset = (new Asset)->container($this->container)->path('path/to/asset.jpg')->syncOriginal(); + + Facades\AssetContainer::shouldReceive('findByHandle')->with('test_container')->andReturn($this->container); + Storage::disk('test')->assertMissing('path/to/asset.jpg'); + + $return = $asset->upload(UploadedFile::fake()->image('asset.jpg', 20, 30)); + + $this->assertEquals($asset, $return); + Storage::disk('test')->assertExists('path/to/asset.jpg'); + $this->assertEquals('path/to/asset.jpg', $asset->path()); + Event::assertDispatched(AssetUploaded::class, function ($event) use ($asset) { + return $event->asset = $asset; + }); + Event::assertDispatched(AssetSaved::class); + $meta = $asset->meta(); + + $this->assertEquals(10, $meta['width']); + $this->assertEquals(15, $meta['height']); + } + + /** @test */ + public function it_doesnt_error_when_uploading_non_glideable_file_with_glide_config() + { + Event::fake(); + + $this->container->glide([ + 'w' => '15', + 'h' => '15', + ]); + + $asset = (new Asset)->container($this->container)->path('path/to/readme.md')->syncOriginal(); + + Facades\AssetContainer::shouldReceive('findByHandle')->with('test_container')->andReturn($this->container); + Storage::disk('test')->assertMissing('path/to/readme.md'); + + $return = $asset->upload(UploadedFile::fake()->create('readme.md')); + + $this->assertEquals($asset, $return); + Storage::disk('test')->assertExists('path/to/readme.md'); + $this->assertEquals('path/to/readme.md', $asset->path()); + Event::assertDispatched(AssetUploaded::class, function ($event) use ($asset) { + return $event->asset = $asset; + }); + Event::assertDispatched(AssetSaved::class); + } + /** @test */ public function it_appends_timestamp_to_uploaded_files_filename_if_it_already_exists() { From 6c85db39bea7db2f091c9030ee389a9fd0250904 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 19 May 2022 16:43:08 -0400 Subject: [PATCH 13/63] Extract upload logic to `Assets\Uploader` class. --- src/Assets/Asset.php | 139 ++---------------------------- src/Assets/Uploader.php | 186 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+), 134 deletions(-) create mode 100644 src/Assets/Uploader.php diff --git a/src/Assets/Asset.php b/src/Assets/Asset.php index 5a4c82512d..beece9ff7d 100644 --- a/src/Assets/Asset.php +++ b/src/Assets/Asset.php @@ -31,7 +31,6 @@ use Statamic\Support\Arr; use Statamic\Support\Str; use Statamic\Support\Traits\FluentlyGetsAndSets; -use Stringy\Stringy; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\Mime\MimeTypes; @@ -680,23 +679,12 @@ public function title() */ public function upload(UploadedFile $file) { - $path = $this->getSafeUploadPath($file); + $path = Uploader::asset($this)->upload($file); - $glide = $this->container()->glide(); - - $sourcePath = $glide - ? $this->glideProcessUploadedFile($file, $glide) - : $file->getRealPath(); - - $this->putFileOnDisk($sourcePath, $path); - - if ($glide) { - $this->glideClearTmpCache(); - } - - $this->path($path)->syncOriginal(); - - $this->save(); + $this + ->path($path) + ->syncOriginal() + ->save(); AssetUploaded::dispatch($this); @@ -844,121 +832,4 @@ public function getQueryableValue(string $field) return $field->fieldtype()->toQueryableValue($value); } - - /** - * Get safe upload path for UploadedFile. - * - * @param UploadedFile $file - * @return string - */ - private function getSafeUploadPath(UploadedFile $file) - { - $ext = $file->getClientOriginalExtension(); - $filename = $this->getSafeFilename(pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME)); - - $directory = $this->folder(); - $directory = ($directory === '.') ? '/' : $directory; - $path = Path::tidy($directory.'/'.$filename.'.'.$ext); - $path = ltrim($path, '/'); - - // If the file exists, we'll append a timestamp to prevent overwriting. - if ($this->disk()->exists($path)) { - $basename = $filename.'-'.Carbon::now()->timestamp.'.'.$ext; - $path = Str::removeLeft(Path::assemble($directory, $basename), '/'); - } - - return $path; - } - - /** - * Get safe filename. - * - * @param string $string - * @return string - */ - private function getSafeFilename($string) - { - $replacements = [ - ' ' => '-', - '#' => '-', - ]; - - $str = Stringy::create(urldecode($string))->toAscii(); - - foreach ($replacements as $from => $to) { - $str = $str->replace($from, $to); - } - - return (string) $str; - } - - /** - * Put file on destination disk. - * - * @param string $sourcePath - * @param string $destinationPath - */ - private function putFileOnDisk($sourcePath, $destinationPath) - { - $stream = fopen($sourcePath, 'r'); - - $this->disk()->put($destinationPath, $stream); - - if (is_resource($stream)) { - fclose($stream); - } - } - - /** - * Get temporary glide cache path in storage for processing uploads. - * - * @return string - */ - private function glideTmpPath() - { - return storage_path('statamic/glide/tmp'); - } - - /** - * Process UploadedFile instance using glide and return cached path. - * - * @param UploadedFile $file - * @param array $params - * @param string - */ - private function glideProcessUploadedFile(UploadedFile $file, $params) - { - $glideTmpPath = $this->glideTmpPath(); - - $server = \League\Glide\ServerFactory::create([ - 'source' => $file->getPath(), - 'cache' => $glideTmpPath, - 'driver' => config('statamic.assets.image_manipulation.driver'), - 'cache_with_file_extensions' => true, - ]); - - $server->makeImage($file->getFilename(), $params); - - $local = app(Filesystem::class); - - $newFilePath = collect($local->files($glideTmpPath.'/'.$file->getFilename())) - ->first() - ->getRealPath(); - - return $newFilePath; - } - - /** - * Clear tmp glide cache. - */ - private function glideClearTmpCache() - { - $glideTmpPath = $this->glideTmpPath(); - - $local = app(Filesystem::class); - - if ($local->exists($glideTmpPath)) { - $local->deleteDirectory($glideTmpPath); - } - } } diff --git a/src/Assets/Uploader.php b/src/Assets/Uploader.php new file mode 100644 index 0000000000..928e751796 --- /dev/null +++ b/src/Assets/Uploader.php @@ -0,0 +1,186 @@ +asset = $asset; + $this->files = app(Filesystem::class); + } + + /** + * Instantiate asset uploader. + * + * @param Asset $asset + * @return static + */ + public static function asset(Asset $asset) + { + return new static($asset); + } + + /** + * Upload file to asset's container. + * + * @param UploadedFile $file + * @return string + */ + public function upload(UploadedFile $file) + { + $path = $this->getSafeUploadPath($file); + + $glide = $this->asset->container()->glide(); + + $sourcePath = $glide + ? $this->glideProcessUploadedFile($file, $glide) + : $file->getRealPath(); + + $this->putFileOnDisk($sourcePath, $path); + + if ($glide) { + $this->glideClearTmpCache(); + } + + return $path; + } + + /** + * Get the container's filesystem disk instance. + * + * @return \Statamic\Filesystem\FlysystemAdapter + */ + private function disk() + { + return $this->asset->container()->disk(); + } + + /** + * Get safe upload path for UploadedFile. + * + * @param UploadedFile $file + * @return string + */ + private function getSafeUploadPath(UploadedFile $file) + { + $ext = $file->getClientOriginalExtension(); + $filename = $this->getSafeFilename(pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME)); + + $directory = $this->asset->folder(); + $directory = ($directory === '.') ? '/' : $directory; + $path = Path::tidy($directory.'/'.$filename.'.'.$ext); + $path = ltrim($path, '/'); + + // If the file exists, we'll append a timestamp to prevent overwriting. + if ($this->disk()->exists($path)) { + $basename = $filename.'-'.Carbon::now()->timestamp.'.'.$ext; + $path = Str::removeLeft(Path::assemble($directory, $basename), '/'); + } + + return $path; + } + + /** + * Get safe filename. + * + * @param string $string + * @return string + */ + private function getSafeFilename($string) + { + $replacements = [ + ' ' => '-', + '#' => '-', + ]; + + $str = Stringy::create(urldecode($string))->toAscii(); + + foreach ($replacements as $from => $to) { + $str = $str->replace($from, $to); + } + + return (string) $str; + } + + /** + * Put file on destination disk. + * + * @param string $sourcePath + * @param string $destinationPath + */ + private function putFileOnDisk($sourcePath, $destinationPath) + { + $stream = fopen($sourcePath, 'r'); + + $this->disk()->put($destinationPath, $stream); + + if (is_resource($stream)) { + fclose($stream); + } + } + + /** + * Get temporary glide cache path in storage for processing uploads. + * + * @return string + */ + private function glideTmpPath() + { + return storage_path('statamic/glide/tmp'); + } + + /** + * Process UploadedFile instance using glide and return cached path. + * + * @param UploadedFile $file + * @param array $params + * @param string + */ + private function glideProcessUploadedFile(UploadedFile $file, $params) + { + $glideTmpPath = $this->glideTmpPath(); + + $server = \League\Glide\ServerFactory::create([ + 'source' => $file->getPath(), + 'cache' => $glideTmpPath, + 'driver' => config('statamic.assets.image_manipulation.driver'), + 'cache_with_file_extensions' => true, + ]); + + $server->makeImage($file->getFilename(), $params); + + $newFilePath = collect($this->files->files($glideTmpPath.'/'.$file->getFilename())) + ->first() + ->getRealPath(); + + return $newFilePath; + } + + /** + * Clear tmp glide cache. + */ + private function glideClearTmpCache() + { + $glideTmpPath = $this->glideTmpPath(); + + if ($this->files->exists($glideTmpPath)) { + $this->files->deleteDirectory($glideTmpPath); + } + } +} From 43d02c90ba6bc67cec0db618b9cbd2d00b0ad6b3 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 19 May 2022 16:44:16 -0400 Subject: [PATCH 14/63] =?UTF-8?q?This=20was=20failing=20test=20?= =?UTF-8?q?=F0=9F=A4=94.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Assets/Uploader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Assets/Uploader.php b/src/Assets/Uploader.php index 928e751796..964a1ffde1 100644 --- a/src/Assets/Uploader.php +++ b/src/Assets/Uploader.php @@ -160,7 +160,7 @@ private function glideProcessUploadedFile(UploadedFile $file, $params) 'source' => $file->getPath(), 'cache' => $glideTmpPath, 'driver' => config('statamic.assets.image_manipulation.driver'), - 'cache_with_file_extensions' => true, + // 'cache_with_file_extensions' => true, // TODO: What is this doing? ]); $server->makeImage($file->getFilename(), $params); From 0a76aeed37fd1d0ad94b05d038acd7b5469c01c0 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 19 May 2022 16:45:01 -0400 Subject: [PATCH 15/63] Import `ServerFactory`. --- src/Assets/Uploader.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Assets/Uploader.php b/src/Assets/Uploader.php index 964a1ffde1..1551d35462 100644 --- a/src/Assets/Uploader.php +++ b/src/Assets/Uploader.php @@ -4,6 +4,7 @@ use Illuminate\Filesystem\Filesystem; use Illuminate\Support\Carbon; +use League\Glide\ServerFactory; use Statamic\Facades\Path; use Statamic\Support\Str; use Stringy\Stringy; @@ -156,7 +157,7 @@ private function glideProcessUploadedFile(UploadedFile $file, $params) { $glideTmpPath = $this->glideTmpPath(); - $server = \League\Glide\ServerFactory::create([ + $server = ServerFactory::create([ 'source' => $file->getPath(), 'cache' => $glideTmpPath, 'driver' => config('statamic.assets.image_manipulation.driver'), From 0a89a0e92c6648663bf873355be0b06936c79cf6 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 19 May 2022 16:56:19 -0400 Subject: [PATCH 16/63] Refactor `glideTmpPath` to property. --- src/Assets/Uploader.php | 24 ++++++------------------ tests/Assets/AssetTest.php | 2 ++ 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/Assets/Uploader.php b/src/Assets/Uploader.php index 1551d35462..69ed22893c 100644 --- a/src/Assets/Uploader.php +++ b/src/Assets/Uploader.php @@ -14,6 +14,7 @@ class Uploader { private $asset; private $files; + private $glideTmpPath; /** * Instantiate asset uploader. @@ -24,6 +25,7 @@ public function __construct(Asset $asset) { $this->asset = $asset; $this->files = app(Filesystem::class); + $this->glideTmpPath = storage_path('statamic/glide/tmp'); } /** @@ -136,16 +138,6 @@ private function putFileOnDisk($sourcePath, $destinationPath) } } - /** - * Get temporary glide cache path in storage for processing uploads. - * - * @return string - */ - private function glideTmpPath() - { - return storage_path('statamic/glide/tmp'); - } - /** * Process UploadedFile instance using glide and return cached path. * @@ -155,18 +147,16 @@ private function glideTmpPath() */ private function glideProcessUploadedFile(UploadedFile $file, $params) { - $glideTmpPath = $this->glideTmpPath(); - $server = ServerFactory::create([ 'source' => $file->getPath(), - 'cache' => $glideTmpPath, + 'cache' => $this->glideTmpPath, 'driver' => config('statamic.assets.image_manipulation.driver'), // 'cache_with_file_extensions' => true, // TODO: What is this doing? ]); $server->makeImage($file->getFilename(), $params); - $newFilePath = collect($this->files->files($glideTmpPath.'/'.$file->getFilename())) + $newFilePath = collect($this->files->files($this->glideTmpPath.'/'.$file->getFilename())) ->first() ->getRealPath(); @@ -178,10 +168,8 @@ private function glideProcessUploadedFile(UploadedFile $file, $params) */ private function glideClearTmpCache() { - $glideTmpPath = $this->glideTmpPath(); - - if ($this->files->exists($glideTmpPath)) { - $this->files->deleteDirectory($glideTmpPath); + if ($this->files->exists($this->glideTmpPath)) { + $this->files->deleteDirectory($this->glideTmpPath); } } } diff --git a/tests/Assets/AssetTest.php b/tests/Assets/AssetTest.php index 6d843383cc..ebb5f9f0b9 100644 --- a/tests/Assets/AssetTest.php +++ b/tests/Assets/AssetTest.php @@ -1006,6 +1006,7 @@ public function it_can_upload_an_image_into_a_container_with_glide_config() $return = $asset->upload(UploadedFile::fake()->image('asset.jpg', 20, 30)); $this->assertEquals($asset, $return); + $this->assertDirectoryNotExists(storage_path('statamic/glide/tmp')); Storage::disk('test')->assertExists('path/to/asset.jpg'); $this->assertEquals('path/to/asset.jpg', $asset->path()); Event::assertDispatched(AssetUploaded::class, function ($event) use ($asset) { @@ -1036,6 +1037,7 @@ public function it_doesnt_error_when_uploading_non_glideable_file_with_glide_con $return = $asset->upload(UploadedFile::fake()->create('readme.md')); $this->assertEquals($asset, $return); + $this->assertDirectoryNotExists(storage_path('statamic/glide/tmp')); Storage::disk('test')->assertExists('path/to/readme.md'); $this->assertEquals('path/to/readme.md', $asset->path()); Event::assertDispatched(AssetUploaded::class, function ($event) use ($asset) { From 64e10ab53f389905eb9e68bdb7a4d89ea61f4b1f Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 19 May 2022 17:07:58 -0400 Subject: [PATCH 17/63] Pass test for non-glideable filetypes. --- src/Assets/Uploader.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Assets/Uploader.php b/src/Assets/Uploader.php index 69ed22893c..5cc48c2778 100644 --- a/src/Assets/Uploader.php +++ b/src/Assets/Uploader.php @@ -154,7 +154,11 @@ private function glideProcessUploadedFile(UploadedFile $file, $params) // 'cache_with_file_extensions' => true, // TODO: What is this doing? ]); - $server->makeImage($file->getFilename(), $params); + try { + $server->makeImage($file->getFilename(), $params); + } catch (\Exception $exception) { + return $file->getRealPath(); + } $newFilePath = collect($this->files->files($this->glideTmpPath.'/'.$file->getFilename())) ->first() From 235254e7d92221833de4aed87a2e62809c074f4a Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Thu, 19 May 2022 17:13:14 -0400 Subject: [PATCH 18/63] Enable watermarks. --- src/Assets/Uploader.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Assets/Uploader.php b/src/Assets/Uploader.php index 5cc48c2778..13e23e8f99 100644 --- a/src/Assets/Uploader.php +++ b/src/Assets/Uploader.php @@ -152,6 +152,7 @@ private function glideProcessUploadedFile(UploadedFile $file, $params) 'cache' => $this->glideTmpPath, 'driver' => config('statamic.assets.image_manipulation.driver'), // 'cache_with_file_extensions' => true, // TODO: What is this doing? + 'watermarks' => public_path(), ]); try { From 239b1cdeac0550fcf309f5e8822b1a5eb2dbddbc Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Fri, 27 May 2022 17:42:33 -0400 Subject: [PATCH 19/63] Add boolean `label_html` to select fieldtypes to allow rendering of html in option labels. --- resources/js/components/fieldtypes/SelectFieldtype.vue | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/resources/js/components/fieldtypes/SelectFieldtype.vue b/resources/js/components/fieldtypes/SelectFieldtype.vue index d3233877d9..6b08e291cb 100644 --- a/resources/js/components/fieldtypes/SelectFieldtype.vue +++ b/resources/js/components/fieldtypes/SelectFieldtype.vue @@ -29,6 +29,14 @@ v-bind="attributes" > + + From e2b95c2f1e6415560cb9cac46b86b5e14e04f500 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Fri, 27 May 2022 17:43:18 -0400 Subject: [PATCH 20/63] Update glide config fields on asset container edit form. --- .../CP/Assets/AssetContainersController.php | 59 +++++++++++++++++-- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/src/Http/Controllers/CP/Assets/AssetContainersController.php b/src/Http/Controllers/CP/Assets/AssetContainersController.php index b75ecc86d2..3a12b2c3e9 100644 --- a/src/Http/Controllers/CP/Assets/AssetContainersController.php +++ b/src/Http/Controllers/CP/Assets/AssetContainersController.php @@ -261,12 +261,38 @@ protected function formBlueprint($container = null) 'instructions' => __('statamic::messages.asset_container_quick_download_instructions'), 'default' => true, ], - 'glide' => [ - 'type' => 'array', - 'display' => __('Glide Processing'), - 'instructions' => __('When enabled, images will be permanently processed with these glide parameters on upload.'), - 'key_header' => __('Param'), - 'add_button' => __('Add Param'), + ], + ], + ]); + + $fields = array_merge($fields, [ + 'image_manipulation' => [ + 'display' => __('Image Manipulation'), + 'fields' => [ + 'glide_source_preset' => [ + 'type' => 'select', + 'display' => __('Process Source Images'), + 'label_html' => true, + 'instructions' => __('When enabled, source images will be permanently processed with this image manipulation preset on upload.'), + 'options' => $this->expandedGlidePresetOptions(), + 'clearable' => true, + ], + 'glide_warm_all_presets' => [ + 'type' => 'toggle', + 'display' => __('Intelligently Warm Glide Caches'), + 'instructions' => __('When enabled, intelligently warm glide caches on upload.'), + 'default' => true, + ], + 'glide_warm_presets' => [ + 'type' => 'select', + 'display' => __('Warm Specific Glide Caches'), + 'instructions' => __('Specify which glide presets to warm on upload.'), + 'multiple' => true, + 'options' => array_keys(config('statamic.assets.image_manipulation.presets')), + 'label_html' => true, + 'if' => [ + 'glide_warm_all_presets' => false, + ], ], ], ], @@ -274,4 +300,25 @@ protected function formBlueprint($container = null) return Blueprint::makeFromSections($fields); } + + private function expandedGlidePresetOptions() + { + return collect(config('statamic.assets.image_manipulation.presets')) + ->mapWithKeys(function ($params, $handle) { + return [$handle => $this->expandedGlidePresetLabel($handle, $params)]; + }); + } + + private function expandedGlidePresetLabel($handle, $params) + { + $separator = '-'; + + $params = collect($params) + ->map(function ($value, $param) { + return "{$param}: {$value}"; + }) + ->implode(' '); + + return "{$handle} {$separator} {$params}"; + } } From c51e0e035a5b4808446613cfe908515d7ef0ed6f Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Fri, 27 May 2022 20:19:05 -0400 Subject: [PATCH 21/63] Finish controller and ensure `glide_warm_intelligent` toggle state loads properly on edit. --- .../CP/Assets/AssetContainersController.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Http/Controllers/CP/Assets/AssetContainersController.php b/src/Http/Controllers/CP/Assets/AssetContainersController.php index 3a12b2c3e9..87e37bf9c0 100644 --- a/src/Http/Controllers/CP/Assets/AssetContainersController.php +++ b/src/Http/Controllers/CP/Assets/AssetContainersController.php @@ -29,7 +29,8 @@ public function index(Request $request) 'allow_renaming' => $container->allowRenaming(), 'allow_uploads' => $container->allowUploads(), 'create_folders' => $container->createFolders(), - 'glide' => $container->glide(), + 'glide_source_preset' => $container->glideSourcePreset(), + 'glide_warm_presets' => $container->glideWarmPresets(), 'edit_url' => $container->editUrl(), 'delete_url' => $container->deleteUrl(), 'blueprint_url' => cp_route('asset-containers.blueprint.edit', $container->handle()), @@ -62,7 +63,9 @@ public function edit($container) 'allow_renaming' => $container->allowRenaming(), 'allow_moving' => $container->allowMoving(), 'create_folders' => $container->createFolders(), - 'glide' => $container->glide(), + 'glide_source_preset' => $container->glideSourcePreset(), + 'glide_warm_intelligent' => $container->glideWarmPresets() === null, + 'glide_warm_presets' => $container->glideWarmPresets(), ]; $fields = ($blueprint = $this->formBlueprint($container)) @@ -96,7 +99,8 @@ public function update(Request $request, $container) ->allowMoving($values['allow_moving']) ->allowUploads($values['allow_uploads']) ->createFolders($values['create_folders']) - ->glide($values['glide']); + ->glideSourcePreset($values['glide_source_preset']) + ->glideWarmPresets($values['glide_warm_intelligent'] ? null : $values['glide_warm_presets']); $container->save(); @@ -143,7 +147,8 @@ public function store(Request $request) ->disk($values['disk']) ->allowUploads($values['allow_uploads']) ->createFolders($values['create_folders']) - ->glide($values['glide']); + ->glideSourcePreset($values['glide_source_preset']) + ->glideWarmPresets($values['glide_warm_intelligent'] ? null : $values['glide_warm_presets']); $container->save(); @@ -277,7 +282,7 @@ protected function formBlueprint($container = null) 'options' => $this->expandedGlidePresetOptions(), 'clearable' => true, ], - 'glide_warm_all_presets' => [ + 'glide_warm_intelligent' => [ 'type' => 'toggle', 'display' => __('Intelligently Warm Glide Caches'), 'instructions' => __('When enabled, intelligently warm glide caches on upload.'), @@ -289,9 +294,8 @@ protected function formBlueprint($container = null) 'instructions' => __('Specify which glide presets to warm on upload.'), 'multiple' => true, 'options' => array_keys(config('statamic.assets.image_manipulation.presets')), - 'label_html' => true, 'if' => [ - 'glide_warm_all_presets' => false, + 'glide_warm_intelligent' => false, ], ], ], From e0614b56c0ebf2465ebecf2fe94eeeae81745e9f Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Fri, 27 May 2022 20:19:37 -0400 Subject: [PATCH 22/63] Store `glide_source_preset` and `glide_warm_presets` instead of `glide`. --- src/Assets/AssetContainer.php | 38 +++++++++++++++++----- src/Stache/Stores/AssetContainersStore.php | 3 +- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/Assets/AssetContainer.php b/src/Assets/AssetContainer.php index b2eece93dd..60933f8d65 100644 --- a/src/Assets/AssetContainer.php +++ b/src/Assets/AssetContainer.php @@ -35,7 +35,8 @@ class AssetContainer implements AssetContainerContract, Augmentable, ArrayAccess protected $allowMoving; protected $allowRenaming; protected $createFolders; - protected $glide; + protected $glideSourcePreset; + protected $glideWarmPresets; protected $searchIndex; public function id($id = null) @@ -446,17 +447,35 @@ public function createFolders($createFolders = null) } /** - * The glide parameters to be applied on image upload. + * The glide source preset to be permanently applied to source image on upload. * - * @param array|null $glide - * @return array|$this + * @param string|null $preset + * @return string|null|$this */ - public function glide($glide = null) + public function glideSourcePreset($preset = null) { return $this - ->fluentlyGetOrSet('glide') - ->getter(function ($glide) { - return (array) ($glide ?? []); + ->fluentlyGetOrSet('glideSourcePreset') + ->getter(function ($preset) { + return $preset ?? null; + }) + ->args(func_get_args()); + } + + /** + * The specific glide presets to be used when warming glide image cache on upload, + * otherwise we intelligently generate image cache for all configured presets, + * with the exception of the glide source preset, if one is configured. + * + * @param array|null $presets + * @return array|null|$this + */ + public function glideWarmPresets($preset = null) + { + return $this + ->fluentlyGetOrSet('glideWarmPresets') + ->getter(function ($presets) { + return $presets !== [] ? $presets : null; }) ->args(func_get_args()); } @@ -472,7 +491,8 @@ public function fileData() 'allow_renaming' => $this->allowRenaming, 'allow_moving' => $this->allowMoving, 'create_folders' => $this->createFolders, - 'glide' => $this->glide, + 'glide_source_preset' => $this->glideSourcePreset, + 'glide_warm_presets' => $this->glideWarmPresets, ]; } diff --git a/src/Stache/Stores/AssetContainersStore.php b/src/Stache/Stores/AssetContainersStore.php index b3f98790a6..07713520e5 100644 --- a/src/Stache/Stores/AssetContainersStore.php +++ b/src/Stache/Stores/AssetContainersStore.php @@ -25,7 +25,8 @@ public function makeItemFromFile($path, $contents) ->allowRenaming(array_get($data, 'allow_renaming')) ->allowUploads(array_get($data, 'allow_uploads')) ->createFolders(array_get($data, 'create_folders')) - ->glide(array_get($data, 'glide')) + ->glideSourcePreset(array_get($data, 'glide_source_preset')) + ->glideWarmPresets(array_get($data, 'glide_warm_presets')) ->searchIndex(array_get($data, 'search_index')); } } From 2ebac81d6c5cbd97ed469a1a359d7b091f12443d Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Fri, 27 May 2022 20:20:24 -0400 Subject: [PATCH 23/63] Load glide preset params from `assets.php` config. --- src/Assets/Uploader.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Assets/Uploader.php b/src/Assets/Uploader.php index 13e23e8f99..0e8dffe789 100644 --- a/src/Assets/Uploader.php +++ b/src/Assets/Uploader.php @@ -5,6 +5,7 @@ use Illuminate\Filesystem\Filesystem; use Illuminate\Support\Carbon; use League\Glide\ServerFactory; +use Statamic\Facades\Config; use Statamic\Facades\Path; use Statamic\Support\Str; use Stringy\Stringy; @@ -49,17 +50,17 @@ public function upload(UploadedFile $file) { $path = $this->getSafeUploadPath($file); - $glide = $this->asset->container()->glide(); + if ($preset = $this->asset->container()->glideSourcePreset()) { + $params = Config::get("statamic.assets.image_manipulation.presets.{$preset}", []); + } - $sourcePath = $glide - ? $this->glideProcessUploadedFile($file, $glide) + $sourcePath = $preset && $params + ? $this->glideProcessUploadedFile($file, $params) : $file->getRealPath(); $this->putFileOnDisk($sourcePath, $path); - if ($glide) { - $this->glideClearTmpCache(); - } + $this->glideClearTmpCache(); return $path; } From bc35a0939455c4de79863e3b1805b142781cc8bd Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Fri, 27 May 2022 20:20:34 -0400 Subject: [PATCH 24/63] Update tests. --- tests/Assets/AssetTest.php | 12 ++++++++---- .../AssetContainers/ListAssetContainersTest.php | 6 ++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/tests/Assets/AssetTest.php b/tests/Assets/AssetTest.php index c69577bb51..10d5568baf 100644 --- a/tests/Assets/AssetTest.php +++ b/tests/Assets/AssetTest.php @@ -994,10 +994,12 @@ public function it_can_upload_an_image_into_a_container_with_glide_config() { Event::fake(); - $this->container->glide([ + config(['statamic.assets.image_manipulation.presets.small' => [ 'w' => '15', 'h' => '15', - ]); + ]]); + + $this->container->glideSourcePreset('small'); $asset = (new Asset)->container($this->container)->path('path/to/asset.jpg')->syncOriginal(); @@ -1025,10 +1027,12 @@ public function it_doesnt_error_when_uploading_non_glideable_file_with_glide_con { Event::fake(); - $this->container->glide([ + config(['statamic.assets.image_manipulation.presets.small' => [ 'w' => '15', 'h' => '15', - ]); + ]]); + + $this->container->glideSourcePreset('small'); $asset = (new Asset)->container($this->container)->path('path/to/readme.md')->syncOriginal(); diff --git a/tests/Feature/AssetContainers/ListAssetContainersTest.php b/tests/Feature/AssetContainers/ListAssetContainersTest.php index 9b4ee65597..14452a4c27 100644 --- a/tests/Feature/AssetContainers/ListAssetContainersTest.php +++ b/tests/Feature/AssetContainers/ListAssetContainersTest.php @@ -57,7 +57,8 @@ public function containerArray() 'allow_renaming' => true, 'allow_uploads' => true, 'create_folders' => true, - 'glide' => [], + 'glide_source_preset' => null, + 'glide_warm_presets' => null, 'edit_url' => 'http://localhost/cp/asset-containers/three/edit', 'delete_url' => 'http://localhost/cp/asset-containers/three', 'blueprint_url' => 'http://localhost/cp/asset-containers/three/blueprint', @@ -72,7 +73,8 @@ public function containerArray() 'allow_renaming' => true, 'allow_uploads' => true, 'create_folders' => true, - 'glide' => [], + 'glide_source_preset' => null, + 'glide_warm_presets' => null, 'edit_url' => 'http://localhost/cp/asset-containers/two/edit', 'delete_url' => 'http://localhost/cp/asset-containers/two', 'blueprint_url' => 'http://localhost/cp/asset-containers/two/blueprint', From 69877d5f6419e0265f9b11a52224fb55e9c94263 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Mon, 30 May 2022 20:54:55 -0400 Subject: [PATCH 25/63] This is redundant. --- src/Assets/AssetContainer.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Assets/AssetContainer.php b/src/Assets/AssetContainer.php index 60933f8d65..244b53ba55 100644 --- a/src/Assets/AssetContainer.php +++ b/src/Assets/AssetContainer.php @@ -456,9 +456,6 @@ public function glideSourcePreset($preset = null) { return $this ->fluentlyGetOrSet('glideSourcePreset') - ->getter(function ($preset) { - return $preset ?? null; - }) ->args(func_get_args()); } From 6104ebec5db469ece2a0a0b6c5ec34b64ae81b15 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Mon, 30 May 2022 20:55:29 -0400 Subject: [PATCH 26/63] Ensure user can explicitly disable intelligent warming of glide presets. --- src/Assets/AssetContainer.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Assets/AssetContainer.php b/src/Assets/AssetContainer.php index 244b53ba55..c51655c01b 100644 --- a/src/Assets/AssetContainer.php +++ b/src/Assets/AssetContainer.php @@ -460,9 +460,7 @@ public function glideSourcePreset($preset = null) } /** - * The specific glide presets to be used when warming glide image cache on upload, - * otherwise we intelligently generate image cache for all configured presets, - * with the exception of the glide source preset, if one is configured. + * The specific glide presets to be used when warming glide image cache on upload. * * @param array|null $presets * @return array|null|$this @@ -472,7 +470,10 @@ public function glideWarmPresets($preset = null) return $this ->fluentlyGetOrSet('glideWarmPresets') ->getter(function ($presets) { - return $presets !== [] ? $presets : null; + return $presets === false ? [] : $presets; + }) + ->setter(function ($presets) { + return $presets === [] ? false : $presets; }) ->args(func_get_args()); } From b7f47f86d31a9bce290af457d5e1831d163b15aa Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Tue, 31 May 2022 09:18:32 -0400 Subject: [PATCH 27/63] Intelligently determine which glide presets to ignore based on container config. --- src/Assets/AssetContainer.php | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/Assets/AssetContainer.php b/src/Assets/AssetContainer.php index c51655c01b..cd0719271a 100644 --- a/src/Assets/AssetContainer.php +++ b/src/Assets/AssetContainer.php @@ -16,6 +16,7 @@ use Statamic\Facades\Asset as AssetAPI; use Statamic\Facades\Blink; use Statamic\Facades\Blueprint; +use Statamic\Facades\Config; use Statamic\Facades\File; use Statamic\Facades\Search; use Statamic\Facades\Stache; @@ -478,6 +479,33 @@ public function glideWarmPresets($preset = null) ->args(func_get_args()); } + /** + * Intelligently determine which glide presets to ignore, based on the `glide_warm_presets` configuration. + * + * @return array + */ + public function glideIgnoredPresets() + { + $presets = array_keys(Config::get('statamic.assets.image_manipulation.presets', [])); + + // If `glide_warm_presets: false`, ignore all user configured presets. + if ($this->glideWarmPresets === false) { + return $presets; + } + + // If `glide_warm_presets` is an array, ignore based on explicit container setting. + if (is_array($this->glideWarmPresets)) { + return array_diff($presets, $this->glideWarmPresets); + } + + // If `glide_source_preset` is set, ignore this preset because uploads will already be processed by it. + if ($this->glideSourcePreset) { + return [$this->glideSourcePreset]; + } + + return []; + } + public function fileData() { return [ From 70b86352f3660ea8ac2e02c3ec37c449b6b96345 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Tue, 31 May 2022 09:19:20 -0400 Subject: [PATCH 28/63] =?UTF-8?q?Ensure=20container=E2=80=99s=20configured?= =?UTF-8?q?=20glide=20settings=20are=20respected=20when=20generating=20pre?= =?UTF-8?q?sets=20for=20asset.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Imaging/PresetGenerator.php | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Imaging/PresetGenerator.php b/src/Imaging/PresetGenerator.php index 8c5a564f46..85dd14fd3a 100644 --- a/src/Imaging/PresetGenerator.php +++ b/src/Imaging/PresetGenerator.php @@ -35,12 +35,16 @@ public function __construct(ImageGenerator $generator, array $presets) */ public function generate(Asset $asset, $preset = null) { - $presets = ($preset) - ? [$preset => []] - : $this->presets; + $presets = $preset ?: array_keys($this->presets); - foreach ($presets as $name => $params) { - $this->generator->generateByAsset($asset, ['p' => $name]); - } + $ignoredPresets = $asset->container()->glideIgnoredPresets(); + + collect($presets) + ->reject(function ($preset) use ($ignoredPresets) { + return in_array($preset, $ignoredPresets); + }) + ->each(function ($preset) use ($asset) { + $this->generator->generateByAsset($asset, ['p' => $preset]); + }); } } From b41c2b8d987c24ef054d1aa0468a5c88b76e5d1f Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Tue, 31 May 2022 11:51:38 -0400 Subject: [PATCH 29/63] Ditch this, since it errors on tmp files in `UploadedFile` instances. --- src/Assets/Uploader.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Assets/Uploader.php b/src/Assets/Uploader.php index 0e8dffe789..5dabcb9b3d 100644 --- a/src/Assets/Uploader.php +++ b/src/Assets/Uploader.php @@ -152,7 +152,6 @@ private function glideProcessUploadedFile(UploadedFile $file, $params) 'source' => $file->getPath(), 'cache' => $this->glideTmpPath, 'driver' => config('statamic.assets.image_manipulation.driver'), - // 'cache_with_file_extensions' => true, // TODO: What is this doing? 'watermarks' => public_path(), ]); From 9d8daa82046a8877fb0330e9af0c6c986314bb21 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Tue, 31 May 2022 12:54:35 -0400 Subject: [PATCH 30/63] Add test coverage for other existing container settings. --- tests/Assets/AssetContainerTest.php | 36 +++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/Assets/AssetContainerTest.php b/tests/Assets/AssetContainerTest.php index fe7385b2b5..bc84deaa39 100644 --- a/tests/Assets/AssetContainerTest.php +++ b/tests/Assets/AssetContainerTest.php @@ -189,6 +189,42 @@ public function it_gets_and_sets_whether_folders_can_be_created() $this->assertFalse($container->createFolders()); } + /** @test */ + public function it_gets_and_sets_whether_renaming_is_allowed() + { + $container = new AssetContainer; + $this->assertTrue($container->allowRenaming()); + + $return = $container->allowRenaming(false); + + $this->assertEquals($container, $return); + $this->assertFalse($container->allowRenaming()); + } + + /** @test */ + public function it_gets_and_sets_whether_moving_is_allowed() + { + $container = new AssetContainer; + $this->assertTrue($container->allowMoving()); + + $return = $container->allowMoving(false); + + $this->assertEquals($container, $return); + $this->assertFalse($container->allowMoving()); + } + + /** @test */ + public function it_gets_and_sets_whether_downloading_is_allowed() + { + $container = new AssetContainer; + $this->assertTrue($container->allowDownloading()); + + $return = $container->allowDownloading(false); + + $this->assertEquals($container, $return); + $this->assertFalse($container->allowDownloading()); + } + /** @test */ public function it_saves_the_container_through_the_api() { From 145ee98b96eebec992043095940200ffc5afe173 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Tue, 31 May 2022 13:14:54 -0400 Subject: [PATCH 31/63] Add test coverage for new glide preset configs. --- tests/Assets/AssetContainerTest.php | 108 ++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/tests/Assets/AssetContainerTest.php b/tests/Assets/AssetContainerTest.php index bc84deaa39..9ded37b7b0 100644 --- a/tests/Assets/AssetContainerTest.php +++ b/tests/Assets/AssetContainerTest.php @@ -225,6 +225,114 @@ public function it_gets_and_sets_whether_downloading_is_allowed() $this->assertFalse($container->allowDownloading()); } + /** @test */ + public function it_gets_and_sets_glide_source_preset_for_upload_processing() + { + $container = new AssetContainer; + $this->assertNull($container->glideSourcePreset()); + + $return = $container->glideSourcePreset('watermarked'); + + $this->assertEquals($container, $return); + $this->assertEquals('watermarked', $container->glideSourcePreset()); + } + + /** @test */ + public function it_gets_and_sets_explicit_glide_warm_presets_config() + { + $container = new AssetContainer; + $this->assertNull($container->glideWarmPresets()); + + // Set explicit presets to warm. + $return = $container->glideWarmPresets(['small', 'medium']); + + $this->assertEquals($container, $return); + $this->assertEquals(['small', 'medium'], $container->glideWarmPresets()); + + // Set `false` to disable warming of presets. + $return = $container->glideWarmPresets(false); + + $this->assertEquals($container, $return); + $this->assertEquals([], $container->glideWarmPresets()); + + // Ensure passing `null` properly clears this config, because `null` should + // allow for Statamic to intelligently determine which presets to warm. + $return = $container->glideWarmPresets(null); + + $this->assertEquals($container, $return); + $this->assertNull($container->glideWarmPresets()); + } + + /** @test */ + public function it_doesnt_ignore_any_glide_presets_when_warming_by_default() + { + $container = new AssetContainer; + + config(['statamic.assets.image_manipulation.presets' => [ + 'small' => ['w' => '15', 'h' => '15'], + 'medium' => ['w' => '500', 'h' => '500'], + 'large' => ['w' => '1000', 'h' => '1000'], + 'max' => ['w' => '3000', 'h' => '3000', 'mark' => 'watermark.jpg'], + ]]); + + $this->assertEquals([], $container->glideIgnoredPresets()); + } + + /** @test */ + public function it_ignores_source_preset_when_warming_because_upload_will_already_have_been_processed() + { + $container = new AssetContainer; + + config(['statamic.assets.image_manipulation.presets' => [ + 'small' => ['w' => '15', 'h' => '15'], + 'medium' => ['w' => '500', 'h' => '500'], + 'large' => ['w' => '1000', 'h' => '1000'], + 'max' => ['w' => '3000', 'h' => '3000', 'mark' => 'watermark.jpg'], + ]]); + + $container->glideSourcePreset('max'); + + $this->assertEquals(['max'], $container->glideIgnoredPresets()); + } + + /** @test */ + public function it_ignores_presets_based_on_explicitly_configured_presets_setting() + { + $container = new AssetContainer; + + config(['statamic.assets.image_manipulation.presets' => [ + 'small' => ['w' => '15', 'h' => '15'], + 'medium' => ['w' => '500', 'h' => '500'], + 'large' => ['w' => '1000', 'h' => '1000'], + 'max' => ['w' => '3000', 'h' => '3000', 'mark' => 'watermark.jpg'], + ]]); + + $container + ->glideSourcePreset('max') // normally we automatically ignore the `max` preset if it's set as the source preset for uploads + ->glideWarmPresets(['medium', 'max']); // but this config should override which presets the user wants to warm + + $this->assertEquals(['small', 'large'], $container->glideIgnoredPresets()); + } + + /** @test */ + public function it_ignores_all_presets_if_explicitly_configured() + { + $container = new AssetContainer; + + config(['statamic.assets.image_manipulation.presets' => [ + 'small' => ['w' => '15', 'h' => '15'], + 'medium' => ['w' => '500', 'h' => '500'], + 'large' => ['w' => '1000', 'h' => '1000'], + 'max' => ['w' => '3000', 'h' => '3000', 'mark' => 'watermark.jpg'], + ]]); + + $container + ->glideSourcePreset('max') // normally we automatically ignore the `max` preset if it's set as the source preset for uploads + ->glideWarmPresets(false); // but this config should override to ensure all the above configured presets are ignored + + $this->assertEquals(['small', 'medium', 'large', 'max'], $container->glideIgnoredPresets()); + } + /** @test */ public function it_saves_the_container_through_the_api() { From 34e68dd00a13fe6db42422a9e58926482ddee044 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Tue, 31 May 2022 13:15:02 -0400 Subject: [PATCH 32/63] Pass tests again. --- src/Assets/AssetContainer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Assets/AssetContainer.php b/src/Assets/AssetContainer.php index cd0719271a..369cf041f9 100644 --- a/src/Assets/AssetContainer.php +++ b/src/Assets/AssetContainer.php @@ -495,7 +495,7 @@ public function glideIgnoredPresets() // If `glide_warm_presets` is an array, ignore based on explicit container setting. if (is_array($this->glideWarmPresets)) { - return array_diff($presets, $this->glideWarmPresets); + return array_values(array_diff($presets, $this->glideWarmPresets)); } // If `glide_source_preset` is set, ignore this preset because uploads will already be processed by it. From e77672fa672346c825cbffee89a8f6cc80b8b0e0 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Tue, 31 May 2022 15:56:21 -0400 Subject: [PATCH 33/63] Add basic test coverage for glide preset generation on upload. --- tests/Assets/AssetTest.php | 87 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/tests/Assets/AssetTest.php b/tests/Assets/AssetTest.php index 10d5568baf..6a3ca7af6c 100644 --- a/tests/Assets/AssetTest.php +++ b/tests/Assets/AssetTest.php @@ -1051,6 +1051,93 @@ public function it_doesnt_error_when_uploading_non_glideable_file_with_glide_con Event::assertDispatched(AssetSaved::class); } + protected function configureGlidePresets($app) + { + $app->config->set('statamic.assets.image_manipulation.presets', [ + 'small' => ['w' => '15', 'h' => '15'], + 'medium' => ['w' => '500', 'h' => '500'], + 'large' => ['w' => '1000', 'h' => '1000'], + 'max' => ['w' => '3000', 'h' => '3000'], + ]); + } + + /** + * @test + * @define-env configureGlidePresets + **/ + public function it_generates_glide_cache_for_all_presets_by_default() + { + $cacheFolder = $this->uploadImageAndAssertGlideCache(); + + // Should be 3 cp presets, and 4 of our custom presets + $this->assertCount(7, File::getFiles($cacheFolder)); + } + + /** + * @test + * @define-env configureGlidePresets + **/ + public function it_generates_glide_cache_for_all_presets_except_configured_source_preset_on_upload() + { + $this->container->glideSourcePreset('max'); + + $cacheFolder = $this->uploadImageAndAssertGlideCache(); + + // Should be 3 cp presets, and 3 of our custom presets, discluding the configured source/upload preset + $this->assertCount(6, File::getFiles($cacheFolder)); + } + + /** + * @test + * @define-env configureGlidePresets + **/ + public function it_generates_glide_cache_for_explicitly_set_presets() + { + $this->container + ->glideSourcePreset('max') // normally we automatically ignore the `max` preset if it's set as the source preset for uploads + ->glideWarmPresets(['max']); // but this config should override which presets the user wants to warm + + $cacheFolder = $this->uploadImageAndAssertGlideCache(); + + // Should be 3 cp presets, and 1 of our custom presets, since we explicitly configured only one this time + $this->assertCount(4, File::getFiles($cacheFolder)); + } + + /** + * @test + * @define-env configureGlidePresets + **/ + public function it_doesnt_generates_glide_cache_for_disabled_user_presets() + { + $this->container->glideSourcePreset('max')->glideWarmPresets(false); + + $cacheFolder = $this->uploadImageAndAssertGlideCache(); + + // Should be 3 cp presets only, discluding all user presets + $this->assertCount(3, File::getFiles($cacheFolder)); + } + + private function uploadImageAndAssertGlideCache() + { + $this->artisan('statamic:glide:clear'); + + $cacheFolder = storage_path('statamic/glide/containers/test_container/path/to/asset.jpg'); + + $this->assertDirectoryNotExists($cacheFolder); + + Facades\AssetContainer::shouldReceive('findByHandle')->with('test_container')->andReturn($this->container); + + $asset = (new Asset) + ->container($this->container) + ->path('path/to/asset.jpg') + ->syncOriginal() + ->upload(UploadedFile::fake()->image('asset.jpg', 20, 30)); + + $this->assertDirectoryExists($cacheFolder); + + return $cacheFolder; + } + /** @test */ public function it_appends_timestamp_to_uploaded_files_filename_if_it_already_exists() { From c1d2843f700599adb8e15dd8a0fd53bf6fb4fee3 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Tue, 31 May 2022 16:40:46 -0400 Subject: [PATCH 34/63] Our `PresetGenerator` already skips ignored presets in console command, but be more transparent in command output. --- src/Console/Commands/AssetsGeneratePresets.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Console/Commands/AssetsGeneratePresets.php b/src/Console/Commands/AssetsGeneratePresets.php index ee52df7231..d6e24e89d2 100644 --- a/src/Console/Commands/AssetsGeneratePresets.php +++ b/src/Console/Commands/AssetsGeneratePresets.php @@ -6,6 +6,7 @@ use Illuminate\Contracts\Bus\Dispatcher; use Statamic\Console\RunsInPlease; use Statamic\Facades\Asset; +use Statamic\Facades\AssetContainer; use Statamic\Facades\Image; use Statamic\Jobs\GeneratePresetImageManipulation; @@ -96,6 +97,8 @@ private function generateCpThumbnails() */ private function generatePresets($presets) { + $ignoredPresetsByContainer = AssetContainer::all()->keyBy->handle()->map->glideIgnoredPresets(); + foreach ($presets as $preset => $params) { $bar = $this->output->createProgressBar($this->imageAssets->count()); @@ -103,7 +106,11 @@ private function generatePresets($presets) $bar->setFormat("[%current%/%max%] $verb $preset... %filename%"); foreach ($this->imageAssets as $asset) { - $bar->setMessage($asset->basename(), 'filename'); + $appendStatus = in_array($preset, $ignoredPresetsByContainer->get($asset->containerHandle())) + ? ' (skipping)' + : ''; + + $bar->setMessage($asset->basename().$appendStatus, 'filename'); $dispatchMethod = $this->shouldQueue ? 'dispatch' From 2f581abc89128c06392d2bfa9a8448daa320be18 Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Tue, 31 May 2022 17:28:54 -0400 Subject: [PATCH 35/63] Make new instruction messages translatable. --- resources/lang/en/messages.php | 3 +++ .../Controllers/CP/Assets/AssetContainersController.php | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/resources/lang/en/messages.php b/resources/lang/en/messages.php index 5c4b807352..3b433f9066 100644 --- a/resources/lang/en/messages.php +++ b/resources/lang/en/messages.php @@ -16,6 +16,9 @@ 'asset_container_quick_download_instructions' => 'When enabled will add a quick download button in the Asset Manager.', 'asset_container_rename_instructions' => 'When enabled will allow users to rename the files in this container.', 'asset_container_title_instructions' => 'Usually a plural noun, like Images or Documents', + 'asset_container_glide_source_preset_instructions' => 'When enabled, source images will be permanently processed with this image manipulation preset on upload.', + 'asset_container_glide_warm_intelligent_instructions' => 'When enabled, intelligently warm glide caches on upload.', + 'asset_container_glide_warm_presets_instructions' => 'Specify which glide presets to warm on upload.', 'asset_folders_directory_instructions' => 'We recommend avoiding spaces and special characters to keep URLs clean.', 'blueprints_intro' => 'Blueprints define and organize fields to create the content models for collections, forms, and other data types.', 'blueprints_hidden_instructions' => 'Hides the blueprint from the create buttons in the CP', diff --git a/src/Http/Controllers/CP/Assets/AssetContainersController.php b/src/Http/Controllers/CP/Assets/AssetContainersController.php index 87e37bf9c0..2f07208cea 100644 --- a/src/Http/Controllers/CP/Assets/AssetContainersController.php +++ b/src/Http/Controllers/CP/Assets/AssetContainersController.php @@ -278,20 +278,20 @@ protected function formBlueprint($container = null) 'type' => 'select', 'display' => __('Process Source Images'), 'label_html' => true, - 'instructions' => __('When enabled, source images will be permanently processed with this image manipulation preset on upload.'), + 'instructions' => __('statamic::messages.asset_container_glide_source_preset_instructions'), 'options' => $this->expandedGlidePresetOptions(), 'clearable' => true, ], 'glide_warm_intelligent' => [ 'type' => 'toggle', 'display' => __('Intelligently Warm Glide Caches'), - 'instructions' => __('When enabled, intelligently warm glide caches on upload.'), + 'instructions' => __('statamic::messages.asset_container_glide_warm_intelligent_instructions'), 'default' => true, ], 'glide_warm_presets' => [ 'type' => 'select', 'display' => __('Warm Specific Glide Caches'), - 'instructions' => __('Specify which glide presets to warm on upload.'), + 'instructions' => __('statamic::messages.asset_container_glide_warm_presets_instructions'), 'multiple' => true, 'options' => array_keys(config('statamic.assets.image_manipulation.presets')), 'if' => [ From 3858974acb63965501aa0e7530ab320f666fe59a Mon Sep 17 00:00:00 2001 From: Jesse Leite Date: Tue, 31 May 2022 21:21:32 -0400 Subject: [PATCH 36/63] Show params in multi-select as well. --- resources/js/components/fieldtypes/SelectFieldtype.vue | 3 ++- resources/sass/vendors/vue-select.scss | 5 ++++- .../Controllers/CP/Assets/AssetContainersController.php | 9 +++++---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/resources/js/components/fieldtypes/SelectFieldtype.vue b/resources/js/components/fieldtypes/SelectFieldtype.vue index 6b08e291cb..87d6d2eb35 100644 --- a/resources/js/components/fieldtypes/SelectFieldtype.vue +++ b/resources/js/components/fieldtypes/SelectFieldtype.vue @@ -43,7 +43,8 @@