diff --git a/composer.json b/composer.json index fde7b7e..21ef7a7 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,14 @@ { "name": "bkwld/croppa", "description": "Image thumbnail creation through specially formatted URLs for Laravel", + "keywords": [ + "image", + "thumb", + "resize", + "laravel" + ], + "homepage": "https://github.com/bkwld/croppa", + "license": "MIT", "authors": [ { "name": "Robert Reinhard" @@ -9,7 +17,6 @@ "name": "Samuel De Backer" } ], - "license": "MIT", "require": { "php": "^8.0.2", "illuminate/console": "^9.0", @@ -23,26 +30,36 @@ }, "require-dev": { "phpunit/phpunit": "^9.5.10", - "mockery/mockery": "^1.4.4" + "mockery/mockery": "^1.4.4", + "nunomaduro/larastan": "^2.0", + "orchestra/testbench": "^7.5" }, "suggest": { "ext-exif": "Required if you want to have Croppa auto-rotate images from devices like mobile phones based on exif meta data." }, "autoload": { - "psr-0": { - "Bkwld\\Croppa": "src/" + "psr-4": { + "Bkwld\\Croppa\\": "src" } }, - "minimum-stability": "dev", - "prefer-stable": true, + "autoload-dev": { + "psr-4": { + "Bkwld\\Croppa\\Test\\": "tests" + } + }, + "scripts": { + "test": "vendor/bin/phpunit" + }, "extra": { "laravel": { "providers": [ "Bkwld\\Croppa\\CroppaServiceProvider" ], "aliases": { - "Croppa": "Bkwld\\Croppa\\Facade" + "Croppa": "Bkwld\\Croppa\\Facades\\Croppa" } } - } + }, + "minimum-stability": "dev", + "prefer-stable": true } diff --git a/src/config/config.php b/config/config.php similarity index 100% rename from src/config/config.php rename to config/config.php diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..be9c617 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,10 @@ +includes: + - ./vendor/nunomaduro/larastan/extension.neon + +parameters: + + paths: + - src + + # The level 9 is the highest level + level: 5 diff --git a/phpunit.xml b/phpunit.xml index 34cd746..feefbc9 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,9 +1,5 @@ - + ./tests/ diff --git a/src/Bkwld/Croppa/Commands/Purge.php b/src/Commands/Purge.php similarity index 97% rename from src/Bkwld/Croppa/Commands/Purge.php rename to src/Commands/Purge.php index 246be63..9e59fbb 100644 --- a/src/Bkwld/Croppa/Commands/Purge.php +++ b/src/Commands/Purge.php @@ -26,7 +26,7 @@ class Purge extends Command protected $description = 'Delete all crops'; /** - * @var Bkwld\Croppa\Storage + * @var \Bkwld\Croppa\Storage */ protected $storage; diff --git a/src/Bkwld/Croppa/CroppaServiceProvider.php b/src/CroppaServiceProvider.php similarity index 85% rename from src/Bkwld/Croppa/CroppaServiceProvider.php rename to src/CroppaServiceProvider.php index dcfa241..31d3435 100644 --- a/src/Bkwld/Croppa/CroppaServiceProvider.php +++ b/src/CroppaServiceProvider.php @@ -25,8 +25,8 @@ public function register() }); // Interact with the disk. - $this->app->singleton(Storage::class, function ($app) { - return new Storage($app, $this->getConfig()); + $this->app->singleton(Storage::class, function () { + return new Storage($this->getConfig()); }); // API for use in apps. @@ -44,8 +44,8 @@ public function register() public function boot() { - $this->mergeConfigFrom(__DIR__.'/../../config/config.php', 'croppa'); - $this->publishes([__DIR__.'/../../config/config.php' => config_path('croppa.php')], 'croppa-config'); + $this->mergeConfigFrom(__DIR__.'/../config/config.php', 'croppa'); + $this->publishes([__DIR__.'/../config/config.php' => config_path('croppa.php')], 'croppa-config'); $this->app['router'] ->get('{path}', 'Bkwld\Croppa\Handler@handle') diff --git a/src/Bkwld/Croppa/Exception.php b/src/Exception.php similarity index 100% rename from src/Bkwld/Croppa/Exception.php rename to src/Exception.php diff --git a/src/Bkwld/Croppa/Facades/Croppa.php b/src/Facades/Croppa.php similarity index 100% rename from src/Bkwld/Croppa/Facades/Croppa.php rename to src/Facades/Croppa.php diff --git a/src/Bkwld/Croppa/Filters/BlackWhite.php b/src/Filters/BlackWhite.php similarity index 100% rename from src/Bkwld/Croppa/Filters/BlackWhite.php rename to src/Filters/BlackWhite.php diff --git a/src/Bkwld/Croppa/Filters/Blur.php b/src/Filters/Blur.php similarity index 100% rename from src/Bkwld/Croppa/Filters/Blur.php rename to src/Filters/Blur.php diff --git a/src/Bkwld/Croppa/Filters/Darkgray.php b/src/Filters/Darkgray.php similarity index 100% rename from src/Bkwld/Croppa/Filters/Darkgray.php rename to src/Filters/Darkgray.php diff --git a/src/Bkwld/Croppa/Filters/FilterInterface.php b/src/Filters/FilterInterface.php similarity index 100% rename from src/Bkwld/Croppa/Filters/FilterInterface.php rename to src/Filters/FilterInterface.php diff --git a/src/Bkwld/Croppa/Filters/Negative.php b/src/Filters/Negative.php similarity index 100% rename from src/Bkwld/Croppa/Filters/Negative.php rename to src/Filters/Negative.php diff --git a/src/Bkwld/Croppa/Filters/OrangeWarhol.php b/src/Filters/OrangeWarhol.php similarity index 100% rename from src/Bkwld/Croppa/Filters/OrangeWarhol.php rename to src/Filters/OrangeWarhol.php diff --git a/src/Bkwld/Croppa/Filters/TurquoiseWarhol.php b/src/Filters/TurquoiseWarhol.php similarity index 100% rename from src/Bkwld/Croppa/Filters/TurquoiseWarhol.php rename to src/Filters/TurquoiseWarhol.php diff --git a/src/Bkwld/Croppa/Handler.php b/src/Handler.php similarity index 95% rename from src/Bkwld/Croppa/Handler.php rename to src/Handler.php index 814f3e0..76ce173 100644 --- a/src/Bkwld/Croppa/Handler.php +++ b/src/Handler.php @@ -12,15 +12,20 @@ */ class Handler extends Controller { + /** + * @var URL + */ + private $url; + /** * @var Storage */ private $storage; /** - * @var URL + * @var Request */ - private $url; + private $request; /** * @var array @@ -42,10 +47,8 @@ public function __construct(URL $url, Storage $storage, Request $request, ?array * Handles a Croppa style route. * * @throws Exception - * - * @return Symfony\Component\HttpFoundation\StreamedResponse */ - public function handle(string $requestPath) + public function handle(string $requestPath): mixed { // Validate the signing token $token = $this->url->signingToken($requestPath); @@ -121,10 +124,6 @@ public function render(string $requestPath): ?string public function getContentType(string $path): string { switch (pathinfo($path, PATHINFO_EXTENSION)) { - case 'jpeg': - case 'jpg': - return 'image/jpeg'; - case 'gif': return 'image/gif'; @@ -133,6 +132,9 @@ public function getContentType(string $path): string case 'webp': return 'image/webp'; + + default: + return 'image/jpeg'; } } } diff --git a/src/Bkwld/Croppa/Helpers.php b/src/Helpers.php similarity index 93% rename from src/Bkwld/Croppa/Helpers.php rename to src/Helpers.php index 04db566..92a5f62 100644 --- a/src/Bkwld/Croppa/Helpers.php +++ b/src/Helpers.php @@ -9,14 +9,19 @@ class Helpers { /** - * @var Bkwld\Croppa\Storage + * @var \Bkwld\Croppa\URL + */ + private $url; + + /** + * @var \Bkwld\Croppa\Storage */ private $storage; /** - * @var Bkwld\Croppa\URL + * @var \Bkwld\Croppa\Handler */ - private $url; + private $handler; /** * Dependency injection. diff --git a/src/Bkwld/Croppa/Image.php b/src/Image.php similarity index 95% rename from src/Bkwld/Croppa/Image.php rename to src/Image.php index c607f96..b55516f 100644 --- a/src/Bkwld/Croppa/Image.php +++ b/src/Image.php @@ -10,7 +10,7 @@ class Image { /** - * @var Intervention\Image\Image + * @var \Intervention\Image\Image */ private $image; @@ -122,10 +122,10 @@ public function trimPerc(array $coords): self list($x1, $y1, $x2, $y2) = $coords; $imgWidth = $this->image->width(); $imgHeight = $this->image->height(); - $x = round($x1 * $imgWidth); - $y = round($y1 * $imgHeight); - $width = round($x2 * $imgWidth - $x); - $height = round($y2 * $imgHeight - $y); + $x = (int) round($x1 * $imgWidth); + $y = (int) round($y1 * $imgHeight); + $width = (int) round($x2 * $imgWidth - $x); + $height = (int) round($y2 * $imgHeight - $y); $this->image->crop($width, $height, $x, $y); return $this; @@ -246,11 +246,8 @@ public function pad(?int $width, ?int $height, array $options): self /** * Apply filters that have been defined in the config as seperate classes. - * - * @param array $filters Array of filter instances - * @param mixed $options */ - public function applyFilters($options): self + public function applyFilters(array $options): self { if (isset($options['filters']) && is_array($options['filters'])) { array_map(function ($filter) { diff --git a/src/Bkwld/Croppa/Storage.php b/src/Storage.php similarity index 91% rename from src/Bkwld/Croppa/Storage.php rename to src/Storage.php index d56c2ed..0a782f4 100644 --- a/src/Bkwld/Croppa/Storage.php +++ b/src/Storage.php @@ -11,51 +11,37 @@ /** * Interact with filesystems. */ -class Storage +final class Storage { - /** - * @var Illuminate\Container\Container - */ - private $app; - /** * @var array */ private $config; /** - * @var FilesystemAdapter + * @var ?FilesystemAdapter */ private $cropsDisk; /** - * @var FilesystemAdapter + * @var ?FilesystemAdapter */ private $srcDisk; /** * Inject dependencies. - * - * @param Illuminate\Container\Container - * @param null|mixed $app */ - public function __construct($app = null, ?array $config = null) + public function __construct(?array $config = null) { - $this->app = $app; $this->config = $config; } /** * Factory function to create an instance and then "mount" disks. - * - * @param Illuminate\Container\Container - * @param mixed $app - * - * @return Bkwld\Croppa\Storage */ - public static function make($app, array $config) + public static function make(array $config) { - return with(new static($app, $config))->mount(); + return with(new static($config))->mount(); } /** @@ -135,8 +121,6 @@ public function cropExists(string $path): bool /** * Get the src path or throw an exception. - * - * @throws Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ public function path(string $path): string { @@ -286,7 +270,7 @@ function ($file) use ($filter) { * Take a an array of results from Flysystem's listContents and get a simpler * array of paths to the files, relative to the crops_disk. */ - protected function justPaths(array $files): array + private function justPaths(array $files): array { // Reset the indexes to be 0 based, mostly for unit testing $files = array_values($files); diff --git a/src/Bkwld/Croppa/URL.php b/src/URL.php similarity index 100% rename from src/Bkwld/Croppa/URL.php rename to src/URL.php diff --git a/tests/TestDelete.php b/tests/TestDelete.php index 37326fe..23d37e4 100644 --- a/tests/TestDelete.php +++ b/tests/TestDelete.php @@ -1,10 +1,13 @@ src_disk = Mockery::mock(FilesystemAdapter::class) ->shouldReceive('fileExists')->with('01/me.jpg')->andReturn(true) diff --git a/tests/TestResizing.php b/tests/TestResizing.php index 17a1e02..41f310a 100644 --- a/tests/TestResizing.php +++ b/tests/TestResizing.php @@ -1,5 +1,7 @@ dir = Mockery::mock(FilesystemAdapter::class) ->shouldReceive('listContents') @@ -50,7 +55,7 @@ public function testAcceptableNumber() public function testTooMany() { - $storage = new Storage(null, ['max_crops' => 3]); + $storage = new Storage(['max_crops' => 3]); $storage->setCropsDisk($this->dir); $this->assertTrue($storage->tooManyCrops('me.jpg')); } diff --git a/tests/TestUrlGenerator.php b/tests/TestUrlGenerator.php index 45e3f73..5fee248 100644 --- a/tests/TestUrlGenerator.php +++ b/tests/TestUrlGenerator.php @@ -1,5 +1,7 @@ url = new URL([ 'path' => 'uploads/(.*)$', ]); diff --git a/tests/TestUrlParsing.php b/tests/TestUrlParsing.php index 0d16510..57d0125 100644 --- a/tests/TestUrlParsing.php +++ b/tests/TestUrlParsing.php @@ -1,5 +1,13 @@ url = new URL([ 'path' => 'uploads/(.*)$', 'filters' => [ - 'gray' => Bkwld\Croppa\Filters\BlackWhite::class, - 'darkgray' => Bkwld\Croppa\Filters\Darkgray::class, - 'blur' => Bkwld\Croppa\Filters\Blur::class, - 'negative' => Bkwld\Croppa\Filters\Negative::class, - 'orange' => Bkwld\Croppa\Filters\OrangeWarhol::class, - 'turquoise' => Bkwld\Croppa\Filters\TurquoiseWarhol::class, + 'gray' => BlackWhite::class, + 'darkgray' => Darkgray::class, + 'blur' => Blur::class, + 'negative' => Negative::class, + 'orange' => OrangeWarhol::class, + 'turquoise' => TurquoiseWarhol::class, ], ]); } @@ -77,8 +87,8 @@ public function testFilters() { $this->assertEquals([ '1/2/file.jpg', 200, 100, ['filters' => [ - new Bkwld\Croppa\Filters\Blur(), - new Bkwld\Croppa\Filters\Negative(), + new Blur(), + new Negative(), ]], ], $this->url->parse('uploads/1/2/file-200x100-filters(blur,negative).jpg')); }