From 00aa2469a72843592f58bc858077a9a2ca8fb10a Mon Sep 17 00:00:00 2001 From: philipp lang Date: Tue, 14 Sep 2021 02:13:29 +0200 Subject: [PATCH] Add lazyloading and PNG support --- Plugin.php | 3 ++- classes/CacheManager.php | 4 ++-- classes/TagGenerator.php | 10 +++++++--- compressors/Factory.php | 1 + compressors/PngCompressor.php | 25 +++++++++++++++++++++++++ tests/ImageTagTest.php | 28 ++++++++++++++++++++++++++++ tests/ResizerTest.php | 18 +++++++++++++++--- 7 files changed, 80 insertions(+), 9 deletions(-) create mode 100644 compressors/PngCompressor.php diff --git a/Plugin.php b/Plugin.php index 5f7046b..5631192 100644 --- a/Plugin.php +++ b/Plugin.php @@ -97,10 +97,11 @@ class Plugin extends PluginBase public function registerMarkupTags() { return [ 'filters' => [ - 'resize' => fn ($media, $size = 'original', $sizes = null) => app(CacheManager::class)->get( + 'resize' => fn ($media, $size = 'original', $sizes = null, $options = []) => app(CacheManager::class)->get( new MediaPath($media), $size, $sizes, + $options, ) ] ]; diff --git a/classes/CacheManager.php b/classes/CacheManager.php index 9157689..bac4da3 100644 --- a/classes/CacheManager.php +++ b/classes/CacheManager.php @@ -16,11 +16,11 @@ class CacheManager $this->tagGenerator = $tagGenerator; } - public function get(MediaPath $path, string $size, ?string $sizes): string + public function get(MediaPath $path, string $size, ?string $sizes, array $options = []): string { return Cache::tags($this->pathTag($path, $size))->rememberForever( $this->cacheKey($path, $size), - fn () => $this->tagGenerator->generate($path, $size, $sizes) + fn () => $this->tagGenerator->generate($path, $size, $sizes, $options) ); } diff --git a/classes/TagGenerator.php b/classes/TagGenerator.php index 10ea4c3..8f40312 100644 --- a/classes/TagGenerator.php +++ b/classes/TagGenerator.php @@ -17,6 +17,9 @@ class TagGenerator { public array $breakpoints; public $path; private CompressorFactory $compressorFactory; + private $defaultOptions = [ + 'lazy' => false, + ]; public function __construct(CompressorFactory $compressorFactory) { @@ -62,8 +65,9 @@ class TagGenerator { : null; } - public function generate(MediaPath $path, ?string $ratio = 'original', $sizes = null): string + public function generate(MediaPath $path, ?string $ratio = 'original', $sizes = null, array $options = []): string { + $options = array_merge($this->defaultOptions, $options); $this->path = $path; try { @@ -90,8 +94,8 @@ class TagGenerator { 'width' => $files->last()->get('width'), 'height' => $files->last()->get('height'), 'sizes' => $sizes->implode(', '), - 'srcset' => $srcset->implode(', '), - 'src' => $files->last()->get('url'), + $options['lazy'] ? 'data-srcset' : 'srcset' => $srcset->implode(', '), + $options['lazy'] ? 'data-src' : 'src' => $files->last()->get('url'), ])); } diff --git a/compressors/Factory.php b/compressors/Factory.php index 115625f..34c224e 100644 --- a/compressors/Factory.php +++ b/compressors/Factory.php @@ -11,6 +11,7 @@ class Factory public array $types = [ 'image/jpeg' => JpgCompressor::class, + 'image/png' => PngCompressor::class, ]; public function fromMedia(string $mediaPath): Compressor diff --git a/compressors/PngCompressor.php b/compressors/PngCompressor.php new file mode 100644 index 0000000..d6cb0b6 --- /dev/null +++ b/compressors/PngCompressor.php @@ -0,0 +1,25 @@ + '.escapeshellarg($output)); + system("mv ".escapeshellarg($output)." ".escapeshellarg($path)); + + return [ + $path => [$path], + ]; + } + + public function shouldGenerateVersions(): bool + { + return true; + } + +} diff --git a/tests/ImageTagTest.php b/tests/ImageTagTest.php index 9ffb7a8..b545d42 100644 --- a/tests/ImageTagTest.php +++ b/tests/ImageTagTest.php @@ -38,6 +38,34 @@ class ImageTagTest extends TestCase ); } + public function testItGeneratesLazyLoadingTags() + { + Setting::set('folders', ['pages']); + Setting::set('sizes', []); + Setting::set('breakpoints', [100]); + $this->media->put('/pages/test.jpg', UploadedFile::fake()->image('test.jpg', 500, 500)->get()); + UploadedFile::fake()->image('test.jpg', 100, 100)->storeAs('uploads/public/c/pages', 'test-100x100.jpg', 'local'); + + $this->assertEquals( + 'width="100" height="100" sizes="(max-width: 100px) 100px" data-srcset="/storage/uploads/public/c/pages/test-100x100.jpg 100w" data-src="/storage/uploads/public/c/pages/test-100x100.jpg"', + app(CacheManager::class)->get(new MediaPath('pages/test.jpg'), 'original', null, ['lazy' => true]), + ); + } + + public function testItGeneratesPngImages() + { + Setting::set('folders', ['pages']); + Setting::set('sizes', []); + Setting::set('breakpoints', [100,200]); + $this->media->put('/pages/test.png', UploadedFile::fake()->image('test.png', 500, 500)->get()); + UploadedFile::fake()->image('test.png', 100, 100)->storeAs('uploads/public/c/pages', 'test-100x100.png', 'local'); + + $this->assertEquals( + 'width="100" height="100" sizes="(max-width: 100px) 100px" srcset="/storage/uploads/public/c/pages/test-100x100.png 100w" src="/storage/uploads/public/c/pages/test-100x100.png"', + app(CacheManager::class)->get(new MediaPath('pages/test.png'), 'original', null), + ); + } + public function testItSkipsImagesWithWrongAspectRatio() { Setting::set('folders', ['pages']); diff --git a/tests/ResizerTest.php b/tests/ResizerTest.php index 327fa2c..bc84eb2 100644 --- a/tests/ResizerTest.php +++ b/tests/ResizerTest.php @@ -171,18 +171,30 @@ class ResizerTest extends TestCase $this->assertHasFile('pages/neu/test-100x80.jpg'); } - public function testDontGenerateSvgImage(): void + public function testDontGenerateSvgImageVesions(): void { Setting::set('folders', [['folder' => '/pages']]); Setting::set('sizes', []); Setting::set('breakpoints', ['100']); - $file = UploadedFile::fake()->image('test.jpg', 500, 400); $media = MediaLibrary::instance(); $media->put('/pages/test.svg', file_get_contents(__DIR__.'/stub/close.svg')); Event::fire('media.file.upload', [null, '/pages/test.svg', null]); - $this->assertFileCount(0, 'pages/neu'); + $this->assertFileCount(1, 'pages'); + } + + public function testGeneratePngImage(): void + { + Setting::set('folders', [['folder' => '/pages']]); + Setting::set('sizes', []); + Setting::set('breakpoints', ['100']); + + $media = MediaLibrary::instance(); + $media->put('/pages/test.png', UploadedFile::fake()->image('test.png', 500, 500)->get()); + Event::fire('media.file.upload', [null, '/pages/test.png', null]); + + $this->assertHasFile('pages/test-100x100.png'); } }