Pixlr::generateHash()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\MediaBundle\Extra;
15
16
use Sonata\MediaBundle\Model\MediaInterface;
17
use Sonata\MediaBundle\Model\MediaManagerInterface;
18
use Sonata\MediaBundle\Provider\MediaProviderInterface;
19
use Sonata\MediaBundle\Provider\Pool;
20
use Symfony\Component\DependencyInjection\ContainerInterface;
21
use Symfony\Component\HttpFoundation\RedirectResponse;
22
use Symfony\Component\HttpFoundation\Request;
23
use Symfony\Component\HttpFoundation\Response;
24
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
25
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
26
use Symfony\Component\Routing\RouterInterface;
27
use Symfony\Component\Templating\EngineInterface;
28
29
/**
30
 * @final since sonata-project/media-bundle 3.21.0
31
 */
32
class Pixlr
33
{
34
    /**
35
     * @var string
36
     */
37
    protected $referrer;
38
39
    /**
40
     * @var string
41
     */
42
    protected $secret;
43
44
    /**
45
     * @var MediaManagerInterface
46
     */
47
    protected $mediaManager;
48
49
    /**
50
     * @var RouterInterface
51
     */
52
    protected $router;
53
54
    /**
55
     * @var Pool
56
     */
57
    protected $pool;
58
59
    /**
60
     * @var EngineInterface
61
     */
62
    protected $templating;
63
64
    /**
65
     * @var ContainerInterface
66
     */
67
    protected $container;
68
69
    /**
70
     * @var string[]
71
     */
72
    protected $validFormats;
73
74
    /**
75
     * @var string
76
     */
77
    protected $allowEreg;
78
79
    /**
80
     * @param string $referrer
81
     * @param string $secret
82
     */
83
    public function __construct($referrer, $secret, Pool $pool, MediaManagerInterface $mediaManager, RouterInterface $router, EngineInterface $templating, ContainerInterface $container)
84
    {
85
        $this->referrer = $referrer;
86
        $this->secret = $secret;
87
        $this->mediaManager = $mediaManager;
88
        $this->router = $router;
89
        $this->pool = $pool;
90
        $this->templating = $templating;
91
        $this->container = $container;
92
93
        $this->validFormats = ['jpg', 'jpeg', 'png'];
94
        $this->allowEreg = '@https?://([a-zA-Z0-9]*).pixlr.com/_temp/[0-9a-z]{24}\.[a-z]*@';
95
    }
96
97
    /**
98
     * @param string $id
99
     * @param string $mode
100
     *
101
     * @throws NotFoundHttpException
102
     *
103
     * @return RedirectResponse
104
     */
105
    public function editAction($id, $mode)
106
    {
107
        if (!\in_array($mode, ['express', 'editor'], true)) {
108
            throw new NotFoundHttpException('Invalid mode');
109
        }
110
111
        $media = $this->getMedia($id);
112
113
        $provider = $this->pool->getProvider($media->getProviderName());
114
115
        $hash = $this->generateHash($media);
116
117
        $parameters = [
118
            's' => 'c', // ??
119
            'referrer' => $this->referrer,
120
            'exit' => $this->router->generate('sonata_media_pixlr_exit', ['hash' => $hash, 'id' => $media->getId()], UrlGeneratorInterface::ABSOLUTE_URL),
121
            'image' => $provider->generatePublicUrl($media, MediaProviderInterface::FORMAT_REFERENCE),
122
            'title' => $media->getName(),
123
            'target' => $this->router->generate('sonata_media_pixlr_target', ['hash' => $hash, 'id' => $media->getId()], UrlGeneratorInterface::ABSOLUTE_URL),
124
            'locktitle' => true,
125
            'locktarget' => true,
126
        ];
127
128
        $url = sprintf('https://pixlr.com/%s/?%s', $mode, $this->buildQuery($parameters));
129
130
        return new RedirectResponse($url);
131
    }
132
133
    /**
134
     * @param string $hash
135
     * @param string $id
136
     *
137
     * @return Response
138
     */
139
    public function exitAction($hash, $id)
140
    {
141
        $media = $this->getMedia($id);
142
143
        $this->checkMedia($hash, $media);
144
145
        return new Response($this->templating->render('@SonataMedia/Extra/pixlr_exit.html.twig'));
146
    }
147
148
    /**
149
     * @param string $hash
150
     * @param string $id
151
     *
152
     * @return Response
153
     */
154
    public function targetAction(Request $request, $hash, $id)
155
    {
156
        $media = $this->getMedia($id);
157
158
        $this->checkMedia($hash, $media);
159
160
        $provider = $this->pool->getProvider($media->getProviderName());
161
162
        /*
163
         * Pixlr send back the new image as an url, add some security check before downloading the file
164
         */
165
        if (!preg_match($this->allowEreg, $request->get('image'), $matches)) {
166
            throw new NotFoundHttpException(sprintf('Invalid image host : %s', $request->get('image')));
167
        }
168
169
        $file = $provider->getReferenceFile($media);
170
        $file->setContent(file_get_contents($request->get('image')));
171
172
        $provider->updateMetadata($media);
173
        $provider->generateThumbnails($media);
174
175
        $this->mediaManager->save($media);
0 ignored issues
show
Documentation introduced by
$media is of type object<Sonata\MediaBundle\Model\MediaInterface>, but the function expects a object<Sonata\Doctrine\Model\T>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
176
177
        return new Response($this->templating->render('@SonataMedia/Extra/pixlr_exit.html.twig'));
178
    }
179
180
    /**
181
     * @return bool
182
     */
183
    public function isEditable(MediaInterface $media)
184
    {
185
        if (!$this->container->get('sonata.media.admin.media')->isGranted('EDIT', $media)) {
186
            return false;
187
        }
188
189
        return \in_array(strtolower($media->getExtension()), $this->validFormats, true);
190
    }
191
192
    /**
193
     * @param string $id
194
     *
195
     * @throws NotFoundHttpException
196
     *
197
     * @return Response
198
     */
199
    public function openEditorAction($id)
200
    {
201
        $media = $this->getMedia($id);
202
203
        if (!$this->isEditable($media)) {
204
            throw new NotFoundHttpException('The media is not editable');
205
        }
206
207
        return new Response($this->templating->render('@SonataMedia/Extra/pixlr_editor.html.twig', [
208
            'media' => $media,
209
            'admin_pool' => $this->container->get('sonata.admin.pool'),
210
        ]));
211
    }
212
213
    private function generateHash(MediaInterface $media): string
214
    {
215
        return sha1($media->getId().$media->getCreatedAt()->format('u').$this->secret);
216
    }
217
218
    /**
219
     * @throws NotFoundHttpException
220
     */
221
    private function getMedia(string $id): MediaInterface
222
    {
223
        $media = $this->mediaManager->findOneBy(['id' => $id]);
224
225
        if (!$media) {
226
            throw new NotFoundHttpException('Media not found');
227
        }
228
229
        return $media;
230
    }
231
232
    /**
233
     * @throws NotFoundHttpException
234
     */
235
    private function checkMedia(string $hash, MediaInterface $media): void
236
    {
237
        if ($hash !== $this->generateHash($media)) {
238
            throw new NotFoundHttpException('Invalid hash');
239
        }
240
241
        if (!$this->isEditable($media)) {
242
            throw new NotFoundHttpException('Media is not editable');
243
        }
244
    }
245
246
    private function buildQuery(array $parameters = []): string
247
    {
248
        $query = [];
249
        foreach ($parameters as $name => $value) {
250
            $query[] = sprintf('%s=%s', $name, $value);
251
        }
252
253
        return implode('&', $query);
254
    }
255
}
256