Compare commits

..

3 Commits

Author SHA1 Message Date
philipp lang 1f87dd9f5e Log wrong requests
continuous-integration/drone/push Build is passing Details
2024-10-08 14:02:22 +02:00
philipp lang bebeb8a817 update guzzle
continuous-integration/drone/push Build is passing Details
2023-02-12 00:26:17 +01:00
philipp lang ea7b2e57ec Add winter config
continuous-integration/drone/push Build is passing Details
2021-12-21 01:02:15 +01:00
27 changed files with 1125 additions and 1621 deletions

1
.ackrc
View File

@ -1 +0,0 @@
--ignore-dir=/vendor

View File

@ -2,25 +2,23 @@
namespace Aweos\Resizer;
use Log;
use Aweos\Resizer\Classes\CacheManager;
use Aweos\Resizer\Classes\FileObserver;
use Aweos\Resizer\Classes\ImageResizer;
use Aweos\Resizer\Console\ResizeCacheClear;
use Aweos\Resizer\Classes\ResizeJob;
use Aweos\Resizer\Console\ResizeMake;
use Aweos\Resizer\Console\ResizePurge;
use Aweos\Resizer\Jobs\DeleteJob;
use Aweos\Resizer\Jobs\MoveJob;
use Aweos\Resizer\Jobs\ResizeJob;
use Aweos\Resizer\Lib\StorageMediaPath;
use Aweos\Resizer\Lib\MediaPath;
use Aweos\Resizer\Models\Setting;
use Event;
use MediaLibrary;
use Queue;
use System\Classes\PluginBase;
use System\Models\File;
use ValidationException;
/**
* resizer Plugin Information File.
* resizer Plugin Information File
*/
class Plugin extends PluginBase
{
@ -35,7 +33,7 @@ class Plugin extends PluginBase
'name' => 'aweos.resizer',
'description' => 'No description provided yet...',
'author' => 'aweos',
'icon' => 'icon-leaf',
'icon' => 'icon-leaf'
];
}
@ -48,7 +46,6 @@ class Plugin extends PluginBase
{
$this->registerConsoleCommand('resizer.resizemake', ResizeMake::class);
$this->registerConsoleCommand('resizer.resizepurge', ResizePurge::class);
$this->registerConsoleCommand('resizer.resize-cache-clear', ResizeCacheClear::class);
}
/**
@ -68,51 +65,23 @@ class Plugin extends PluginBase
app()->bind('resize', fn () => app(CacheManager::class));
Event::listen('media.folder.create', function ($widget, string $folder) {
$folder = '/' . trim($folder, '/');
$pathinfo = pathinfo($folder);
if ('/' === $pathinfo['dirname']) {
$sluggedFolder = '/' . StorageMediaPath::sluggifyString(trim($folder, '/'));
if ($sluggedFolder !== $folder) {
if (MediaLibrary::instance()->folderExists($sluggedFolder)) {
MediaLibrary::instance()->deleteFolder($folder);
throw new ValidationException(['error' => 'Ordner existiert bereits.']);
}
MediaLibrary::instance()->moveFolder($folder, $sluggedFolder);
}
} else {
$sluggedFolder = $pathinfo['dirname'] . '/' . StorageMediaPath::sluggifyString($pathinfo['filename']);
if ($sluggedFolder !== $folder) {
if (MediaLibrary::instance()->folderExists($sluggedFolder)) {
MediaLibrary::instance()->deleteFolder($folder);
throw new ValidationException(['error' => 'Ordner existiert bereits.']);
}
MediaLibrary::instance()->moveFolder($folder, $sluggedFolder);
}
}
});
Event::listen('media.file.upload', function ($widget, $filePath, $uploadedFile) {
$sluggedPath = (new StorageMediaPath($filePath))->sluggifyPath();
if ($filePath !== $sluggedPath) {
MediaLibrary::instance()->moveFile($filePath, $sluggedPath);
}
if ((new StorageMediaPath($sluggedPath))->shouldProcess()) {
Queue::push(ResizeJob::class, [$sluggedPath], Setting::get('queue'));
if ((new MediaPath($filePath))->shouldProcess()) {
Queue::push(ResizeJob::class, [$filePath], Setting::get('queue'));
}
});
Event::listen('media.file.delete', function ($widget, $filePath) {
Queue::push(DeleteJob::class, [$filePath], Setting::get('queue'));
app(FileObserver::class)->delete(new MediaPath($filePath));
app(CacheManager::class)->delete(new MediaPath($filePath));
});
Event::listen('media.file.move', function ($widget, $old, $new) {
if ((new StorageMediaPath($new))->shouldProcess() || (new StorageMediaPath($old))->shouldProcess()) {
Queue::push(MoveJob::class, [$old, $new . '/' . pathinfo($old, PATHINFO_FILENAME)], Setting::get('queue'));
}
app(FileObserver::class)->rename(new MediaPath($old), new MediaPath($new));
app(CacheManager::class)->delete(new MediaPath($old));
});
Event::listen('media.file.rename', function ($widget, $old, $new) {
if ((new StorageMediaPath($new))->shouldProcess() || (new StorageMediaPath($old))->shouldProcess()) {
Queue::push(MoveJob::class, [$old, $new], Setting::get('queue'));
}
app(FileObserver::class)->rename(new MediaPath($old), new MediaPath($new));
app(CacheManager::class)->delete(new MediaPath($old));
});
}
@ -127,8 +96,8 @@ class Plugin extends PluginBase
'class' => '\Aweos\Resizer\Models\Setting',
'order' => 500,
'keywords' => 'setting',
'permissions' => ['aweos.resizer.*'],
],
'permissions' => ['aweos.resizer.*']
]
];
}
@ -136,13 +105,18 @@ class Plugin extends PluginBase
{
return [
'filters' => [
'resize' => fn ($media, $size = 'original', $sizes = null, $options = []) => app(CacheManager::class)->get(
new StorageMediaPath($media),
'resize' => function ($media, $size = 'original', $sizes = null, $options = []) {
if (is_null($media)) {
Log::warning('Media not found in path ' . url()->current());
}
return app(CacheManager::class)->get(
new MediaPath($media),
$size,
$sizes,
$options,
),
],
);
}
]
];
}
}

View File

@ -3,7 +3,6 @@
namespace Aweos\Resizer\Classes;
use Aweos\Resizer\Lib\MediaPath;
use Aweos\Resizer\Lib\StorageMediaPath;
use Cache;
class CacheManager
@ -19,7 +18,7 @@ class CacheManager
public function get(MediaPath $path, string $size, ?string $sizes, array $options = []): string
{
return Cache::tags($this->pathTag($path))->rememberForever(
return Cache::tags($this->pathTag($path, $size))->rememberForever(
$this->cacheKey($path, $size),
fn () => $this->tagGenerator->generate($path, $size, $sizes, $options)
);
@ -27,7 +26,7 @@ class CacheManager
public function delete(MediaPath $path): void
{
Cache::tags($this->pathTag($path))->flush();
Cache::tags([$this->singlePathTag($path)])->flush();
}
public function flush(): void
@ -40,7 +39,7 @@ class CacheManager
return "resizer.{$size}.{$path->normal()}";
}
private function pathTag(MediaPath $path): array
private function pathTag(MediaPath $path, string $size): array
{
return [$this->tagAll, $this->singlePathTag($path)];
}
@ -52,8 +51,9 @@ class CacheManager
public function biggestVersion(string $path, string $size): string
{
$path = new StorageMediaPath($path);
$path = new MediaPath($path);
return $this->tagGenerator->singleFile($path, $size);
}
}

View File

@ -2,20 +2,21 @@
namespace Aweos\Resizer\Classes;
use Aweos\Resizer\Compressors\Compressor;
use Aweos\Resizer\Exceptions\ResizerException;
use Aweos\Resizer\Lib\MediaPath;
use Aweos\Resizer\Models\Setting;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Support\Collection;
use October\Rain\Resize\Resizer;
use Storage;
class ImageResizer
{
private FilesystemAdapter $disk;
private string $uploadDir;
private MediaPath $file;
private bool $update;
private Compressor $compressor;
public function __construct(FilesystemAdapter $disk, string $uploadDir)
{
@ -26,23 +27,22 @@ class ImageResizer
public function generate(MediaPath $file, bool $update): void
{
$this->file = $file;
$this->compressor = $this->file->compressor();
$this->update = $update;
if (!$file->exists()) {
throw new ResizerException('File versions cannot be generated. Root file "'.$file->root().'" doesnt exist.');
}
if ($this->compressor->shouldGenerateVersions()) {
$this->compressor->start();
if ($this->file->compressor()->shouldGenerateVersions()) {
$this->file->compressor()->start();
$this->generateVersions();
$this->compressor->end();
$this->file->compressor()->end();
}
}
private function dimensions(): Collection
{
[$width, $height] = $this->compressor->originalSize();
[$width, $height] = $this->file->compressor()->originalSize();
return collect(compact('width', 'height'));
}
@ -60,21 +60,20 @@ class ImageResizer
{
$return = collect([]);
$ratios = collect();
$dimensions = $this->dimensions();
$ratios->push($dimensions);
$ratios->push($this->dimensions());
$ratios = $ratios->merge($this->sizes());
foreach (collect(Setting::get('breakpoints'))->push($dimensions->get('width'))->unique() as $size) {
foreach (collect(Setting::get('breakpoints'))->push($this->dimensions()->get('width'))->unique() as $size) {
foreach ($ratios as $ratio) {
$width = $size;
$height = $size * $ratio->get('height') / $ratio->get('width');
if ($height > $dimensions->get('height')) {
$width = $width * $dimensions->get('height') / $height;
$height = $dimensions->get('height');
if ($height > $this->dimensions()->get('height')) {
$width = $width * $this->dimensions()->get('height') / $height;
$height = $this->dimensions()->get('height');
}
if (ceil($width) > $dimensions->get('width') || ceil($height) > $dimensions->get('height')) {
if (ceil($width) > $this->dimensions()->get('width') || ceil($height) > $this->dimensions()->get('height')) {
continue;
}
@ -91,14 +90,15 @@ class ImageResizer
private function generateVersions(): void
{
foreach ($this->possibleSizes() as $size) {
$this->compressor->resize($size, $this->update, function ($media, $file) {
$this->file->compressor()->resize($size, $this->update, function($media, $file) {
if (!file_exists($file)) {
throw new ResizerException('File versions cannot be generated. Version file "'.$file.'" of "'.$this->file->root().'" doesnt exist.');
}
if (file_exists($file) || !$this->update) {
$this->compressor->make($file);
$this->file->compressor()->make($file);
}
});
}
}
}

View File

@ -1,11 +1,8 @@
<?php
namespace Aweos\Resizer\Jobs;
namespace Aweos\Resizer\Classes;
use Aweos\Resizer\Classes\CacheManager;
use Aweos\Resizer\Classes\ImageResizer;
use Aweos\Resizer\Lib\MediaPath;
use Aweos\Resizer\Lib\TempMediaPath;
use Log;
use Throwable;
@ -15,11 +12,7 @@ class ResizeJob
public function fire($job, $params)
{
list($file) = $params;
$media = new TempMediaPath($file);
app(ImageResizer::class)->generate($media, $params['update'] ?? false);
app(CacheManager::class)->delete($media);
unset ($media);
app(ImageResizer::class)->generate(new MediaPath($file), $params['update'] ?? false);
$job->delete();
}

View File

@ -2,92 +2,57 @@
namespace Aweos\Resizer\Classes;
use Aweos\Resizer\Compressors\Compressor;
use Aweos\Resizer\Compressors\CompressorNotFoundException;
use Aweos\Resizer\Compressors\Factory as CompressorFactory;
use Aweos\Resizer\Exceptions\ResizerException;
use Aweos\Resizer\Lib\MediaPath;
use Aweos\Resizer\Models\Setting;
use Cache;
use Exception;
use Illuminate\Support\Collection;
use Storage;
class TagGenerator
{
private Compressor $compressor;
public MediaPath $path;
private array $defaultOptions = [
class TagGenerator {
public array $breakpoints;
public $path;
private CompressorFactory $compressorFactory;
private $defaultOptions = [
'lazy' => false,
];
public function generate(MediaPath $path, ?string $ratio = 'original', $sizes = null, array $options = []): string
public function __construct(CompressorFactory $compressorFactory)
{
$options = array_merge($this->defaultOptions, $options);
$this->path = $path;
$this->compressor = $this->path->compressor();
$this->compressor->start();
try {
if (!$this->compressor->shouldGenerateVersions()) {
return $this->fallback();
}
} catch (CompressorNotFoundException $e) {
return $this->fallback();
$this->compressorFactory = $compressorFactory;
$this->breakpoints = Setting::get('breakpoints');
ksort($this->breakpoints);
}
$files = $this->possibleFiles($ratio);
if (null === $files) {
return $this->fallback();
}
$sizes = $this->parseSizes($files, $sizes);
$srcset = $files->map(function ($file) {
return "{$file->get('url')} {$file->get('width')}w";
});
$html = $this->htmlAttributes(collect([
'width' => $files->last()->get('width'),
'height' => $files->last()->get('height'),
'sizes' => $sizes->implode(', '),
$options['lazy'] ? 'data-srcset' : 'srcset' => $srcset->implode(', '),
$options['lazy'] ? 'data-src' : 'src' => $files->last()->get('url'),
'class' => data_get($options, 'class'),
])->filter(fn ($value) => (bool) $value));
$this->compressor->end();
return $html;
}
public function singleFile(MediaPath $path, ?string $ratio = 'original'): string
public function size(string $name): array
{
$this->path = $path;
$this->compressor = $this->path->compressor();
$this->compressor->start();
$versions = $this->possibleFiles($ratio);
throw_unless($versions && count($versions), Exception::class, "No files for {$path->root()} found");
$possibleFiles = url($this->possibleFiles($ratio)->last()->get('url'));
$this->compressor->end();
$size = collect(Setting::get('sizes'))->filter(fn ($size) => $size['name'] === $name)
->first();
return $possibleFiles;
if (is_null($size)) {
throw new ResizerException("Size with name {$name} not found.");
}
private function possibleFiles(string $ratio): ?Collection
return explode('x', $size['aspect_ratio']);
}
public function possibleFiles(string $ratio): ?Collection
{
$filename = $this->path->filename();
$basePath = $this->path->versionsDirPath();
[$originalWidth, $originalHeight] = $this->compressor->originalSize();
$aspectRatio = 'original' === $ratio
[$originalWidth, $originalHeight] = $this->path->compressor()->originalSize();
$aspectRatio = $ratio === 'original'
? $originalWidth / $originalHeight
: $this->size($ratio)[0] / $this->size($ratio)[1];
$result = collect([]);
foreach ($this->path->versions() as $version) {
if ('1' === $version->get('height')) {
continue;
}
if ($version->get('width') / ($version->get('height') + 1) > $aspectRatio || $version->get('width') / ($version->get('height') - 1) < $aspectRatio) {
if ($version->get('width') / ($version->get('height')+1) > $aspectRatio || $version->get('width') / ($version->get('height')-1) < $aspectRatio) {
continue;
}
@ -104,9 +69,53 @@ class TagGenerator
: null;
}
private function htmlAttributes($attr): string
public function generate(MediaPath $path, ?string $ratio = 'original', $sizes = null, array $options = []): string
{
return $attr->map(function ($value, $key) {
$options = array_merge($this->defaultOptions, $options);
$this->path = $path;
try {
if (!$path->compressor()->shouldGenerateVersions()) {
return $this->fallback();
}
} catch (CompressorNotFoundException $e) {
return $this->fallback();
}
$files = $this->possibleFiles($ratio);
if ($files === null) {
return $this->fallback();
}
$sizes = $this->parseSizes($files, $sizes);
$srcset = $files->map(function($file) {
return "{$file->get('url')} {$file->get('width')}w";
});
return $this->htmlAttributes(collect([
'width' => $files->last()->get('width'),
'height' => $files->last()->get('height'),
'sizes' => $sizes->implode(', '),
$options['lazy'] ? 'data-srcset' : 'srcset' => $srcset->implode(', '),
$options['lazy'] ? 'data-src' : 'src' => $files->last()->get('url'),
]));
}
public function singleFile(MediaPath $path, ?string $ratio = 'original'): string
{
$this->path = $path;
$versions = $this->possibleFiles($ratio);
throw_unless($versions && count($versions), Exception::class, "No files for {$path->root()} found");
return url($this->possibleFiles($ratio)->last()->get('url'));
}
private function htmlAttributes($attr) {
return $attr->map(function($value, $key) {
return "{$key}=\"{$value}\"";
})->implode(' ');
}
@ -114,18 +123,18 @@ class TagGenerator
private function parseSizes(Collection $files, ?string $sizes = null): Collection
{
if (is_null($sizes)) {
return $files->map(function ($file) {
return $files->map(function($file) {
return "(max-width: {$file->get('width')}px) {$file->get('width')}px";
});
}
$sizes = collect(explode('|', $sizes));
$minSize = $sizes->shift();
$sizes = $sizes->sortByDesc(function ($size) {
$sizes = $sizes->sortByDesc(function($size) {
return explode(':', $size)[0];
});
return $sizes->map(function ($size) {
return $sizes->map(function($size) {
$components = explode(':', $size);
return "(min-width: {$components[0]}px) {$components[1]}";
@ -136,16 +145,4 @@ class TagGenerator
{
return 'src="'.$this->path->publicUrl().'"';
}
private function size(string $name): array
{
$size = collect(Setting::get('sizes'))->filter(fn ($size) => $size['name'] === $name)
->first();
if (is_null($size)) {
throw new ResizerException("Size with name {$name} not found.");
}
return explode('x', $size['aspect_ratio']);
}
}

View File

@ -2,7 +2,7 @@
"name": "aweos/oc-resizer-plugin",
"type": "october-plugin",
"require": {
"guzzlehttp/guzzle": "^6.3",
"guzzlehttp/guzzle": "^7.5",
"intervention/image": "^2.6"
},
"require-dev": {
@ -18,11 +18,7 @@
"autoload": {
"psr-4": {
"Aweos\\Resizer\\Compilers\\": "./compilers",
"Aweos\\Resizer\\Exceptions\\": "./exceptions",
"Aweos\\Resizer\\Compressors\\": "./compressors",
"Aweos\\Resizer\\Lib\\": "./lib",
"Aweos\\Resizer\\Jobs\\": "./jobs",
"Aweos\\Resizer\\Classes\\": "./classes"
"Aweos\\Resizer\\Exceptions\\": "./exceptions"
}
}
}

1907
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,6 @@
namespace Aweos\Resizer\Compressors;
use Aweos\Resizer\Lib\MediaPath;
use Illuminate\Support\Collection;
use Storage;
abstract class Compressor
@ -12,12 +11,10 @@ abstract class Compressor
protected MediaPath $media;
abstract function make(string $path): array;
abstract protected function getExtension(): string;
abstract protected function getExtension();
abstract public function getExtensionRegex(): string;
abstract public function shouldGenerateVersions(): bool;
abstract public function start(): void;
abstract public function end(): void;
abstract public function resize(Collection $size, bool $update, callable $callback): void;
public function __construct(MediaPath $media)
{

View File

@ -2,8 +2,6 @@
namespace Aweos\Resizer\Compressors;
use Illuminate\Support\Collection;
class DefaultCompressor extends Compressor {
public function getExtension(): string
@ -26,18 +24,4 @@ class DefaultCompressor extends Compressor {
return false;
}
public function start(): void
{
//
}
public function end(): void
{
//
}
public function resize(Collection $size, bool $update, callable $callback): void {
//
}
}

View File

@ -2,12 +2,13 @@
namespace Aweos\Resizer\Compressors;
use Aweos\Resizer\Exceptions\ResizerException;
use Illuminate\Support\Collection;
use Intervention\Image\ImageManager;
use Storage;
class JpgCompressor extends Compressor
{
class JpgCompressor extends Compressor {
public function getExtensionRegex(): string
{
return 'jpg';
@ -23,7 +24,7 @@ class JpgCompressor extends Compressor
$output = $this->tmpPath();
system('imagemin '.escapeshellarg($path).' --plugin=jpegtran --plugin=mozjpeg --plugin.mozjpeg.quality=70 > '.escapeshellarg($output));
system('mv '.escapeshellarg($output).' '.escapeshellarg($path));
system("mv ".escapeshellarg($output)." ".escapeshellarg($path));
return [
$path => [$path],
@ -54,8 +55,6 @@ class JpgCompressor extends Compressor
$versionFilename = $this->media->versionsDirPath().'/'.$this->versionFilename($destWidth, $destHeight);
if ($update && Storage::exists($versionFilename)) {
Storage::delete($temp);
return;
}
@ -65,9 +64,12 @@ class JpgCompressor extends Compressor
public function start(): void
{
//
}
public function end(): void
{
//
}
}

View File

@ -9,7 +9,6 @@ use Storage;
class PdfCompressor extends Compressor
{
private string $originalImage;
public function getExtensionRegex(): string
{
@ -27,7 +26,7 @@ class PdfCompressor extends Compressor
$mimetype = mime_content_type($path);
system('imagemin '.escapeshellarg($path).' --plugin=jpegtran --plugin=mozjpeg --plugin.mozjpeg.quality=70 > '.escapeshellarg($output));
system('mv '.escapeshellarg($output).' '.escapeshellarg($path));
system("mv ".escapeshellarg($output)." ".escapeshellarg($path));
return [
$path => [$path],
@ -42,7 +41,6 @@ class PdfCompressor extends Compressor
public function start(): void
{
@unlink($this->imagePath());
$this->originalImage = $this->extractImage();
}
public function end(): void
@ -67,7 +65,10 @@ class PdfCompressor extends Compressor
public function originalSize(): array
{
return getimagesize($this->originalImage);
$filename = $this->extractImage($this->media->root());
$size = getimagesize($filename);
return $size;
}
public function shouldGenerateVersions(): bool
@ -77,9 +78,10 @@ class PdfCompressor extends Compressor
public function resize(Collection $size, bool $update, callable $callback): void
{
$tempBefore = pathinfo($this->originalImage, PATHINFO_FILENAME).'compiled.'.pathinfo($this->originalImage, PATHINFO_EXTENSION);
$temp = $this->extractImage();
$tempBefore = PATHINFO($temp, PATHINFO_FILENAME).'compiled.'.pathinfo($temp, PATHINFO_EXTENSION);
$r = app(ImageManager::class)->make($this->originalImage)
$r = app(ImageManager::class)->make($temp)
->fit($size->get('width'), $size->get('height'))
->save($tempBefore);
@ -90,4 +92,5 @@ class PdfCompressor extends Compressor
unlink($tempBefore);
call_user_func($callback, $this->media, Storage::path($versionFilename));
}
}

View File

@ -6,8 +6,8 @@ use Illuminate\Support\Collection;
use Intervention\Image\ImageManager;
use Storage;
class PngCompressor extends Compressor
{
class PngCompressor extends Compressor {
protected function getExtension(): string
{
return 'png';
@ -24,7 +24,7 @@ class PngCompressor extends Compressor
$mimetype = mime_content_type($path);
system('imagemin '.escapeshellarg($path).' --plugin=pngquant > '.escapeshellarg($output));
system('mv '.escapeshellarg($output).' '.escapeshellarg($path));
system("mv ".escapeshellarg($output)." ".escapeshellarg($path));
return [
$path => [$path],
@ -43,10 +43,12 @@ class PngCompressor extends Compressor
public function start(): void
{
//
}
public function end(): void
{
//
}
public function resize(Collection $size, bool $update, callable $callback): void
@ -63,13 +65,8 @@ class PngCompressor extends Compressor
$versionFilename = $this->media->versionsDirPath().'/'.$this->versionFilename($destWidth, $destHeight);
if ($update && Storage::exists($versionFilename)) {
Storage::delete($temp);
return;
}
$this->moveTo($temp, $versionFilename);
call_user_func($callback, $this->media, Storage::path($versionFilename));
}
}

View File

@ -1,52 +0,0 @@
<?php
namespace Aweos\Resizer\Console;
use Aweos\Resizer\Classes\CacheManager;
use Aweos\Resizer\Lib\StorageMediaPath;
use Illuminate\Console\Command;
use Storage;
use Symfony\Component\Console\Input\InputArgument;
class ResizeCacheClear extends Command
{
/**
* @var string The console command name.
*/
protected $name = 'rcc';
/**
* @var string The console command description.
*/
protected $description = 'Clears cache for a specific file';
/**
* Execute the console command.
* @return void
*/
public function handle()
{
$path = new StorageMediaPath($this->argument('path'));
app(CacheManager::class)->delete($path);
}
/**
* Get the console command arguments.
* @return array
*/
protected function getArguments()
{
return [
['path', InputArgument::REQUIRED, 'The path on the storage'],
];
}
/**
* Get the console command options.
* @return array
*/
protected function getOptions()
{
return [];
}
}

View File

@ -1,7 +1,7 @@
<?php namespace Aweos\Resizer\Console;
use Aweos\Resizer\Classes\CacheManager;
use Aweos\Resizer\Jobs\ResizeJob;
use Aweos\Resizer\Classes\ResizeJob;
use Aweos\Resizer\Models\Setting;
use Exception;
use GuzzleHttp\Client;
@ -17,7 +17,7 @@ use Symfony\Component\Console\Input\InputOption;
class ResizeMake extends Command
{
public MediaLibrary $media;
public $media = null;
/**
* @var string The console command name.

View File

@ -1,36 +0,0 @@
<?php
namespace Aweos\Resizer\Jobs;
use Aweos\Resizer\Classes\CacheManager;
use Aweos\Resizer\Classes\FileObserver;
use Aweos\Resizer\Lib\MediaPath;
use Aweos\Resizer\Lib\StorageMediaPath;
use Log;
use Throwable;
class DeleteJob
{
public function fire($job, $params)
{
list($file) = $params;
$media = new StorageMediaPath($file);
app(FileObserver::class)->delete($media);
app(CacheManager::class)->delete($media);
unset ($media);
$job->delete();
}
public function failed($data, Throwable $e)
{
Log::error("Deleting of image failed", [
'message' => $e->getMessage(),
'exception' => $e,
'data' => $data,
]);
throw $e;
}
}

View File

@ -1,38 +0,0 @@
<?php
namespace Aweos\Resizer\Jobs;
use Aweos\Resizer\Classes\CacheManager;
use Aweos\Resizer\Classes\FileObserver;
use Aweos\Resizer\Lib\MediaPath;
use Aweos\Resizer\Lib\StorageMediaPath;
use Log;
use Throwable;
class MoveJob
{
public function fire($job, $params)
{
list($old, $new) = $params;
$old = new StorageMediaPath($old);
$new = new StorageMediaPath($new);
app(FileObserver::class)->rename($old, $new);
app(CacheManager::class)->delete($old);
unset ($old);
unset ($new);
$job->delete();
}
public function failed($data, Throwable $e)
{
Log::error("Deleting of image failed", [
'message' => $e->getMessage(),
'exception' => $e,
'data' => $data,
]);
throw $e;
}
}

View File

@ -6,23 +6,29 @@ use Aweos\Resizer\Compressors\Compressor;
use Aweos\Resizer\Compressors\Factory as CompressorFactory;
use Aweos\Resizer\Models\Setting;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage;
use MediaLibrary;
use Storage;
abstract class MediaPath
class MediaPath
{
protected string $path;
abstract public function get(): string;
abstract public function root(): string;
abstract public function publicUrl(): string;
private string $path;
public function __construct(string $path)
{
$this->path = $path;
}
public function root(): string
{
return Storage::path($this->storagePath());
}
public function storagePath(): string
{
return "media/{$this->normal()}";
}
public function normal(): string
{
return preg_replace('|^/*|', '', $this->path);
@ -35,7 +41,7 @@ abstract class MediaPath
public function filename(): string
{
return pathinfo($this->root(), PATHINFO_FILENAME);
return pathinfo($this->path, PATHINFO_FILENAME);
}
public function exists(): bool
@ -54,7 +60,7 @@ abstract class MediaPath
public function extension(): string
{
return pathinfo($this->root(), PATHINFO_EXTENSION);
return pathinfo($this->path, PATHINFO_EXTENSION);
}
public function versionsPath(): string
@ -64,14 +70,24 @@ abstract class MediaPath
public function versionsDirPath(): string
{
return pathinfo($this->versionsPath(), PATHINFO_DIRNAME);
return pathinfo("uploads/public/c/{$this->normal()}", PATHINFO_DIRNAME);
}
public function publicUrl(): string
{
return MediaLibrary::instance()->findFiles($this->path)[0]->publicUrl;
}
public function get(): string
{
return MediaLibrary::instance()->get($this->path);
}
public function shouldProcess(): bool
{
return null !== collect(Setting::get('folders'))->pluck('folder')->first(
return collect(Setting::get('folders'))->pluck('folder')->first(
fn ($folder) => starts_with('/'.$this->normal(), $folder.'/')
);
) !== null;
}
public function versions(): Collection
@ -106,29 +122,4 @@ abstract class MediaPath
return $return;
}
public function sluggifyPath(): string
{
$fileinfo = pathinfo($this->path);
$filename = $fileinfo['dirname'].'/';
return $filename
.static::sluggifyString($fileinfo['filename'])
.'.'
.$fileinfo['extension'];
}
protected function storagePath(): string
{
return "media/{$this->normal()}";
}
public static function sluggifyString(string $input): string
{
return str_slug(strtr($input, [
'ö' => 'oe',
'ä' => 'ae',
'ü' => 'ue',
'ß' => 'ss',
]));
}
}

View File

@ -1,36 +0,0 @@
<?php
namespace Aweos\Resizer\Lib;
use Aweos\Resizer\Compressors\Compressor;
use Aweos\Resizer\Compressors\Factory as CompressorFactory;
use Aweos\Resizer\Models\Setting;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage;
use MediaLibrary;
class StorageMediaPath extends MediaPath
{
public function __construct(string $path)
{
parent::__construct($path);
$this->path = $path;
}
public function root(): string
{
return Storage::path($this->storagePath());
}
public function publicUrl(): string
{
return MediaLibrary::instance()->findFiles($this->path)[0]->publicUrl;
}
public function get(): string
{
return MediaLibrary::instance()->get($this->path);
}
}

View File

@ -1,59 +0,0 @@
<?php
namespace Aweos\Resizer\Lib;
use Aweos\Resizer\Compressors\Compressor;
use Aweos\Resizer\Compressors\Factory as CompressorFactory;
use Aweos\Resizer\Models\Setting;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage;
use MediaLibrary;
class TempMediaPath extends MediaPath
{
private string $tempPath;
public function __construct(string $path)
{
parent::__construct($path);
$this->createTemp();
}
public function __destruct()
{
$this->destroyTemp();
}
public function root(): string
{
return $this->tempPath;
}
public function publicUrl(): string
{
return '';
}
public function get(): string
{
return file_get_contents($this->tempPath);
}
private function createTemp(): void
{
$this->tempPath = '/tmp/'.pathinfo($this->path, PATHINFO_FILENAME);
if (Storage::exists($this->storagePath())) {
$stream = Storage::readStream($this->storagePath());
$contents = stream_get_contents($stream);
file_put_contents($this->tempPath, $contents);
}
}
private function destroyTemp(): void
{
@unlink($this->tempPath);
}
}

View File

@ -1,13 +0,0 @@
parameters:
paths:
- classes
- compressors
- console
- exceptions
- lib
# The level 8 is the highest level
level: 6
checkMissingIterableValueType: false

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="../../../modules/system/tests/bootstrap.php"
bootstrap="../../../tests/bootstrap.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"

View File

@ -6,7 +6,6 @@ use Aweos\Resizer\Classes\CacheManager;
use Aweos\Resizer\Classes\TagGenerator;
use Aweos\Resizer\Exceptions\ResizerException;
use Aweos\Resizer\Lib\MediaPath;
use Aweos\Resizer\Lib\StorageMediaPath;
use Aweos\Resizer\Models\Setting;
use Aweos\Resizer\Tests\TestCase;
use Cache;
@ -22,11 +21,11 @@ class ImageTagTest extends TestCase
{
parent::setUp();
Storage::fake('local');
Setting::set('folders', [['folder' => '/pages']]);
}
public function testItGeneratesAnImageTagWithOriginalSize()
{
Setting::set('folders', ['pages']);
Setting::set('sizes', []);
Setting::set('breakpoints', [100,200]);
$this->media->put('/pages/test.jpg', UploadedFile::fake()->image('test.jpg', 500, 500)->get());
@ -36,23 +35,25 @@ class ImageTagTest extends TestCase
$this->assertEquals(
'width="500" height="500" sizes="(max-width: 100px) 100px, (max-width: 200px) 200px, (max-width: 500px) 500px" srcset="/storage/uploads/public/c/pages/test-100x100.jpg 100w, /storage/uploads/public/c/pages/test-200x200.jpg 200w, /storage/uploads/public/c/pages/test-500x500.jpg 500w" src="/storage/uploads/public/c/pages/test-500x500.jpg"',
app(CacheManager::class)->get(new StorageMediaPath('pages/test.jpg'), 'original', null),
app(CacheManager::class)->get(new MediaPath('pages/test.jpg'), 'original', null),
);
}
public function testItThrowsExceptionWhenSizeNotFound()
{
$this->expectException(ResizerException::class);
Setting::set('folders', ['pages']);
Setting::set('sizes', []);
Setting::set('breakpoints', []);
$this->media->put('/pages/test.jpg', UploadedFile::fake()->image('test.jpg', 500, 500)->get());
UploadedFile::fake()->image('test.jpg', 500, 500)->storeAs('uploads/public/c/pages', 'test-500x500.jpg', 'local');
dd(app(CacheManager::class)->get(new StorageMediaPath('pages/test.jpg'), 'notfound', null));
dd(app(CacheManager::class)->get(new MediaPath('pages/test.jpg'), 'notfound', null));
}
public function testFetchPdfImage()
{
Setting::set('folders', ['pages']);
Setting::set('sizes', []);
Setting::set('breakpoints', [100,200]);
$this->media->put('/pages/test.pdf', file_get_contents(__DIR__.'/stub/dummy.pdf'));
@ -67,6 +68,7 @@ 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());
@ -74,12 +76,13 @@ class ImageTagTest extends TestCase
$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 StorageMediaPath('pages/test.jpg'), 'original', null, ['lazy' => true]),
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());
@ -87,12 +90,13 @@ class ImageTagTest extends TestCase
$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 StorageMediaPath('pages/test.png'), 'original', null),
app(CacheManager::class)->get(new MediaPath('pages/test.png'), 'original', null),
);
}
public function testItSkipsImagesWithWrongAspectRatio()
{
Setting::set('folders', ['pages']);
Setting::set('sizes', []);
Setting::set('breakpoints', [100,200]);
$this->media->put('/pages/test.jpg', UploadedFile::fake()->image('test.jpg', 500, 500)->get());
@ -107,6 +111,7 @@ class ImageTagTest extends TestCase
public function testItCanGenerateAAspectRatio()
{
Setting::set('folders', ['pages']);
Setting::set('sizes', [['name' => 'size', 'aspect_ratio' => '1x2']]);
Setting::set('breakpoints', [100,200]);
$this->media->put('/pages/test.jpg', UploadedFile::fake()->image('test.jpg', 500, 500)->get());
@ -128,6 +133,7 @@ class ImageTagTest extends TestCase
public function testItServesAspectRatiosThatCanBeOnePixelLarger()
{
Setting::set('folders', ['pages']);
Setting::set('sizes', [['name' => 'size', 'aspect_ratio' => '1200x280']]);
Setting::set('breakpoints', [640]);
$this->media->put('/pages/test.jpg', UploadedFile::fake()->image('test.jpg', 1920, 899)->get());
@ -141,6 +147,7 @@ class ImageTagTest extends TestCase
public function testGenerateCache()
{
Setting::set('folders', ['pages']);
Setting::set('sizes', [['name' => 'size', 'aspect_ratio' => '1200x280']]);
Setting::set('breakpoints', [640]);
$this->media->put('/pages/test.jpg', UploadedFile::fake()->image('test.jpg', 1920, 899)->get());
@ -152,6 +159,7 @@ class ImageTagTest extends TestCase
public function testPickOriginalImageWhenSvgIsGiven()
{
Setting::set('folders', ['pages']);
Setting::set('sizes', [['name' => 'size', 'aspect_ratio' => '1200x280']]);
Setting::set('breakpoints', [640]);
$this->media->put('/pages/test.svg', file_get_contents(__DIR__.'/stub/close.svg'));
@ -166,6 +174,7 @@ class ImageTagTest extends TestCase
public function testNormalizeFilePathForCache()
{
Setting::set('folders', ['pages']);
Setting::set('sizes', [['name' => 'size', 'aspect_ratio' => '1200x280']]);
Setting::set('breakpoints', [640]);
$this->media->put('/pages/test.svg', file_get_contents(__DIR__.'/stub/close.svg'));
@ -176,6 +185,7 @@ class ImageTagTest extends TestCase
public function testGenerateSizesAttribute()
{
Setting::set('folders', ['pages']);
Setting::set('sizes', []);
Setting::set('breakpoints', [100, 200]);
$this->media->put('/pages/test.jpg', UploadedFile::fake()->image('test.jpg', 500, 500)->get());
@ -189,6 +199,7 @@ class ImageTagTest extends TestCase
public function testItGeneratesOnlySingleImage()
{
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());

View File

@ -21,13 +21,13 @@ class MoveTest extends TestCase
public function testItMovesAllVersionsOfAFile()
{
Cache::tags(['resizer', 'resizer.pages/alt/test.jpg'])->set('resizer.original.pages/alt/test.jpg', 'aa');
Setting::set('folders', [['folder' => '/pages']]);
Setting::set('folders', ['pages']);
Setting::set('sizes', []);
Setting::set('breakpoints', []);
$this->media->put('/pages/alt/test.jpg', UploadedFile::fake()->image('test.jpg', 100, 100)->get());
UploadedFile::fake()->image('test.jpg', 100, 100)->storeAs('uploads/public/c/pages/alt', 'test-200x300.jpg', 'local');
Event::fire('media.file.move', [null, '/pages/alt/test.jpg', '/pages/neu']);
Event::fire('media.file.move', [null, '/pages/alt/test.jpg', '/pages/neu/test.jpg']);
$this->assertFileCount(0, 'pages/alt');
$this->assertHasFile('pages/neu/test-200x300.jpg');
@ -36,7 +36,7 @@ class MoveTest extends TestCase
public function testItMovesFilesOnRename()
{
Setting::set('folders', [['folder' => '/pages']]);
Setting::set('folders', ['pages']);
Setting::set('sizes', []);
Setting::set('breakpoints', []);
$this->media->put('/pages/test.jpg', UploadedFile::fake()->image('test.jpg', 100, 100)->get());
@ -48,27 +48,9 @@ class MoveTest extends TestCase
$this->assertHasFile('pages/testneu-200x300.jpg');
}
public function testitDeletesOldAndNewCacheWhenMoving()
{
Setting::set('folders', [['folder' => '/pages']]);
Setting::set('sizes', []);
Setting::set('breakpoints', []);
$this->media->put('/pages/test.jpg', UploadedFile::fake()->image('test.jpg', 100, 100)->get());
UploadedFile::fake()->image(100, 100)->storeAs('uploads/public/c/pages', 'test-200x300.jpg', 'local');
Cache::tags(['resizer', 'resizer.pages/test.jpg'])->put('resizer.original.pages/test.jpg', 'AAA');
Cache::tags(['resizer', 'resizer.pages/testneu.jpg'])->put('resizer.original.pages/testneu.jpg', 'AAA');
Event::fire('media.file.rename', [null, '/pages/test.jpg', '/pages/testneu.jpg']);
$this->assertFileCount(1, 'pages');
$this->assertHasFile('pages/testneu-200x300.jpg');
$this->assertFalse(Cache::tags(['resizer', 'resizer.pages/test.jpg'])->has('resizer.original.pages/test.jpg'));
$this->assertFalse(Cache::tags(['resizer', 'resizer.pages/testneu.jpg'])->has('resizer.original.pages/test.jpg'));
}
public function testRenamePdfHeaderFile()
{
Setting::set('folders', [['folder' => '/pages']]);
Setting::set('folders', ['pages']);
Setting::set('sizes', []);
Setting::set('breakpoints', []);
$this->media->put('/pages/test.pdf', file_get_contents(__DIR__.'/stub/dummy.pdf'));
@ -83,7 +65,7 @@ class MoveTest extends TestCase
public function testItDoesntMoveOtherFilesInTheSameDirectory()
{
Cache::tags(['resizer', 'resizer.pages/test.jpg'])->set('resizer.original.pages/test.jpg', 'aa');
Setting::set('folders', [['folder' => '/pages']]);
Setting::set('folders', ['pages']);
Setting::set('sizes', []);
Setting::set('breakpoints', []);
$this->media->put('/pages/test.jpg', UploadedFile::fake()->image('test.jpg', 100, 100)->get());

View File

@ -4,14 +4,15 @@ namespace Aweos\Resizer\Tests;
use Aweos\Resizer\Exceptions\ResizerException;
use Aweos\Resizer\Models\Setting;
use Aweos\Resizer\Tests\TestCase;
use Event;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Cache;
use MediaLibrary;
use Storage;
class ResizerTest extends TestCase
{
public function setUp(): void
{
parent::setUp();
@ -25,28 +26,13 @@ class ResizerTest extends TestCase
Setting::set('sizes', []);
Setting::set('breakpoints', []);
$file = UploadedFile::fake()->image('test.jpg', 500, 600);
$this->media->put('/pages/test.jpg', $file->get());
$this->media->put('/pages/test.jpg', $file);
Event::fire('media.file.upload', [null, '/pages/test.jpg', null]);
$this->assertFileCount(0, '');
}
public function testDeleteOldCacheWhenUploadingFile(): void
{
Setting::set('folders', [['folder' => '/pages']]);
Setting::set('sizes', []);
Setting::set('breakpoints', []);
$file = UploadedFile::fake()->image('test.jpg', 500, 600);
$this->media->put('/pages/test.jpg', $file->get());
Cache::tags(['resizer', 'resizer.pages/test.jpg'])->put('resizer.original.pages/test.jpg', 'AAA');
Event::fire('media.file.upload', [null, '/pages/test.jpg', null]);
$this->assertFileCount(0, '');
$this->assertFalse(Cache::tags(['resizer', 'resizer.pages/test.jpg'])->has('resizer.original.pages/test.jpg'));
}
public function testThrowExceptionWhenOriginalFileNotFound(): void
{
$this->expectException(ResizerException::class);
@ -88,21 +74,6 @@ class ResizerTest extends TestCase
$this->assertHasFile('pages/test-500x600.jpg');
}
public function testSluggifyFilename(): void
{
Setting::set('folders', [['folder' => '/pages']]);
Setting::set('sizes', []);
Setting::set('breakpoints', []);
$file = UploadedFile::fake()->image('test.jpg', 500, 600);
$this->media->put('/pages/test ö space.jpg', $file->get());
Event::fire('media.file.upload', [null, 'pages/test ö space.jpg', null]);
Storage::assertExists('media/pages/test-oe-space.jpg');
$this->assertFileCount(1, 'pages');
$this->assertHasFile('pages/test-oe-space-500x600.jpg');
}
public function testCopyTwoDirectoriesDeepButNotAnotherDirectory(): void
{
Setting::set('folders', [['folder' => '/pages']]);
@ -269,4 +240,5 @@ class ResizerTest extends TestCase
$this->assertHasFile('pages/test-1275x1650.pdf.jpg');
$this->assertFileCount(4, 'pages');
}
}

View File

@ -1,59 +0,0 @@
<?php
namespace Aweos\Resizer\Tests;
use Event;
use Illuminate\Http\UploadedFile;
use MediaLibrary;
use Storage;
class SlugTest extends TestCase
{
public function setUp(): void
{
parent::setUp();
Storage::fake('local');
$this->media = MediaLibrary::instance();
}
public function testDontRenameFolderIfSluggingIsNotNeeded(): void
{
$file = UploadedFile::fake()->image('test.jpg', 500, 600);
$this->media->makeFolder('testbb');
Event::fire('media.folder.create', [null, '//testbb', null]);
Storage::disk('local')->assertExists('media/testbb');
}
public function testRenameFolder(): void
{
$file = UploadedFile::fake()->image('test.jpg', 500, 600);
$this->media->makeFolder('test bb');
Event::fire('media.folder.create', [null, '//test bb', null]);
Storage::disk('local')->assertExists('media/test-bb');
Storage::disk('local')->assertMissing('media/test bb');
}
public function testRenameSubfolder(): void
{
$file = UploadedFile::fake()->image('test.jpg', 500, 600);
$this->media->makeFolder('test/aa bb');
Event::fire('media.folder.create', [null, '/test/aa bb', null]);
Storage::disk('local')->assertExists('media/test/aa-bb');
}
public function testRenameSubfolderWithDoubleSlash(): void
{
$file = UploadedFile::fake()->image('test.jpg', 500, 600);
$this->media->makeFolder('test/aa bb');
Event::fire('media.folder.create', [null, '//test/aa bb', null]);
Storage::disk('local')->assertExists('media/test/aa-bb');
}
}

View File

@ -19,6 +19,10 @@ class TestCase extends PluginTestCase
Setting::set('queue', 'default');
$this->media = MediaLibrary::instance();
$pluginManager = PluginManager::instance();
$pluginManager->registerAll(true);
$pluginManager->bootAll(true);
}
public function assertHasFile($file): void