Completed
Push — master ( 2644b8...e286ab )
by
unknown
10:21
created

AbstractProvider::restoreErrorHandler()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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