Modifs
This commit is contained in:
		
							
								
								
									
										27
									
								
								composer.json
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										27
									
								
								composer.json
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | { | ||||||
|  |     "name": "meoran/images", | ||||||
|  |     "description": "Gestion des images en base de données", | ||||||
|  |     "type": "library", | ||||||
|  |     "license": "MIT", | ||||||
|  |     "authors": [ | ||||||
|  |         { | ||||||
|  |             "name": "Cassandre Cantet", | ||||||
|  |             "email": "pro@cassandrecantet.fr" | ||||||
|  |         } | ||||||
|  |     ], | ||||||
|  |     "require": { | ||||||
|  |         "php": ">=7.0.0", | ||||||
|  |         "laravel/lumen-framework": "5.4.*", | ||||||
|  |         "symfony/process" : "3.*", | ||||||
|  |         "intervention/image": "^2.4", | ||||||
|  |         "intervention/imagecache": "^2.3", | ||||||
|  |         "spatie/laravel-image-optimizer": "^1.1" | ||||||
|  |     }, | ||||||
|  |     "autoload": { | ||||||
|  |         "psr-4": { | ||||||
|  |             "Meoran\\Images\\": "src/" | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     "prefer-stable": true, | ||||||
|  |     "minimum-stability": "dev" | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								config/image.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										15
									
								
								config/image.php
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | return [ | ||||||
|  |     'route' => 'images', | ||||||
|  |     'path' => storage_path('images'), | ||||||
|  |     'templates' => array( | ||||||
|  |         'small' => \Meoran\Images\Templates\Small::class, | ||||||
|  |         'medium' => \Meoran\Images\Templates\Medium::class, | ||||||
|  |         'large' => \Meoran\Images\Templates\Large::class, | ||||||
|  |     ), | ||||||
|  |     'lifetime' => 10, | ||||||
|  |     'cache' => [ | ||||||
|  |         'path' => storage_path('app') | ||||||
|  |     ] | ||||||
|  | ]; | ||||||
							
								
								
									
										34
									
								
								database/migrations/2017_10_03_135933_create_images__table.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										34
									
								
								database/migrations/2017_10_03_135933_create_images__table.php
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | use Illuminate\Database\Migrations\Migration; | ||||||
|  | use Illuminate\Database\Schema\Blueprint; | ||||||
|  | use Illuminate\Support\Facades\Schema; | ||||||
|  |  | ||||||
|  | class CreateImagesTable extends Migration | ||||||
|  | { | ||||||
|  |     /** | ||||||
|  |      * Run the migrations. | ||||||
|  |      * | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function up() | ||||||
|  |     { | ||||||
|  |         Schema::create('images', function (Blueprint $table) { | ||||||
|  |             $table->integer('id', true); | ||||||
|  |             $table->string('filename'); | ||||||
|  |             $table->dateTime('created_at'); | ||||||
|  |             $table->dateTime('updated_at'); | ||||||
|  |             $table->unique('filename'); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Reverse the migrations. | ||||||
|  |      * | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function down() | ||||||
|  |     { | ||||||
|  |         Schema::drop('images'); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										38
									
								
								database/migrations/2017_10_03_140902_create_associate_images.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										38
									
								
								database/migrations/2017_10_03_140902_create_associate_images.php
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | use Illuminate\Database\Migrations\Migration; | ||||||
|  | use Illuminate\Database\Schema\Blueprint; | ||||||
|  | use Illuminate\Support\Facades\Schema; | ||||||
|  |  | ||||||
|  | class CreateAssociateImages extends Migration | ||||||
|  | { | ||||||
|  |     /** | ||||||
|  |      * Run the migrations. | ||||||
|  |      * | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function up() | ||||||
|  |     { | ||||||
|  |         Schema::create('associate_images', function (Blueprint $table) { | ||||||
|  |             $table->integer('id', true); | ||||||
|  |             $table->integer('image_id'); | ||||||
|  |             $table->string('relation_type'); | ||||||
|  |             $table->integer('relation_id'); | ||||||
|  |             $table->integer('position')->nullable(); | ||||||
|  |  | ||||||
|  |             $table->foreign('image_id')->references('id')->on('images'); | ||||||
|  |  | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Reverse the migrations. | ||||||
|  |      * | ||||||
|  |      * @return void | ||||||
|  |      */ | ||||||
|  |     public function down() | ||||||
|  |     { | ||||||
|  |         Schema::drop('associate_images'); | ||||||
|  |  | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										8
									
								
								src/Exception/InvalidContent.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										8
									
								
								src/Exception/InvalidContent.php
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | namespace Meoran\Images\Exception; | ||||||
|  |  | ||||||
|  | class InvalidContent extends \Exception | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										132
									
								
								src/Http/Controllers/ImagesController.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										132
									
								
								src/Http/Controllers/ImagesController.php
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,132 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | namespace Meoran\Images\Http\Controllers; | ||||||
|  |  | ||||||
|  | use Closure; | ||||||
|  | use Illuminate\Http\Request; | ||||||
|  | use Laravel\Lumen\Routing\Controller as BaseController; | ||||||
|  | use Meoran\Images\Model\Image; | ||||||
|  |  | ||||||
|  | class ImagesController extends BaseController | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     public function get($template, $filename) | ||||||
|  |     { | ||||||
|  |         switch (strtolower($template)) { | ||||||
|  |             case 'original': | ||||||
|  |                 return $this->getOriginal($filename); | ||||||
|  |             case 'download': | ||||||
|  |                 return $this->getDownload($filename); | ||||||
|  |             default: | ||||||
|  |                 return $this->getImage($template, $filename); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function upload(Request $request) | ||||||
|  |     { | ||||||
|  |         $this->validate($request, [ | ||||||
|  |            'image' => 'required|file|image' | ||||||
|  |         ]); | ||||||
|  |  | ||||||
|  |         $image = new Image(['content' => $request->input('image')]); | ||||||
|  |         $image->save(); | ||||||
|  |  | ||||||
|  |         return response()->json($image); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private function getOriginal($filename) | ||||||
|  |     { | ||||||
|  |         $path = $this->getImagePathOrAbort($filename); | ||||||
|  |         return $this->buildResponse(file_get_contents($path)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private function getDownload($filename) | ||||||
|  |     { | ||||||
|  |         $response = $this->getOriginal($filename); | ||||||
|  |  | ||||||
|  |         return $response->header( | ||||||
|  |             'Content-Disposition', | ||||||
|  |             'attachment; filename=' . $filename | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private function getImagePathOrAbort($filename) | ||||||
|  |     { | ||||||
|  |         $path = Image::getAbsolutePath($filename); | ||||||
|  |         if (is_file($path)) { | ||||||
|  |             return $path; | ||||||
|  |         } | ||||||
|  |         abort(404); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function getImage($template, $filename) | ||||||
|  |     { | ||||||
|  |         $template = $this->getTemplate($template); | ||||||
|  |         $path = $this->getImagePathOrAbort($filename); | ||||||
|  |  | ||||||
|  |         $lifetime = config('image.lifetime'); | ||||||
|  |         if (empty($lifetime)) { | ||||||
|  |             $content = $this->applyTemplate($template,$path)->encode(); | ||||||
|  |         } else { | ||||||
|  |             $content = app('image')->cache(function ($image) use ($template, $path) { | ||||||
|  |                 $this->applyTemplate($template,$path,$image); | ||||||
|  |                 return $image; | ||||||
|  |             }, $lifetime); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return $this->buildResponse($content); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private function applyTemplate($template, $path, $image = null) | ||||||
|  |     { | ||||||
|  |         if (empty($image)) { | ||||||
|  |             $image = app('image'); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if ($template instanceof Closure) { | ||||||
|  |             // build from closure callback template | ||||||
|  |             return $template($image->make($path)); | ||||||
|  |         } else { | ||||||
|  |             // build from filter template | ||||||
|  |             return $image->make($path)->filter($template); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Returns corresponding template object from given template name | ||||||
|  |      * | ||||||
|  |      * @param  string $template | ||||||
|  |      * @return mixed | ||||||
|  |      */ | ||||||
|  |     private function getTemplate($template) | ||||||
|  |     { | ||||||
|  |         $template = config("image.templates.{$template}"); | ||||||
|  |         switch (true) { | ||||||
|  |             // closure template found | ||||||
|  |             case is_callable($template): | ||||||
|  |                 return $template; | ||||||
|  |  | ||||||
|  |             // filter template found | ||||||
|  |             case class_exists($template): | ||||||
|  |                 return new $template; | ||||||
|  |  | ||||||
|  |             default: | ||||||
|  |                 // template not found | ||||||
|  |                 abort(404); | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private function buildResponse($content) | ||||||
|  |     { | ||||||
|  |         // define mime type | ||||||
|  |         $mime = finfo_buffer(finfo_open(FILEINFO_MIME_TYPE), $content); | ||||||
|  |  | ||||||
|  |         // return http response | ||||||
|  |         return response($content, 200, array( | ||||||
|  |             'Content-Type' => $mime, | ||||||
|  |             'Cache-Control' => 'max-age=' . (config('image.lifetime') * 60) . ', public', | ||||||
|  |             'Etag' => md5($content) | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										174
									
								
								src/Model/Image.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										174
									
								
								src/Model/Image.php
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,174 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | namespace Meoran\Images\Model; | ||||||
|  |  | ||||||
|  | use Illuminate\Database\Eloquent\Model; | ||||||
|  | use Intervention\Image\Exception\NotReadableException; | ||||||
|  | use Meoran\Images\Exception\InvalidContent; | ||||||
|  | use Spatie\ImageOptimizer\OptimizerChain; | ||||||
|  | use \Intervention\Image\Image as InterventionImage; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Class Image | ||||||
|  |  * @property Image $content | ||||||
|  |  * @package App\Model | ||||||
|  |  */ | ||||||
|  | class Image extends Model | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     protected $_content; | ||||||
|  |  | ||||||
|  |     protected $table = 'images'; | ||||||
|  |  | ||||||
|  |     public $fillable = [ | ||||||
|  |         'filename', | ||||||
|  |         'content', | ||||||
|  |         'position', | ||||||
|  |         'created', | ||||||
|  |         'updated' | ||||||
|  |     ]; | ||||||
|  |     protected $dates = ['created_at', 'updated_at']; | ||||||
|  |     protected $appends = ['url']; | ||||||
|  |     protected $hidden = []; | ||||||
|  |  | ||||||
|  |     public function getUrlAttribute() | ||||||
|  |     { | ||||||
|  |         return app('url')->to('/' . config('image.route') . '/original/' . $this->filename); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected static function boot() | ||||||
|  |     { | ||||||
|  |         parent::boot(); | ||||||
|  |  | ||||||
|  |         static::creating(function (Image $model) { | ||||||
|  |             if (empty($model->content)) { | ||||||
|  |                 throw new InvalidContent("Content must be defined to save image"); | ||||||
|  |             } | ||||||
|  |             if (!($model->content instanceof InterventionImage)) { | ||||||
|  |                 throw new InvalidContent("Content must be an instance of Intervention\Image"); | ||||||
|  |             } | ||||||
|  |             $model->savePicture(); | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         static::updating(function (Image $model) { | ||||||
|  |             $model->savePicture(); | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         static::deleted(function (Image $model) { | ||||||
|  |             $model->deletePicture(); | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function getPath() | ||||||
|  |     { | ||||||
|  |         if (empty($this->filename)) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return self::getAbsolutePath($this->filename); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     static function getAbsolutePath($filename) | ||||||
|  |     { | ||||||
|  |         $basePath = config('image.path'); | ||||||
|  |  | ||||||
|  |         $parts = array_slice(str_split(mb_strtolower(str_slug($filename, '')), 2), 0, 2); | ||||||
|  |  | ||||||
|  |         $path = $basePath . '/' . implode('/', $parts) . '/' . $filename; | ||||||
|  |  | ||||||
|  |         return $path; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     static function generateRandomFilename() | ||||||
|  |     { | ||||||
|  |         return mb_strtolower(str_random(60)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     static function sanitizeFilename($filename) | ||||||
|  |     { | ||||||
|  |         return str_slug($filename, '-'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function setFilenameAttribute($value) | ||||||
|  |     { | ||||||
|  |         $pattern = '/[^a-z_\-\.0-9]/i'; | ||||||
|  |         if (preg_match($pattern, $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; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function fileExist() { | ||||||
|  |         return is_file($this->getPath()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function generateFilename($force = false) | ||||||
|  |     { | ||||||
|  |         if ($this->filename && !$force) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         $this->filename = self::generateRandomFilename(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function setContentAttribute($content) | ||||||
|  |     { | ||||||
|  |         $this->_content = app('image')->make($content); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function getContentAttribute($value) | ||||||
|  |     { | ||||||
|  |         if (empty($this->_content)) { | ||||||
|  |             try { | ||||||
|  |                 $this->_content = app('image')->make($this->getPath()); | ||||||
|  |             } catch (NotReadableException $e) { | ||||||
|  |                 return null; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return $this->_content; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function savePicture() | ||||||
|  |     { | ||||||
|  |         if (empty($this->content)) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         $this->generateFilename(); | ||||||
|  |         return $this->saveContent(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function saveContent() | ||||||
|  |     { | ||||||
|  |         if (empty($this->content)) { | ||||||
|  |             throw new \InvalidArgumentException("Content is Empty"); | ||||||
|  |         } | ||||||
|  |         $path = $this->getPath(); | ||||||
|  |         $dir = dirname($path); | ||||||
|  |         if (!is_dir($dir)) { | ||||||
|  |             mkdir($dir, 0775, true); | ||||||
|  |         } | ||||||
|  |         $res = $this->content->save($path); | ||||||
|  |         app(OptimizerChain::class)->optimize($path); | ||||||
|  |         return $res; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function deletePicture() | ||||||
|  |     { | ||||||
|  |         $path = $this->getPath(); | ||||||
|  |         if (is_file($path)) { | ||||||
|  |             return unlink($path); | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function toArray() | ||||||
|  |     { | ||||||
|  |         $attributes = parent::toArray(); | ||||||
|  |  | ||||||
|  |         if (isset($attributes['pivot']) && array_key_exists('position', $attributes['pivot'])) { | ||||||
|  |             $attributes['position'] = $attributes['pivot']['position']; | ||||||
|  |         } | ||||||
|  |         unset($attributes['pivot']); | ||||||
|  |         return $attributes; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										43
									
								
								src/Providers/ImagesServiceProvider.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										43
									
								
								src/Providers/ImagesServiceProvider.php
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,43 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | namespace Meoran\Images\Providers; | ||||||
|  |  | ||||||
|  | use Illuminate\Support\ServiceProvider; | ||||||
|  | use Intervention\Image\ImageServiceProvider; | ||||||
|  | use Spatie\LaravelImageOptimizer\ImageOptimizerServiceProvider; | ||||||
|  |  | ||||||
|  | class ImagesServiceProvider extends ServiceProvider | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     public function boot() | ||||||
|  |     { | ||||||
|  |         require_once __DIR__ . '/../functions.php'; | ||||||
|  |  | ||||||
|  |         $this->loadMigrationsFrom(__DIR__ . '/../../database/migrations'); | ||||||
|  |         $this->mergeConfigFrom(__DIR__ . '/../../config/image.php', 'image'); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         $this->app->register(ImageServiceProvider::class); | ||||||
|  |         $this->app->register(ImageOptimizerServiceProvider::class); | ||||||
|  |  | ||||||
|  |         $this->loadRoutes(); | ||||||
|  |  | ||||||
|  |         if ($this->app->runningInConsole()) { | ||||||
|  |             $this->publishes([ | ||||||
|  | //                __DIR__ . '/../../config/synchronize.php' => base_path('config/synchronize.php') | ||||||
|  |             ]); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function loadRoutes() | ||||||
|  |     { | ||||||
|  |         $this->app->post('images/upload', [ | ||||||
|  |             'as' => 'uploadImage', 'uses' => '\Meoran\Images\Http\Controllers\ImagesController@upload' | ||||||
|  |         ]); | ||||||
|  |  | ||||||
|  |         $this->app->get('images/{template}/{filename}', [ | ||||||
|  |             'as' => 'getPicture', 'uses' => '\Meoran\Images\Http\Controllers\ImagesController@get' | ||||||
|  |         ]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								src/Templates/Large.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										18
									
								
								src/Templates/Large.php
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | namespace Meoran\Images\Templates; | ||||||
|  |  | ||||||
|  | use Intervention\Image\Constraint; | ||||||
|  | use Intervention\Image\Filters\FilterInterface; | ||||||
|  | use Intervention\Image\Image; | ||||||
|  |  | ||||||
|  | class Large implements FilterInterface | ||||||
|  | { | ||||||
|  |     public function applyFilter(Image $image) | ||||||
|  |     { | ||||||
|  |         return $image->resize(1920, null, function (Constraint $constraint) { | ||||||
|  |             $constraint->upsize(); | ||||||
|  |             $constraint->aspectRatio(); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								src/Templates/Medium.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										18
									
								
								src/Templates/Medium.php
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | namespace Meoran\Images\Templates; | ||||||
|  |  | ||||||
|  | use Intervention\Image\Constraint; | ||||||
|  | use Intervention\Image\Filters\FilterInterface; | ||||||
|  | use Intervention\Image\Image; | ||||||
|  |  | ||||||
|  | class Medium implements FilterInterface | ||||||
|  | { | ||||||
|  |     public function applyFilter(Image $image) | ||||||
|  |     { | ||||||
|  |         return $image->resize(240, null, function (Constraint $constraint) { | ||||||
|  |             $constraint->upsize(); | ||||||
|  |             $constraint->aspectRatio(); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								src/Templates/Small.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										18
									
								
								src/Templates/Small.php
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | namespace Meoran\Images\Templates; | ||||||
|  |  | ||||||
|  | use Intervention\Image\Constraint; | ||||||
|  | use Intervention\Image\Filters\FilterInterface; | ||||||
|  | use Intervention\Image\Image; | ||||||
|  |  | ||||||
|  | class Small implements FilterInterface | ||||||
|  | { | ||||||
|  |     public function applyFilter(Image $image) | ||||||
|  |     { | ||||||
|  |         return $image->resize(120, null, function (Constraint $constraint) { | ||||||
|  |             $constraint->upsize(); | ||||||
|  |             $constraint->aspectRatio(); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								src/functions.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										14
									
								
								src/functions.php
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | if (!function_exists('config_path')) { | ||||||
|  |     /** | ||||||
|  |      * Get the configuration path. | ||||||
|  |      * | ||||||
|  |      * @param  string $path | ||||||
|  |      * @return string | ||||||
|  |      */ | ||||||
|  |     function config_path($path = '') | ||||||
|  |     { | ||||||
|  |         return app()->basePath() . '/config' . ($path ? '/' . $path : $path); | ||||||
|  |     } | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 Cassandre Cantet
					Cassandre Cantet