Completed
Pull Request — master (#1220)
by
unknown
01:30
created

ImagineController   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 132
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 0
Metric Value
wmc 12
lcom 1
cbo 10
dl 0
loc 132
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 2
A filterAction() 0 9 1
A filterRuntimeAction() 0 23 3
B createRedirectResponse() 0 20 6
1
<?php
2
3
/*
4
 * This file is part of the `liip/LiipImagineBundle` project.
5
 *
6
 * (c) https://github.com/liip/LiipImagineBundle/graphs/contributors
7
 *
8
 * For the full copyright and license information, please view the LICENSE.md
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Liip\ImagineBundle\Controller;
13
14
use Imagine\Exception\RuntimeException;
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\Cache\SignerInterface;
20
use Liip\ImagineBundle\Imagine\Data\DataManager;
21
use Liip\ImagineBundle\Service\FilterService;
22
use Symfony\Component\HttpFoundation\RedirectResponse;
23
use Symfony\Component\HttpFoundation\Request;
24
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
25
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
26
27
class ImagineController
28
{
29
    /**
30
     * @var FilterService
31
     */
32
    private $filterService;
33
34
    /**
35
     * @var DataManager
36
     */
37
    private $dataManager;
38
39
    /**
40
     * @var SignerInterface
41
     */
42
    private $signer;
43
44
    /**
45
     * @var ControllerConfig
46
     */
47
    private $controllerConfig;
48
49
    /**
50
     * @param FilterService         $filterService
51
     * @param DataManager           $dataManager
52
     * @param SignerInterface       $signer
53
     * @param ControllerConfig|null $controllerConfig
54
     */
55
    public function __construct(FilterService $filterService, DataManager $dataManager, SignerInterface $signer, ?ControllerConfig $controllerConfig = null)
56
    {
57
        $this->filterService = $filterService;
58
        $this->dataManager = $dataManager;
59
        $this->signer = $signer;
60
61
        if (null === $controllerConfig) {
62
            @trigger_error(sprintf(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
63
                'Instantiating "%s" without a forth argument of type "%s" is deprecated since 2.2.0 and will be required in 3.0.', self::class, ControllerConfig::class
64
            ), E_USER_DEPRECATED);
65
        }
66
67
        $this->controllerConfig = $controllerConfig ?? new ControllerConfig(301);
68
    }
69
70
    /**
71
     * This action applies a given filter to a given image, saves the image and redirects the browser to the stored
72
     * image.
73
     *
74
     * The resulting image is cached so subsequent requests will redirect to the cached image instead applying the
75
     * filter and storing the image again.
76
     *
77
     * @param Request $request
78
     * @param string  $path
79
     * @param string  $filter
80
     *
81
     * @throws RuntimeException
82
     * @throws NotFoundHttpException
83
     *
84
     * @return RedirectResponse
85
     */
86
    public function filterAction(Request $request, $path, $filter)
87
    {
88
        $path = PathHelper::urlPathToFilePath($path);
89
        $resolver = $request->get('resolver');
90
91
        return $this->createRedirectResponse(function () use ($path, $filter, $resolver) {
92
            return $this->filterService->getUrlOfFilteredImage($path, $filter, $resolver);
93
        }, $path, $filter);
94
    }
95
96
    /**
97
     * This action applies a given filter -merged with additional runtime filters- to a given image, saves the image and
98
     * redirects the browser to the stored image.
99
     *
100
     * The resulting image is cached so subsequent requests will redirect to the cached image instead applying the
101
     * filter and storing the image again.
102
     *
103
     * @param Request $request
104
     * @param string  $hash
105
     * @param string  $path
106
     * @param string  $filter
107
     *
108
     * @throws RuntimeException
109
     * @throws BadRequestHttpException
110
     * @throws NotFoundHttpException
111
     *
112
     * @return RedirectResponse
113
     */
114
    public function filterRuntimeAction(Request $request, $hash, $path, $filter)
115
    {
116
        $resolver = $request->get('resolver');
117
        $path = PathHelper::urlPathToFilePath($path);
118
        $runtimeConfig = $request->query->get('filters', []);
119
120
        if (!\is_array($runtimeConfig)) {
121
            throw new NotFoundHttpException(sprintf('Filters must be an array. Value was "%s"', $runtimeConfig));
122
        }
123
124
        if (true !== $this->signer->check($hash, $path, $runtimeConfig)) {
125
            throw new BadRequestHttpException(sprintf(
126
                'Signed url does not pass the sign check for path "%s" and filter "%s" and runtime config %s',
127
                $path,
128
                $filter,
129
                json_encode($runtimeConfig)
130
            ));
131
        }
132
133
        return $this->createRedirectResponse(function () use ($path, $filter, $runtimeConfig, $resolver) {
134
            return $this->filterService->getUrlOfFilteredImageWithRuntimeFilters($path, $filter, $runtimeConfig, $resolver);
135
        }, $path, $filter, $hash);
136
    }
137
138
    private function createRedirectResponse(\Closure $url, string $path, string $filter, ?string $hash = null): RedirectResponse
139
    {
140
        try {
141
            return new RedirectResponse($url(), $this->controllerConfig->getRedirectResponseCode());
142
        } catch (NotLoadableException $exception) {
143
            if (null !== $this->dataManager->getDefaultImageUrl($filter)) {
144
                return new RedirectResponse($this->dataManager->getDefaultImageUrl($filter));
145
            }
146
147
            throw new NotFoundHttpException(sprintf('Source image for path "%s" could not be found', $path));
148
        } catch (NonExistingFilterException $exception) {
149
            throw new NotFoundHttpException(sprintf('Requested non-existing filter "%s"', $filter));
150
        } catch (RuntimeException $exception) {
151
            throw new \RuntimeException(vsprintf('Unable to create image for path "%s" and filter "%s". Message was "%s"', [
152
                $hash ? sprintf('%s/%s', $hash, $path) : $path,
153
                $filter,
154
                $exception->getMessage(),
155
            ]), 0, $exception);
156
        }
157
    }
158
}
159