Completed
Push — master ( ea7d11...c6eea4 )
by
unknown
03:49
created

AbstractProvider::updateImage()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 0
cts 15
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 8
nc 2
nop 1
crap 6
1
<?php
2
3
namespace MediaMonks\SonataMediaBundle\Provider;
4
5
use League\Flysystem\Filesystem;
6
use MediaMonks\SonataMediaBundle\Entity\Media;
7
use MediaMonks\SonataMediaBundle\Form\Type\MediaFocalPointType;
8
use MediaMonks\SonataMediaBundle\Model\MediaInterface;
9
use Sonata\AdminBundle\Form\FormMapper;
10
use Sonata\CoreBundle\Validator\ErrorElement;
11
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
12
use Symfony\Component\Form\Extension\Core\Type\FileType;
13
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
14
use Symfony\Component\Form\Extension\Core\Type\TextType;
15
use Symfony\Component\HttpFoundation\File\UploadedFile;
16
use Symfony\Component\Translation\TranslatorInterface;
17
use Symfony\Component\Validator\Constraints as Constraint;
18
19
abstract class AbstractProvider implements ProviderInterface
20
{
21
    const SUPPORT_EMBED = 'embed';
22
    const SUPPORT_IMAGE = 'image';
23
    const SUPPORT_DOWNLOAD = 'download';
24
25
    const TYPE_AUDIO = 'audio';
26
    const TYPE_IMAGE = 'image';
27
    const TYPE_FILE = 'file';
28
    const TYPE_VIDEO = 'video';
29
30
    /**
31
     * @var Filesystem
32
     */
33
    protected $filesystem;
34
35
    /**
36
     * @var TranslatorInterface
37
     */
38
    private $translator;
39
40
    /**
41
     * @var array
42
     */
43
    private $imageConstraintOptions = [];
44
45
    /**
46
     * @var Media
47
     */
48
    private $media;
49
50
    /**
51
     * @param Filesystem $filesystem
52
     */
53
    public function setFilesystem(Filesystem $filesystem)
54
    {
55
        $this->filesystem = $filesystem;
56
    }
57
58
    /**
59
     * @param TranslatorInterface $translator
60
     */
61
    public function setTranslator(TranslatorInterface $translator)
62
    {
63
        $this->translator = $translator;
64
    }
65
66
    /**
67
     * @return \Symfony\Component\Translation\TranslatorInterface
68
     */
69
    public function getTranslator()
70
    {
71
        return $this->translator;
72
    }
73
74
    /**
75
     * @param array $options
76
     */
77
    public function setImageConstraintOptions(array $options)
78
    {
79
        $this->imageConstraintOptions = $options;
80
    }
81
82
    /**
83
     * @return Filesystem
84
     */
85
    public function getFilesystem()
86
    {
87
        return $this->filesystem;
88
    }
89
90
    /**
91
     * @param Media $media
92
     * @return AbstractProvider
93
     */
94
    public function setMedia($media)
95
    {
96
        $this->media = $media;
97
98
        return $this;
99
    }
100
101
    /**
102
     * @param Media $media
103
     * @param $providerReferenceUpdated
104
     */
105
    public function update(Media $media, $providerReferenceUpdated)
106
    {
107
        $this->updateImage($media);
108
    }
109
110
    /**
111
     * @return string
112
     */
113
    public function getTranslationDomain()
114
    {
115
        return 'MediaMonksSonataMediaBundle';
116
    }
117
118
    /**
119
     * @param MediaInterface $media
120
     * @param array $options
121
     * @return array
122
     */
123
    public function toArray(MediaInterface $media, array $options = [])
124
    {
125
        return [
126
            'type'        => $this->getName(),
127
            'title'       => $media->getTitle(),
128
            'description' => $media->getDescription(),
129
            'authorName'  => $media->getAuthorName(),
130
            'copyright'   => $media->getCopyright(),
131
            'reference'   => $media->getProviderReference(),
132
        ];
133
    }
134
135
    /**
136
     * @return array
137
     */
138
    protected function getFocalPoint()
139
    {
140
        return array_flip(
141
            [
142
                'top-left'     => $this->translator->trans(
143
                    'form.image_focal_point.top_left'
144
                ),
145
                'top'          => $this->translator->trans(
146
                    'form.image_focal_point.top'
147
                ),
148
                'top-right'    => $this->translator->trans(
149
                    'form.image_focal_point.top_right'
150
                ),
151
                'left'         => $this->translator->trans(
152
                    'form.image_focal_point.left'
153
                ),
154
                'center'       => $this->translator->trans(
155
                    'form.image_focal_point.center'
156
                ),
157
                'right'        => $this->translator->trans(
158
                    'form.image_focal_point.right'
159
                ),
160
                'bottom-left'  => $this->translator->trans(
161
                    'form.image_focal_point.bottom_left'
162
                ),
163
                'bottom'       => $this->translator->trans(
164
                    'form.image_focal_point.bottom'
165
                ),
166
                'bottom-right' => $this->translator->trans(
167
                    'form.image_focal_point.bottom_right'
168
                ),
169
            ]
170
        );
171
    }
172
173
    /**
174
     * @param FormMapper $formMapper
175
     */
176
    public function buildCreateForm(FormMapper $formMapper)
177
    {
178
        $formMapper
179
            ->add('provider', 'hidden');
180
181
        $this->buildProviderCreateForm($formMapper);
182
    }
183
184
    /**
185
     * @param FormMapper $formMapper
186
     */
187
    public function buildEditForm(FormMapper $formMapper)
188
    {
189
        $formMapper
190
            ->tab('General')
191
            ->add('provider', HiddenType::class);
192
193
        $this->buildProviderEditFormBefore($formMapper);
194
195
        $formMapper->add(
196
            'imageContent',
197
            'file',
198
            [
199
                'required'    => false,
200
                'constraints' => [
201
                    new Constraint\File(),
202
                ],
203
                'label'       => 'form.replacement_image',
204
            ]
205
        )
206
            ->add('title', TextType::class, ['label' => 'form.title'])
207
            ->add(
208
                'description',
209
                TextType::class,
210
                ['label' => 'form.description', 'required' => false]
211
            )
212
            ->add(
213
                'authorName',
214
                TextType::class,
215
                ['label' => 'form.authorName', 'required' => false]
216
            )
217
            ->add(
218
                'copyright',
219
                TextType::class,
220
                ['label' => 'form.copyright', 'required' => false]
221
            )
222
            ->end()
223
            ->end()
224
            ->tab('Image')
225
            ->add('focalPoint', MediaFocalPointType::class, [
226
                'media' => $this->media
227
            ])
228
            ->end()
229
            ->end()
230
        ;
231
232
        $this->buildProviderEditFormAfter($formMapper);
233
    }
234
235
    /**
236
     * @param FormMapper $formMapper
237
     */
238
    public function buildProviderEditFormBefore(FormMapper $formMapper)
239
    {
240
    }
241
242
    /**
243
     * @param FormMapper $formMapper
244
     */
245
    public function buildProviderEditFormAfter(FormMapper $formMapper)
246
    {
247
    }
248
249
    /**
250
     * @param Media $media
251
     * @param bool $useAsImage
252
     * @return string|void
253
     */
254
    protected function handleFileUpload(Media $media, $useAsImage = false)
255
    {
256
        /**
257
         * @var UploadedFile $file
258
         */
259
        $file = $media->getBinaryContent();
260
261
        if (empty($file)) {
262
            return;
263
        }
264
265
        $filename = $this->getFilenameByFile($file);
266
        $this->writeToFilesystem($file, $filename);
267
268
        $media->setProviderMetadata(
269
            array_merge(
270
                $media->getProviderMetaData(),
271
                $this->getFileMetaData($file)
272
            )
273
        );
274
275
        if (empty($media->getImage()) && $useAsImage) {
276
            $media->setImage($filename);
277
            $media->setImageMetaData($media->getProviderMetaData());
278
        }
279
280
        if (empty($media->getTitle())) {
281
            $media->setTitle(
282
                str_replace(
283
                    '_',
284
                    ' ',
285
                    pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME)
286
                )
287
            );
288
        }
289
290
        return $filename;
291
    }
292
293
    /**
294
     * @param UploadedFile $file
295
     * @return array
296
     */
297
    protected function getFileMetaData(UploadedFile $file)
298
    {
299
        $fileData = [
300
            'originalName'      => $file->getClientOriginalName(),
301
            'originalExtension' => $file->getClientOriginalExtension(),
302
            'mimeType'          => $file->getClientMimeType(),
303
            'size'              => $file->getSize(),
304
        ];
305
306
        if (strpos($file->getClientMimeType(), 'image') !== false) {
307
            $this->disableErrorHandler();
308
            $imageSize = getimagesize($file->getRealPath());
309
            if (is_array($imageSize)) {
310
                list($width, $height) = $imageSize;
311
                if (is_int($width) && is_int($height)) {
312
                    $fileData['height'] = $height;
313
                    $fileData['width']  = $width;
314
                }
315
            }
316
            $this->restoreErrorHandler();
317
        }
318
319
        return $fileData;
320
    }
321
322
    /**
323
     * @param Media $media
324
     */
325
    public function updateImage(Media $media)
326
    {
327
        /**
328
         * @var UploadedFile $file
329
         */
330
        $file = $media->getImageContent();
331
        if (empty($file)) {
332
            return;
333
        }
334
335
        $filename = $this->getFilenameByFile($file);
336
        $this->writeToFilesystem($file, $filename);
337
338
        $media->setImage($filename);
339
        $media->setImageMetaData($this->getFileMetaData($file));
340
    }
341
342
    /**
343
     * @param \Sonata\AdminBundle\Form\FormMapper $formMapper
344
     * @param $name
345
     * @param $label
346
     * @param $required
347
     * @param array $constraints
348
     */
349
    protected function doAddFileField(
350
        FormMapper $formMapper,
351
        $name,
352
        $label,
353
        $required,
354
        $constraints = []
355
    ) {
356
        if ($required) {
357
            $constraints = array_merge(
358
                [
359
                    new Constraint\NotBlank(),
360
                    new Constraint\NotNull(),
361
                ],
362
                $constraints
363
            );
364
        }
365
366
        $formMapper
367
            ->add(
368
                $name,
369
                FileType::class,
370
                [
371
                    'multiple'    => false,
372
                    'data_class'  => null,
373
                    'constraints' => $constraints,
374
                    'label'       => $label,
375
                    'required'    => $required,
376
                ]
377
            );
378
    }
379
380
    /**
381
     * @param FormMapper $formMapper
382
     * @param string $name
383
     * @param string $label
384
     * @param array $options
385
     */
386 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...
387
        FormMapper $formMapper,
388
        $name,
389
        $label,
390
        $options = []
391
    ) {
392
        $this->doAddFileField(
393
            $formMapper,
394
            $name,
395
            $label,
396
            false,
397
            [
398
                new Constraint\Image(
399
                    array_merge($this->imageConstraintOptions, $options)
400
                ),
401
            ]
402
        );
403
    }
404
405
    /**
406
     * @param FormMapper $formMapper
407
     * @param $name
408
     * @param $label
409
     * @param array $options
410
     */
411 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...
412
        FormMapper $formMapper,
413
        $name,
414
        $label,
415
        $options = []
416
    ) {
417
        $this->doAddFileField(
418
            $formMapper,
419
            $name,
420
            $label,
421
            true,
422
            [
423
                new Constraint\Image(
424
                    array_merge($this->imageConstraintOptions, $options)
425
                ),
426
            ]
427
        );
428
    }
429
430
    /**
431
     * @param UploadedFile $file
432
     * @return string
433
     */
434
    protected function getFilenameByFile(UploadedFile $file)
435
    {
436
        return sprintf(
437
            '%s_%d.%s',
438
            sha1($file->getClientOriginalName()),
439
            time(),
440
            $file->getClientOriginalExtension()
441
        );
442
    }
443
444
    /**
445
     * @param UploadedFile $file
446
     * @param $filename
447
     * @throws \Exception
448
     */
449
    protected function writeToFilesystem(UploadedFile $file, $filename)
450
    {
451
        set_error_handler(
452
            function () {
453
            }
454
        );
455
        $stream = fopen($file->getRealPath(), 'r+');
456
        $written = $this->getFilesystem()->writeStream($filename, $stream);
457
        fclose($stream); // this sometime messes up
458
        restore_error_handler();
459
460
        if (!$written) {
461
            throw new \Exception('Could not write to file system');
462
        }
463
    }
464
465
    /**
466
     * @param $renderType
467
     * @return boolean
468
     */
469
    public function supports($renderType)
470
    {
471
        if ($renderType === self::SUPPORT_EMBED) {
472
            return $this->supportsEmbed();
473
        }
474
        if ($renderType === self::SUPPORT_IMAGE) {
475
            return $this->supportsImage();
476
        }
477
        if ($renderType === self::SUPPORT_DOWNLOAD) {
478
            return $this->supportsDownload();
479
        }
480
481
        return false;
482
    }
483
484
    /**
485
     *
486
     */
487
    protected function disableErrorHandler()
488
    {
489
        set_error_handler(
490
            function () {
491
            }
492
        );
493
    }
494
495
    /**
496
     *
497
     */
498
    protected function restoreErrorHandler()
499
    {
500
        restore_error_handler();
501
    }
502
503
    /**
504
     * @param ErrorElement $errorElement
505
     * @param Media $media
506
     */
507
    public function validate(ErrorElement $errorElement, Media $media)
508
    {
509
    }
510
511
    /**
512
     * @return string
513
     */
514
    public function getEmbedTemplate()
515
    {
516
        return sprintf(
517
            'MediaMonksSonataMediaBundle:Provider:%s_embed.html.twig',
518
            $this->getName()
519
        );
520
    }
521
522
    /**
523
     * @return string
524
     */
525
    public function getTitle()
526
    {
527
        return $this->translator->trans($this->getName());
528
    }
529
}
530