Completed
Pull Request — 3.x (#6145)
by Wojciech
05:53 queued 02:45
created

SonataAdminExtension::configureTwigTextExtension()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
rs 8.8497
c 0
b 0
f 0
cc 6
nc 6
nop 3
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\AdminBundle\DependencyInjection;
15
16
use JMS\DiExtraBundle\DependencyInjection\Configuration as JMSDiExtraBundleDependencyInjectionConfiguration;
17
use Sonata\AdminBundle\DependencyInjection\Compiler\ModelManagerCompilerPass;
18
use Sonata\AdminBundle\Model\ModelManagerInterface;
19
use Symfony\Component\Config\FileLocator;
20
use Symfony\Component\DependencyInjection\ContainerBuilder;
21
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
22
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
23
use Symfony\Component\DependencyInjection\Reference;
24
use Symfony\Component\Form\Extension\Core\Type\ChoiceType as SymfonyChoiceType;
25
use Symfony\Component\Form\Extension\Core\Type\DateTimeType as SymfonyDateTimeType;
26
use Symfony\Component\Form\Extension\Core\Type\DateType as SymfonyDateType;
27
use Symfony\Component\Form\Extension\Core\Type\EmailType as SymfonyEmailType;
28
use Symfony\Component\Form\Extension\Core\Type\IntegerType as SymfonyIntegerType;
29
use Symfony\Component\Form\Extension\Core\Type\TextareaType as SymfonyTextareaType;
30
use Symfony\Component\Form\Extension\Core\Type\TextType as SymfonyTextType;
31
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
32
use Twig\Extensions\TextExtension;
33
34
/**
35
 * @final since sonata-project/admin-bundle 3.52
36
 *
37
 * @author Thomas Rabaix <[email protected]>
38
 * @author Michael Williams <[email protected]>
39
 */
40
class SonataAdminExtension extends Extension implements PrependExtensionInterface
41
{
42
    public function load(array $configs, ContainerBuilder $container)
43
    {
44
        $bundles = $container->getParameter('kernel.bundles');
45
46
        if (isset($bundles['SonataUserBundle'])) {
47
            // integrate the SonataUserBundle / FOSUserBundle if the bundle exists
48
            array_unshift($configs, [
49
                'templates' => [
50
                    'user_block' => '@SonataUser/Admin/Core/user_block.html.twig',
51
                ],
52
            ]);
53
        }
54
55
        if (isset($bundles['SonataIntlBundle'])) {
56
            // integrate the SonataUserBundle if the bundle exists
57
            array_unshift($configs, [
58
                'templates' => [
59
                    'history_revision_timestamp' => '@SonataIntl/CRUD/history_revision_timestamp.html.twig',
60
                ],
61
            ]);
62
        }
63
64
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
65
        $loader->load('actions.xml');
66
        $loader->load('block.xml');
67
        $loader->load('commands.xml');
68
        $loader->load('core.xml');
69
        $loader->load('event_listener.xml');
70
        $loader->load('form_types.xml');
71
        $loader->load('menu.xml');
72
        $loader->load('route.xml');
73
        $loader->load('twig.xml');
74
        $loader->load('validator.xml');
75
76
        if (isset($bundles['MakerBundle'])) {
77
            $loader->load('makers.xml');
78
        }
79
80
        if (isset($bundles['SonataExporterBundle'])) {
81
            $loader->load('exporter.xml');
82
        }
83
84
        $configuration = $this->getConfiguration($configs, $container);
85
        $config = $this->processConfiguration($configuration, $configs);
0 ignored issues
show
Documentation introduced by
$configuration is of type null|object, but the function expects a object<Symfony\Component...ConfigurationInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
86
87
        $this->configureTwigTextExtension($container, $loader, $config);
88
89
        $config['options']['javascripts'] = $this->buildJavascripts($config);
90
        $config['options']['stylesheets'] = $this->buildStylesheets($config);
91
        $config['options']['role_admin'] = $config['security']['role_admin'];
92
        $config['options']['role_super_admin'] = $config['security']['role_super_admin'];
93
        $config['options']['search'] = $config['search'];
94
95
        $pool = $container->getDefinition('sonata.admin.pool');
96
        $pool->replaceArgument(1, $config['title']);
97
        $pool->replaceArgument(2, $config['title_logo']);
98
        $pool->replaceArgument(3, $config['options']);
99
100
        if (false === $config['options']['lock_protection']) {
101
            $container->removeDefinition('sonata.admin.lock.extension');
102
        }
103
104
        $container->setParameter('sonata.admin.configuration.global_search.empty_boxes', $config['global_search']['empty_boxes']);
105
        $container->setParameter('sonata.admin.configuration.global_search.case_sensitive', $config['global_search']['case_sensitive']);
106
        $container->setParameter('sonata.admin.configuration.templates', $config['templates']);
107
        $container->setParameter('sonata.admin.configuration.admin_services', $config['admin_services']);
108
        $container->setParameter('sonata.admin.configuration.dashboard_groups', $config['dashboard']['groups']);
109
        $container->setParameter('sonata.admin.configuration.dashboard_blocks', $config['dashboard']['blocks']);
110
        $container->setParameter('sonata.admin.configuration.sort_admins', $config['options']['sort_admins']);
111
        $container->setParameter(
112
            'sonata.admin.configuration.mosaic_background',
113
            $config['options']['mosaic_background']
114
        );
115
        $container->setParameter('sonata.admin.configuration.default_group', $config['options']['default_group']);
116
        $container->setParameter('sonata.admin.configuration.default_label_catalogue', $config['options']['default_label_catalogue']);
117
        $container->setParameter('sonata.admin.configuration.default_icon', $config['options']['default_icon']);
118
        $container->setParameter('sonata.admin.configuration.breadcrumbs', $config['breadcrumbs']);
119
120
        if (null === $config['security']['acl_user_manager'] && isset($bundles['FOSUserBundle'])) {
121
            $container->setParameter('sonata.admin.security.acl_user_manager', 'fos_user.user_manager');
122
        } else {
123
            $container->setParameter('sonata.admin.security.acl_user_manager', $config['security']['acl_user_manager']);
124
        }
125
126
        $container->setAlias('sonata.admin.security.handler', $config['security']['handler']);
127
128
        switch ($config['security']['handler']) {
129
            case 'sonata.admin.security.handler.role':
130
                if (0 === \count($config['security']['information'])) {
131
                    $config['security']['information'] = [
132
                        'EDIT' => ['EDIT'],
133
                        'LIST' => ['LIST'],
134
                        'CREATE' => ['CREATE'],
135
                        'VIEW' => ['VIEW'],
136
                        'DELETE' => ['DELETE'],
137
                        'EXPORT' => ['EXPORT'],
138
                        'ALL' => ['ALL'],
139
                    ];
140
                }
141
142
                break;
143
            case 'sonata.admin.security.handler.acl':
144
                if (0 === \count($config['security']['information'])) {
145
                    $config['security']['information'] = [
146
                        'GUEST' => ['VIEW', 'LIST'],
147
                        'STAFF' => ['EDIT', 'LIST', 'CREATE'],
148
                        'EDITOR' => ['OPERATOR', 'EXPORT'],
149
                        'ADMIN' => ['MASTER'],
150
                    ];
151
                }
152
153
                break;
154
        }
155
156
        $container->setParameter('sonata.admin.configuration.security.role_admin', $config['security']['role_admin']);
157
        $container->setParameter('sonata.admin.configuration.security.role_super_admin', $config['security']['role_super_admin']);
158
        $container->setParameter('sonata.admin.configuration.security.information', $config['security']['information']);
159
        $container->setParameter('sonata.admin.configuration.security.admin_permissions', $config['security']['admin_permissions']);
160
        $container->setParameter('sonata.admin.configuration.security.object_permissions', $config['security']['object_permissions']);
161
162
        $loader->load('security.xml');
163
164
        $container->setParameter('sonata.admin.extension.map', $config['extensions']);
165
166
        /*
167
         * This is a work in progress, so for now it is hardcoded
168
         */
169
        $classes = [
170
            SymfonyChoiceType::class => '',
171
            SymfonyDateType::class => 'sonata-medium-date',
172
            SymfonyDateTimeType::class => 'sonata-medium-date',
173
            SymfonyEmailType::class => '',
174
            SymfonyIntegerType::class => '',
175
            SymfonyTextareaType::class => '',
176
            SymfonyTextType::class => '',
177
        ];
178
179
        $container->getDefinition('sonata.admin.form.extension.field')
180
            ->replaceArgument(0, $classes)
181
            ->replaceArgument(1, $config['options']);
182
183
        // remove non used service
184
        if (!isset($bundles['JMSTranslationBundle'])) {
185
            $container->removeDefinition('sonata.admin.translator.extractor.jms_translator_bundle');
186
        }
187
188
        // remove non-Mopa compatibility layer
189
        if (isset($bundles['MopaBootstrapBundle'])) {
190
            $container->removeDefinition('sonata.admin.form.extension.field.mopa');
191
        }
192
193
        // set filter persistence
194
        $container->setParameter('sonata.admin.configuration.filters.persist', $config['persist_filters']);
195
        $container->setParameter('sonata.admin.configuration.filters.persister', $config['filter_persister']);
196
197
        $container->setParameter('sonata.admin.configuration.show.mosaic.button', $config['show_mosaic_button']);
198
199
        $container->setParameter('sonata.admin.configuration.translate_group_label', $config['translate_group_label']);
200
201
        $this->replacePropertyAccessor($container);
202
203
        $container
204
            ->registerForAutoconfiguration(ModelManagerInterface::class)
205
            ->addTag(ModelManagerCompilerPass::MANAGER_TAG);
206
    }
207
208
    /**
209
     * Allow an extension to prepend the extension configurations.
210
     *
211
     * NEXT_MAJOR: remove all code that deals with JMSDiExtraBundle
212
     */
213
    public function prepend(ContainerBuilder $container)
214
    {
215
        $bundles = $container->getParameter('kernel.bundles');
216
217
        if (!isset($bundles['JMSDiExtraBundle'])) {
218
            return;
219
        }
220
221
        $configs = $container->getExtensionConfig($this->getAlias());
222
        $config = $this->processConfiguration(new Configuration(), $configs);
223
        if (!$config['options']['enable_jms_di_extra_autoregistration']) {
224
            return;
225
        }
226
227
        $sonataAdminPattern = 'Sonata\AdminBundle\Annotation';
228
        $annotationPatternsConfigured = false;
229
230
        $diExtraConfigs = $container->getExtensionConfig('jms_di_extra');
231
        foreach ($diExtraConfigs as $diExtraConfig) {
232
            if (isset($diExtraConfig['annotation_patterns'])) {
233
                // don't add our own pattern if user has already done so
234
                if (false !== array_search($sonataAdminPattern, $diExtraConfig['annotation_patterns'], true)) {
235
                    return;
236
                }
237
                $annotationPatternsConfigured = true;
238
239
                break;
240
            }
241
        }
242
243
        @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...
244
            'Automatic registration of annotations is deprecated since 3.14, to be removed in 4.0.',
245
            E_USER_DEPRECATED
246
        );
247
248
        if ($annotationPatternsConfigured) {
249
            $annotationPatterns = [$sonataAdminPattern];
250
        } else {
251
            // get annotation_patterns default from DiExtraBundle configuration
252
            $diExtraConfigDefinition = new JMSDiExtraBundleDependencyInjectionConfiguration();
253
            // FIXME: this will break if DiExtraBundle adds any mandatory configuration
254
            $diExtraConfig = $this->processConfiguration($diExtraConfigDefinition, []);
255
256
            $annotationPatterns = $diExtraConfig['annotation_patterns'];
257
            $annotationPatterns[] = $sonataAdminPattern;
258
        }
259
260
        $container->prependExtensionConfig(
261
            'jms_di_extra',
262
            [
263
                'annotation_patterns' => $annotationPatterns,
264
            ]
265
        );
266
    }
267
268
    /**
269
     * NEXT_MAJOR: remove this property.
270
     *
271
     * @deprecated since sonata-project/admin-bundle 3.56
272
     */
273
    public function configureClassesToCompile()
274
    {
275
    }
276
277
    public function getNamespace()
278
    {
279
        return 'https://sonata-project.org/schema/dic/admin';
280
    }
281
282
    private function buildStylesheets(array $config): array
283
    {
284
        return $this->mergeArray(
285
            $config['assets']['stylesheets'],
286
            $config['assets']['extra_stylesheets'],
287
            $config['assets']['remove_stylesheets']
288
        );
289
    }
290
291
    private function buildJavascripts(array $config): array
292
    {
293
        return $this->mergeArray(
294
            $config['assets']['javascripts'],
295
            $config['assets']['extra_javascripts'],
296
            $config['assets']['remove_javascripts']
297
        );
298
    }
299
300
    private function mergeArray(array $array, array $addArray, array $removeArray = []): array
301
    {
302
        foreach ($addArray as $toAdd) {
303
            array_push($array, $toAdd);
304
        }
305
        foreach ($removeArray as $toRemove) {
306
            if (\in_array($toRemove, $array, true)) {
307
                array_splice($array, array_search($toRemove, $array, true), 1);
308
            }
309
        }
310
311
        return $array;
312
    }
313
314
    private function replacePropertyAccessor(ContainerBuilder $container): void
315
    {
316
        if (!$container->has('form.property_accessor')) {
317
            return;
318
        }
319
320
        $pool = $container->getDefinition('sonata.admin.pool');
321
        $pool->replaceArgument(4, new Reference('form.property_accessor'));
322
323
        $modelChoice = $container->getDefinition('sonata.admin.form.type.model_choice');
324
        $modelChoice->replaceArgument(0, new Reference('form.property_accessor'));
325
    }
326
327
    /**
328
     * NEXT_MAJOR: remove this method.
329
     */
330
    private function configureTwigTextExtension(ContainerBuilder $container, XmlFileLoader $loader, array $config): void
331
    {
332
        $bundles = $container->getParameter('kernel.bundles');
333
334
        $container->setParameter('sonata.admin.configuration.legacy_twig_text_extension', $config['options']['legacy_twig_text_extension']);
335
        $loader->load('twig_string.xml');
336
337
        $stringExtension = $container->getDefinition('sonata.string.twig.extension');
338
        $stringExtension->replaceArgument(1, $config['options']['legacy_twig_text_extension']);
339
340
        if (false === $config['options']['legacy_twig_text_extension']) {
341
            return;
342
        }
343
344
        $textExtension = null;
345
346
        if (isset($bundles['SonataCoreBundle'])) {
347
            $textExtension = new Reference('sonata.core.twig.extension.text');
348
        } elseif (isset($bundles['SonataTwigBundle'])) {
349
            if ($container->hasDefinition('sonata.twig.extension.deprecated_text_extension')) {
350
                $textExtension = new Reference('sonata.twig.extension.deprecated_text_extension');
351
            }
352
        } elseif (class_exists(TextExtension::class)) {
353
            $textExtension = new TextExtension();
354
        }
355
356
        $stringExtension->replaceArgument(0, $textExtension);
357
    }
358
}
359