Completed
Push — 3.x ( 223ba5...fee8cc )
by Grégoire
36:15
created

SonataAdminExtension   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 311
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
wmc 31
lcom 1
cbo 8
dl 0
loc 311
rs 9.92
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getNamespace() 0 4 1
A buildStylesheets() 0 8 1
A buildJavascripts() 0 8 1
A mergeArray() 0 13 4
A replacePropertyAccessor() 0 12 2
F load() 0 189 14
B prepend() 0 54 7
A configureClassesToCompile() 0 3 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\AdminBundle\DependencyInjection;
15
16
use JMS\DiExtraBundle\DependencyInjection\Configuration as JMSDiExtraBundleDependencyInjectionConfiguration;
17
use Symfony\Component\Config\FileLocator;
18
use Symfony\Component\DependencyInjection\ContainerBuilder;
19
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
20
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
21
use Symfony\Component\DependencyInjection\Reference;
22
use Symfony\Component\Form\Extension\Core\Type\ChoiceType as SymfonyChoiceType;
23
use Symfony\Component\Form\Extension\Core\Type\DateTimeType as SymfonyDateTimeType;
24
use Symfony\Component\Form\Extension\Core\Type\DateType as SymfonyDateType;
25
use Symfony\Component\Form\Extension\Core\Type\EmailType as SymfonyEmailType;
26
use Symfony\Component\Form\Extension\Core\Type\IntegerType as SymfonyIntegerType;
27
use Symfony\Component\Form\Extension\Core\Type\TextareaType as SymfonyTextareaType;
28
use Symfony\Component\Form\Extension\Core\Type\TextType as SymfonyTextType;
29
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
30
31
/**
32
 * @final since sonata-project/admin-bundle 3.52
33
 *
34
 * @author Thomas Rabaix <[email protected]>
35
 * @author Michael Williams <[email protected]>
36
 */
37
class SonataAdminExtension extends Extension implements PrependExtensionInterface
38
{
39
    public function load(array $configs, ContainerBuilder $container)
40
    {
41
        $bundles = $container->getParameter('kernel.bundles');
42
43
        if (isset($bundles['SonataUserBundle'])) {
44
            // integrate the SonataUserBundle / FOSUserBundle if the bundle exists
45
            array_unshift($configs, [
46
                'templates' => [
47
                    'user_block' => '@SonataUser/Admin/Core/user_block.html.twig',
48
                ],
49
            ]);
50
        }
51
52
        if (isset($bundles['SonataIntlBundle'])) {
53
            // integrate the SonataUserBundle if the bundle exists
54
            array_unshift($configs, [
55
                'templates' => [
56
                    'history_revision_timestamp' => '@SonataIntl/CRUD/history_revision_timestamp.html.twig',
57
                ],
58
            ]);
59
        }
60
61
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
62
        $loader->load('twig.xml');
63
        $loader->load('core.xml');
64
        $loader->load('form_types.xml');
65
        $loader->load('validator.xml');
66
        $loader->load('route.xml');
67
        $loader->load('block.xml');
68
        $loader->load('menu.xml');
69
        $loader->load('commands.xml');
70
        $loader->load('actions.xml');
71
72
        if (isset($bundles['MakerBundle'])) {
73
            $loader->load('makers.xml');
74
        }
75
76
        if (isset($bundles['SonataExporterBundle'])) {
77
            $loader->load('exporter.xml');
78
        }
79
80
        $configuration = $this->getConfiguration($configs, $container);
81
        $config = $this->processConfiguration($configuration, $configs);
0 ignored issues
show
Documentation introduced by
$configuration is of type object|null, 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...
82
83
        $config['options']['javascripts'] = $this->buildJavascripts($config);
84
        $config['options']['stylesheets'] = $this->buildStylesheets($config);
85
        $config['options']['role_admin'] = $config['security']['role_admin'];
86
        $config['options']['role_super_admin'] = $config['security']['role_super_admin'];
87
        $config['options']['search'] = $config['search'];
88
89
        $pool = $container->getDefinition('sonata.admin.pool');
90
        $pool->replaceArgument(1, $config['title']);
91
        $pool->replaceArgument(2, $config['title_logo']);
92
        $pool->replaceArgument(3, $config['options']);
93
94
        if (false === $config['options']['lock_protection']) {
95
            $container->removeDefinition('sonata.admin.lock.extension');
96
        }
97
98
        $container->setParameter('sonata.admin.configuration.global_search.empty_boxes', $config['global_search']['empty_boxes']);
99
        $container->setParameter('sonata.admin.configuration.global_search.case_sensitive', $config['global_search']['case_sensitive']);
100
        $container->setParameter('sonata.admin.configuration.templates', $config['templates'] + [
101
            'user_block' => '@SonataAdmin/Core/user_block.html.twig',
102
            'add_block' => '@SonataAdmin/Core/add_block.html.twig',
103
            'layout' => '@SonataAdmin/standard_layout.html.twig',
104
            'ajax' => '@SonataAdmin/ajax_layout.html.twig',
105
            'dashboard' => '@SonataAdmin/Core/dashboard.html.twig',
106
            'list' => '@SonataAdmin/CRUD/list.html.twig',
107
            'filter' => '@SonataAdmin/Form/filter_admin_fields.html.twig',
108
            'show' => '@SonataAdmin/CRUD/show.html.twig',
109
            'show_compare' => '@SonataAdmin/CRUD/show_compare.html.twig',
110
            'edit' => '@SonataAdmin/CRUD/edit.html.twig',
111
            'history' => '@SonataAdmin/CRUD/history.html.twig',
112
            'history_revision_timestamp' => '@SonataAdmin/CRUD/history_revision_timestamp.html.twig',
113
            'acl' => '@SonataAdmin/CRUD/acl.html.twig',
114
            'action' => '@SonataAdmin/CRUD/action.html.twig',
115
            'short_object_description' => '@SonataAdmin/Helper/short-object-description.html.twig',
116
            'preview' => '@SonataAdmin/CRUD/preview.html.twig',
117
            'list_block' => '@SonataAdmin/Block/block_admin_list.html.twig',
118
            'delete' => '@SonataAdmin/CRUD/delete.html.twig',
119
            'batch' => '@SonataAdmin/CRUD/list__batch.html.twig',
120
            'select' => '@SonataAdmin/CRUD/list__select.html.twig',
121
            'batch_confirmation' => '@SonataAdmin/CRUD/batch_confirmation.html.twig',
122
            'inner_list_row' => '@SonataAdmin/CRUD/list_inner_row.html.twig',
123
            'base_list_field' => '@SonataAdmin/CRUD/base_list_field.html.twig',
124
            'pager_links' => '@SonataAdmin/Pager/links.html.twig',
125
            'pager_results' => '@SonataAdmin/Pager/results.html.twig',
126
            'tab_menu_template' => '@SonataAdmin/Core/tab_menu_template.html.twig',
127
            'knp_menu_template' => '@SonataAdmin/Menu/sonata_menu.html.twig',
128
            'outer_list_rows_mosaic' => '@SonataAdmin/CRUD/list_outer_rows_mosaic.html.twig',
129
            'outer_list_rows_list' => '@SonataAdmin/CRUD/list_outer_rows_list.html.twig',
130
            'outer_list_rows_tree' => '@SonataAdmin/CRUD/list_outer_rows_tree.html.twig',
131
        ]);
132
        $container->setParameter('sonata.admin.configuration.admin_services', $config['admin_services']);
133
        $container->setParameter('sonata.admin.configuration.dashboard_groups', $config['dashboard']['groups']);
134
        $container->setParameter('sonata.admin.configuration.dashboard_blocks', $config['dashboard']['blocks']);
135
        $container->setParameter('sonata.admin.configuration.sort_admins', $config['options']['sort_admins']);
136
        $container->setParameter(
137
            'sonata.admin.configuration.mosaic_background',
138
            $config['options']['mosaic_background']
139
        );
140
        $container->setParameter('sonata.admin.configuration.default_group', $config['options']['default_group']);
141
        $container->setParameter('sonata.admin.configuration.default_label_catalogue', $config['options']['default_label_catalogue']);
142
        $container->setParameter('sonata.admin.configuration.default_icon', $config['options']['default_icon']);
143
        $container->setParameter('sonata.admin.configuration.breadcrumbs', $config['breadcrumbs']);
144
145
        if (null === $config['security']['acl_user_manager'] && isset($bundles['FOSUserBundle'])) {
146
            $container->setParameter('sonata.admin.security.acl_user_manager', 'fos_user.user_manager');
147
        } else {
148
            $container->setParameter('sonata.admin.security.acl_user_manager', $config['security']['acl_user_manager']);
149
        }
150
151
        $container->setAlias('sonata.admin.security.handler', $config['security']['handler']);
152
153
        switch ($config['security']['handler']) {
154
            case 'sonata.admin.security.handler.role':
155
                if (0 === \count($config['security']['information'])) {
156
                    $config['security']['information'] = [
157
                        'EDIT' => ['EDIT'],
158
                        'LIST' => ['LIST'],
159
                        'CREATE' => ['CREATE'],
160
                        'VIEW' => ['VIEW'],
161
                        'DELETE' => ['DELETE'],
162
                        'EXPORT' => ['EXPORT'],
163
                        'ALL' => ['ALL'],
164
                    ];
165
                }
166
167
                break;
168
            case 'sonata.admin.security.handler.acl':
169
                if (0 === \count($config['security']['information'])) {
170
                    $config['security']['information'] = [
171
                        'GUEST' => ['VIEW', 'LIST'],
172
                        'STAFF' => ['EDIT', 'LIST', 'CREATE'],
173
                        'EDITOR' => ['OPERATOR', 'EXPORT'],
174
                        'ADMIN' => ['MASTER'],
175
                    ];
176
                }
177
178
                break;
179
        }
180
181
        $container->setParameter('sonata.admin.configuration.security.role_admin', $config['security']['role_admin']);
182
        $container->setParameter('sonata.admin.configuration.security.role_super_admin', $config['security']['role_super_admin']);
183
        $container->setParameter('sonata.admin.configuration.security.information', $config['security']['information']);
184
        $container->setParameter('sonata.admin.configuration.security.admin_permissions', $config['security']['admin_permissions']);
185
        $container->setParameter('sonata.admin.configuration.security.object_permissions', $config['security']['object_permissions']);
186
187
        $loader->load('security.xml');
188
189
        $container->setParameter('sonata.admin.extension.map', $config['extensions']);
190
191
        /*
192
         * This is a work in progress, so for now it is hardcoded
193
         */
194
        $classes = [
195
            SymfonyChoiceType::class => '',
196
            SymfonyDateType::class => 'sonata-medium-date',
197
            SymfonyDateTimeType::class => 'sonata-medium-date',
198
            SymfonyEmailType::class => '',
199
            SymfonyIntegerType::class => '',
200
            SymfonyTextareaType::class => '',
201
            SymfonyTextType::class => '',
202
        ];
203
204
        $container->getDefinition('sonata.admin.form.extension.field')
205
            ->replaceArgument(0, $classes)
206
            ->replaceArgument(1, $config['options']);
207
208
        // remove non used service
209
        if (!isset($bundles['JMSTranslationBundle'])) {
210
            $container->removeDefinition('sonata.admin.translator.extractor.jms_translator_bundle');
211
        }
212
213
        //remove non-Mopa compatibility layer
214
        if (isset($bundles['MopaBootstrapBundle'])) {
215
            $container->removeDefinition('sonata.admin.form.extension.field.mopa');
216
        }
217
218
        // set filter persistence
219
        $container->setParameter('sonata.admin.configuration.filters.persist', $config['persist_filters']);
220
        $container->setParameter('sonata.admin.configuration.filters.persister', $config['filter_persister']);
221
222
        $container->setParameter('sonata.admin.configuration.show.mosaic.button', $config['show_mosaic_button']);
223
224
        $container->setParameter('sonata.admin.configuration.translate_group_label', $config['translate_group_label']);
225
226
        $this->replacePropertyAccessor($container);
227
    }
228
229
    /**
230
     * Allow an extension to prepend the extension configurations.
231
     *
232
     * NEXT_MAJOR: remove all code that deals with JMSDiExtraBundle
233
     */
234
    public function prepend(ContainerBuilder $container)
235
    {
236
        $bundles = $container->getParameter('kernel.bundles');
237
238
        if (!isset($bundles['JMSDiExtraBundle'])) {
239
            return;
240
        }
241
242
        $configs = $container->getExtensionConfig($this->getAlias());
243
        $config = $this->processConfiguration(new Configuration(), $configs);
244
        if (!$config['options']['enable_jms_di_extra_autoregistration']) {
245
            return;
246
        }
247
248
        $sonataAdminPattern = 'Sonata\AdminBundle\Annotation';
249
        $annotationPatternsConfigured = false;
250
251
        $diExtraConfigs = $container->getExtensionConfig('jms_di_extra');
252
        foreach ($diExtraConfigs as $diExtraConfig) {
253
            if (isset($diExtraConfig['annotation_patterns'])) {
254
                // don't add our own pattern if user has already done so
255
                if (false !== array_search($sonataAdminPattern, $diExtraConfig['annotation_patterns'], true)) {
256
                    return;
257
                }
258
                $annotationPatternsConfigured = true;
259
260
                break;
261
            }
262
        }
263
264
        @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...
265
            'Automatic registration of annotations is deprecated since 3.14, to be removed in 4.0.',
266
            E_USER_DEPRECATED
267
        );
268
269
        if ($annotationPatternsConfigured) {
270
            $annotationPatterns = [$sonataAdminPattern];
271
        } else {
272
            // get annotation_patterns default from DiExtraBundle configuration
273
            $diExtraConfigDefinition = new JMSDiExtraBundleDependencyInjectionConfiguration();
274
            // FIXME: this will break if DiExtraBundle adds any mandatory configuration
275
            $diExtraConfig = $this->processConfiguration($diExtraConfigDefinition, []);
276
277
            $annotationPatterns = $diExtraConfig['annotation_patterns'];
278
            $annotationPatterns[] = $sonataAdminPattern;
279
        }
280
281
        $container->prependExtensionConfig(
282
            'jms_di_extra',
283
            [
284
                'annotation_patterns' => $annotationPatterns,
285
            ]
286
        );
287
    }
288
289
    /**
290
     * NEXT_MAJOR: remove this property.
291
     *
292
     * @deprecated since sonata-project/admin-bundle 3.x
293
     */
294
    public function configureClassesToCompile()
295
    {
296
    }
297
298
    public function getNamespace()
299
    {
300
        return 'https://sonata-project.org/schema/dic/admin';
301
    }
302
303
    private function buildStylesheets($config): array
304
    {
305
        return $this->mergeArray(
306
            $config['assets']['stylesheets'],
307
            $config['assets']['extra_stylesheets'],
308
            $config['assets']['remove_stylesheets']
309
        );
310
    }
311
312
    private function buildJavascripts($config): array
313
    {
314
        return $this->mergeArray(
315
            $config['assets']['javascripts'],
316
            $config['assets']['extra_javascripts'],
317
            $config['assets']['remove_javascripts']
318
        );
319
    }
320
321
    private function mergeArray(array $array, array $addArray, array $removeArray = []): array
322
    {
323
        foreach ($addArray as $toAdd) {
324
            array_push($array, $toAdd);
325
        }
326
        foreach ($removeArray as $toRemove) {
327
            if (\in_array($toRemove, $array, true)) {
328
                array_splice($array, array_search($toRemove, $array, true), 1);
329
            }
330
        }
331
332
        return $array;
333
    }
334
335
    private function replacePropertyAccessor(ContainerBuilder $container): void
336
    {
337
        if (!$container->has('form.property_accessor')) {
338
            return;
339
        }
340
341
        $pool = $container->getDefinition('sonata.admin.pool');
342
        $pool->replaceArgument(4, new Reference('form.property_accessor'));
343
344
        $modelChoice = $container->getDefinition('sonata.admin.form.type.model_choice');
345
        $modelChoice->replaceArgument(0, new Reference('form.property_accessor'));
346
    }
347
}
348