Completed
Push — master ( 173f5d...31a9ea )
by
unknown
15:41 queued 11s
created

SonataMediaExtension::configureStringExtension()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
cc 3
nc 2
nop 1
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\DependencyInjection;
15
16
use Sonata\ClassificationBundle\Model\CategoryInterface;
17
use Sonata\EasyExtendsBundle\Mapper\DoctrineCollector;
18
use Symfony\Component\Config\Definition\Processor;
19
use Symfony\Component\Config\FileLocator;
20
use Symfony\Component\DependencyInjection\ContainerBuilder;
21
use Symfony\Component\DependencyInjection\Definition;
22
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
23
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
24
use Symfony\Component\DependencyInjection\Reference;
25
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
26
use Twig\Extra\String\StringExtension;
27
28
/**
29
 * @final since sonata-project/media-bundle 3.21.0
30
 *
31
 * @author Thomas Rabaix <[email protected]>
32
 */
33
class SonataMediaExtension extends Extension implements PrependExtensionInterface
34
{
35
    /**
36
     * @var array
37
     */
38
    private $bundleConfigs;
39
40
    /**
41
     * {@inheritdoc}
42
     */
43
    public function load(array $configs, ContainerBuilder $container): void
44
    {
45
        $processor = new Processor();
46
        $configuration = new Configuration();
47
        $config = $processor->processConfiguration($configuration, $configs);
48
49
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
50
        $loader->load('provider.xml');
51
        $loader->load('media.xml');
52
        $loader->load('twig.xml');
53
        $loader->load('security.xml');
54
        $loader->load('extra.xml');
55
        $loader->load('form.xml');
56
        $loader->load('gaufrette.xml');
57
        $loader->load('validators.xml');
58
        $loader->load('serializer.xml');
59
        $loader->load('command.xml');
60
61
        $bundles = $container->getParameter('kernel.bundles');
62
63
        if (isset($bundles['FOSRestBundle'], $bundles['NelmioApiDocBundle'])) {
64
            $loader->load(sprintf('api_form_%s.xml', $config['db_driver']));
65
66
            if ('doctrine_orm' === $config['db_driver']) {
67
                $loader->load('api_controllers.xml');
68
            }
69
        }
70
71
        if (isset($bundles['SonataNotificationBundle'])) {
72
            $loader->load('consumer.xml');
73
        }
74
75
        if (isset($bundles['SonataFormatterBundle'])) {
76
            $loader->load('formatter.xml');
77
        }
78
79
        if (isset($bundles['SonataBlockBundle'])) {
80
            $loader->load('block.xml');
81
        }
82
83
        if (isset($bundles['SonataSeoBundle'])) {
84
            $loader->load('seo_block.xml');
85
        }
86
87
        if (!isset($bundles['LiipImagineBundle'])) {
88
            $container->removeDefinition('sonata.media.thumbnail.liip_imagine');
89
        }
90
91
        if ($this->isClassificationEnabled($config)) {
92
            $loader->load('category.xml');
93
            $categoryManagerAlias = 'sonata.media.manager.category';
94
            $container->setAlias($categoryManagerAlias, $config['category_manager']);
95
            $categoryManager = $container->getAlias($categoryManagerAlias);
96
            $categoryManager->setPublic(true);
97
        }
98
99
        if (!\array_key_exists($config['default_context'], $config['contexts'])) {
100
            throw new \InvalidArgumentException(sprintf('SonataMediaBundle - Invalid default context : %s, available : %s', $config['default_context'], json_encode(array_keys($config['contexts']))));
101
        }
102
103
        $loader->load(sprintf('%s.xml', $config['db_driver']));
104
105
        if (isset($bundles['SonataAdminBundle'])) {
106
            $loader->load(sprintf('%s_admin.xml', $config['db_driver']));
107
108
            $sonataAdminConfig = $this->bundleConfigs['SonataAdminBundle'];
109
110
            $sonataRoles = [];
111
            if (isset($sonataAdminConfig['security']['role_admin'])) {
112
                $sonataRoles[] = $sonataAdminConfig['security']['role_admin'];
113
            } else {
114
                $sonataRoles[] = 'ROLE_ADMIN';
115
            }
116
117
            if (isset($sonataAdminConfig['security']['role_super_admin'])) {
118
                $sonataRoles[] = $sonataAdminConfig['security']['role_super_admin'];
119
            } else {
120
                $sonataRoles[] = 'ROLE_SUPER_ADMIN';
121
            }
122
123
            $container->getDefinition('sonata.media.security.superadmin_strategy')
124
                ->replaceArgument(2, $sonataRoles);
125
        }
126
127
        $this->configureStringExtension($container);
128
129
        $this->configureFilesystemAdapter($container, $config);
130
        $this->configureCdnAdapter($container, $config);
131
132
        $pool = $container->getDefinition('sonata.media.pool');
133
        $pool->replaceArgument(0, $config['default_context']);
134
135
        $strategies = [];
136
137
        foreach ($config['contexts'] as $name => $settings) {
138
            $formats = [];
139
140
            foreach ($settings['formats'] as $format => $value) {
141
                $formats[$name.'_'.$format] = $value;
142
            }
143
144
            $strategies[] = $settings['download']['strategy'];
145
            $pool->addMethodCall('addContext', [$name, $settings['providers'], $formats, $settings['download']]);
146
        }
147
148
        $container->setParameter('sonata.media.admin_format', $config['admin_format']);
149
150
        $strategies = array_unique($strategies);
151
152
        foreach ($strategies as $strategyId) {
153
            $pool->addMethodCall('addDownloadStrategy', [$strategyId, new Reference($strategyId)]);
154
        }
155
156
        if ('doctrine_orm' === $config['db_driver']) {
157
            $this->registerDoctrineMapping($config);
158
        }
159
160
        $container->setParameter('sonata.media.resizer.simple.adapter.mode', $config['resizer']['simple']['mode']);
161
        $container->setParameter('sonata.media.resizer.square.adapter.mode', $config['resizer']['square']['mode']);
162
163
        $this->configureParameterClass($container, $config);
164
        $this->configureExtra($container, $config);
165
        $this->configureBuzz($container, $config);
166
        $this->configureProviders($container, $config);
167
        $this->configureAdapters($container, $config);
168
        $this->configureResizers($container, $config);
169
    }
170
171
    public function configureProviders(ContainerBuilder $container, array $config): void
172
    {
173
        $container->getDefinition('sonata.media.provider.image')
174
            ->replaceArgument(5, array_map('strtolower', $config['providers']['image']['allowed_extensions']))
175
            ->replaceArgument(6, $config['providers']['image']['allowed_mime_types'])
176
            ->replaceArgument(7, new Reference($config['providers']['image']['adapter']))
177
        ;
178
179
        $container->getDefinition('sonata.media.provider.file')
180
            ->replaceArgument(5, $config['providers']['file']['allowed_extensions'])
181
            ->replaceArgument(6, $config['providers']['file']['allowed_mime_types'])
182
        ;
183
184
        $container->getDefinition('sonata.media.provider.youtube')->replaceArgument(7, $config['providers']['youtube']['html5']);
185
    }
186
187
    public function configureBuzz(ContainerBuilder $container, array $config): void
188
    {
189
        $container->getDefinition('sonata.media.buzz.browser')
190
            ->replaceArgument(0, new Reference($config['buzz']['connector']));
191
192
        foreach ([
193
            'sonata.media.buzz.connector.curl',
194
            'sonata.media.buzz.connector.file_get_contents',
195
        ] as $connector) {
196
            $container->getDefinition($connector)
197
                ->addMethodCall('setIgnoreErrors', [$config['buzz']['client']['ignore_errors']])
198
                ->addMethodCall('setMaxRedirects', [$config['buzz']['client']['max_redirects']])
199
                ->addMethodCall('setTimeout', [$config['buzz']['client']['timeout']])
200
                ->addMethodCall('setVerifyPeer', [$config['buzz']['client']['verify_peer']])
201
                ->addMethodCall('setProxy', [$config['buzz']['client']['proxy']]);
202
        }
203
    }
204
205
    public function configureParameterClass(ContainerBuilder $container, array $config): void
206
    {
207
        $container->setParameter('sonata.media.admin.media.entity', $config['class']['media']);
208
        $container->setParameter('sonata.media.admin.gallery.entity', $config['class']['gallery']);
209
        $container->setParameter('sonata.media.admin.gallery_item.entity', $config['class']['gallery_item']);
210
211
        $container->setParameter('sonata.media.media.class', $config['class']['media']);
212
        $container->setParameter('sonata.media.gallery.class', $config['class']['gallery']);
213
214
        $container->getDefinition('sonata.media.form.type.media')->replaceArgument(1, $config['class']['media']);
215
    }
216
217
    public function registerDoctrineMapping(array $config): void
218
    {
219
        $collector = DoctrineCollector::getInstance();
220
221
        $collector->addAssociation($config['class']['media'], 'mapOneToMany', [
222
            'fieldName' => 'galleryItems',
223
            'targetEntity' => $config['class']['gallery_item'],
224
            'cascade' => [
225
                'persist',
226
            ],
227
            'mappedBy' => 'media',
228
            'orphanRemoval' => false,
229
        ]);
230
231
        $collector->addAssociation($config['class']['gallery_item'], 'mapManyToOne', [
232
            'fieldName' => 'gallery',
233
            'targetEntity' => $config['class']['gallery'],
234
            'cascade' => [
235
                'persist',
236
            ],
237
            'mappedBy' => null,
238
            'inversedBy' => 'galleryItems',
239
            'joinColumns' => [
240
                [
241
                    'name' => 'gallery_id',
242
                    'referencedColumnName' => 'id',
243
                    'onDelete' => 'CASCADE',
244
                ],
245
            ],
246
            'orphanRemoval' => false,
247
        ]);
248
249
        $collector->addAssociation($config['class']['gallery_item'], 'mapManyToOne', [
250
            'fieldName' => 'media',
251
            'targetEntity' => $config['class']['media'],
252
            'cascade' => [
253
                 'persist',
254
            ],
255
            'mappedBy' => null,
256
            'inversedBy' => 'galleryItems',
257
            'joinColumns' => [
258
                [
259
                    'name' => 'media_id',
260
                    'referencedColumnName' => 'id',
261
                    'onDelete' => 'CASCADE',
262
                ],
263
            ],
264
            'orphanRemoval' => false,
265
        ]);
266
267
        $collector->addAssociation($config['class']['gallery'], 'mapOneToMany', [
268
            'fieldName' => 'galleryItems',
269
            'targetEntity' => $config['class']['gallery_item'],
270
            'cascade' => [
271
                'persist',
272
            ],
273
            'mappedBy' => 'gallery',
274
            'orphanRemoval' => true,
275
            'orderBy' => [
276
                'position' => 'ASC',
277
            ],
278
        ]);
279
280
        if ($this->isClassificationEnabled($config)) {
281
            $collector->addAssociation($config['class']['media'], 'mapManyToOne', [
282
                'fieldName' => 'category',
283
                'targetEntity' => $config['class']['category'],
284
                'cascade' => [
285
                    'persist',
286
                ],
287
                'mappedBy' => null,
288
                'inversedBy' => null,
289
                'joinColumns' => [
290
                    [
291
                     'name' => 'category_id',
292
                     'referencedColumnName' => 'id',
293
                     'onDelete' => 'SET NULL',
294
                    ],
295
                ],
296
                'orphanRemoval' => false,
297
            ]);
298
        }
299
    }
300
301
    /**
302
     * Inject CDN dependency to default provider.
303
     */
304
    public function configureCdnAdapter(ContainerBuilder $container, array $config): void
305
    {
306
        // add the default configuration for the server cdn
307
        if ($container->hasDefinition('sonata.media.cdn.server') && isset($config['cdn']['server'])) {
308
            $container->getDefinition('sonata.media.cdn.server')
309
                ->replaceArgument(0, $config['cdn']['server']['path'])
310
            ;
311
        } else {
312
            $container->removeDefinition('sonata.media.cdn.server');
313
        }
314
315
        if ($container->hasDefinition('sonata.media.cdn.panther') && isset($config['cdn']['panther'])) {
316
            $container->getDefinition('sonata.media.cdn.panther')
317
                ->replaceArgument(0, $config['cdn']['panther']['path'])
318
                ->replaceArgument(1, $config['cdn']['panther']['username'])
319
                ->replaceArgument(2, $config['cdn']['panther']['password'])
320
                ->replaceArgument(3, $config['cdn']['panther']['site_id'])
321
            ;
322
        } else {
323
            $container->removeDefinition('sonata.media.cdn.panther');
324
        }
325
326
        if ($container->hasDefinition('sonata.media.cdn.cloudfront') && isset($config['cdn']['cloudfront'])) {
327
            $container->getDefinition('sonata.media.cdn.cloudfront')
328
                ->replaceArgument(0, $config['cdn']['cloudfront']['path'])
329
                ->replaceArgument(1, $config['cdn']['cloudfront']['key'])
330
                ->replaceArgument(2, $config['cdn']['cloudfront']['secret'])
331
                ->replaceArgument(3, $config['cdn']['cloudfront']['distribution_id'])
332
            ;
333
        } else {
334
            $container->removeDefinition('sonata.media.cdn.cloudfront');
335
        }
336
337
        if ($container->hasDefinition('sonata.media.cdn.fallback') && isset($config['cdn']['fallback'])) {
338
            $container->getDefinition('sonata.media.cdn.fallback')
339
                ->replaceArgument(0, new Reference($config['cdn']['fallback']['master']))
340
                ->replaceArgument(1, new Reference($config['cdn']['fallback']['fallback']))
341
            ;
342
        } else {
343
            $container->removeDefinition('sonata.media.cdn.fallback');
344
        }
345
    }
346
347
    /**
348
     * Inject filesystem dependency to default provider.
349
     */
350
    public function configureFilesystemAdapter(ContainerBuilder $container, array $config): void
351
    {
352
        // add the default configuration for the local filesystem
353
        if ($container->hasDefinition('sonata.media.adapter.filesystem.local') && isset($config['filesystem']['local'])) {
354
            $container->getDefinition('sonata.media.adapter.filesystem.local')
355
                ->addArgument($config['filesystem']['local']['directory'])
356
                ->addArgument($config['filesystem']['local']['create'])
357
            ;
358
        } else {
359
            $container->removeDefinition('sonata.media.adapter.filesystem.local');
360
        }
361
362
        // add the default configuration for the FTP filesystem
363
        if ($container->hasDefinition('sonata.media.adapter.filesystem.ftp') && isset($config['filesystem']['ftp'])) {
364
            $container->getDefinition('sonata.media.adapter.filesystem.ftp')
365
                ->addArgument($config['filesystem']['ftp']['directory'])
366
                ->addArgument($config['filesystem']['ftp']['host'])
367
                ->addArgument([
368
                    'port' => $config['filesystem']['ftp']['port'],
369
                    'username' => $config['filesystem']['ftp']['username'],
370
                    'password' => $config['filesystem']['ftp']['password'],
371
                    'passive' => $config['filesystem']['ftp']['passive'],
372
                    'create' => $config['filesystem']['ftp']['create'],
373
                    'mode' => $config['filesystem']['ftp']['mode'],
374
                ])
375
            ;
376
        } else {
377
            $container->removeDefinition('sonata.media.adapter.filesystem.ftp');
378
            $container->removeDefinition('sonata.media.filesystem.ftp');
379
        }
380
381
        // add the default configuration for the S3 filesystem
382
        if ($container->hasDefinition('sonata.media.adapter.filesystem.s3') && isset($config['filesystem']['s3'])) {
383
            $container->getDefinition('sonata.media.adapter.filesystem.s3')
384
                ->replaceArgument(0, new Reference('sonata.media.adapter.service.s3'))
385
                ->replaceArgument(1, $config['filesystem']['s3']['bucket'])
386
                ->replaceArgument(2, ['create' => $config['filesystem']['s3']['create'], 'region' => $config['filesystem']['s3']['region'], 'directory' => $config['filesystem']['s3']['directory'], 'ACL' => $config['filesystem']['s3']['acl']])
387
            ;
388
389
            $container->getDefinition('sonata.media.metadata.amazon')
390
                ->replaceArgument(0, [
391
                        'acl' => $config['filesystem']['s3']['acl'],
392
                        'storage' => $config['filesystem']['s3']['storage'],
393
                        'encryption' => $config['filesystem']['s3']['encryption'],
394
                        'meta' => $config['filesystem']['s3']['meta'],
395
                        'cache_control' => $config['filesystem']['s3']['cache_control'],
396
                ])
397
            ;
398
399
            if (3 === $config['filesystem']['s3']['sdk_version']) {
400
                $arguments = [
401
                    'region' => $config['filesystem']['s3']['region'],
402
                    'version' => $config['filesystem']['s3']['version'],
403
                ];
404
405
                if (isset($config['filesystem']['s3']['secretKey'], $config['filesystem']['s3']['accessKey'])) {
406
                    $arguments['credentials'] = [
407
                        'secret' => $config['filesystem']['s3']['secretKey'],
408
                        'key' => $config['filesystem']['s3']['accessKey'],
409
                    ];
410
                }
411
412
                $container->getDefinition('sonata.media.adapter.service.s3')
413
                    ->replaceArgument(0, $arguments)
414
                ;
415
            } else {
416
                $container->getDefinition('sonata.media.adapter.service.s3')
417
                    ->replaceArgument(0, [
418
                        'secret' => $config['filesystem']['s3']['secretKey'],
419
                        'key' => $config['filesystem']['s3']['accessKey'],
420
                    ])
421
                ;
422
            }
423
        } else {
424
            $container->removeDefinition('sonata.media.adapter.filesystem.s3');
425
            $container->removeDefinition('sonata.media.filesystem.s3');
426
        }
427
428
        if ($container->hasDefinition('sonata.media.adapter.filesystem.replicate') && isset($config['filesystem']['replicate'])) {
429
            $container->getDefinition('sonata.media.adapter.filesystem.replicate')
430
                ->replaceArgument(0, new Reference($config['filesystem']['replicate']['master']))
431
                ->replaceArgument(1, new Reference($config['filesystem']['replicate']['slave']))
432
            ;
433
        } else {
434
            $container->removeDefinition('sonata.media.adapter.filesystem.replicate');
435
            $container->removeDefinition('sonata.media.filesystem.replicate');
436
        }
437
438
        if ($container->hasDefinition('sonata.media.adapter.filesystem.mogilefs') && isset($config['filesystem']['mogilefs'])) {
439
            $container->getDefinition('sonata.media.adapter.filesystem.mogilefs')
440
                ->replaceArgument(0, $config['filesystem']['mogilefs']['domain'])
441
                ->replaceArgument(1, $config['filesystem']['mogilefs']['hosts'])
442
            ;
443
        } else {
444
            $container->removeDefinition('sonata.media.adapter.filesystem.mogilefs');
445
            $container->removeDefinition('sonata.media.filesystem.mogilefs');
446
        }
447
448
        if ($container->hasDefinition('sonata.media.adapter.filesystem.opencloud') &&
449
            (isset($config['filesystem']['openstack']) || isset($config['filesystem']['rackspace']))) {
450
            if (isset($config['filesystem']['openstack'])) {
451
                $container->setParameter('sonata.media.adapter.filesystem.opencloud.class', 'OpenCloud\OpenStack');
452
                $settings = 'openstack';
453
            } else {
454
                $container->setParameter('sonata.media.adapter.filesystem.opencloud.class', 'OpenCloud\Rackspace');
455
                $settings = 'rackspace';
456
            }
457
            $container->getDefinition('sonata.media.adapter.filesystem.opencloud.connection')
458
                ->replaceArgument(0, $config['filesystem'][$settings]['url'])
459
                ->replaceArgument(1, $config['filesystem'][$settings]['secret'])
460
                ;
461
            $container->getDefinition('sonata.media.adapter.filesystem.opencloud')
462
                ->replaceArgument(1, $config['filesystem'][$settings]['containerName'])
463
                ->replaceArgument(2, $config['filesystem'][$settings]['create_container']);
464
            $container->getDefinition('sonata.media.adapter.filesystem.opencloud.objectstore')
465
                ->replaceArgument(1, $config['filesystem'][$settings]['region']);
466
        } else {
467
            $container->removeDefinition('sonata.media.adapter.filesystem.opencloud');
468
            $container->removeDefinition('sonata.media.adapter.filesystem.opencloud.connection');
469
            $container->removeDefinition('sonata.media.adapter.filesystem.opencloud.objectstore');
470
            $container->removeDefinition('sonata.media.filesystem.opencloud');
471
        }
472
    }
473
474
    public function configureExtra(ContainerBuilder $container, array $config): void
475
    {
476
        if ($config['pixlr']['enabled']) {
477
            $container->getDefinition('sonata.media.extra.pixlr')
478
                ->replaceArgument(0, $config['pixlr']['referrer'])
479
                ->replaceArgument(1, $config['pixlr']['secret'])
480
            ;
481
        } else {
482
            $container->removeDefinition('sonata.media.extra.pixlr');
483
        }
484
    }
485
486
    /**
487
     * Allow an extension to prepend the extension configurations.
488
     */
489
    public function prepend(ContainerBuilder $container): void
490
    {
491
        $bundles = $container->getParameter('kernel.bundles');
492
493
        // Store SonataAdminBundle configuration for later use
494
        if (isset($bundles['SonataAdminBundle'])) {
495
            $this->bundleConfigs['SonataAdminBundle'] = current($container->getExtensionConfig('sonata_admin'));
496
        }
497
    }
498
499
    /**
500
     * Checks if the classification of media is enabled.
501
     */
502
    private function isClassificationEnabled(array $config): bool
503
    {
504
        return interface_exists(CategoryInterface::class)
505
            && !$config['force_disable_category'];
506
    }
507
508
    private function configureAdapters(ContainerBuilder $container, array $config): void
509
    {
510
        foreach (['gd', 'imagick', 'gmagick'] as $adapter) {
511
            if ($container->hasParameter('sonata.media.adapter.image.'.$adapter.'.class')) {
512
                $container->register(
513
                    'sonata.media.adapter.image.'.$adapter,
514
                    $container->getParameter('sonata.media.adapter.image.'.$adapter.'.class')
515
                );
516
            }
517
        }
518
        $container->setAlias('sonata.media.adapter.image.default', $config['adapters']['default']);
519
    }
520
521
    private function configureResizers(ContainerBuilder $container, array $config): void
522
    {
523
        if ($container->hasParameter('sonata.media.resizer.simple.class')) {
524
            $class = $container->getParameter('sonata.media.resizer.simple.class');
525
            $definition = new Definition($class, [
526
                new Reference('sonata.media.adapter.image.default'),
527
                '%sonata.media.resizer.simple.adapter.mode%',
528
                new Reference('sonata.media.metadata.proxy'),
529
            ]);
530
            $definition->addTag('sonata.media.resizer');
531
            $container->setDefinition('sonata.media.resizer.simple', $definition);
532
        }
533
534
        if ($container->hasParameter('sonata.media.resizer.square.class')) {
535
            $class = $container->getParameter('sonata.media.resizer.square.class');
536
            $definition = new Definition($class, [
537
                new Reference('sonata.media.adapter.image.default'),
538
                '%sonata.media.resizer.square.adapter.mode%',
539
                new Reference('sonata.media.metadata.proxy'),
540
            ]);
541
            $definition->addTag('sonata.media.resizer');
542
            $container->setDefinition('sonata.media.resizer.square', $definition);
543
        }
544
545
        $container->setAlias('sonata.media.resizer.default', $config['resizers']['default']);
546
    }
547
548
    private function configureStringExtension(ContainerBuilder $container): void
549
    {
550
        if (!$container->hasDefinition('twig.extension.string') || !is_a($container->getDefinition('twig.extension.string')->getClass(), StringExtension::class)) {
551
            $definition = new Definition(StringExtension::class);
552
            $definition->addTag('twig.extension');
553
554
            $container->setDefinition(StringExtension::class, $definition);
555
        }
556
    }
557
}
558