Completed
Push — master ( 162ac8...74252e )
by
unknown
19:44
created

AbstractProvider::supports()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

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