Completed
Push — master ( fd8346...c1962d )
by
unknown
08:45 queued 06:48
created

AbstractProvider::writeToFilesystem()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
ccs 9
cts 9
cp 1
cc 2
eloc 8
nc 2
nop 2
crap 2
1
<?php
2
3
namespace MediaMonks\SonataMediaBundle\Provider;
4
5
use League\Flysystem\FilesystemInterface;
6
use League\Glide\Filesystem\FilesystemException;
7
use MediaMonks\SonataMediaBundle\Client\HttpClientInterface;
8
use MediaMonks\SonataMediaBundle\ErrorHandlerTrait;
9
use MediaMonks\SonataMediaBundle\Model\AbstractMedia;
10
use MediaMonks\SonataMediaBundle\Form\Type\MediaFocalPointType;
11
use Sonata\AdminBundle\Form\FormMapper;
12
use Sonata\CoreBundle\Validator\ErrorElement;
13
use Symfony\Component\Form\Extension\Core\Type\FileType;
14
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
15
use Symfony\Component\Form\Extension\Core\Type\TextType;
16
use Symfony\Component\HttpFoundation\File\UploadedFile;
17
use Symfony\Component\HttpKernel\Config\FileLocator;
18
use Symfony\Component\Translation\TranslatorInterface;
19
use Symfony\Component\Validator\Constraints as Constraint;
20
21
abstract class AbstractProvider implements ProviderInterface
22
{
23
    use ErrorHandlerTrait;
24
25
    const SUPPORT_EMBED = 'embed';
26
    const SUPPORT_IMAGE = 'image';
27
    const SUPPORT_DOWNLOAD = 'download';
28
29
    const TYPE_AUDIO = 'audio';
30
    const TYPE_IMAGE = 'image';
31
    const TYPE_FILE = 'file';
32
    const TYPE_VIDEO = 'video';
33
34
    /**
35
     * @var FilesystemInterface
36
     */
37
    protected $filesystem;
38
39
    /**
40
     * @var TranslatorInterface
41
     */
42
    private $translator;
43
44
    /**
45
     * @var array
46
     */
47
    private $imageConstraintOptions = [];
48
49
    /**
50
     * @var HttpClientInterface
51
     */
52
    private $httpClient;
53
54
    /**
55
     * @var FileLocator
56
     */
57
    private $fileLocator;
58
59
    /**
60
     * @var AbstractMedia
61
     */
62
    private $media;
63
64
    /**
65
     * @param FilesystemInterface $filesystem
66
     */
67 14
    public function setFilesystem(FilesystemInterface $filesystem)
68
    {
69 14
        $this->filesystem = $filesystem;
70 14
    }
71
72
    /**
73
     * @param TranslatorInterface $translator
74
     */
75 13
    public function setTranslator(TranslatorInterface $translator)
76
    {
77 13
        $this->translator = $translator;
78 13
    }
79
80
    /**
81
     * @return \Symfony\Component\Translation\TranslatorInterface
82
     */
83 1
    public function getTranslator()
84
    {
85 1
        return $this->translator;
86
    }
87
88
    /**
89
     * @param array $options
90
     */
91 13
    public function setImageConstraintOptions(array $options)
92
    {
93 13
        $this->imageConstraintOptions = $options;
94 13
    }
95
96
    /**
97
     * @param HttpClientInterface $httpClient
98
     */
99 15
    public function setHttpClient(HttpClientInterface $httpClient)
100
    {
101 15
        $this->httpClient = $httpClient;
102 15
    }
103
104
    /**
105
     * @return FileLocator
106
     */
107 2
    public function getFileLocator()
108
    {
109 2
        return $this->fileLocator;
110
    }
111
112
    /**
113
     * @param FileLocator $fileLocator
114
     */
115 13
    public function setFileLocator(FileLocator $fileLocator)
116
    {
117 13
        $this->fileLocator = $fileLocator;
118 13
    }
119
120
    /**
121
     * @return HttpClientInterface
122
     */
123 6
    public function getHttpClient()
124
    {
125 6
        return $this->httpClient;
126
    }
127
128
    /**
129
     * @return FilesystemInterface
130
     */
131 8
    public function getFilesystem()
132
    {
133 8
        return $this->filesystem;
134
    }
135
136
    /**
137
     * @param AbstractMedia $media
138
     * @return AbstractProvider
139
     */
140 11
    public function setMedia($media)
141
    {
142 11
        $this->media = $media;
143
144 11
        return $this;
145
    }
146
147
    /**
148
     * @param AbstractMedia $media
149
     * @param $providerReferenceUpdated
150
     */
151 7
    public function update(AbstractMedia $media, $providerReferenceUpdated)
152
    {
153 7
        $this->updateImage($media);
154 7
    }
155
156
    /**
157
     * @param FormMapper $formMapper
158
     */
159 11
    public function buildCreateForm(FormMapper $formMapper)
160
    {
161
        $formMapper
162 11
            ->add('provider', 'hidden');
163
164 11
        $this->buildProviderCreateForm($formMapper);
165 11
    }
166
167
    /**
168
     * @param FormMapper $formMapper
169
     */
170 7
    public function buildEditForm(FormMapper $formMapper)
171
    {
172
        $formMapper
173 7
            ->tab('general')
174 7
            ->add('provider', HiddenType::class);
175
176 7
        $this->buildProviderEditFormBefore($formMapper);
177
178 7
        $formMapper->add(
179 7
            'imageContent',
180 7
            'file',
181
            [
182 7
                'required'    => false,
183
                'constraints' => [
184 7
                    new Constraint\File(),
185
                ],
186 7
                'label'       => 'form.replacement_image',
187
            ]
188
        )
189 7
            ->add('title', TextType::class, ['label' => 'form.title'])
190 7
            ->add(
191 7
                'description',
192 7
                TextType::class,
193 7
                ['label' => 'form.description', 'required' => false]
194
            )
195 7
            ->add(
196 7
                'authorName',
197 7
                TextType::class,
198 7
                ['label' => 'form.authorName', 'required' => false]
199
            )
200 7
            ->add(
201 7
                'copyright',
202 7
                TextType::class,
203 7
                ['label' => 'form.copyright', 'required' => false]
204
            )
205 7
            ->end()
206 7
            ->end()
207 7
            ->tab('image')
208 7
            ->add('focalPoint', MediaFocalPointType::class, [
209 7
                'media' => $this->media
210
            ])
211 7
            ->end()
212 7
            ->end()
213
        ;
214
215 7
        $this->buildProviderEditFormAfter($formMapper);
216 7
    }
217
218
    /**
219
     * @param FormMapper $formMapper
220
     * @codeCoverageIgnore
221
     */
222
    public function buildProviderEditFormBefore(FormMapper $formMapper)
223
    {
224
    }
225
226
    /**
227
     * @param FormMapper $formMapper
228
     * @codeCoverageIgnore
229
     */
230
    public function buildProviderEditFormAfter(FormMapper $formMapper)
231
    {
232
    }
233
234
    /**
235
     * @param AbstractMedia $media
236
     * @param bool $useAsImage
237
     * @return string|void
238
     */
239 4
    protected function handleFileUpload(AbstractMedia $media, $useAsImage = false)
240
    {
241
        /**
242
         * @var UploadedFile $file
243
         */
244 4
        $file = $media->getBinaryContent();
245
246 4
        if (empty($file)) {
247
            return;
248
        }
249
250 4
        $filename = $this->getFilenameByFile($file);
251 4
        $this->writeToFilesystem($file, $filename);
252
253 4
        $media->setProviderMetadata(
254 4
            array_merge(
255 4
                $media->getProviderMetaData(),
256 4
                $this->getFileMetaData($file)
257
            )
258
        );
259
260 4
        if (empty($media->getImage()) && $useAsImage) {
261 2
            $media->setImage($filename);
262 2
            $media->setImageMetaData($media->getProviderMetaData());
263
        }
264
265 4
        if (empty($media->getTitle())) {
266 4
            $media->setTitle(
267 4
                str_replace(
268 4
                    '_',
269 4
                    ' ',
270 4
                    pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME)
271
                )
272
            );
273
        }
274
275 4
        return $filename;
276
    }
277
278
    /**
279
     * @param UploadedFile $file
280
     * @return array
281
     */
282 4
    protected function getFileMetaData(UploadedFile $file)
283
    {
284
        $fileData = [
285 4
            'originalName'      => $file->getClientOriginalName(),
286 4
            'originalExtension' => $file->getClientOriginalExtension(),
287 4
            'mimeType'          => $file->getClientMimeType(),
288 4
            'size'              => $file->getSize(),
289
        ];
290
291
292 4
        $this->disableErrorHandler();
293 4
        $imageSize = getimagesize($file->getRealPath());
294 4
        if (is_array($imageSize)) {
295 4
            if (is_int($imageSize[0]) && is_int($imageSize[1])) {
296 4
                $fileData['height'] = $imageSize[0];
297 4
                $fileData['width']  = $imageSize[1];
298
            }
299 4
            if (isset($imageSize['bits'])) {
300 4
                $fileData['bits'] = $imageSize['bits'];
301
            }
302 4
            if (isset($imageSize['channels'])) {
303 2
                $fileData['channels'] = $imageSize['channels'];
304
            }
305
        }
306 4
        $this->restoreErrorHandler();
307
308 4
        return $fileData;
309
    }
310
311
    /**
312
     * @param AbstractMedia $media
313
     */
314 7
    public function updateImage(AbstractMedia $media)
315
    {
316
        /**
317
         * @var UploadedFile $file
318
         */
319 7
        $file = $media->getImageContent();
320 7
        if (empty($file)) {
321 5
            return;
322
        }
323
324 2
        $filename = $this->getFilenameByFile($file);
325 2
        $this->writeToFilesystem($file, $filename);
326
327 2
        $media->setImage($filename);
328 2
        $media->setImageMetaData($this->getFileMetaData($file));
329 2
    }
330
331
    /**
332
     * @param \Sonata\AdminBundle\Form\FormMapper $formMapper
333
     * @param $name
334
     * @param $label
335
     * @param $required
336
     * @param array $constraints
337
     */
338 7
    protected function doAddFileField(
339
        FormMapper $formMapper,
340
        $name,
341
        $label,
342
        $required,
343
        $constraints = []
344
    ) {
345 7
        if ($required) {
346 7
            $constraints = array_merge(
347
                [
348 7
                    new Constraint\NotBlank(),
349 7
                    new Constraint\NotNull(),
350
                ],
351 7
                $constraints
352
            );
353
        }
354
355
        $formMapper
356 7
            ->add(
357 7
                $name,
358 7
                FileType::class,
359
                [
360 7
                    'multiple'    => false,
361
                    'data_class'  => null,
362 7
                    'constraints' => $constraints,
363 7
                    'label'       => $label,
364 7
                    'required'    => $required,
365
                ]
366
            );
367 7
    }
368
369
    /**
370
     * @param FormMapper $formMapper
371
     * @param string $name
372
     * @param string $label
373
     * @param array $options
374
     */
375 2 View Code Duplication
    public function addImageField(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
376
        FormMapper $formMapper,
377
        $name,
378
        $label,
379
        $options = []
380
    ) {
381 2
        $this->doAddFileField(
382 2
            $formMapper,
383 2
            $name,
384 2
            $label,
385 2
            false,
386
            [
387 2
                new Constraint\Image(
388 2
                    array_merge($this->imageConstraintOptions, $options)
389
                ),
390
            ]
391
        );
392 2
    }
393
394
    /**
395
     * @param FormMapper $formMapper
396
     * @param $name
397
     * @param $label
398
     * @param array $options
399
     */
400 3 View Code Duplication
    public function addRequiredImageField(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
401
        FormMapper $formMapper,
402
        $name,
403
        $label,
404
        $options = []
405
    ) {
406 3
        $this->doAddFileField(
407 3
            $formMapper,
408 3
            $name,
409 3
            $label,
410 3
            true,
411
            [
412 3
                new Constraint\Image(
413 3
                    array_merge($this->imageConstraintOptions, $options)
414
                ),
415
            ]
416
        );
417 3
    }
418
419
    /**
420
     * @param UploadedFile $file
421
     * @return string
422
     */
423 4
    protected function getFilenameByFile(UploadedFile $file)
424
    {
425 4
        return sprintf(
426 4
            '%s_%d.%s',
427 4
            sha1($file->getClientOriginalName()),
428 4
            time(),
429 4
            $file->getClientOriginalExtension()
430
        );
431
    }
432
433
    /**
434
     * @param UploadedFile $file
435
     * @param $filename
436
     * @throws FilesystemException
437
     */
438 5
    protected function writeToFilesystem(UploadedFile $file, $filename)
439
    {
440 5
        $this->disableErrorHandler();
441 5
        $stream = fopen($file->getRealPath(), 'r+');
442 5
        $written = $this->getFilesystem()->writeStream($filename, $stream);
443 5
        fclose($stream); // this sometime messes up
444 5
        $this->restoreErrorHandler();
445
446 5
        if (!$written) {
447 1
            throw new FilesystemException('Could not write to file system');
448
        }
449 4
    }
450
451
    /**
452
     * @param ErrorElement $errorElement
453
     * @param AbstractMedia $media
454
     */
455 7
    public function validate(ErrorElement $errorElement, AbstractMedia $media)
456
    {
457 7
    }
458
459
    /**
460
     * @return string
461
     */
462 3
    public function getEmbedTemplate()
463
    {
464 3
        return sprintf(
465 3
            'MediaMonksSonataMediaBundle:Provider:%s_embed.html.twig',
466 3
            $this->getName()
467
        );
468
    }
469
}
470