Completed
Push — master ( 08177a...06cf5d )
by Grégoire
11s
created

ImageProvider   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 225
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 13

Importance

Changes 0
Metric Value
wmc 30
lcom 2
cbo 13
dl 0
loc 225
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A getProviderMetadata() 0 10 1
D getHelperProperties() 0 88 15
A updateMetadata() 0 26 3
A generatePublicUrl() 0 15 3
A generatePrivateUrl() 0 4 1
B doTransform() 0 33 6
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\Provider;
15
16
use Gaufrette\Filesystem;
17
use Imagine\Image\ImagineInterface;
18
use Sonata\MediaBundle\CDN\CDNInterface;
19
use Sonata\MediaBundle\Generator\GeneratorInterface;
20
use Sonata\MediaBundle\Metadata\MetadataBuilderInterface;
21
use Sonata\MediaBundle\Model\MediaInterface;
22
use Sonata\MediaBundle\Thumbnail\ThumbnailInterface;
23
use Symfony\Component\HttpFoundation\File\File;
24
use Symfony\Component\HttpFoundation\File\UploadedFile;
25
26
class ImageProvider extends FileProvider
27
{
28
    /**
29
     * @var ImagineInterface
30
     */
31
    protected $imagineAdapter;
32
33
    /**
34
     * @param string                   $name
35
     * @param Filesystem               $filesystem
36
     * @param CDNInterface             $cdn
37
     * @param GeneratorInterface       $pathGenerator
38
     * @param ThumbnailInterface       $thumbnail
39
     * @param array                    $allowedExtensions
40
     * @param array                    $allowedMimeTypes
41
     * @param ImagineInterface         $adapter
42
     * @param MetadataBuilderInterface $metadata
43
     */
44
    public function __construct($name, Filesystem $filesystem, CDNInterface $cdn, GeneratorInterface $pathGenerator, ThumbnailInterface $thumbnail, array $allowedExtensions, array $allowedMimeTypes, ImagineInterface $adapter, MetadataBuilderInterface $metadata = null)
45
    {
46
        parent::__construct($name, $filesystem, $cdn, $pathGenerator, $thumbnail, $allowedExtensions, $allowedMimeTypes, $metadata);
47
48
        $this->imagineAdapter = $adapter;
49
    }
50
51
    /**
52
     * {@inheritdoc}
53
     */
54
    public function getProviderMetadata()
55
    {
56
        return new Metadata(
57
            $this->getName(),
58
            $this->getName().'.description',
59
            null,
60
            'SonataMediaBundle',
61
            ['class' => 'fa fa-picture-o']
62
        );
63
    }
64
65
    /**
66
     * {@inheritdoc}
67
     */
68
    public function getHelperProperties(MediaInterface $media, $format, $options = [])
69
    {
70
        if (isset($options['srcset'], $options['picture'])) {
71
            throw new \LogicException("The 'srcset' and 'picture' options must not be used simultaneously.");
72
        }
73
74
        if (MediaProviderInterface::FORMAT_REFERENCE === $format) {
75
            $box = $media->getBox();
76
        } else {
77
            $resizerFormat = $this->getFormat($format);
78
            if (false === $resizerFormat) {
79
                throw new \RuntimeException(sprintf('The image format "%s" is not defined.
80
                        Is the format registered in your ``sonata_media`` configuration?', $format));
81
            }
82
83
            $box = $this->resizer->getBox($media, $resizerFormat);
84
        }
85
86
        $mediaWidth = $box->getWidth();
87
88
        $params = [
89
            'alt' => $media->getName(),
90
            'title' => $media->getName(),
91
            'src' => $this->generatePublicUrl($media, $format),
92
            'width' => $mediaWidth,
93
            'height' => $box->getHeight(),
94
        ];
95
96
        if (isset($options['picture'])) {
97
            $pictureParams = [];
98
            foreach ($options['picture'] as $key => $pictureFormat) {
99
                $formatName = $this->getFormatName($media, $pictureFormat);
100
                $settings = $this->getFormat($formatName);
101
                $src = $this->generatePublicUrl($media, $formatName);
102
                $mediaQuery = \is_string($key)
103
                    ? $key
104
                    : sprintf('(max-width: %dpx)', $this->resizer->getBox($media, $settings)->getWidth());
0 ignored issues
show
Security Bug introduced by
It seems like $settings defined by $this->getFormat($formatName) on line 100 can also be of type false; however, Sonata\MediaBundle\Resiz...izerInterface::getBox() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
105
106
                $pictureParams['source'][] = ['media' => $mediaQuery, 'srcset' => $src];
107
            }
108
109
            unset($options['picture']);
110
            $pictureParams['img'] = $params + $options;
111
            $params = ['picture' => $pictureParams];
112
        } elseif (MediaProviderInterface::FORMAT_ADMIN !== $format) {
113
            $srcSetFormats = $this->getFormats();
114
115
            if (isset($options['srcset']) && \is_array($options['srcset'])) {
116
                $srcSetFormats = [];
117
                foreach ($options['srcset'] as $srcSetFormat) {
118
                    $formatName = $this->getFormatName($media, $srcSetFormat);
119
                    $srcSetFormats[$formatName] = $this->getFormat($formatName);
120
                }
121
                unset($options['srcset']);
122
123
                // Make sure the requested format is also in the srcSetFormats
124
                if (!isset($srcSetFormats[$format])) {
125
                    $srcSetFormats[$format] = $this->getFormat($format);
126
                }
127
            }
128
129
            if (!isset($options['srcset'])) {
130
                $srcSet = [];
131
132
                foreach ($srcSetFormats as $providerFormat => $settings) {
133
                    // Check if format belongs to the current media's context
134
                    if (0 === strpos($providerFormat, $media->getContext())) {
135
                        $width = $this->resizer->getBox($media, $settings)->getWidth();
136
137
                        $srcSet[] = sprintf('%s %dw', $this->generatePublicUrl($media, $providerFormat), $width);
138
                    }
139
                }
140
141
                // The reference format is not in the formats list
142
                $srcSet[] = sprintf(
143
                    '%s %dw',
144
                    $this->generatePublicUrl($media, MediaProviderInterface::FORMAT_REFERENCE),
145
                    $media->getBox()->getWidth()
146
                );
147
148
                $params['srcset'] = implode(', ', $srcSet);
149
            }
150
151
            $params['sizes'] = sprintf('(max-width: %1$dpx) 100vw, %1$dpx', $mediaWidth);
152
        }
153
154
        return array_merge($params, $options);
155
    }
156
157
    /**
158
     * {@inheritdoc}
159
     */
160
    public function updateMetadata(MediaInterface $media, $force = true): void
161
    {
162
        try {
163
            if (!$media->getBinaryContent() instanceof \SplFileInfo) {
164
                // this is now optimized at all!!!
165
                $path = tempnam(sys_get_temp_dir(), 'sonata_update_metadata');
166
                $fileObject = new \SplFileObject($path, 'w');
167
                $fileObject->fwrite($this->getReferenceFile($media)->getContent());
168
            } else {
169
                $fileObject = $media->getBinaryContent();
170
            }
171
172
            $image = $this->imagineAdapter->open($fileObject->getPathname());
173
            $size = $image->getSize();
174
175
            $media->setSize($fileObject->getSize());
176
            $media->setWidth($size->getWidth());
177
            $media->setHeight($size->getHeight());
178
        } catch (\LogicException $e) {
179
            $media->setProviderStatus(MediaInterface::STATUS_ERROR);
180
181
            $media->setSize(0);
182
            $media->setWidth(0);
183
            $media->setHeight(0);
184
        }
185
    }
186
187
    /**
188
     * {@inheritdoc}
189
     */
190
    public function generatePublicUrl(MediaInterface $media, $format)
191
    {
192
        if (MediaProviderInterface::FORMAT_REFERENCE === $format) {
193
            $path = $this->getReferenceImage($media);
194
        } else {
195
            $path = $this->thumbnail->generatePublicUrl($this, $media, $format);
196
        }
197
198
        // if $path is already an url, no further action is required
199
        if (null !== parse_url($path, PHP_URL_SCHEME)) {
200
            return $path;
201
        }
202
203
        return $this->getCdn()->getPath($path, $media->getCdnIsFlushable());
204
    }
205
206
    /**
207
     * {@inheritdoc}
208
     */
209
    public function generatePrivateUrl(MediaInterface $media, $format)
210
    {
211
        return $this->thumbnail->generatePrivateUrl($this, $media, $format);
212
    }
213
214
    /**
215
     * {@inheritdoc}
216
     */
217
    protected function doTransform(MediaInterface $media): void
218
    {
219
        parent::doTransform($media);
220
221
        if ($media->getBinaryContent() instanceof UploadedFile) {
222
            $fileName = $media->getBinaryContent()->getClientOriginalName();
223
        } elseif ($media->getBinaryContent() instanceof File) {
224
            $fileName = $media->getBinaryContent()->getFilename();
225
        } else {
226
            // Should not happen, FileProvider should throw an exception in that case
227
            return;
228
        }
229
230
        if (!\in_array(strtolower(pathinfo($fileName, PATHINFO_EXTENSION)), $this->allowedExtensions, true)
231
            || !\in_array($media->getBinaryContent()->getMimeType(), $this->allowedMimeTypes, true)) {
232
            return;
233
        }
234
235
        try {
236
            $image = $this->imagineAdapter->open($media->getBinaryContent()->getPathname());
237
        } catch (\RuntimeException $e) {
238
            $media->setProviderStatus(MediaInterface::STATUS_ERROR);
239
240
            return;
241
        }
242
243
        $size = $image->getSize();
244
245
        $media->setWidth($size->getWidth());
246
        $media->setHeight($size->getHeight());
247
248
        $media->setProviderStatus(MediaInterface::STATUS_OK);
249
    }
250
}
251