diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c9f294..2ef6fa0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,12 +13,24 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: PHP-CS-Fixer uses: docker://oskarstark/php-cs-fixer-ga with: - args: --config=.php-cs-fixer.php --diff --dry-run + args: --config=.php-cs-fixer.php --diff --dry-run + + phpstan: + name: PHPStan + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: PHPStan + uses: docker://oskarstark/phpstan-ga + env: + REQUIRE_DEV: true ci: name: Test PHP ${{ matrix.php-version }} ${{ matrix.name }} @@ -36,7 +48,7 @@ jobs: name: '(prefer lowest dependencies)' steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup PHP, with composer and extensions uses: shivammathur/setup-php@v2 diff --git a/Command/GifOptimizerCommand.php b/Command/GifOptimizerCommand.php index d4db898..1bb6d4d 100644 --- a/Command/GifOptimizerCommand.php +++ b/Command/GifOptimizerCommand.php @@ -77,15 +77,30 @@ protected function execute(InputInterface $input, OutputInterface $output): int { $imageDir = $input->getArgument('image_dir'); - if (!is_dir($imageDir)) { + if (!\is_string($imageDir) || !is_dir($imageDir)) { throw new \RuntimeException($imageDir . ' is not a valid directory'); } $pattern = $imageDir . '/*/*.gif'; - foreach (glob($pattern) as $path) { + $images = glob($pattern); + + if (!$images) { + throw new \RuntimeException('No images found in ' . $pattern); + } + + foreach ($images as $path) { $realPath = realpath($path); + + if (!$realPath) { + throw new \RuntimeException('Could not find ' . $path); + } + $originalFileSize = filesize($realPath); + if (!$originalFileSize) { + throw new \RuntimeException('Could not get file size for ' . $realPath); + } + $output->writeln(sprintf('Optimizing image: %s', $realPath)); $output->writeln(sprintf('Before: %s', $this->formatBytes($originalFileSize))); @@ -96,6 +111,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $optimizedFileSize = filesize($realPath); + if (!$optimizedFileSize) { + throw new \RuntimeException('Could not get file size for ' . $realPath); + } + $output->writeln(sprintf('After: %s', $this->formatBytes($optimizedFileSize))); $percentage = 100 - (($optimizedFileSize / $originalFileSize) * 100); diff --git a/DependencyInjection/GifExceptionExtension.php b/DependencyInjection/GifExceptionExtension.php index 0a7f1fa..dd4f043 100644 --- a/DependencyInjection/GifExceptionExtension.php +++ b/DependencyInjection/GifExceptionExtension.php @@ -30,13 +30,21 @@ public function load(array $configs, ContainerBuilder $container): void $gifs = []; $pattern = __DIR__ . '/../Resources/public/images/*/*.gif'; - foreach (glob($pattern) as $path) { - $gifs[basename(\dirname($path))][] = basename($path); + $images = glob($pattern); + + if ($images) { + foreach ($images as $path) { + $gifs[basename(\dirname($path))][] = basename($path); + } } $pattern = __DIR__ . '/../Resources/public/images/other/*.gif'; - foreach (glob($pattern) as $path) { - $gifs['other'][] = basename($path); + $images = glob($pattern); + + if ($images) { + foreach ($images as $path) { + $gifs['other'][] = basename($path); + } } $container->getDefinition('gif_exception.listener.replace_image')->replaceArgument(0, $gifs); diff --git a/EventListener/ReplaceImageListener.php b/EventListener/ReplaceImageListener.php index d820372..2990326 100644 --- a/EventListener/ReplaceImageListener.php +++ b/EventListener/ReplaceImageListener.php @@ -37,6 +37,10 @@ public function onKernelResponse(ResponseEvent $event): void } $exception = $event->getRequest()->attributes->get('exception'); + if (!($exception instanceof \Throwable)) { + return; + } + // Status code is not set by the exception controller but only by the // kernel at the very end. // So lets use the status code from the flatten exception instead. @@ -51,7 +55,7 @@ public function onKernelResponse(ResponseEvent $event): void $gif = $this->getRandomGif($dir); $url = $this->getGifUrl($dir, $gif); - $content = $event->getResponse()->getContent(); + $content = (string) $event->getResponse()->getContent(); $content = preg_replace( '@
(.*?)
@ims', @@ -62,9 +66,6 @@ public function onKernelResponse(ResponseEvent $event): void $event->getResponse()->setContent($content); } - /** - * {@inheritdoc} - */ public static function getSubscribedEvents(): array { return [ @@ -78,7 +79,7 @@ public static function getSubscribedEvents(): array private function getGifDir(int $statusCode): string { if (\array_key_exists($statusCode, $this->gifs) && \count($this->gifs[$statusCode]) > 0) { - return $statusCode; + return (string) $statusCode; } return 'other'; @@ -89,6 +90,10 @@ private function getGifDir(int $statusCode): string */ private function getRandomGif(string $dir): string { + if (!\array_key_exists($dir, $this->gifs) || 0 === \count($this->gifs[$dir])) { + return ''; + } + $imageIndex = random_int(0, \count($this->gifs[$dir]) - 1); return $this->gifs[$dir][$imageIndex]; diff --git a/Makefile b/Makefile index cb409ec..85e0cbb 100644 --- a/Makefile +++ b/Makefile @@ -13,3 +13,6 @@ cs_dry_run: ## Test if PHP CS is correct test: ## Run the test suite vendor/bin/simple-phpunit + +phpstan: ## Run static analysis + vendor/bin/phpstan analyse -c phpstan.neon diff --git a/bin/optimizer.php b/bin/optimizer.php index 8e6f758..5e91c81 100755 --- a/bin/optimizer.php +++ b/bin/optimizer.php @@ -10,7 +10,7 @@ * file that was distributed with this source code. */ -use Joli\GifExceptionBundle\Tests\app\AppKernel; +use Joli\GifExceptionBundle\Tests\app\src\Kernel; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Input\ArgvInput; @@ -36,6 +36,6 @@ array_unshift($args, __DIR__ . '/optimizer.php'); $input = new ArgvInput($args); -$kernel = new AppKernel('dev', false); +$kernel = new Kernel('dev', false); $application = new Application($kernel); $application->run($input); diff --git a/composer.json b/composer.json index c56a67a..cee731b 100644 --- a/composer.json +++ b/composer.json @@ -23,19 +23,21 @@ "symfony/twig-bundle": "^5.4 || ^6.0" }, "require-dev": { - "doctrine/annotations": "^1.2", - "friendsofphp/php-cs-fixer": "^3.0", + "doctrine/annotations": "^2.0", + "friendsofphp/php-cs-fixer": "^3.17", + "phpstan/phpstan": "^1.10", "ps/image-optimizer": "^1.0.4 || ^2.0", "symfony/asset": "^5.4 || ^6.0", "symfony/browser-kit": "^5.4 || ^6.0", "symfony/config": "^5.4 || ^6.0", - "symfony/console": "^6.3", - "symfony/debug": "^4.4", + "symfony/console": "^5.4 || ^6.0", "symfony/dependency-injection": "^5.4 || ^6.0", + "symfony/error-handler": "^5.4 || ^6.0", "symfony/http-kernel": "^5.4 || ^6.0", "symfony/monolog-bundle": "^3.8", - "symfony/phpunit-bridge": "^5.4 || ^6.0", - "symfony/profiler-pack": "^1.0", + "symfony/phpunit-bridge": "^6.3", + "symfony/stopwatch": "^5.4 || ^6.0", + "symfony/web-profiler-bundle": "^5.4 || ^6.0", "symfony/yaml": "^5.4 || ^6.0" }, "config": { diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..e38533b --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,7 @@ +parameters: + level: 9 + paths: + - . + excludePaths: + - vendor + - tests diff --git a/tests/app/config/config.yml b/tests/app/config/config.yml index 96e20e7..08d2505 100644 --- a/tests/app/config/config.yml +++ b/tests/app/config/config.yml @@ -7,7 +7,6 @@ framework: http_method_override: false profiler: only_exceptions: false - collect_serializer_data: true web_profiler: toolbar: true