Completed
Push — master ( 97e40f...89ec5c )
by André
40:26 queued 12:35
created

EzPublishCoreExtension::getConfiguration()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 2
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the EzPublishCoreExtension class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Bundle\EzPublishCoreBundle\DependencyInjection;
10
11
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\ConfigParser;
12
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\SiteAccessAware\ConfigurationProcessor;
13
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\Suggestion\Collector\SuggestionCollector;
14
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\Suggestion\Collector\SuggestionCollectorAwareInterface;
15
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\Suggestion\Formatter\YamlSuggestionFormatter;
16
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Security\PolicyProvider\PoliciesConfigBuilder;
17
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Security\PolicyProvider\PolicyProviderInterface;
18
use eZ\Bundle\EzPublishCoreBundle\SiteAccess\SiteAccessConfigurationFilter;
19
use Symfony\Component\Config\Resource\FileResource;
20
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
21
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
22
use Symfony\Component\DependencyInjection\ContainerBuilder;
23
use Symfony\Component\DependencyInjection\Loader;
24
use Symfony\Component\DependencyInjection\Loader\FileLoader;
25
use Symfony\Component\Config\FileLocator;
26
use InvalidArgumentException;
27
use Symfony\Component\Yaml\Yaml;
28
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\ParserInterface;
29
30
class EzPublishCoreExtension extends Extension implements PrependExtensionInterface
31
{
32
    /**
33
     * @var \eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\Suggestion\Collector\SuggestionCollector
34
     */
35
    private $suggestionCollector;
36
37
    /**
38
     * @var \eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\ParserInterface
39
     */
40
    private $mainConfigParser;
41
42
    /**
43
     * @var \eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\ParserInterface[]
44
     */
45
    private $configParsers;
46
47
    /**
48
     * @var PolicyProviderInterface[]
49
     */
50
    private $policyProviders = [];
51
52
    /**
53
     * Holds a collection of YAML files, as an array with directory path as a
54
     * key to the array of contained file names.
55
     *
56
     * @var array
57
     */
58
    private $defaultSettingsCollection = [];
59
60
    /**
61
     * @var \eZ\Bundle\EzPublishCoreBundle\SiteAccess\SiteAccessConfigurationFilter[]
62
     */
63
    private $siteaccessConfigurationFilters = [];
64
65
    public function __construct(array $configParsers = array())
66
    {
67
        $this->configParsers = $configParsers;
68
        $this->suggestionCollector = new SuggestionCollector();
69
    }
70
71
    public function getAlias()
72
    {
73
        return 'ezpublish';
74
    }
75
76
    /**
77
     * Loads a specific configuration.
78
     *
79
     * @param mixed[] $configs An array of configuration values
80
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container A ContainerBuilder instance
81
     *
82
     * @throws \InvalidArgumentException When provided tag is not defined in this extension
83
     *
84
     * @api
85
     */
86
    public function load(array $configs, ContainerBuilder $container)
87
    {
88
        $loader = new Loader\YamlFileLoader(
89
            $container,
90
            new FileLocator(__DIR__ . '/../Resources/config')
91
        );
92
93
        $configuration = $this->getConfiguration($configs, $container);
94
95
        // Note: this is where the transformation occurs
96
        $config = $this->processConfiguration($configuration, $configs);
97
98
        // Base services and services overrides
99
        $loader->load('services.yml');
100
        // Security services
101
        $loader->load('security.yml');
102
        // Slots
103
        $loader->load('slot.yml');
104
105
        if (interface_exists('FOS\JsRoutingBundle\Extractor\ExposedRoutesExtractorInterface')) {
106
            $loader->load('routing/js_routing.yml');
107
        }
108
109
        // Default settings
110
        $this->handleDefaultSettingsLoading($container, $loader);
111
112
        $this->registerRepositoriesConfiguration($config, $container);
113
        $this->registerSiteAccessConfiguration($config, $container);
114
        $this->registerImageMagickConfiguration($config, $container);
115
        $this->registerPageConfiguration($config, $container);
116
117
        // Routing
118
        $this->handleRouting($config, $container, $loader);
119
        // Public API loading
120
        $this->handleApiLoading($container, $loader);
121
        $this->handleTemplating($container, $loader);
122
        $this->handleSessionLoading($container, $loader);
123
        $this->handleCache($config, $container, $loader);
124
        $this->handleLocale($config, $container, $loader);
125
        $this->handleHelpers($config, $container, $loader);
126
        $this->handleImage($config, $container, $loader);
127
128
        // Map settings
129
        $processor = new ConfigurationProcessor($container, 'ezsettings');
130
        $processor->mapConfig($config, $this->getMainConfigParser());
131
132
        if ($this->suggestionCollector->hasSuggestions()) {
133
            $message = '';
134
            $suggestionFormatter = new YamlSuggestionFormatter();
135
            foreach ($this->suggestionCollector->getSuggestions() as $suggestion) {
136
                $message .= $suggestionFormatter->format($suggestion) . "\n\n";
137
            }
138
139
            throw new InvalidArgumentException($message);
140
        }
141
142
        $this->handleSiteAccessesRelation($container);
143
        $this->buildPolicyMap($container);
144
    }
145
146
    /**
147
     * @param array $config
148
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
149
     *
150
     * @return \eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration
151
     */
152
    public function getConfiguration(array $config, ContainerBuilder $container)
153
    {
154
        $configuration = new Configuration($this->getMainConfigParser(), $this->suggestionCollector);
155
        $configuration->setSiteAccessConfigurationFilters($this->siteaccessConfigurationFilters);
156
157
        return $configuration;
158
    }
159
160
    /**
161
     * @return \eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\ParserInterface
162
     */
163
    private function getMainConfigParser()
164
    {
165
        if ($this->mainConfigParser === null) {
166
            foreach ($this->configParsers as $parser) {
167
                if ($parser instanceof SuggestionCollectorAwareInterface) {
168
                    $parser->setSuggestionCollector($this->suggestionCollector);
169
                }
170
            }
171
172
            $this->mainConfigParser = new ConfigParser($this->configParsers);
173
        }
174
175
        return $this->mainConfigParser;
176
    }
177
178
    /**
179
     * Handle default settings.
180
     *
181
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
182
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
183
     */
184
    private function handleDefaultSettingsLoading(ContainerBuilder $container, FileLoader $loader)
185
    {
186
        $loader->load('default_settings.yml');
187
188
        foreach ($this->defaultSettingsCollection as $fileLocation => $files) {
189
            $externalLoader = new Loader\YamlFileLoader($container, new FileLocator($fileLocation));
190
            foreach ($files as $file) {
191
                $externalLoader->load($file);
192
            }
193
        }
194
    }
195
196
    private function registerRepositoriesConfiguration(array $config, ContainerBuilder $container)
197
    {
198
        if (!isset($config['repositories'])) {
199
            $config['repositories'] = array();
200
        }
201
202
        foreach ($config['repositories'] as $name => &$repository) {
203
            if (empty($repository['fields_groups']['list'])) {
204
                $repository['fields_groups']['list'] = $container->getParameter('ezsettings.default.content.field_groups.list');
205
            }
206
        }
207
208
        $container->setParameter('ezpublish.repositories', $config['repositories']);
209
    }
210
211
    private function registerSiteAccessConfiguration(array $config, ContainerBuilder $container)
212
    {
213
        if (!isset($config['siteaccess'])) {
214
            $config['siteaccess'] = array();
215
            $config['siteaccess']['list'] = array('setup');
216
            $config['siteaccess']['default_siteaccess'] = 'setup';
217
            $config['siteaccess']['groups'] = array();
218
            $config['siteaccess']['match'] = null;
219
        }
220
221
        $container->setParameter('ezpublish.siteaccess.list', $config['siteaccess']['list']);
222
        ConfigurationProcessor::setAvailableSiteAccesses($config['siteaccess']['list']);
223
        $container->setParameter('ezpublish.siteaccess.default', $config['siteaccess']['default_siteaccess']);
224
        $container->setParameter('ezpublish.siteaccess.match_config', $config['siteaccess']['match']);
225
226
        // Register siteaccess groups + reverse
227
        $container->setParameter('ezpublish.siteaccess.groups', $config['siteaccess']['groups']);
228
        $groupsBySiteaccess = array();
229 View Code Duplication
        foreach ($config['siteaccess']['groups'] as $groupName => $groupMembers) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
230
            foreach ($groupMembers as $member) {
231
                if (!isset($groupsBySiteaccess[$member])) {
232
                    $groupsBySiteaccess[$member] = array();
233
                }
234
235
                $groupsBySiteaccess[$member][] = $groupName;
236
            }
237
        }
238
        $container->setParameter('ezpublish.siteaccess.groups_by_siteaccess', $groupsBySiteaccess);
239
        ConfigurationProcessor::setGroupsBySiteAccess($groupsBySiteaccess);
240
    }
241
242
    private function registerImageMagickConfiguration(array $config, ContainerBuilder $container)
243
    {
244
        if (isset($config['imagemagick'])) {
245
            $container->setParameter('ezpublish.image.imagemagick.enabled', $config['imagemagick']['enabled']);
246
            if ($config['imagemagick']['enabled']) {
247
                $container->setParameter('ezpublish.image.imagemagick.executable_path', dirname($config['imagemagick']['path']));
248
                $container->setParameter('ezpublish.image.imagemagick.executable', basename($config['imagemagick']['path']));
249
            }
250
        }
251
252
        $filters = isset($config['imagemagick']['filters']) ? $config['imagemagick']['filters'] : array();
253
        $filters = $filters + $container->getParameter('ezpublish.image.imagemagick.filters');
254
        $container->setParameter('ezpublish.image.imagemagick.filters', $filters);
255
    }
256
257
    private function registerPageConfiguration(array $config, ContainerBuilder $container)
258
    {
259
        if (isset($config['ezpage']['layouts'])) {
260
            $container->setParameter(
261
                'ezpublish.ezpage.layouts',
262
                $config['ezpage']['layouts'] + $container->getParameter('ezpublish.ezpage.layouts')
263
            );
264
        }
265
        if (isset($config['ezpage']['blocks'])) {
266
            $container->setParameter(
267
                'ezpublish.ezpage.blocks',
268
                $config['ezpage']['blocks'] + $container->getParameter('ezpublish.ezpage.blocks')
269
            );
270
        }
271
        if (isset($config['ezpage']['enabledLayouts'])) {
272
            $container->setParameter(
273
                'ezpublish.ezpage.enabledLayouts',
274
                $config['ezpage']['enabledLayouts'] + $container->getParameter('ezpublish.ezpage.enabledLayouts')
275
            );
276
        }
277
        if (isset($config['ezpage']['enabledBlocks'])) {
278
            $container->setParameter(
279
                'ezpublish.ezpage.enabledBlocks',
280
                $config['ezpage']['enabledBlocks'] + $container->getParameter('ezpublish.ezpage.enabledBlocks')
281
            );
282
        }
283
    }
284
285
    /**
286
     * Handle routing parameters.
287
     *
288
     * @param array $config
289
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
290
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
291
     */
292
    private function handleRouting(array $config, ContainerBuilder $container, FileLoader $loader)
293
    {
294
        $loader->load('routing.yml');
295
        $container->setAlias('router', 'ezpublish.chain_router');
296
297
        if (isset($config['router']['default_router']['non_siteaccess_aware_routes'])) {
298
            $container->setParameter(
299
                'ezpublish.default_router.non_siteaccess_aware_routes',
300
                array_merge(
301
                    $container->getParameter('ezpublish.default_router.non_siteaccess_aware_routes'),
302
                    $config['router']['default_router']['non_siteaccess_aware_routes']
303
                )
304
            );
305
        }
306
    }
307
308
    /**
309
     * Handle public API loading.
310
     *
311
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
312
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
313
     */
314
    private function handleApiLoading(ContainerBuilder $container, FileLoader $loader)
315
    {
316
        // Loading configuration from Core/settings
317
        $coreLoader = new Loader\YamlFileLoader(
318
            $container,
319
            new FileLocator(__DIR__ . '/../../../Publish/Core/settings')
320
        );
321
        $coreLoader->load('repository.yml');
322
        $coreLoader->load('repository/inner.yml');
323
        $coreLoader->load('repository/signalslot.yml');
324
        $coreLoader->load('fieldtype_external_storages.yml');
325
        $coreLoader->load('fieldtypes.yml');
326
        $coreLoader->load('indexable_fieldtypes.yml');
327
        $coreLoader->load('roles.yml');
328
        $coreLoader->load('storage_engines/common.yml');
329
        $coreLoader->load('storage_engines/cache.yml');
330
        $coreLoader->load('storage_engines/legacy.yml');
331
        $coreLoader->load('storage_engines/shortcuts.yml');
332
        $coreLoader->load('search_engines/common.yml');
333
        $coreLoader->load('utils.yml');
334
        $coreLoader->load('io.yml');
335
336
        // Public API services
337
        $loader->load('papi.yml');
338
339
        // Built-in field types
340
        $loader->load('fieldtype_services.yml');
341
342
        // Storage engine
343
        $loader->load('storage_engines.yml');
344
    }
345
346
    /**
347
     * Handle templating parameters.
348
     *
349
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
350
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
351
     */
352
    private function handleTemplating(ContainerBuilder $container, FileLoader $loader)
0 ignored issues
show
Unused Code introduced by
The parameter $container is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
353
    {
354
        $loader->load('templating.yml');
355
    }
356
357
    /**
358
     * Handle session parameters.
359
     *
360
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
361
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
362
     */
363
    private function handleSessionLoading(ContainerBuilder $container, FileLoader $loader)
0 ignored issues
show
Unused Code introduced by
The parameter $container is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
364
    {
365
        $loader->load('session.yml');
366
    }
367
368
    /**
369
     * Handle cache parameters.
370
     *
371
     * @param array $config
372
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
373
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
374
     *
375
     * @throws \InvalidArgumentException
376
     */
377
    private function handleCache(array $config, ContainerBuilder $container, FileLoader $loader)
378
    {
379
        $loader->load('cache.yml');
380
381
        $purgeService = null;
0 ignored issues
show
Unused Code introduced by
$purgeService is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
382
        if (isset($config['http_cache']['purge_type'])) {
383
            $container->setParameter('ezpublish.http_cache.purge_type', $config['http_cache']['purge_type']);
384
        }
385
    }
386
387
    /**
388
     * Handle locale parameters.
389
     *
390
     * @param array $config
391
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
392
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
393
     */
394
    private function handleLocale(array $config, ContainerBuilder $container, FileLoader $loader)
395
    {
396
        $loader->load('locale.yml');
397
        $container->setParameter(
398
            'ezpublish.locale.conversion_map',
399
            $config['locale_conversion'] + $container->getParameter('ezpublish.locale.conversion_map')
400
        );
401
    }
402
403
    /**
404
     * Handle helpers.
405
     *
406
     * @param array $config
407
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
408
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
409
     */
410
    private function handleHelpers(array $config, ContainerBuilder $container, FileLoader $loader)
0 ignored issues
show
Unused Code introduced by
The parameter $config is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $container is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
411
    {
412
        $loader->load('helpers.yml');
413
    }
414
415
    /**
416
     * Handles relation between SiteAccesses.
417
     * Related SiteAccesses share the same repository and root location id.
418
     *
419
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
420
     */
421
    private function handleSiteAccessesRelation(ContainerBuilder $container)
422
    {
423
        $configResolver = $container->get('ezpublish.config.resolver.core');
424
        $configResolver->setContainer($container);
425
426
        $saRelationMap = array();
427
        $saList = $container->getParameter('ezpublish.siteaccess.list');
428
        // First build the SiteAccess relation map, indexed by repository and rootLocationId.
429
        foreach ($saList as $sa) {
430
            $repository = $configResolver->getParameter('repository', 'ezsettings', $sa);
431
            if (!isset($saRelationMap[$repository])) {
432
                $saRelationMap[$repository] = array();
433
            }
434
435
            $rootLocationId = $configResolver->getParameter('content.tree_root.location_id', 'ezsettings', $sa);
436
            if (!isset($saRelationMap[$repository][$rootLocationId])) {
437
                $saRelationMap[$repository][$rootLocationId] = array();
438
            }
439
            $saRelationMap[$repository][$rootLocationId][] = $sa;
440
        }
441
        $container->setParameter('ezpublish.siteaccess.relation_map', $saRelationMap);
442
443
        // Now build the related SiteAccesses list, based on the relation map.
444
        foreach ($saList as $sa) {
445
            $repository = $configResolver->getParameter('repository', 'ezsettings', $sa);
446
            $rootLocationId = $configResolver->getParameter('content.tree_root.location_id', 'ezsettings', $sa);
447
            $container->setParameter(
448
                "ezsettings.$sa.related_siteaccesses",
449
                $saRelationMap[$repository][$rootLocationId]
450
            );
451
        }
452
    }
453
454
    /**
455
     * @param array $config
456
     * @param ContainerBuilder $container
457
     * @param FileLoader $loader
458
     */
459
    private function handleImage(array $config, ContainerBuilder $container, FileLoader $loader)
0 ignored issues
show
Unused Code introduced by
The parameter $config is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $container is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
460
    {
461
        $loader->load('image.yml');
462
    }
463
464
    private function buildPolicyMap(ContainerBuilder $container)
465
    {
466
        $policiesBuilder = new PoliciesConfigBuilder($container);
467
        foreach ($this->policyProviders as $provider) {
468
            $provider->addPolicies($policiesBuilder);
469
        }
470
    }
471
472
    public function prepend(ContainerBuilder $container)
473
    {
474
        // Default settings for FOSHttpCacheBundle
475
        $configFile = __DIR__ . '/../Resources/config/fos_http_cache.yml';
476
        $config = Yaml::parse(file_get_contents($configFile));
477
        $container->prependExtensionConfig('fos_http_cache', $config);
478
        $container->addResource(new FileResource($configFile));
479
    }
480
481
    /**
482
     * Adds a new policy provider to the internal collection.
483
     * One can call this method from a bundle `build()` method.
484
     *
485
     * ```php
486
     * public function build(ContainerBuilder $container)
487
     * {
488
     *     $ezExtension = $container->getExtension('ezpublish');
489
     *     $ezExtension->addPolicyProvider($myPolicyProvider);
490
     * }
491
     * ```
492
     *
493
     * @since 6.0
494
     *
495
     * @param PolicyProviderInterface $policyProvider
496
     */
497
    public function addPolicyProvider(PolicyProviderInterface $policyProvider)
498
    {
499
        $this->policyProviders[] = $policyProvider;
500
    }
501
502
    /**
503
     * Adds a new config parser to the internal collection.
504
     * One can call this method from a bundle `build()` method.
505
     *
506
     * ```php
507
     * public function build(ContainerBuilder $container)
508
     * {
509
     *     $ezExtension = $container->getExtension('ezpublish');
510
     *     $ezExtension->addConfigParser($myConfigParser);
511
     * }
512
     * ```
513
     *
514
     * @since 6.0
515
     *
516
     * @param \eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\ParserInterface $configParser
517
     */
518
    public function addConfigParser(ParserInterface $configParser)
519
    {
520
        $this->configParsers[] = $configParser;
521
    }
522
523
    /**
524
     * Adds new default settings to the internal collection.
525
     * One can call this method from a bundle `build()` method.
526
     *
527
     * ```php
528
     * public function build(ContainerBuilder $container)
529
     * {
530
     *     $ezExtension = $container->getExtension('ezpublish');
531
     *     $ezExtension->addDefaultSettings(
532
     *         __DIR__ . '/Resources/config',
533
     *         ['default_settings.yml']
534
     *     );
535
     * }
536
     * ```
537
     *
538
     * @since 6.0
539
     *
540
     * @param string $fileLocation
541
     * @param array $files
542
     */
543
    public function addDefaultSettings($fileLocation, array $files)
544
    {
545
        $this->defaultSettingsCollection[$fileLocation] = $files;
546
    }
547
548
    public function addSiteAccessConfigurationFilter(SiteAccessConfigurationFilter $filter)
549
    {
550
        $this->siteaccessConfigurationFilters[] = $filter;
551
    }
552
}
553