Completed
Pull Request — 3.x (#601)
by Jordi Sala
01:29
created

SonataNewsExtension::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\NewsBundle\DependencyInjection;
15
16
use Sonata\Doctrine\Mapper\Builder\OptionsBuilder;
17
use Sonata\Doctrine\Mapper\DoctrineCollector;
18
use Sonata\EasyExtendsBundle\Mapper\DoctrineCollector as DeprecatedDoctrineCollector;
19
use Symfony\Component\Config\Definition\Processor;
20
use Symfony\Component\Config\FileLocator;
21
use Symfony\Component\DependencyInjection\ContainerBuilder;
22
use Symfony\Component\DependencyInjection\Definition;
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
 * @author Thomas Rabaix <[email protected]>
30
 */
31
class SonataNewsExtension extends Extension
32
{
33
    /**
34
     * @throws \InvalidArgumentException
35
     */
36
    public function load(array $configs, ContainerBuilder $container)
37
    {
38
        $processor = new Processor();
39
        $configuration = new Configuration();
40
        $config = $processor->processConfiguration($configuration, $configs);
41
        $bundles = $container->getParameter('kernel.bundles');
42
43
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
44
        $loader->load('actions.xml');
45
        $loader->load('twig.xml');
46
        $loader->load('form.xml');
47
        $loader->load('core.xml');
48
        $loader->load('serializer.xml');
49
        $loader->load('command.xml');
50
51
        if (isset($bundles['SonataBlockBundle'])) {
52
            $loader->load('block.xml');
53
        }
54
55
        if (isset($bundles['FOSRestBundle'], $bundles['NelmioApiDocBundle'])) {
56
            $loader->load(sprintf('api_form_%s.xml', $config['db_driver']));
57
            if ('doctrine_orm' === $config['db_driver']) {
58
                $loader->load('api_controllers.xml');
59
            }
60
        }
61
62
        $loader->load(sprintf('%s.xml', $config['db_driver']));
63
64
        if (isset($bundles['SonataAdminBundle'])) {
65
            $loader->load(sprintf('%s_admin.xml', $config['db_driver']));
66
        }
67
68
        if (!isset($config['salt'])) {
69
            throw new \InvalidArgumentException(
70
                'The configuration node "salt" is not set for the SonataNewsBundle (sonata_news)'
71
            );
72
        }
73
74
        if (!isset($config['comment'])) {
75
            throw new \InvalidArgumentException(
76
                'The configuration node "comment" is not set for the SonataNewsBundle (sonata_news)'
77
            );
78
        }
79
80
        $container->getDefinition('sonata.news.hash.generator')
81
            ->replaceArgument(0, $config['salt']);
82
83
        $container->getDefinition('sonata.news.permalink.date')
84
            ->replaceArgument(0, $config['permalink']['date']);
85
86
        $container->setAlias('sonata.news.permalink.generator', $config['permalink_generator']);
87
88
        $container->setDefinition('sonata.news.blog', new Definition('Sonata\NewsBundle\Model\Blog', [
89
            $config['title'],
90
            $config['link'],
91
            $config['description'],
92
            new Reference('sonata.news.permalink.generator'),
93
        ]));
94
95
        $container->getDefinition('sonata.news.hash.generator')
96
            ->replaceArgument(0, $config['salt']);
97
98
        $container->getDefinition('sonata.news.mailer')
99
            ->replaceArgument(5, [
100
                'notification' => $config['comment']['notification'],
101
            ]);
102
103
        if ('doctrine_orm' === $config['db_driver']) {
104
            if (isset($bundles['SonataDoctrineBundle'])) {
105
                $this->registerSonataDoctrineMapping($config);
106
            } else {
107
                // NEXT MAJOR: Throw error when not registering SonataDoctrineBundle
108
                @trigger_error(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
109
                    'Using SonataEasyExtendsBundle is deprecated since sonata-project/news-bundle 3.x. Please register SonataDoctrineBundle as a bundle instead.',
110
                    E_USER_DEPRECATED
111
                );
112
113
                $this->registerDoctrineMapping($config);
114
            }
115
        }
116
117
        $this->configureClass($config, $container);
118
        $this->configureAdmin($config, $container);
119
        $this->configureStringExtension($container);
120
    }
121
122
    /**
123
     * @param array $config
124
     */
125
    public function configureClass($config, ContainerBuilder $container)
126
    {
127
        // admin configuration
128
        $container->setParameter('sonata.news.admin.post.entity', $config['class']['post']);
129
        $container->setParameter('sonata.news.admin.comment.entity', $config['class']['comment']);
130
131
        // manager configuration
132
        $container->setParameter('sonata.news.manager.post.entity', $config['class']['post']);
133
        $container->setParameter('sonata.news.manager.comment.entity', $config['class']['comment']);
134
    }
135
136
    /**
137
     * @param array $config
138
     */
139
    public function configureAdmin($config, ContainerBuilder $container)
140
    {
141
        $container->setParameter('sonata.news.admin.post.class', $config['admin']['post']['class']);
142
        $container->setParameter('sonata.news.admin.post.controller', $config['admin']['post']['controller']);
143
        $container->setParameter('sonata.news.admin.post.translation_domain', $config['admin']['post']['translation']);
144
145
        $container->setParameter('sonata.news.admin.comment.class', $config['admin']['comment']['class']);
146
        $container->setParameter('sonata.news.admin.comment.controller', $config['admin']['comment']['controller']);
147
        $container->setParameter('sonata.news.admin.comment.translation_domain', $config['admin']['comment']['translation']);
148
    }
149
150
    public function registerDoctrineMapping(array $config)
151
    {
152
        $collector = DeprecatedDoctrineCollector::getInstance();
153
154
        foreach ($config['class'] as $type => $class) {
155
            if (!class_exists($class)) {
156
                /*
157
                 * NEXT_MAJOR:
158
                 * Throw an exception if the class is not defined
159
                 */
160
                @trigger_error(sprintf(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
161
                    'The "%s" class is not defined or does not exist. This is tolerated now but will be forbidden in 4.0',
162
                    $class
163
                ), E_USER_DEPRECATED);
164
165
                return;
166
            }
167
        }
168
169
        $collector->addAssociation($config['class']['post'], 'mapOneToMany', [
170
            'fieldName' => 'comments',
171
            'targetEntity' => $config['class']['comment'],
172
            'cascade' => [
173
                    0 => 'remove',
174
                    1 => 'persist',
175
                ],
176
            'mappedBy' => 'post',
177
            'orphanRemoval' => true,
178
            'orderBy' => [
179
                    'createdAt' => 'DESC',
180
                ],
181
        ]);
182
183
        $collector->addAssociation($config['class']['post'], 'mapManyToOne', [
184
            'fieldName' => 'image',
185
            'targetEntity' => $config['class']['media'],
186
            'cascade' => [
187
                    0 => 'remove',
188
                    1 => 'persist',
189
                    2 => 'refresh',
190
                    3 => 'merge',
191
                    4 => 'detach',
192
                ],
193
            'mappedBy' => null,
194
            'inversedBy' => null,
195
            'joinColumns' => [
196
                    [
197
                        'name' => 'image_id',
198
                        'referencedColumnName' => 'id',
199
                    ],
200
                ],
201
            'orphanRemoval' => false,
202
        ]);
203
204
        $collector->addAssociation($config['class']['post'], 'mapManyToOne', [
205
            'fieldName' => 'author',
206
            'targetEntity' => $config['class']['user'],
207
            'cascade' => [
208
                    1 => 'persist',
209
                ],
210
            'mappedBy' => null,
211
            'inversedBy' => null,
212
            'joinColumns' => [
213
                    [
214
                        'name' => 'author_id',
215
                        'referencedColumnName' => 'id',
216
                    ],
217
                ],
218
            'orphanRemoval' => false,
219
        ]);
220
221
        $collector->addAssociation($config['class']['post'], 'mapManyToOne', [
222
            'fieldName' => 'collection',
223
            'targetEntity' => $config['class']['collection'],
224
            'cascade' => [
225
                    1 => 'persist',
226
                ],
227
            'mappedBy' => null,
228
            'inversedBy' => null,
229
            'joinColumns' => [
230
                    [
231
                        'name' => 'collection_id',
232
                        'referencedColumnName' => 'id',
233
                    ],
234
                ],
235
            'orphanRemoval' => false,
236
        ]);
237
238
        $collector->addAssociation($config['class']['post'], 'mapManyToMany', [
239
            'fieldName' => 'tags',
240
            'targetEntity' => $config['class']['tag'],
241
            'cascade' => [
242
                    1 => 'persist',
243
                ],
244
            'joinTable' => [
245
                    'name' => $config['table']['post_tag'],
246
                    'joinColumns' => [
247
                            [
248
                                'name' => 'post_id',
249
                                'referencedColumnName' => 'id',
250
                            ],
251
                        ],
252
                    'inverseJoinColumns' => [
253
                            [
254
                                'name' => 'tag_id',
255
                                'referencedColumnName' => 'id',
256
                            ],
257
                        ],
258
                ],
259
        ]);
260
261
        $collector->addAssociation($config['class']['comment'], 'mapManyToOne', [
262
            'fieldName' => 'post',
263
            'targetEntity' => $config['class']['post'],
264
            'cascade' => [
265
            ],
266
            'mappedBy' => null,
267
            'inversedBy' => 'comments',
268
            'joinColumns' => [
269
                    [
270
                        'name' => 'post_id',
271
                        'referencedColumnName' => 'id',
272
                        'nullable' => false,
273
                    ],
274
                ],
275
            'orphanRemoval' => false,
276
        ]);
277
    }
278
279
    private function configureStringExtension(ContainerBuilder $container): void
280
    {
281
        if (!$container->hasDefinition('twig.extension.string') || !is_a($container->getDefinition('twig.extension.string')->getClass(), StringExtension::class)) {
282
            $definition = new Definition(StringExtension::class);
283
            $definition->addTag('twig.extension');
284
285
            $container->setDefinition(StringExtension::class, $definition);
286
        }
287
    }
288
289
    private function registerSonataDoctrineMapping(array $config): void
290
    {
291
        foreach ($config['class'] as $type => $class) {
292
            if (!class_exists($class)) {
293
                return;
294
            }
295
        }
296
297
        $collector = DoctrineCollector::getInstance();
298
299
        $commentsOptions = OptionsBuilder::createOneToMany('comments', $config['class']['comment'])
300
            ->cascade(['remove', 'persist'])
301
            ->mappedBy('post')
302
            ->orphanRemoval()
303
            ->addOrder('createdAt', 'DESC');
304
305
        $imageOptions = OptionsBuilder::createManyToOne('image', $config['class']['media'])
306
            ->cascade(['remove', 'persist', 'refresh', 'merge', 'detach'])
307
            ->addJoin([
308
                'name' => 'image_id',
309
                'referencedColumnName' => 'id',
310
            ]);
311
312
        $authorOptions = OptionsBuilder::createManyToOne('author', $config['class']['user'])
313
            ->cascade(['persist'])
314
            ->addJoin([
315
                'name' => 'author_id',
316
                'referencedColumnName' => 'id',
317
            ]);
318
319
        $collectionOptions = OptionsBuilder::createManyToOne('collection', $config['class']['collection'])
320
            ->cascade(['persist'])
321
            ->addJoin([
322
                'name' => 'collection_id',
323
                'referencedColumnName' => 'id',
324
            ]);
325
326
        $tagsOptions = OptionsBuilder::createManyToMany('tags', $config['class']['tag'])
327
            ->cascade(['persist'])
328
            ->addJoinTable($config['table']['post_tag'], [[
329
                'name' => 'post_id',
330
                'referencedColumnName' => 'id',
331
            ]], [[
332
                'name' => 'tag_id',
333
                'referencedColumnName' => 'id',
334
            ]]);
335
336
        $postOptions = OptionsBuilder::createManyToOne('post', $config['class']['post'])
337
            ->inversedBy('comments')
338
            ->addJoin([
339
                'name' => 'post_id',
340
                'referencedColumnName' => 'id',
341
                'nullable' => false,
342
            ]);
343
344
        $collector->addAssociation($config['class']['post'], 'mapOneToMany', $commentsOptions);
345
        $collector->addAssociation($config['class']['post'], 'mapManyToOne', $imageOptions);
346
        $collector->addAssociation($config['class']['post'], 'mapManyToOne', $authorOptions);
347
        $collector->addAssociation($config['class']['post'], 'mapManyToOne', $collectionOptions);
348
        $collector->addAssociation($config['class']['post'], 'mapManyToMany', $tagsOptions);
349
        $collector->addAssociation($config['class']['comment'], 'mapManyToOne', $postOptions);
350
    }
351
}
352