Completed
Push — 3.x ( b0e4d8...846f8c )
by Grégoire
03:01
created

SonataAdminExtension::mergeArray()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

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