Completed
Pull Request — master (#5769)
by Grégoire
08:45
created

SonataAdminExtension::configureClassesToCompile()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
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
final class SonataAdminExtension extends Extension implements PrependExtensionInterface
38
{
39
    public function load(array $configs, ContainerBuilder $container): void
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): void
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
    public function configureClassesToCompile(): void
290
    {
291
    }
292
293
    public function getNamespace()
294
    {
295
        return 'https://sonata-project.org/schema/dic/admin';
296
    }
297
298
    private function buildStylesheets($config): array
299
    {
300
        return $this->mergeArray(
301
            $config['assets']['stylesheets'],
302
            $config['assets']['extra_stylesheets'],
303
            $config['assets']['remove_stylesheets']
304
        );
305
    }
306
307
    private function buildJavascripts($config): array
308
    {
309
        return $this->mergeArray(
310
            $config['assets']['javascripts'],
311
            $config['assets']['extra_javascripts'],
312
            $config['assets']['remove_javascripts']
313
        );
314
    }
315
316
    private function mergeArray(array $array, array $addArray, array $removeArray = []): array
317
    {
318
        foreach ($addArray as $toAdd) {
319
            array_push($array, $toAdd);
320
        }
321
        foreach ($removeArray as $toRemove) {
322
            if (\in_array($toRemove, $array, true)) {
323
                array_splice($array, array_search($toRemove, $array, true), 1);
324
            }
325
        }
326
327
        return $array;
328
    }
329
330
    private function replacePropertyAccessor(ContainerBuilder $container): void
331
    {
332
        if (!$container->has('form.property_accessor')) {
333
            return;
334
        }
335
336
        $pool = $container->getDefinition('sonata.admin.pool');
337
        $pool->replaceArgument(4, new Reference('form.property_accessor'));
338
339
        $modelChoice = $container->getDefinition('sonata.admin.form.type.model_choice');
340
        $modelChoice->replaceArgument(0, new Reference('form.property_accessor'));
341
    }
342
}
343