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' => [