Add uploads folder
This commit is contained in:
parent
fa6a328860
commit
15a4046402
|
@ -8,3 +8,4 @@
|
||||||
/formwidgets/responsiveimage/assets/css/responsiveimage.build.css.map
|
/formwidgets/responsiveimage/assets/css/responsiveimage.build.css.map
|
||||||
/formwidgets/responsiveimage/assets/js/responsiveimage.build.js.map
|
/formwidgets/responsiveimage/assets/js/responsiveimage.build.js.map
|
||||||
/formwidgets/responsiveimage/assets/js/responsiveimage.build.js.LICENSE.txt
|
/formwidgets/responsiveimage/assets/js/responsiveimage.build.js.LICENSE.txt
|
||||||
|
/.phpunit.result.cache
|
||||||
|
|
158
Plugin.php
158
Plugin.php
|
@ -1,16 +1,21 @@
|
||||||
<?php namespace Aweos\Resizer;
|
<?php namespace Aweos\Resizer;
|
||||||
|
|
||||||
use Storage;
|
use Aweos\Resizer\Classes\FileObserver;
|
||||||
use Backend;
|
use Aweos\Resizer\Classes\ImageResizer;
|
||||||
use System\Classes\PluginBase;
|
use Aweos\Resizer\Classes\ResizeJob;
|
||||||
use System\Classes\MediaLibrary;
|
use Aweos\Resizer\Classes\TagGenerator;
|
||||||
use Aweos\Resizer\Models\Setting;
|
|
||||||
use Aweos\Resizer\Console\ClearOld;
|
use Aweos\Resizer\Console\ClearOld;
|
||||||
use Aweos\Resizer\Console\ResizeMake;
|
use Aweos\Resizer\Console\ResizeMake;
|
||||||
use Illuminate\Support\Facades\Cache;
|
|
||||||
use Aweos\Resizer\Console\ResizePurge;
|
use Aweos\Resizer\Console\ResizePurge;
|
||||||
use Aweos\Resizer\FormWidgets\Responsiveimage;
|
use Aweos\Resizer\FormWidgets\Responsiveimage;
|
||||||
use Aweos\Resizer\Classes\TagPresenter;
|
use Aweos\Resizer\Models\Setting;
|
||||||
|
use Event;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use Queue;
|
||||||
|
use Storage;
|
||||||
|
use System\Classes\MediaLibrary;
|
||||||
|
use System\Classes\PluginBase;
|
||||||
|
use System\Models\File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* resizer Plugin Information File
|
* resizer Plugin Information File
|
||||||
|
@ -51,58 +56,29 @@ class Plugin extends PluginBase
|
||||||
*/
|
*/
|
||||||
public function boot()
|
public function boot()
|
||||||
{
|
{
|
||||||
|
app()->bind(ImageResizer::class, function() {
|
||||||
|
$disk = (new File())->getDisk();
|
||||||
|
$dir = (new File(['is_public' => true]))->getStorageDirectory().'c/';
|
||||||
|
$media = MediaLibrary::instance();
|
||||||
|
|
||||||
|
return new ImageResizer($disk, $dir, $media);
|
||||||
|
});
|
||||||
|
|
||||||
|
Event::listen('media.file.upload', function($widget, $filePath, $uploadedFile) {
|
||||||
|
if (app(FileObserver::class)->shouldProcessFile($filePath)) {
|
||||||
|
Queue::push(ResizeJob::class, [$filePath]);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
Event::listen('media.file.delete', function($widget, $filePath) {
|
||||||
|
app(FileObserver::class)->delete($filePath);
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
Event::listen('media.file.move', function($widget, $old, $new) {
|
||||||
* Registers any front-end components implemented in this plugin.
|
app(FileObserver::class)->rename($old, $new);
|
||||||
*
|
});
|
||||||
* @return array
|
Event::listen('media.file.rename', function($widget, $old, $new) {
|
||||||
*/
|
app(FileObserver::class)->rename($old, $new);
|
||||||
public function registerComponents()
|
});
|
||||||
{
|
|
||||||
return []; // Remove this line to activate
|
|
||||||
|
|
||||||
return [
|
|
||||||
'Aweos\Resizer\Components\MyComponent' => 'myComponent',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers any back-end permissions used by this plugin.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function registerPermissions()
|
|
||||||
{
|
|
||||||
return []; // Remove this line to activate
|
|
||||||
|
|
||||||
return [
|
|
||||||
'aweos.resizer.some_permission' => [
|
|
||||||
'tab' => 'resizer',
|
|
||||||
'label' => 'Some permission'
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers back-end navigation items for this plugin.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function registerNavigation()
|
|
||||||
{
|
|
||||||
return []; // Remove this line to activate
|
|
||||||
|
|
||||||
return [
|
|
||||||
'resizer' => [
|
|
||||||
'label' => 'resizer',
|
|
||||||
'url' => Backend::url('aweos/resizer/mycontroller'),
|
|
||||||
'icon' => 'icon-leaf',
|
|
||||||
'permissions' => ['aweos.resizer.*'],
|
|
||||||
'order' => 500,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function registerSettings() {
|
public function registerSettings() {
|
||||||
|
@ -123,75 +99,9 @@ class Plugin extends PluginBase
|
||||||
public function registerMarkupTags() {
|
public function registerMarkupTags() {
|
||||||
return [
|
return [
|
||||||
'filters' => [
|
'filters' => [
|
||||||
'resize' => function($media, $breakpoints = [], $name = '') {
|
'resize' => function($media, $size = 'original') {
|
||||||
return Cache::remember('resized_image.'.$name.$media, 3600, function() use ($media, $breakpoints) {
|
return app(TagGenerator::class)->generate($media, $size);
|
||||||
ksort($breakpoints);
|
|
||||||
$l = MediaLibrary::instance();
|
|
||||||
$folders = Setting::get('folders');
|
|
||||||
$sizes = Setting::get('srcx');
|
|
||||||
|
|
||||||
$media = '/'.ltrim($media, '/');
|
|
||||||
$filename = basename($media);
|
|
||||||
$dirname = dirname($media);
|
|
||||||
$extension = pathinfo($media, PATHINFO_EXTENSION);
|
|
||||||
|
|
||||||
if (! $l->folderExists($dirname.'/c')) {
|
|
||||||
return 'src="'.$l->getPathUrl($media).'"';
|
|
||||||
}
|
|
||||||
|
|
||||||
$sizes = collect($l->listFolderContents($dirname.'/c'))
|
|
||||||
->filter(function($f) use ($sizes, $filename) {
|
|
||||||
foreach ($sizes as $size) {
|
|
||||||
if (pathinfo($f->path, PATHINFO_FILENAME).'.'.pathinfo($filename, PATHINFO_EXTENSION)
|
|
||||||
== pathinfo($filename, PATHINFO_FILENAME).'-'.$size.'t.'.pathinfo($filename, PATHINFO_EXTENSION)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pathinfo($f->path, PATHINFO_FILENAME).'.'.pathinfo($filename, PATHINFO_EXTENSION)
|
|
||||||
== pathinfo($filename, PATHINFO_FILENAME).'-'.$size.'.'.pathinfo($filename, PATHINFO_EXTENSION)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
})
|
|
||||||
->map(function($fileVersion) use ($l) {
|
|
||||||
$sizes = getimagesize(Storage::path('media/'.$fileVersion->path));
|
|
||||||
|
|
||||||
return [$l->getPathUrl($fileVersion->path), $sizes[0], $sizes[1]];
|
|
||||||
})->sortBy(function($size) {
|
|
||||||
return $size[1];
|
|
||||||
})
|
|
||||||
;
|
|
||||||
|
|
||||||
if ($sizes->isEmpty()) {
|
|
||||||
return 'src="'.$l->getPathUrl($media).'"';
|
|
||||||
}
|
|
||||||
|
|
||||||
$srcset = 'srcset="';
|
|
||||||
$s = '';
|
|
||||||
|
|
||||||
foreach($sizes as $size) {
|
|
||||||
$srcset .= $size[0].' '.$size[1].'w, ';
|
|
||||||
$s .= '(max-width: '.$size[1].'px) '.$size[1].'px, ';
|
|
||||||
}
|
|
||||||
|
|
||||||
$s = 'sizes="'.substr($s, 0, -2).', 1920px"';
|
|
||||||
|
|
||||||
if (!empty($breakpoints)) {
|
|
||||||
$s = $this->breakpointsToSizes($breakpoints);
|
|
||||||
}
|
|
||||||
|
|
||||||
$srcset = substr($srcset, 0, -2).'"';
|
|
||||||
|
|
||||||
$normalSize = 'width="'.$sizes->last()[1].'" height="'.$sizes->last()[2].'"';
|
|
||||||
|
|
||||||
return 'src="'.$l->getPathUrl($media).'" '.$srcset.' '.$s.' '.$normalSize;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
'responsiveimage' => function($id, $data = []) {
|
|
||||||
return (new TagPresenter($id, $data))->cacheOutput();
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aweos\Resizer\Classes;
|
||||||
|
|
||||||
|
use Aweos\Resizer\Models\Setting;
|
||||||
|
use Storage;
|
||||||
|
|
||||||
|
class FileObserver
|
||||||
|
{
|
||||||
|
|
||||||
|
public function versionsPath(string $mediaPath): string
|
||||||
|
{
|
||||||
|
return "uploads/public/c/{$this->normalizePath($mediaPath)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function normalizePath(string $path): string
|
||||||
|
{
|
||||||
|
return preg_replace('|^/*|', '', $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fullMediaPath(string $path): string
|
||||||
|
{
|
||||||
|
return "media/{$this->normalizePath($path)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldProcessFile($file): bool
|
||||||
|
{
|
||||||
|
return collect(Setting::get('folders'))->pluck('folder')->first(
|
||||||
|
fn ($folder) => starts_with($file, $folder.'/')
|
||||||
|
) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete($path): void
|
||||||
|
{
|
||||||
|
$dir = pathinfo($path, PATHINFO_DIRNAME);
|
||||||
|
$base = $dir.'/'.pathinfo($path, PATHINFO_FILENAME);
|
||||||
|
|
||||||
|
Storage::delete("uploads/public/c{$path}");
|
||||||
|
|
||||||
|
collect(Storage::files("uploads/public/c{$dir}"))->filter(
|
||||||
|
fn ($file) => preg_match('|'.preg_quote("uploads/public/c{$base}", '|').'-[0-9]+x[0-9]+\.[a-zA-Z]+$|', $file)
|
||||||
|
)->each(function ($path) {
|
||||||
|
Storage::delete($path);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (empty(Storage::allFiles("uploads/public/c{$dir}"))) {
|
||||||
|
Storage::deleteDirectory("uploads/public/c{$dir}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rename(string $old, string $new): void
|
||||||
|
{
|
||||||
|
$dir = pathinfo($old, PATHINFO_DIRNAME);
|
||||||
|
$base = pathinfo($old, PATHINFO_FILENAME);
|
||||||
|
$newBase = pathinfo($new, PATHINFO_FILENAME);
|
||||||
|
$newDir = pathinfo($new, PATHINFO_DIRNAME);
|
||||||
|
|
||||||
|
foreach (Storage::files("uploads/public/c{$dir}") as $file) {
|
||||||
|
if (!preg_match_all('|'.preg_quote("uploads/public/c{$dir}/{$base}", '|').'(-[0-9]+x[0-9]+)?(\.[a-zA-Z]+)$|', $file, $matches)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$size = $matches[1][0];
|
||||||
|
$ext = $matches[2][0];
|
||||||
|
|
||||||
|
Storage::move($file, "uploads/public/c{$newDir}/{$newBase}{$size}{$ext}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,38 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Aweos\Resizer\Classes;
|
|
||||||
|
|
||||||
class FirstLetterStrategy {
|
|
||||||
|
|
||||||
public function sourcePath($fileName) {
|
|
||||||
return 'source';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function sourceFileBasename($uploadedFile, $data) {
|
|
||||||
return str_slug($data['title']);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function publicPath($filename) {
|
|
||||||
return strtolower($filename[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function smallFilename($filename, $width) {
|
|
||||||
return pathinfo($filename, PATHINFO_FILENAME).'-'.$width.'.'.pathinfo($filename, PATHINFO_EXTENSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function versionRegex($filename) {
|
|
||||||
$ext = preg_quote(pathinfo($filename, PATHINFO_EXTENSION), '/');
|
|
||||||
$name = preg_quote(pathinfo($filename, PATHINFO_FILENAME), '/');
|
|
||||||
|
|
||||||
return "/^{$name}-[0-9]+\.{$ext}$/";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function croppedPath() {
|
|
||||||
return 'cropped';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function croppedFilename($filename, $crop) {
|
|
||||||
return $filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aweos\Resizer\Classes;
|
||||||
|
|
||||||
|
use Aweos\Resizer\Models\Setting;
|
||||||
|
use Illuminate\Filesystem\FilesystemAdapter;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Intervention\Image\ImageManager;
|
||||||
|
use Media\Classes\MediaLibrary;
|
||||||
|
use October\Rain\Resize\Resizer;
|
||||||
|
use Storage;
|
||||||
|
|
||||||
|
class ImageResizer
|
||||||
|
{
|
||||||
|
|
||||||
|
private FilesystemAdapter $disk;
|
||||||
|
private string $uploadDir;
|
||||||
|
private MediaLibrary $media;
|
||||||
|
|
||||||
|
public function __construct(FilesystemAdapter $disk, string $uploadDir, MediaLibrary $media)
|
||||||
|
{
|
||||||
|
$this->disk = $disk;
|
||||||
|
$this->uploadDir = $uploadDir;
|
||||||
|
$this->media = $media;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generate(string $file): void
|
||||||
|
{
|
||||||
|
$this->source = app(FileObserver::class)->normalizePath($file);
|
||||||
|
if ($this->media->findFiles($this->source)[0]->getFileType() !== 'image') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->copyOriginalImage();
|
||||||
|
$this->generateVersions();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function copyOriginalImage()
|
||||||
|
{
|
||||||
|
$this->disk->put($this->destinationFilename(), $this->media->get($this->source));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function destinationFilename(): string
|
||||||
|
{
|
||||||
|
return $this->uploadDir.$this->source;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function dimensions(): Collection
|
||||||
|
{
|
||||||
|
[$width, $height] = getimagesize(Storage::path($this->destinationFilename()));
|
||||||
|
|
||||||
|
return collect(compact('width', 'height'));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sizes(): Collection
|
||||||
|
{
|
||||||
|
$sizes = Setting::get('sizes');
|
||||||
|
|
||||||
|
return collect(array_column($sizes, 'aspect_ratio'))->map(
|
||||||
|
fn ($ratio) => collect(array_combine(['width', 'height'], explode('x', $ratio))),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function possibleSizes(): Collection
|
||||||
|
{
|
||||||
|
$return = collect([]);
|
||||||
|
$ratios = collect();
|
||||||
|
$ratios->push($this->dimensions());
|
||||||
|
$ratios = $ratios->merge($this->sizes());
|
||||||
|
|
||||||
|
foreach (collect(Setting::get('breakpoints'))->push($this->dimensions()->get('width'))->unique() as $size) {
|
||||||
|
foreach ($ratios as $ratio) {
|
||||||
|
$height = $size * $ratio->get('height') / $ratio->get('width');
|
||||||
|
|
||||||
|
$return->push(collect([
|
||||||
|
'width' => round($size),
|
||||||
|
'height' => round($height),
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function generateVersions(): void
|
||||||
|
{
|
||||||
|
foreach ($this->possibleSizes() as $size) {
|
||||||
|
$temp = microtime().'.jpg';
|
||||||
|
$this->disk->copy($this->destinationFilename(), $temp);
|
||||||
|
$fullOriginalPath = $this->disk->path($this->destinationFilename());
|
||||||
|
$pathinfo = collect(pathinfo($this->destinationFilename()));
|
||||||
|
|
||||||
|
$r = app(ImageManager::class)->make($this->disk->path($temp))
|
||||||
|
->fit($size->get('width'), $size->get('height'), fn ($constraint) => $constraint->upsize())
|
||||||
|
->save($this->disk->path($temp));
|
||||||
|
list($destWidth, $destHeight) = getimagesize($this->disk->path($temp));
|
||||||
|
|
||||||
|
$versionFilename = $pathinfo->get('dirname').
|
||||||
|
'/'.
|
||||||
|
$pathinfo->get('filename').
|
||||||
|
'-'.
|
||||||
|
$destWidth.
|
||||||
|
'x'.
|
||||||
|
$destHeight.
|
||||||
|
'.'.
|
||||||
|
$pathinfo->get('extension');
|
||||||
|
|
||||||
|
if ($this->disk->exists($versionFilename)) {
|
||||||
|
$this->disk->delete($versionFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->disk->move($temp, $versionFilename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aweos\Resizer\Classes;
|
||||||
|
|
||||||
|
class ResizeJob
|
||||||
|
{
|
||||||
|
|
||||||
|
public function fire($job, $params)
|
||||||
|
{
|
||||||
|
list($file) = $params;
|
||||||
|
app(ImageResizer::class)->generate($file);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aweos\Resizer\Classes;
|
||||||
|
|
||||||
|
use Aweos\Resizer\Models\Attachment;
|
||||||
|
use Aweos\Resizer\Models\Setting;
|
||||||
|
use Cache;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Media\Classes\MediaLibrary;
|
||||||
|
use Storage;
|
||||||
|
|
||||||
|
class TagGenerator {
|
||||||
|
|
||||||
|
public MediaLibrary $media;
|
||||||
|
public array $breakpoints;
|
||||||
|
public $path;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->media = MediaLibrary::instance();
|
||||||
|
$this->breakpoints = Setting::get('breakpoints');
|
||||||
|
ksort($this->breakpoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cacheOutput() {
|
||||||
|
return Cache::rememberForever('responsive-image-'.$this->attachment->id, function() {
|
||||||
|
return $this->output();
|
||||||
|
}).' '.$this->attrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function size(string $name): array
|
||||||
|
{
|
||||||
|
$size = collect(Setting::get('sizes'))->filter(fn ($size) => $size['name'] === $name)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
return explode('x', $size['aspect_ratio']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function possibleFiles(string $ratio): Collection
|
||||||
|
{
|
||||||
|
if (Storage::mimeType(app(FileObserver::class)->fullMediaPath($this->path)) !== 'image/jpeg') {
|
||||||
|
return collect([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$filename = pathinfo($this->path, PATHINFO_FILENAME);
|
||||||
|
$basePath = app(FileObserver::class)->versionsPath(pathinfo($this->path, PATHINFO_DIRNAME));
|
||||||
|
[$originalWidth, $originalHeight] = getimagesize(Storage::path(app(FileObserver::class)->fullMediaPath($this->path)));
|
||||||
|
$aspectRatio = $ratio === 'original'
|
||||||
|
? $originalWidth / $originalHeight
|
||||||
|
: $this->size($ratio)[0] / $this->size($ratio)[1];
|
||||||
|
|
||||||
|
$result = collect([]);
|
||||||
|
|
||||||
|
foreach (Storage::files($basePath) as $file) {
|
||||||
|
if (!preg_match('|'.preg_quote($basePath.'/'.$filename, '|').'-([0-9]+x[0-9]+)\.([a-zA-Z]+)$|', $file, $matches)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$width = explode('x', $matches[1])[0];
|
||||||
|
$height = explode('x', $matches[1])[1];
|
||||||
|
if ($width / ($height+1) > $aspectRatio || $width / ($height-1) < $aspectRatio) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result->push(collect([
|
||||||
|
'url' => Storage::url($file),
|
||||||
|
'width' => $width,
|
||||||
|
'height' => $height,
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result->sortBy('width');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generate(string $path, ?string $ratio = 'original'): string
|
||||||
|
{
|
||||||
|
$this->path = $path;
|
||||||
|
$files = $this->possibleFiles($ratio);
|
||||||
|
|
||||||
|
if ($files->isEmpty()) {
|
||||||
|
return 'src="/storage/app/media/'.$path.'"';
|
||||||
|
}
|
||||||
|
|
||||||
|
$sizes = $files->map(function($file) {
|
||||||
|
return "(max-width: {$file->get('width')}px) {$file->get('width')}px";
|
||||||
|
});
|
||||||
|
|
||||||
|
$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(', '),
|
||||||
|
'srcset' => $srcset->implode(', '),
|
||||||
|
'src' => $files->last()->get('url'),
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function htmlAttributes($attr) {
|
||||||
|
return $attr->map(function($value, $key) {
|
||||||
|
return "{$key}=\"{$value}\"";
|
||||||
|
})->implode(' ');
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,72 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Aweos\Resizer\Classes;
|
|
||||||
|
|
||||||
use Cache;
|
|
||||||
use Storage;
|
|
||||||
use Aweos\Resizer\Models\Attachment;
|
|
||||||
use Aweos\Resizer\Models\Setting;
|
|
||||||
|
|
||||||
class TagPresenter {
|
|
||||||
|
|
||||||
public $attachment;
|
|
||||||
public $disk = 'uploads';
|
|
||||||
public $attrs;
|
|
||||||
public $breakpoints;
|
|
||||||
public $sizes;
|
|
||||||
|
|
||||||
public function __construct($id, $data = []) {
|
|
||||||
$this->attachment = Attachment::find($id);
|
|
||||||
$this->attrs = data_get($data, 'attrs');
|
|
||||||
$this->breakpoints = data_get($data, 'breakpoints', []);
|
|
||||||
$this->sizes = Setting::get('srcx');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function cacheOutput() {
|
|
||||||
return Cache::rememberForever('responsive-image-'.$this->attachment->id, function() {
|
|
||||||
return $this->output();
|
|
||||||
}).' '.$this->attrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function output() {
|
|
||||||
ksort($this->breakpoints);
|
|
||||||
|
|
||||||
$files = collect(Storage::disk($this->disk)->files($this->attachment->path))->filter(function($file) {
|
|
||||||
return preg_match($this->attachment->versionRegex, $file);
|
|
||||||
})->map(function($file) {
|
|
||||||
$sizes = getimagesize(Storage::disk($this->disk)->path($file));
|
|
||||||
|
|
||||||
return collect([
|
|
||||||
'url' => Storage::disk($this->disk)->url($file),
|
|
||||||
'width' => $sizes[0],
|
|
||||||
'height' => $sizes[1]
|
|
||||||
]);
|
|
||||||
})->sortBy('width');
|
|
||||||
|
|
||||||
if ($files->isEmpty()) {
|
|
||||||
return 'src="'.$this->attachment->url.'"';
|
|
||||||
}
|
|
||||||
|
|
||||||
$sizes = $files->map(function($file) {
|
|
||||||
return "(max-width: {$file->get('width')}px) {$file->get('width')}px";
|
|
||||||
});
|
|
||||||
|
|
||||||
$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(', '),
|
|
||||||
'srcset' => $srcset->implode(', '),
|
|
||||||
'alt' => $this->attachment->title
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
private function htmlAttributes($attr) {
|
|
||||||
return $attr->map(function($value, $key) {
|
|
||||||
return "{$key}=\"{$value}\"";
|
|
||||||
})->implode(' ');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,8 @@
|
||||||
"name": "aweos/oc-resizer-plugin",
|
"name": "aweos/oc-resizer-plugin",
|
||||||
"type": "october-plugin",
|
"type": "october-plugin",
|
||||||
"require": {
|
"require": {
|
||||||
"guzzlehttp/guzzle": "^6.3"
|
"guzzlehttp/guzzle": "^6.3",
|
||||||
|
"intervention/image": "^2.6"
|
||||||
},
|
},
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "82331c61df9e7f95117f9b82b35b6ce2",
|
"content-hash": "d44b27fd707830b38897f254dc4f9040",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "guzzlehttp/guzzle",
|
"name": "guzzlehttp/guzzle",
|
||||||
|
@ -193,6 +193,90 @@
|
||||||
],
|
],
|
||||||
"time": "2019-07-01T23:21:34+00:00"
|
"time": "2019-07-01T23:21:34+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "intervention/image",
|
||||||
|
"version": "2.6.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Intervention/image.git",
|
||||||
|
"reference": "0925f10b259679b5d8ca58f3a2add9255ffcda45"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/Intervention/image/zipball/0925f10b259679b5d8ca58f3a2add9255ffcda45",
|
||||||
|
"reference": "0925f10b259679b5d8ca58f3a2add9255ffcda45",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-fileinfo": "*",
|
||||||
|
"guzzlehttp/psr7": "~1.1 || ^2.0",
|
||||||
|
"php": ">=5.4.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "~0.9.2",
|
||||||
|
"phpunit/phpunit": "^4.8 || ^5.7 || ^7.5.15"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-gd": "to use GD library based image processing.",
|
||||||
|
"ext-imagick": "to use Imagick based image processing.",
|
||||||
|
"intervention/imagecache": "Caching extension for the Intervention Image library"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "2.4-dev"
|
||||||
|
},
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"Intervention\\Image\\ImageServiceProvider"
|
||||||
|
],
|
||||||
|
"aliases": {
|
||||||
|
"Image": "Intervention\\Image\\Facades\\Image"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Intervention\\Image\\": "src/Intervention/Image"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Oliver Vogel",
|
||||||
|
"email": "oliver@olivervogel.com",
|
||||||
|
"homepage": "http://olivervogel.com/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Image handling and manipulation library with support for Laravel integration",
|
||||||
|
"homepage": "http://image.intervention.io/",
|
||||||
|
"keywords": [
|
||||||
|
"gd",
|
||||||
|
"image",
|
||||||
|
"imagick",
|
||||||
|
"laravel",
|
||||||
|
"thumbnail",
|
||||||
|
"watermark"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/Intervention/image/issues",
|
||||||
|
"source": "https://github.com/Intervention/image/tree/2.6.1"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://www.paypal.me/interventionphp",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/Intervention",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2021-07-22T14:31:53+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/http-message",
|
"name": "psr/http-message",
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
|
@ -291,5 +375,6 @@
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": [],
|
"platform": [],
|
||||||
"platform-dev": []
|
"platform-dev": [],
|
||||||
|
"plugin-api-version": "2.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
<?php namespace Aweos\Resizer\Console;
|
<?php namespace Aweos\Resizer\Console;
|
||||||
|
|
||||||
use Storage;
|
use Aweos\Resizer\Classes\ResizeJob;
|
||||||
use GuzzleHttp\Client;
|
|
||||||
use Illuminate\Console\Command;
|
|
||||||
use System\Classes\MediaLibrary;
|
|
||||||
use Aweos\Resizer\Models\Setting;
|
use Aweos\Resizer\Models\Setting;
|
||||||
|
use GuzzleHttp\Client;
|
||||||
use GuzzleHttp\Exception\ClientException;
|
use GuzzleHttp\Exception\ClientException;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
use October\Rain\Database\Attach\Resizer;
|
use October\Rain\Database\Attach\Resizer;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Queue;
|
||||||
|
use Storage;
|
||||||
use Symfony\Component\Console\Helper\ProgressBar;
|
use Symfony\Component\Console\Helper\ProgressBar;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use System\Classes\MediaLibrary;
|
||||||
|
|
||||||
class ResizeMake extends Command
|
class ResizeMake extends Command
|
||||||
{
|
{
|
||||||
public $media = null;
|
public $media = null;
|
||||||
public $http = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string The console command name.
|
* @var string The console command name.
|
||||||
|
@ -26,14 +27,14 @@ class ResizeMake extends Command
|
||||||
*/
|
*/
|
||||||
protected $description = 'Resizes configured images';
|
protected $description = 'Resizes configured images';
|
||||||
|
|
||||||
public function forAllResizables($callback) {
|
public function resize(string $folder): void
|
||||||
$folders = Setting::get('folders');
|
{
|
||||||
$sizes = Setting::get('srcx');
|
foreach ($this->media->listFolderContents($folder) as $item) {
|
||||||
|
if ($item->type === 'folder') {
|
||||||
sort($sizes);
|
$this->resize($item->path);
|
||||||
|
} else {
|
||||||
foreach($folders as $folder) {
|
Queue::push(ResizeJob::class, [$item->path]);
|
||||||
$this->start($folder['folder'], $sizes, $callback);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,117 +44,12 @@ class ResizeMake extends Command
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$this->http = new Client(['base_uri' => 'https://api.tinify.com']);
|
|
||||||
$this->media = MediaLibrary::instance();
|
$this->media = MediaLibrary::instance();
|
||||||
ProgressBar::setFormatDefinition('custom', '%current%/%max% %bar% -- %message% (%size%)');
|
ProgressBar::setFormatDefinition('custom', '%current%/%max% %bar% -- %message% (%size%)');
|
||||||
$tinifyKey = Setting::get('tinify') ? Setting::get('tinypngkey') : null;
|
Storage::deleteDirectory('uploads/public/c');
|
||||||
|
|
||||||
$i = 0;
|
foreach (Setting::get('folders') as $folder) {
|
||||||
$this->forAllResizables(function($file, $w) use (&$i) {
|
$this->resize($folder['folder']);
|
||||||
$i++;
|
|
||||||
});
|
|
||||||
|
|
||||||
$bar = $this->output->createProgressBar($i);
|
|
||||||
$bar->setFormat('custom');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param File $file The current filename
|
|
||||||
* @param int $w Current width
|
|
||||||
* @param string $compressed compressed file
|
|
||||||
* @param string $uncompressed uncompressed file
|
|
||||||
*/
|
|
||||||
$this->forAllResizables(function($file, $w, $compressed, $uncompressed) use ($bar, $tinifyKey) {
|
|
||||||
$bar->setMessage($file->path);
|
|
||||||
$bar->setMessage($w, 'size');
|
|
||||||
$bar->advance();
|
|
||||||
|
|
||||||
if (Storage::exists($compressed)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Storage::exists($uncompressed)) {
|
|
||||||
$r = Resizer::open(Storage::disk('local')->path('media'.$file->path));
|
|
||||||
$r->resize($w, 0);
|
|
||||||
$r->save(Storage::disk('local')->path($uncompressed));
|
|
||||||
$this->info(Storage::url($uncompressed));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_null($tinifyKey)) {
|
|
||||||
$newUrl = url($this->media->getPathUrl(preg_replace('/^media/', '', $uncompressed)));
|
|
||||||
|
|
||||||
try {
|
|
||||||
$response = $this->http->post('/shrink', [
|
|
||||||
'headers' => [
|
|
||||||
'Content-Type' => 'application/json',
|
|
||||||
'Accept' => 'application/json',
|
|
||||||
'Authorization' => 'Basic '.base64_encode('api:'.$tinifyKey)
|
|
||||||
],
|
|
||||||
'json' => [
|
|
||||||
'source' => ['url' => $newUrl]
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
$output = json_decode((string) $response->getBody());
|
|
||||||
$url = $output->output->url;
|
|
||||||
|
|
||||||
$response = $this->http->get($output->output->url, [
|
|
||||||
'headers' => [
|
|
||||||
'Authorization' => 'Basic '.base64_encode('api:'.$tinifyKey)
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
$image = (string) $response->getBody();
|
|
||||||
|
|
||||||
Storage::put($compressed, $image);
|
|
||||||
Storage::delete($uncompressed);
|
|
||||||
} catch(ClientException $e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$bar->advance();
|
|
||||||
});
|
|
||||||
|
|
||||||
$bar->finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMediaOfType($f, $type) {
|
|
||||||
return array_filter($this->media->listFolderContents($f, 'title', 'image'), function($item) use ($f, $type) {
|
|
||||||
return $item->type == $type && $item->path != $f.'/c';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function start($f, $sizes, $callback) {
|
|
||||||
$f = '/'.ltrim(rtrim($f, '/'), '/');
|
|
||||||
|
|
||||||
$folders = $this->getMediaOfType($f, 'folder');
|
|
||||||
|
|
||||||
foreach ($folders as $folder) {
|
|
||||||
$this->start($folder->path, $sizes, $callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
$files = $this->getMediaOfType($f, 'file');
|
|
||||||
|
|
||||||
// Create C-Folder as current subfolder if it doesnt exist yet
|
|
||||||
if(count($files) && !$this->media->folderExists($f.'/c')) {
|
|
||||||
$this->media->makeFolder($f.'/c');
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($files as $file) {
|
|
||||||
foreach ($sizes as $w) {
|
|
||||||
$imagesize = getimagesize(Storage::path('media'.$file->path));
|
|
||||||
|
|
||||||
$uncompressedFilename = pathinfo($file->path, PATHINFO_FILENAME).'-'.$w.'.'.pathinfo($file->path, PATHINFO_EXTENSION);
|
|
||||||
$compressedFilename = pathinfo($file->path, PATHINFO_FILENAME).'-'.$w.'t.'.pathinfo($file->path, PATHINFO_EXTENSION);
|
|
||||||
|
|
||||||
$compressed = 'media'.dirname($file->path).'/c/'.$compressedFilename;
|
|
||||||
$uncompressed = 'media'.dirname($file->path).'/c/'.$uncompressedFilename;
|
|
||||||
|
|
||||||
if ($imagesize[0] < $w) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
call_user_func($callback, $file, $w, $compressed, $uncompressed);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,27 +5,29 @@
|
||||||
fields:
|
fields:
|
||||||
folders:
|
folders:
|
||||||
type: repeater
|
type: repeater
|
||||||
|
label: Überwachte Ordner
|
||||||
form:
|
form:
|
||||||
fields:
|
fields:
|
||||||
folder:
|
folder:
|
||||||
type: mediafinder
|
type: mediafinder
|
||||||
label: Folder
|
label: Folder
|
||||||
srcx:
|
breakpoints:
|
||||||
type: taglist
|
type: taglist
|
||||||
mode: array
|
mode: array
|
||||||
label: Source X
|
label: Breakpoints
|
||||||
srcy:
|
comment: Von diesen Werten werden Bilder generiert mit entsprechender Breite. Bitte nur die Breite in Pixel angeben. Die Höhe bestimmt sich nach der Zielgröße
|
||||||
type: taglist
|
sizes:
|
||||||
mode: array
|
type: repeater
|
||||||
label: Source Y
|
label: Seitenverhältnisse
|
||||||
|
form:
|
||||||
|
fields:
|
||||||
|
name:
|
||||||
|
label: Name
|
||||||
|
span: left
|
||||||
|
comment: Bitte im Slug Format eingeben - z.B. "big-box"
|
||||||
|
aspect_ratio:
|
||||||
|
label: Seitenverhältnis
|
||||||
|
comment: Bitte im Format [x]x[y] eingeben - z.B. 1280x700
|
||||||
|
span: right
|
||||||
|
comment: Ein Bild mit den selben Seitenverhältnissen des Originalbildes wird immer generiert. Gebe hier die Seitenverhältnisse in "x/y" an, die sonst noch generiert werden sollen, z.B. 16/9
|
||||||
|
|
||||||
tinify:
|
|
||||||
type: checkbox
|
|
||||||
label: Tinyfy with tinypng
|
|
||||||
tinypngkey:
|
|
||||||
type: text
|
|
||||||
label: Tinypng API Key
|
|
||||||
trigger:
|
|
||||||
action: show
|
|
||||||
field: tinify
|
|
||||||
condition: checked
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<phpunit backupGlobals="false"
|
||||||
|
backupStaticAttributes="false"
|
||||||
|
bootstrap="../../../modules/system/tests/bootstrap.php"
|
||||||
|
colors="true"
|
||||||
|
convertErrorsToExceptions="true"
|
||||||
|
convertNoticesToExceptions="true"
|
||||||
|
convertWarningsToExceptions="true"
|
||||||
|
processIsolation="false"
|
||||||
|
stopOnFailure="false"
|
||||||
|
>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="Plugin Unit Test Suite">
|
||||||
|
<directory>./tests</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
<php>
|
||||||
|
<env name="APP_ENV" value="testing" />
|
||||||
|
<env name="CACHE_DRIVER" value="array" />
|
||||||
|
<env name="SESSION_DRIVER" value="array" />
|
||||||
|
<env name="ACTIVE_THEME" value="test" />
|
||||||
|
<env name="CONVERT_LINE_ENDINGS" value="true" />
|
||||||
|
<env name="CMS_ROUTE_CACHE" value="true" />
|
||||||
|
<env name="CMS_TWIG_CACHE" value="false" />
|
||||||
|
<env name="ENABLE_CSRF" value="false" />
|
||||||
|
<env name="DB_CONNECTION" value="sqlite" />
|
||||||
|
<env name="DB_DATABASE" value=":memory:" />
|
||||||
|
</php>
|
||||||
|
</phpunit>
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aweos\Resizer\Tests\MediaTest;
|
||||||
|
|
||||||
|
use Aweos\Resizer\Models\Setting;
|
||||||
|
use Aweos\Resizer\Tests\TestCase;
|
||||||
|
use Event;
|
||||||
|
use Illuminate\Http\UploadedFile;
|
||||||
|
use Storage;
|
||||||
|
|
||||||
|
class DeleteTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
Storage::fake('local');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItDeletesAllVersionsIfOriginalImageDeleted()
|
||||||
|
{
|
||||||
|
Setting::set('folders', ['pages']);
|
||||||
|
Setting::set('sizes', []);
|
||||||
|
Setting::set('breakpoints', []);
|
||||||
|
|
||||||
|
UploadedFile::fake()->image(100, 100)->storeAs('uploads/public/c/pages', 'test.jpg', 'local');
|
||||||
|
Event::fire('media.file.delete', [null, '/pages/test.jpg', null]);
|
||||||
|
|
||||||
|
$this->assertFileCount(0, 'pages');
|
||||||
|
Storage::assertMissing('uploads/public/c/pages');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItPreservesDirectoryWhenThereAreOtherFiles()
|
||||||
|
{
|
||||||
|
Setting::set('folders', ['pages']);
|
||||||
|
Setting::set('sizes', []);
|
||||||
|
Setting::set('breakpoints', []);
|
||||||
|
|
||||||
|
UploadedFile::fake()->image(100, 100)->storeAs('uploads/public/c/pages', 'test.jpg', 'local');
|
||||||
|
UploadedFile::fake()->image(100, 100)->storeAs('uploads/public/c/pages', 'test2.jpg', 'local');
|
||||||
|
Event::fire('media.file.delete', [null, '/pages/test.jpg', null]);
|
||||||
|
|
||||||
|
$this->assertHasFile('pages/test2.jpg');
|
||||||
|
$this->assertDoesntHaveFile('pages/test.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItDeletesFileVersions()
|
||||||
|
{
|
||||||
|
Setting::set('folders', ['pages']);
|
||||||
|
Setting::set('sizes', []);
|
||||||
|
Setting::set('breakpoints', []);
|
||||||
|
|
||||||
|
UploadedFile::fake()->image(100, 100)->storeAs('uploads/public/c/pages', 'test.jpg', 'local');
|
||||||
|
UploadedFile::fake()->image(300, 500)->storeAs('uploads/public/c/pages', 'test-300x500.jpg', 'local');
|
||||||
|
Event::fire('media.file.delete', [null, '/pages/test.jpg', null]);
|
||||||
|
|
||||||
|
$this->assertDoesntHaveFile('pages/test-300x500.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aweos\Resizer\Tests\MediaTest;
|
||||||
|
|
||||||
|
use Aweos\Resizer\Classes\TagGenerator;
|
||||||
|
use Aweos\Resizer\Models\Setting;
|
||||||
|
use Aweos\Resizer\Tests\TestCase;
|
||||||
|
use Event;
|
||||||
|
use Illuminate\Http\UploadedFile;
|
||||||
|
use Storage;
|
||||||
|
|
||||||
|
class ImageTagTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
Storage::fake('local');
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
UploadedFile::fake()->image('test.jpg', 500, 500)->storeAs('uploads/public/c/pages', 'test-500x500.jpg', 'local');
|
||||||
|
UploadedFile::fake()->image('test.jpg', 200, 200)->storeAs('uploads/public/c/pages', 'test-200x200.jpg', 'local');
|
||||||
|
UploadedFile::fake()->image('test.jpg', 100, 100)->storeAs('uploads/public/c/pages', 'test-100x100.jpg', 'local');
|
||||||
|
|
||||||
|
$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(TagGenerator::class)->generate('pages/test.jpg'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
UploadedFile::fake()->image('test.jpg', 100, 100)->storeAs('uploads/public/c/pages', 'test-100x100.jpg', 'local');
|
||||||
|
UploadedFile::fake()->image('test.jpg', 150, 100)->storeAs('uploads/public/c/pages', 'test-150x100.jpg', 'local');
|
||||||
|
|
||||||
|
$this->assertFalse(str_contains(
|
||||||
|
app(TagGenerator::class)->generate('pages/test.jpg'),
|
||||||
|
'150x100',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
UploadedFile::fake()->image('test.jpg', 100, 100)->storeAs('uploads/public/c/pages', 'test-100x100.jpg', 'local');
|
||||||
|
UploadedFile::fake()->image('test.jpg', 150, 100)->storeAs('uploads/public/c/pages', 'test-150x100.jpg', 'local');
|
||||||
|
UploadedFile::fake()->image('test.jpg', 250, 500)->storeAs('uploads/public/c/pages', 'test-250x500.jpg', 'local');
|
||||||
|
UploadedFile::fake()->image('test.jpg', 200, 400)->storeAs('uploads/public/c/pages', 'test-200x400.jpg', 'local');
|
||||||
|
UploadedFile::fake()->image('test.jpg', 100, 200)->storeAs('uploads/public/c/pages', 'test-100x200.jpg', 'local');
|
||||||
|
|
||||||
|
$this->assertFalse(str_contains(
|
||||||
|
app(TagGenerator::class)->generate('pages/test.jpg', 'size'),
|
||||||
|
'100x100',
|
||||||
|
));
|
||||||
|
$this->assertTrue(str_contains(
|
||||||
|
app(TagGenerator::class)->generate('pages/test.jpg', 'size'),
|
||||||
|
'200x400',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
UploadedFile::fake()->image('test.jpg', 640, 149)->storeAs('uploads/public/c/pages', 'test-640x149.jpg', 'local');
|
||||||
|
|
||||||
|
$this->assertTrue(str_contains(
|
||||||
|
app(TagGenerator::class)->generate('pages/test.jpg', 'size'),
|
||||||
|
'640x149',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aweos\Resizer\Tests\MediaTest;
|
||||||
|
|
||||||
|
use Aweos\Resizer\Models\Setting;
|
||||||
|
use Aweos\Resizer\Tests\TestCase;
|
||||||
|
use Event;
|
||||||
|
use Illuminate\Http\UploadedFile;
|
||||||
|
use Storage;
|
||||||
|
|
||||||
|
class MoveTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
Storage::fake('local');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItMovesAllVersionsOfAFile()
|
||||||
|
{
|
||||||
|
Setting::set('folders', ['pages']);
|
||||||
|
Setting::set('sizes', []);
|
||||||
|
Setting::set('breakpoints', []);
|
||||||
|
$this->media->put('/pages/alt/test.jpg', UploadedFile::fake()->image(100, 100)->get());
|
||||||
|
UploadedFile::fake()->image(100, 100)->storeAs('uploads/public/c/pages/alt', 'test.jpg', 'local');
|
||||||
|
UploadedFile::fake()->image(100, 100)->storeAs('uploads/public/c/pages/alt', 'test-200x300.jpg', 'local');
|
||||||
|
|
||||||
|
Event::fire('media.file.move', [null, '/pages/alt/test.jpg', '/pages/neu/test.jpg']);
|
||||||
|
|
||||||
|
$this->assertFileCount(0, 'pages/alt');
|
||||||
|
$this->assertHasFile('pages/neu/test.jpg');
|
||||||
|
$this->assertHasFile('pages/neu/test-200x300.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItMovesFilesOnRename()
|
||||||
|
{
|
||||||
|
Setting::set('folders', ['pages']);
|
||||||
|
Setting::set('sizes', []);
|
||||||
|
Setting::set('breakpoints', []);
|
||||||
|
$this->media->put('/pages/test.jpg', UploadedFile::fake()->image(100, 100)->get());
|
||||||
|
UploadedFile::fake()->image(100, 100)->storeAs('uploads/public/c/pages', 'test.jpg', 'local');
|
||||||
|
UploadedFile::fake()->image(100, 100)->storeAs('uploads/public/c/pages', 'test-200x300.jpg', 'local');
|
||||||
|
|
||||||
|
Event::fire('media.file.rename', [null, '/pages/test.jpg', '/pages/testneu.jpg']);
|
||||||
|
|
||||||
|
$this->assertFileCount(2, 'pages');
|
||||||
|
$this->assertHasFile('pages/testneu.jpg');
|
||||||
|
$this->assertHasFile('pages/testneu-200x300.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItDoesntMoveOtherFilesInTheSameDirectory()
|
||||||
|
{
|
||||||
|
Setting::set('folders', ['pages']);
|
||||||
|
Setting::set('sizes', []);
|
||||||
|
Setting::set('breakpoints', []);
|
||||||
|
$this->media->put('/pages/test.jpg', UploadedFile::fake()->image(100, 100)->get());
|
||||||
|
UploadedFile::fake()->image(100, 100)->storeAs('uploads/public/c/pages', 'test.jpg', 'local');
|
||||||
|
UploadedFile::fake()->image(100, 100)->storeAs('uploads/public/c/pages', 'test-200x300.jpg', 'local');
|
||||||
|
UploadedFile::fake()->image(100, 100)->storeAs('uploads/public/c/pages', 'testother.jpg', 'local');
|
||||||
|
|
||||||
|
Event::fire('media.file.rename', [null, '/pages/test.jpg', '/pages/testneu.jpg']);
|
||||||
|
|
||||||
|
$this->assertFileCount(3, 'pages');
|
||||||
|
$this->assertHasFile('pages/testneu.jpg');
|
||||||
|
$this->assertHasFile('pages/testneu-200x300.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,158 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aweos\Resizer\Tests\MediaTest;
|
||||||
|
|
||||||
|
use Aweos\Resizer\Models\Setting;
|
||||||
|
use Aweos\Resizer\Tests\TestCase;
|
||||||
|
use Event;
|
||||||
|
use Illuminate\Http\UploadedFile;
|
||||||
|
use Media\Classes\MediaLibrary;
|
||||||
|
use Storage;
|
||||||
|
|
||||||
|
class ResizerTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
Storage::fake('local');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDontCopyOriginalFileWhenSettingsAreNotSet(): void
|
||||||
|
{
|
||||||
|
Setting::set('folders', []);
|
||||||
|
Setting::set('sizes', []);
|
||||||
|
Setting::set('breakpoints', []);
|
||||||
|
|
||||||
|
$file = UploadedFile::fake()->image('test.jpg', 500, 600);
|
||||||
|
$media = MediaLibrary::instance();
|
||||||
|
$media->put('/pages/test.jpg', $file);
|
||||||
|
Event::fire('media.file.upload', [null, '/pages/test.jpg', null]);
|
||||||
|
|
||||||
|
$this->assertFileCount(0, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCopyOriginalFileWithoutSizesWhenNoSizesAreSet(): void
|
||||||
|
{
|
||||||
|
Setting::set('folders', [['folder' => '/pages']]);
|
||||||
|
Setting::set('sizes', []);
|
||||||
|
Setting::set('breakpoints', []);
|
||||||
|
|
||||||
|
$file = UploadedFile::fake()->image('test.jpg', 500, 600);
|
||||||
|
$media = MediaLibrary::instance();
|
||||||
|
$media->put('/pages/test.jpg', $file->get());
|
||||||
|
Event::fire('media.file.upload', [null, '/pages/test.jpg', null]);
|
||||||
|
|
||||||
|
$this->assertFileCount(2, 'pages');
|
||||||
|
$this->assertHasFile('pages/test.jpg');
|
||||||
|
$this->assertHasFile('pages/test-500x600.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCopyTwoDirectoriesDeepButNotAnotherDirectory(): void
|
||||||
|
{
|
||||||
|
Setting::set('folders', [['folder' => '/pages']]);
|
||||||
|
Setting::set('sizes', []);
|
||||||
|
Setting::set('breakpoints', []);
|
||||||
|
|
||||||
|
$file = UploadedFile::fake()->image('test.jpg', 500, 600);
|
||||||
|
$media = MediaLibrary::instance();
|
||||||
|
$media->put('/pages-neu/test.jpg', $file->get());
|
||||||
|
Event::fire('media.file.upload', [null, '/pages-neu/test.jpg', null]);
|
||||||
|
|
||||||
|
$this->assertFileCount(0, 'pages');
|
||||||
|
$this->assertFileCount(0, 'pages-neu');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCopySubdirectoriesOfSelectedPath(): void
|
||||||
|
{
|
||||||
|
Setting::set('folders', [['folder' => '/pages']]);
|
||||||
|
Setting::set('sizes', []);
|
||||||
|
Setting::set('breakpoints', []);
|
||||||
|
|
||||||
|
$file = UploadedFile::fake()->image('test.jpg', 500, 600);
|
||||||
|
$media = MediaLibrary::instance();
|
||||||
|
$media->put('/pages/neu/test.jpg', $file->get());
|
||||||
|
Event::fire('media.file.upload', [null, '/pages/neu/test.jpg', null]);
|
||||||
|
|
||||||
|
$this->assertFileCount(2, 'pages/neu');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGenerateSizeIfSizeIsSmallerWithSameAspectRatio(): void
|
||||||
|
{
|
||||||
|
Setting::set('folders', [['folder' => '/pages']]);
|
||||||
|
Setting::set('sizes', []);
|
||||||
|
Setting::set('breakpoints', ['250']);
|
||||||
|
|
||||||
|
$file = UploadedFile::fake()->image('test.jpg', 500, 600);
|
||||||
|
$media = MediaLibrary::instance();
|
||||||
|
$media->put('/pages/neu/test.jpg', $file->get());
|
||||||
|
Event::fire('media.file.upload', [null, '/pages/neu/test.jpg', null]);
|
||||||
|
|
||||||
|
$this->assertFileCount(3, 'pages/neu');
|
||||||
|
$this->assertHasFile('pages/neu/test-250x300.jpg');
|
||||||
|
$this->assertHasFile('pages/neu/test-500x600.jpg');
|
||||||
|
$this->assertHasFile('pages/neu/test.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGenerateSizeIfSizeIsSmallerWithDifferentAspectRatio(): void
|
||||||
|
{
|
||||||
|
Setting::set('folders', [['folder' => '/pages']]);
|
||||||
|
Setting::set('sizes', []);
|
||||||
|
Setting::set('breakpoints', ['250']);
|
||||||
|
|
||||||
|
$file = UploadedFile::fake()->image('test.jpg', 500, 100);
|
||||||
|
$media = MediaLibrary::instance();
|
||||||
|
$media->put('/pages/neu/test.jpg', $file->get());
|
||||||
|
Event::fire('media.file.upload', [null, '/pages/neu/test.jpg', null]);
|
||||||
|
|
||||||
|
$this->assertHasFile('pages/neu/test-250x50.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDontGenerateSizeIfOriginalFileIsSmaller(): void
|
||||||
|
{
|
||||||
|
Setting::set('folders', [['folder' => '/pages']]);
|
||||||
|
Setting::set('sizes', []);
|
||||||
|
Setting::set('breakpoints', ['250']);
|
||||||
|
|
||||||
|
$file = UploadedFile::fake()->image('test.jpg', 250, 1000);
|
||||||
|
$media = MediaLibrary::instance();
|
||||||
|
$media->put('/pages/neu/test.jpg', $file->get());
|
||||||
|
Event::fire('media.file.upload', [null, '/pages/neu/test.jpg', null]);
|
||||||
|
|
||||||
|
$this->assertFileCount(2, 'pages/neu');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDontGenerateSizeIfImageWouldBeLarger(): void
|
||||||
|
{
|
||||||
|
Setting::set('folders', [['folder' => '/pages']]);
|
||||||
|
Setting::set('sizes', []);
|
||||||
|
Setting::set('breakpoints', ['250']);
|
||||||
|
|
||||||
|
$file = UploadedFile::fake()->image('test.jpg', 249, 1000);
|
||||||
|
$media = MediaLibrary::instance();
|
||||||
|
$media->put('/pages/neu/test.jpg', $file->get());
|
||||||
|
Event::fire('media.file.upload', [null, '/pages/neu/test.jpg', null]);
|
||||||
|
|
||||||
|
$this->assertFileCount(2, 'pages/neu');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGenerateBreakpointImage(): void
|
||||||
|
{
|
||||||
|
Setting::set('folders', [['folder' => '/pages']]);
|
||||||
|
Setting::set('sizes', [['name' => 'testas', 'aspect_ratio' => '5x8']]);
|
||||||
|
Setting::set('breakpoints', ['100']);
|
||||||
|
|
||||||
|
$file = UploadedFile::fake()->image('test.jpg', 500, 400);
|
||||||
|
$media = MediaLibrary::instance();
|
||||||
|
$media->put('/pages/neu/test.jpg', $file->get());
|
||||||
|
Event::fire('media.file.upload', [null, '/pages/neu/test.jpg', null]);
|
||||||
|
|
||||||
|
$this->assertFileCount(5, 'pages/neu');
|
||||||
|
$this->assertHasFile('pages/neu/test.jpg');
|
||||||
|
$this->assertHasFile('pages/neu/test-500x400.jpg');
|
||||||
|
$this->assertHasFile('pages/neu/test-250x400.jpg');
|
||||||
|
$this->assertHasFile('pages/neu/test-100x160.jpg');
|
||||||
|
$this->assertHasFile('pages/neu/test-100x80.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Aweos\Resizer\Tests;
|
||||||
|
|
||||||
|
use Media\Classes\MediaLibrary;
|
||||||
|
use PluginTestCase;
|
||||||
|
use Storage;
|
||||||
|
use System\Classes\PluginManager;
|
||||||
|
|
||||||
|
class TestCase extends PluginTestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public MediaLibrary $media;
|
||||||
|
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->media = MediaLibrary::instance();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function assertHasFile($file): void
|
||||||
|
{
|
||||||
|
Storage::disk('local')->assertExists("uploads/public/c/{$this->normalizeFilePath($file)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function assertDoesntHaveFile($file): void
|
||||||
|
{
|
||||||
|
Storage::disk('local')->assertMissing("uploads/public/c/{$this->normalizeFilePath($file)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function assertFileCount($count, $dir): void
|
||||||
|
{
|
||||||
|
$this->assertCount($count, Storage::disk('local')->files("uploads/public/c/{$this->normalizeFilePath($dir)}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function normalizeFilePath(string $path): string
|
||||||
|
{
|
||||||
|
return preg_replace('|^/*|', '', $path);
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 130 KiB |
Loading…
Reference in New Issue