diff --git a/composer.json b/composer.json index 02747f8..8128a4e 100755 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ ], "require": { "php": ">=7.0.0", - "laravel/lumen-framework": "5.4.*", + "laravel/lumen-framework": "5.*", "symfony/process" : "3.*", "intervention/image": "^2.4", "intervention/imagecache": "^2.3", diff --git a/src/Console/Commands/CacheGarbageCollectorCommand.php b/src/Console/Commands/CacheGarbageCollectorCommand.php new file mode 100755 index 0000000..119ab35 --- /dev/null +++ b/src/Console/Commands/CacheGarbageCollectorCommand.php @@ -0,0 +1,80 @@ +getPathname()), 0, 10); + if (!is_numeric($time)) { + continue; + } + + if ($time <= time()) { + unlink($file->getPathname()); + $expiredFileCount++; + } else { + $activeFileCount++; + + } + } + + $this->line('Total expired cache files removed: '.$expiredFileCount); + $this->line('Total active cache files remaining: '.$activeFileCount); + } + + /** + * Get the console command options. + * + * @return array + */ + protected function getOptions() + { + return []; + } + +} diff --git a/src/Console/Commands/RemoveUselessPicturesCommand.php b/src/Console/Commands/RemoveUselessPicturesCommand.php new file mode 100755 index 0000000..305680c --- /dev/null +++ b/src/Console/Commands/RemoveUselessPicturesCommand.php @@ -0,0 +1,107 @@ +removeNonExistentPictures(); +// $this->removeNotUsedPictures(); + } + + private function removeNonExistentPictures() + { + $base = config('image.path'); + + $it = new FilesystemIterator($base); + + $fs = new Filesystem(); + $files = $fs->allFiles($base); + + var_dump($files); + exit; + /** + * Suppression des images qui n'existent pas physiquement + */ + $linesToDelete = Image::whereNotIn('filename', $files)->get(); + $delete = 0; + foreach ($linesToDelete as $lineToDelete) { + $lineToDelete->delete(); + $delete++; + } + $this->info("Images supprimées en base : ".$delete); + + /** + * Suppression des images qui ne sont pas en base + */ + $pictures = Image::select('filename')->getQuery()->get()->transform(function ($item) { + return $item->filename; + })->all(); + $delete = 0; + foreach ($files as $file) { + if (!in_array($file, $pictures)) { + unlink($base . $file); + $delete++; + } + } + $this->info("Images supprimées physiquement : ".$delete); + + } + + /** + * Suppression des images qui existent physiquement et en base mais qui ne sont pas utilisées + */ + private function removeNotUsedPictures() + { + $base = config('picturesPath'); + + $pictures = Image::whereDoesntHave('section', function ($query) { + $query->withTrashed(); + })->whereDoesntHave('news', function ($query) { + $query->withTrashed(); + })->whereDoesntHave('pages', function ($query) { + $query->withTrashed(); + })->get(); + $delete = 0; + foreach ($pictures as $picture) { + if (is_file($base . $picture->filename)) { + unlink($base . $picture->filename); + } + $picture->delete(); + $delete++; + } + $this->info("Images supprimées car non utilisées : ".$delete); + } +} diff --git a/src/Http/Controllers/ImagesController.php b/src/Http/Controllers/ImagesController.php index f82018d..5f155c0 100755 --- a/src/Http/Controllers/ImagesController.php +++ b/src/Http/Controllers/ImagesController.php @@ -103,7 +103,7 @@ class ImagesController extends BaseController */ private function getTemplate($template) { - $template = config("image.templates.{$template}"); + $template = config("images.templates.{$template}"); switch (true) { // closure template found case is_callable($template): diff --git a/src/Model/Image.php b/src/Model/Image.php index dafc761..d564cc3 100755 --- a/src/Model/Image.php +++ b/src/Model/Image.php @@ -4,6 +4,7 @@ namespace Meoran\Images\Model; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\MorphToMany; +use Illuminate\Database\Query\Builder; use Intervention\Image\Exception\NotReadableException; use Intervention\Image\Image as InterventionImage; use Meoran\Images\Exception\InvalidContent; @@ -11,12 +12,15 @@ use Spatie\ImageOptimizer\OptimizerChain; /** * Class Image - * @property Image $content + * @property InterventionImage $content * @package App\Model */ class Image extends Model { + /** + * @var InterventionImage $_content + */ protected $_content; protected $table = 'images'; @@ -99,7 +103,8 @@ class Image extends Model public function setFilenameAttribute($value) { $pattern = '/[^a-z_\-\.0-9]/i'; - if (preg_match($pattern, $value)) { + $patternLetter = '/[a-z0-9]+/i'; + if (preg_match($pattern, $value) || !preg_match($patternLetter, $value)) { throw new \InvalidArgumentException("Invalid filename. Must be only composed only with a-z, A-Z, 0-9 and dot minus underscore"); } $this->attributes['filename'] = $value; @@ -121,6 +126,31 @@ class Image extends Model public function setContentAttribute($content) { $this->_content = app('image')->make($content); + $this->setHash(); + } + + public function getHashAttribute() + { + if (!array_key_exists('hash', $this->attributes)) { + $this->setHash(); + } + return $this->attributes['hash']; + } + + protected function setHash() + { + if (empty($this->content)) { + $this->attributes['hash'] = null; + return; + } + $this->attributes['hash'] = sha1($this->content->getEncoded()); + } + + public function same(Image $image) + { + $hash1 = $this->hash; + $hash2 = $image->hash; + return !empty($hash1) && !empty($hash2) && $hash1 === $hash2; } public function getContentAttribute($value) @@ -199,4 +229,8 @@ class Image extends Model return $attributes; } + + public function scopeContent(Builder $builder, Image $image) { + $builder->where('hash', $image->hash); + } } diff --git a/src/Providers/ImagesServiceProvider.php b/src/Providers/ImagesServiceProvider.php index 08165b8..f65278b 100755 --- a/src/Providers/ImagesServiceProvider.php +++ b/src/Providers/ImagesServiceProvider.php @@ -4,6 +4,8 @@ namespace Meoran\Images\Providers; use Illuminate\Support\ServiceProvider; use Intervention\Image\ImageServiceProvider; +use Meoran\Images\Console\Commands\CacheGarbageCollectorCommand; +use Meoran\Images\Console\Commands\RemoveUselessPicturesCommand; use Spatie\LaravelImageOptimizer\ImageOptimizerServiceProvider; class ImagesServiceProvider extends ServiceProvider @@ -14,7 +16,7 @@ class ImagesServiceProvider extends ServiceProvider require_once __DIR__ . '/../functions.php'; $this->loadMigrationsFrom(__DIR__ . '/../../database/migrations'); - $this->mergeConfigFrom(__DIR__ . '/../../config/image.php', 'image'); + $this->mergeConfigFrom(__DIR__ . '/../../config/image.php', 'images'); $this->app->register(ImageServiceProvider::class); @@ -26,6 +28,11 @@ class ImagesServiceProvider extends ServiceProvider $this->publishes([ // __DIR__ . '/../../config/synchronize.php' => base_path('config/synchronize.php') ]); + + $this->commands([ +// CacheGarbageCollectorCommand::class, +// RemoveUselessPicturesCommand::class, + ]); } }