• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tito10047 / progressive-image-bundle / 22202243069

19 Feb 2026 10:11PM UTC coverage: 75.816% (-14.5%) from 90.276%
22202243069

Pull #10

github

web-flow
Merge 7c6c5a0cf into 142ac29cb
Pull Request #10: add support for avif format

0 of 16 new or added lines in 3 files covered. (0.0%)

1 existing line in 1 file now uncovered.

743 of 980 relevant lines covered (75.82%)

9.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Controller/LiipImagineController.php
1
<?php
2

3
/*
4
 * This file is part of the Progressive Image Bundle.
5
 *
6
 * (c) Jozef Môstka <https://github.com/tito10047/progressive-image-bundle>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
declare(strict_types=1);
12

13
namespace Tito10047\ProgressiveImageBundle\Controller;
14

15
use Liip\ImagineBundle\Config\Controller\ControllerConfig;
16
use Liip\ImagineBundle\Exception\Binary\Loader\NotLoadableException;
17
use Liip\ImagineBundle\Exception\Imagine\Filter\NonExistingFilterException;
18
use Liip\ImagineBundle\Imagine\Cache\Helper\PathHelper;
19
use Liip\ImagineBundle\Imagine\Data\DataManager;
20
use Liip\ImagineBundle\Imagine\Filter\FilterConfiguration;
21
use Liip\ImagineBundle\Service\FilterService;
22
use Liip\ImagineBundle\Service\FormatNegotiator;
23
use Symfony\Component\HttpFoundation\RedirectResponse;
24
use Symfony\Component\HttpFoundation\Request;
25
use Symfony\Component\HttpFoundation\Response;
26
use Symfony\Component\HttpFoundation\UriSigner;
27
use Symfony\Component\HttpKernel\Attribute\MapQueryParameter;
28
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
29
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
30
use Tito10047\ProgressiveImageBundle\Service\LiipImagineRuntimeConfigGeneratorInterface;
31
use Tito10047\ProgressiveImageBundle\Service\MetadataReaderInterface;
32

33
final class LiipImagineController
34
{
35
    public function __construct(
36
        private readonly UriSigner $signer,
37
        private readonly FilterService $filterService,
38
        private readonly DataManager $dataManager,
39
        private readonly FilterConfiguration $filterConfiguration,
40
        private readonly ControllerConfig $controllerConfig,
41
        private readonly LiipImagineRuntimeConfigGeneratorInterface $runtimeConfigGenerator,
42
        private readonly MetadataReaderInterface $metadataReader,
43
        private readonly ?FormatNegotiator $formatNegotiator = null,
44
        private readonly array $alternativeFormats = [],
45
    ) {
46
    }
×
47

48
    public function index(
49
        Request $request,
50
        #[MapQueryParameter] string $path,
51
        #[MapQueryParameter] int $width,
52
        #[MapQueryParameter] int $height,
53
        #[MapQueryParameter] ?string $filter = null,
54
        #[MapQueryParameter] ?string $pointInterest = null,
55
    ): Response {
56
        $path = PathHelper::urlPathToFilePath($path);
×
57

58
        $context = $request->query->all();
×
59
        unset($context['path'], $context['width'], $context['height'], $context['filter'], $context['pointInterest'], $context['_hash'], $context['_expiration']);
×
60

61
        $origWidth = null;
×
62
        $origHeight = null;
×
63
        if ($pointInterest) {
×
64
            $metadata = $this->metadataReader->getMetadata($path);
×
65
            $origWidth = $metadata->width;
×
66
            $origHeight = $metadata->height;
×
67
        }
68

69
        $result = $this->runtimeConfigGenerator->generate($width, $height, $filter, $pointInterest, $origWidth, $origHeight, $context);
×
70
        $filterName = $result['filterName'];
×
71
        $config = $result['config'];
×
72

73
        $this->filterConfiguration->set($filterName, $config);
×
74

75
        if (true !== $this->signer->checkRequest($request) && $request->attributes->get('_route') !== null) {
×
76
            throw new BadRequestHttpException(\sprintf('Signed url does not pass the sign check for path "%s" and filter "%s"', $path, $filter));
×
77
        }
78

79
        return $this->createRedirectResponse(function () use ($path, $filterName, $request) {
×
80
            return $this->filterService->getUrlOfFilteredImage(
×
81
                $path,
×
82
                $filterName,
×
83
                null,
×
NEW
84
                false,
×
NEW
85
                $this->getAlternativeFormats($request)
×
86
            );
×
87
        }, $path, $filterName);
×
88
    }
89

90
    private function getAlternativeFormats(Request $request): array
91
    {
NEW
92
        if (null === $this->formatNegotiator) {
×
NEW
93
            return false !== mb_stripos($request->headers->get('accept', ''), 'image/webp') ? ['webp'] : [];
×
94
        }
95

NEW
96
        return $this->formatNegotiator->negotiate($request, $this->alternativeFormats);
×
97
    }
98

99
    private function createRedirectResponse(\Closure $url, string $path, string $filter): RedirectResponse
100
    {
101
        try {
102
            return new RedirectResponse($url(), $this->controllerConfig->getRedirectResponseCode());
×
103
        } catch (NotLoadableException $exception) {
×
104
            if (null !== $this->dataManager->getDefaultImageUrl($filter)) {
×
105
                return new RedirectResponse($this->dataManager->getDefaultImageUrl($filter));
×
106
            }
107

108
            throw new NotFoundHttpException(\sprintf('Source image for path "%s" could not be found', $path), $exception);
×
109
        } catch (NonExistingFilterException $exception) {
×
110
            throw new NotFoundHttpException(\sprintf('Requested non-existing filter "%s"', $filter), $exception);
×
111
        } catch (\RuntimeException $exception) {
×
112
            throw new \RuntimeException(\sprintf('Unable to create image for path "%s" and filter "%s". Message was "%s"', $path, $filter, $exception->getMessage()), 0, $exception);
×
113
        }
114
    }
115
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc