From abda88bd66b0f807b52a9a67a16235998b63676b Mon Sep 17 00:00:00 2001 From: Samuel De Backer Date: Sun, 15 May 2022 22:47:32 +0200 Subject: [PATCH 1/4] psr-4 --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index fde7b7e..e601d55 100644 --- a/composer.json +++ b/composer.json @@ -29,8 +29,8 @@ "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", From 8f00f43ecbd86aac7ab939cf320e74d24c3c4f25 Mon Sep 17 00:00:00 2001 From: Samuel De Backer Date: Sun, 15 May 2022 22:48:20 +0200 Subject: [PATCH 2/4] Namespace for tests --- composer.json | 7 ++++++- tests/TestDelete.php | 3 +++ tests/TestListAllCrops.php | 3 +++ tests/TestResizing.php | 2 ++ tests/TestTooManyCrops.php | 3 +++ tests/TestUrlGenerator.php | 2 ++ tests/TestUrlMatching.php | 2 ++ tests/TestUrlParsing.php | 24 ++++++++++++++++-------- 8 files changed, 37 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index e601d55..76b250f 100644 --- a/composer.json +++ b/composer.json @@ -33,6 +33,11 @@ "Bkwld\\Croppa\\": "src/" } }, + "autoload-dev": { + "psr-4": { + "Bkwld\\Croppa\\Test\\": "tests" + } + }, "minimum-stability": "dev", "prefer-stable": true, "extra": { @@ -41,7 +46,7 @@ "Bkwld\\Croppa\\CroppaServiceProvider" ], "aliases": { - "Croppa": "Bkwld\\Croppa\\Facade" + "Croppa": "Bkwld\\Croppa\\Facades\\Croppa" } } } 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 @@ 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 +85,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')); } From 70bc676ee45a65fae96c89afaeacd43ec3fbc692 Mon Sep 17 00:00:00 2001 From: Samuel De Backer Date: Sun, 15 May 2022 23:06:23 +0200 Subject: [PATCH 3/4] Update composer.json --- composer.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 76b250f..708f11b 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", From 4cee5064e06640a144eef53259c579988ba307a0 Mon Sep 17 00:00:00 2001 From: Samuel De Backer Date: Sun, 15 May 2022 23:28:57 +0200 Subject: [PATCH 4/4] psr4 + PHPStan --- composer.json | 15 ++++++---- {src/config => config}/config.php | 0 phpstan.neon | 10 +++++++ phpunit.xml | 6 +--- src/{Bkwld/Croppa => }/Commands/Purge.php | 2 +- .../Croppa => }/CroppaServiceProvider.php | 8 ++--- src/{Bkwld/Croppa => }/Exception.php | 0 src/{Bkwld/Croppa => }/Facades/Croppa.php | 0 src/{Bkwld/Croppa => }/Filters/BlackWhite.php | 0 src/{Bkwld/Croppa => }/Filters/Blur.php | 0 src/{Bkwld/Croppa => }/Filters/Darkgray.php | 0 .../Croppa => }/Filters/FilterInterface.php | 0 src/{Bkwld/Croppa => }/Filters/Negative.php | 0 .../Croppa => }/Filters/OrangeWarhol.php | 0 .../Croppa => }/Filters/TurquoiseWarhol.php | 0 src/{Bkwld/Croppa => }/Handler.php | 20 +++++++------ src/{Bkwld/Croppa => }/Helpers.php | 11 +++++-- src/{Bkwld/Croppa => }/Image.php | 15 ++++------ src/{Bkwld/Croppa => }/Storage.php | 30 +++++-------------- src/{Bkwld/Croppa => }/URL.php | 0 tests/TestListAllCrops.php | 2 ++ tests/TestResizing.php | 2 ++ tests/TestTooManyCrops.php | 4 ++- tests/TestUrlMatching.php | 2 ++ tests/TestUrlParsing.php | 2 ++ 25 files changed, 69 insertions(+), 60 deletions(-) rename {src/config => config}/config.php (100%) create mode 100644 phpstan.neon rename src/{Bkwld/Croppa => }/Commands/Purge.php (97%) rename src/{Bkwld/Croppa => }/CroppaServiceProvider.php (85%) rename src/{Bkwld/Croppa => }/Exception.php (100%) rename src/{Bkwld/Croppa => }/Facades/Croppa.php (100%) rename src/{Bkwld/Croppa => }/Filters/BlackWhite.php (100%) rename src/{Bkwld/Croppa => }/Filters/Blur.php (100%) rename src/{Bkwld/Croppa => }/Filters/Darkgray.php (100%) rename src/{Bkwld/Croppa => }/Filters/FilterInterface.php (100%) rename src/{Bkwld/Croppa => }/Filters/Negative.php (100%) rename src/{Bkwld/Croppa => }/Filters/OrangeWarhol.php (100%) rename src/{Bkwld/Croppa => }/Filters/TurquoiseWarhol.php (100%) rename src/{Bkwld/Croppa => }/Handler.php (95%) rename src/{Bkwld/Croppa => }/Helpers.php (93%) rename src/{Bkwld/Croppa => }/Image.php (95%) rename src/{Bkwld/Croppa => }/Storage.php (91%) rename src/{Bkwld/Croppa => }/URL.php (100%) diff --git a/composer.json b/composer.json index 708f11b..21ef7a7 100644 --- a/composer.json +++ b/composer.json @@ -30,14 +30,16 @@ }, "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-4": { - "Bkwld\\Croppa\\": "src/" + "Bkwld\\Croppa\\": "src" } }, "autoload-dev": { @@ -45,8 +47,9 @@ "Bkwld\\Croppa\\Test\\": "tests" } }, - "minimum-stability": "dev", - "prefer-stable": true, + "scripts": { + "test": "vendor/bin/phpunit" + }, "extra": { "laravel": { "providers": [ @@ -56,5 +59,7 @@ "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/TestListAllCrops.php b/tests/TestListAllCrops.php index 9143ee4..66ccd75 100644 --- a/tests/TestListAllCrops.php +++ b/tests/TestListAllCrops.php @@ -26,6 +26,8 @@ class TestListAllCrops extends TestCase public function setUp(): void { + parent::setUp(); + // Mock src dir $this->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 1cf49ba..41f310a 100644 --- a/tests/TestResizing.php +++ b/tests/TestResizing.php @@ -20,6 +20,8 @@ class TestResizing extends TestCase public function setUp(): void { + parent::setUp(); + // Make an image $gd = imagecreate(500, 400); ob_start(); diff --git a/tests/TestTooManyCrops.php b/tests/TestTooManyCrops.php index f932111..29d7102 100644 --- a/tests/TestTooManyCrops.php +++ b/tests/TestTooManyCrops.php @@ -18,6 +18,8 @@ class TestTooManyCrops extends TestCase public function setUp(): void { + parent::setUp(); + // Mock flysystem $this->dir = Mockery::mock(FilesystemAdapter::class) ->shouldReceive('listContents') @@ -53,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/TestUrlMatching.php b/tests/TestUrlMatching.php index a07db3d..ff4a853 100644 --- a/tests/TestUrlMatching.php +++ b/tests/TestUrlMatching.php @@ -15,6 +15,8 @@ class TestUrlMatching extends TestCase public function setUp(): void { + parent::setUp(); + $this->url = new URL([ 'path' => 'uploads/(.*)$', ]); diff --git a/tests/TestUrlParsing.php b/tests/TestUrlParsing.php index 2eaebf8..57d0125 100644 --- a/tests/TestUrlParsing.php +++ b/tests/TestUrlParsing.php @@ -21,6 +21,8 @@ class TestUrlParsing extends TestCase public function setUp(): void { + parent::setUp(); + $this->url = new URL([ 'path' => 'uploads/(.*)$', 'filters' => [