Completed
Push — siteaccess_configuration_filte... ( 262eeb )
by
unknown
23:12 queued 08:44
created

EzPublishCoreExtension::prepend()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 8
Ratio 100 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 1
dl 8
loc 8
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
use RuntimeException;
30
31
class EzPublishCoreExtension extends Extension implements PrependExtensionInterface
32
{
33
    /**
34
     * @var \eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\Suggestion\Collector\SuggestionCollector
35
     */
36
    private $suggestionCollector;
37
38
    /**
39
     * @var \eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\ParserInterface
40
     */
41
    private $mainConfigParser;
42
43
    /**
44
     * @var \eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\ParserInterface[]
45
     */
46
    private $configParsers;
47
48
    /**
49
     * @var PolicyProviderInterface[]
50
     */
51
    private $policyProviders = [];
52
53
    /**
54
     * Holds a collection of YAML files, as an array with directory path as a
55
     * key to the array of contained file names.
56
     *
57
     * @var array
58
     */
59
    private $defaultSettingsCollection = [];
60
61
    /**
62
     * @var \eZ\Bundle\EzPublishCoreBundle\SiteAccess\SiteAccessConfigurationFilter[]
63
     */
64
    private $siteaccessConfigurationFilters;
65
66
    public function __construct(array $configParsers = array())
67
    {
68
        $this->configParsers = $configParsers;
69
        $this->suggestionCollector = new SuggestionCollector();
70
    }
71
72
    public function getAlias()
73
    {
74
        return 'ezpublish';
75
    }
76
77
    /**
78
     * Loads a specific configuration.
79
     *
80
     * @param mixed[] $configs An array of configuration values
81
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container A ContainerBuilder instance
82
     *
83
     * @throws \InvalidArgumentException When provided tag is not defined in this extension
84
     *
85
     * @api
86
     */
87
    public function load(array $configs, ContainerBuilder $container)
88
    {
89
        $loader = new Loader\YamlFileLoader(
90
            $container,
91
            new FileLocator(__DIR__ . '/../Resources/config')
92
        );
93
94
        $configuration = $this->getConfiguration($configs, $container);
95
96
        // Note: this is where the transformation occurs
97
        $config = $this->processConfiguration($configuration, $configs);
98
99
        // Base services and services overrides
100
        $loader->load('services.yml');
101
        // Security services
102
        $loader->load('security.yml');
103
        // Slots
104
        $loader->load('slot.yml');
105
106
        // Default settings
107
        $this->handleDefaultSettingsLoading($container, $loader);
108
109
        $this->registerRepositoriesConfiguration($config, $container);
110
        $this->registerSiteAccessConfiguration($config, $container);
111
        $this->registerImageMagickConfiguration($config, $container);
112
        $this->registerPageConfiguration($config, $container);
113
114
        // Routing
115
        $this->handleRouting($config, $container, $loader);
116
        // Public API loading
117
        $this->handleApiLoading($container, $loader);
118
        $this->handleTemplating($container, $loader);
119
        $this->handleSessionLoading($container, $loader);
120
        $this->handleCache($config, $container, $loader);
121
        $this->handleLocale($config, $container, $loader);
122
        $this->handleHelpers($config, $container, $loader);
123
        $this->handleImage($config, $container, $loader);
124
125
        // Map settings
126
        $processor = new ConfigurationProcessor($container, 'ezsettings');
127
        $processor->mapConfig($config, $this->getMainConfigParser());
128
129
        if ($this->suggestionCollector->hasSuggestions()) {
130
            $message = '';
131
            $suggestionFormatter = new YamlSuggestionFormatter();
132
            foreach ($this->suggestionCollector->getSuggestions() as $suggestion) {
133
                $message .= $suggestionFormatter->format($suggestion) . "\n\n";
134
            }
135
136
            throw new InvalidArgumentException($message);
137
        }
138
139
        $this->handleSiteAccessesRelation($container);
140
        $this->buildPolicyMap($container);
141
    }
142
143
    /**
144
     * @param array $config
145
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
146
     *
147
     * @return \eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration
148
     */
149
    public function getConfiguration(array $config, ContainerBuilder $container)
150
    {
151
        return new Configuration($this->getMainConfigParser(), $this->suggestionCollector);
152
    }
153
154
    /**
155
     * @return \eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\ParserInterface
156
     */
157
    private function getMainConfigParser()
158
    {
159
        if ($this->mainConfigParser === null) {
160
            foreach ($this->configParsers as $parser) {
161
                if ($parser instanceof SuggestionCollectorAwareInterface) {
162
                    $parser->setSuggestionCollector($this->suggestionCollector);
163
                }
164
            }
165
166
            $this->mainConfigParser = new ConfigParser($this->configParsers);
167
        }
168
169
        return $this->mainConfigParser;
170
    }
171
172
    /**
173
     * Handle default settings.
174
     *
175
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
176
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
177
     */
178
    private function handleDefaultSettingsLoading(ContainerBuilder $container, FileLoader $loader)
179
    {
180
        $loader->load('default_settings.yml');
181
182
        foreach ($this->defaultSettingsCollection as $fileLocation => $files) {
183
            $externalLoader = new Loader\YamlFileLoader($container, new FileLocator($fileLocation));
184
            foreach ($files as $file) {
185
                $externalLoader->load($file);
186
            }
187
        }
188
    }
189
190
    private function registerRepositoriesConfiguration(array $config, ContainerBuilder $container)
191
    {
192
        if (!isset($config['repositories'])) {
193
            $config['repositories'] = array();
194
        }
195
196
        $container->setParameter('ezpublish.repositories', $config['repositories']);
197
    }
198
199
    private function registerSiteAccessConfiguration(array $config, ContainerBuilder $container)
200
    {
201
        if (!isset($config['siteaccess'])) {
202
            $config['siteaccess'] = array();
203
            $config['siteaccess']['list'] = array('setup');
204
            $config['siteaccess']['default_siteaccess'] = 'setup';
205
            $config['siteaccess']['groups'] = array();
206
            $config['siteaccess']['match'] = null;
207
        }
208
209
210
        $siteAccessConfig = &$config['siteaccess'];
211
        $this->filterSiteaccessConfiguration($siteAccessConfig);
212
213
        $container->setParameter('ezpublish.siteaccess.list', $config['siteaccess']['list']);
214
        ConfigurationProcessor::setAvailableSiteAccesses($config['siteaccess']['list']);
215
        $container->setParameter('ezpublish.siteaccess.default', $config['siteaccess']['default_siteaccess']);
216
        $container->setParameter('ezpublish.siteaccess.match_config', $config['siteaccess']['match']);
217
218
        // Register siteaccess groups + reverse
219
        $container->setParameter('ezpublish.siteaccess.groups', $config['siteaccess']['groups']);
220
        $groupsBySiteaccess = array();
221 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...
222
            foreach ($groupMembers as $member) {
223
                if (!isset($groupsBySiteaccess[$member])) {
224
                    $groupsBySiteaccess[$member] = array();
225
                }
226
227
                $groupsBySiteaccess[$member][] = $groupName;
228
            }
229
        }
230
        $container->setParameter('ezpublish.siteaccess.groups_by_siteaccess', $groupsBySiteaccess);
231
        ConfigurationProcessor::setGroupsBySiteAccess($groupsBySiteaccess);
232
    }
233
234
    private function registerImageMagickConfiguration(array $config, ContainerBuilder $container)
235
    {
236
        if (isset($config['imagemagick'])) {
237
            $container->setParameter('ezpublish.image.imagemagick.enabled', $config['imagemagick']['enabled']);
238
            if ($config['imagemagick']['enabled']) {
239
                $container->setParameter('ezpublish.image.imagemagick.executable_path', dirname($config['imagemagick']['path']));
240
                $container->setParameter('ezpublish.image.imagemagick.executable', basename($config['imagemagick']['path']));
241
            }
242
        }
243
244
        $filters = isset($config['imagemagick']['filters']) ? $config['imagemagick']['filters'] : array();
245
        $filters = $filters + $container->getParameter('ezpublish.image.imagemagick.filters');
246
        $container->setParameter('ezpublish.image.imagemagick.filters', $filters);
247
    }
248
249
    private function registerPageConfiguration(array $config, ContainerBuilder $container)
250
    {
251
        if (isset($config['ezpage']['layouts'])) {
252
            $container->setParameter(
253
                'ezpublish.ezpage.layouts',
254
                $config['ezpage']['layouts'] + $container->getParameter('ezpublish.ezpage.layouts')
255
            );
256
        }
257
        if (isset($config['ezpage']['blocks'])) {
258
            $container->setParameter(
259
                'ezpublish.ezpage.blocks',
260
                $config['ezpage']['blocks'] + $container->getParameter('ezpublish.ezpage.blocks')
261
            );
262
        }
263
        if (isset($config['ezpage']['enabledLayouts'])) {
264
            $container->setParameter(
265
                'ezpublish.ezpage.enabledLayouts',
266
                $config['ezpage']['enabledLayouts'] + $container->getParameter('ezpublish.ezpage.enabledLayouts')
267
            );
268
        }
269
        if (isset($config['ezpage']['enabledBlocks'])) {
270
            $container->setParameter(
271
                'ezpublish.ezpage.enabledBlocks',
272
                $config['ezpage']['enabledBlocks'] + $container->getParameter('ezpublish.ezpage.enabledBlocks')
273
            );
274
        }
275
    }
276
277
    /**
278
     * Handle routing parameters.
279
     *
280
     * @param array $config
281
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
282
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
283
     */
284
    private function handleRouting(array $config, ContainerBuilder $container, FileLoader $loader)
285
    {
286
        $loader->load('routing.yml');
287
        $container->setAlias('router', 'ezpublish.chain_router');
288
289
        if (isset($config['router']['default_router']['non_siteaccess_aware_routes'])) {
290
            $container->setParameter(
291
                'ezpublish.default_router.non_siteaccess_aware_routes',
292
                array_merge(
293
                    $container->getParameter('ezpublish.default_router.non_siteaccess_aware_routes'),
294
                    $config['router']['default_router']['non_siteaccess_aware_routes']
295
                )
296
            );
297
        }
298
    }
299
300
    /**
301
     * Handle public API loading.
302
     *
303
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
304
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
305
     */
306
    private function handleApiLoading(ContainerBuilder $container, FileLoader $loader)
307
    {
308
        // Loading configuration from Core/settings
309
        $coreLoader = new Loader\YamlFileLoader(
310
            $container,
311
            new FileLocator(__DIR__ . '/../../../Publish/Core/settings')
312
        );
313
        $coreLoader->load('repository.yml');
314
        $coreLoader->load('fieldtype_external_storages.yml');
315
        $coreLoader->load('fieldtypes.yml');
316
        $coreLoader->load('indexable_fieldtypes.yml');
317
        $coreLoader->load('roles.yml');
318
        $coreLoader->load('storage_engines/common.yml');
319
        $coreLoader->load('storage_engines/cache.yml');
320
        $coreLoader->load('storage_engines/legacy.yml');
321
        $coreLoader->load('storage_engines/shortcuts.yml');
322
        $coreLoader->load('search_engines/common.yml');
323
        $coreLoader->load('utils.yml');
324
        $coreLoader->load('io.yml');
325
326
        // Public API services
327
        $loader->load('papi.yml');
328
329
        // Built-in field types
330
        $loader->load('fieldtype_services.yml');
331
332
        // Storage engine
333
        $loader->load('storage_engines.yml');
334
    }
335
336
    /**
337
     * Handle templating parameters.
338
     *
339
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
340
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
341
     */
342
    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...
343
    {
344
        $loader->load('templating.yml');
345
    }
346
347
    /**
348
     * Handle session parameters.
349
     *
350
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
351
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
352
     */
353
    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...
354
    {
355
        $loader->load('session.yml');
356
    }
357
358
    /**
359
     * Handle cache parameters.
360
     *
361
     * @param array $config
362
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
363
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
364
     *
365
     * @throws \InvalidArgumentException
366
     */
367
    private function handleCache(array $config, ContainerBuilder $container, FileLoader $loader)
368
    {
369
        $loader->load('cache.yml');
370
371
        if (isset($config['http_cache']['purge_type'])) {
372
            switch ($config['http_cache']['purge_type']) {
373
                case 'local':
374
                    $purgeService = 'ezpublish.http_cache.purge_client.local';
375
                    break;
376
                case 'http':
377
                    $purgeService = 'ezpublish.http_cache.purge_client.fos';
378
                    break;
379
                default:
380
                    if (!$container->has($config['http_cache']['purge_type'])) {
381
                        throw new \InvalidArgumentException("Invalid ezpublish.http_cache.purge_type. Can be 'single', 'multiple' or a valid service identifier implementing PurgeClientInterface.");
382
                    }
383
384
                    $purgeService = $config['http_cache']['purge_type'];
385
            }
386
387
            $container->setAlias('ezpublish.http_cache.purge_client', $purgeService);
388
        }
389
    }
390
391
    /**
392
     * Handle locale parameters.
393
     *
394
     * @param array $config
395
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
396
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
397
     */
398
    private function handleLocale(array $config, ContainerBuilder $container, FileLoader $loader)
399
    {
400
        $loader->load('locale.yml');
401
        $container->setParameter(
402
            'ezpublish.locale.conversion_map',
403
            $config['locale_conversion'] + $container->getParameter('ezpublish.locale.conversion_map')
404
        );
405
    }
406
407
    /**
408
     * Handle helpers.
409
     *
410
     * @param array $config
411
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
412
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
413
     */
414
    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...
415
    {
416
        $loader->load('helpers.yml');
417
    }
418
419
    /**
420
     * Handles relation between SiteAccesses.
421
     * Related SiteAccesses share the same repository and root location id.
422
     *
423
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
424
     */
425
    private function handleSiteAccessesRelation(ContainerBuilder $container)
426
    {
427
        $configResolver = $container->get('ezpublish.config.resolver.core');
428
        $configResolver->setContainer($container);
429
430
        $saRelationMap = array();
431
        $saList = $container->getParameter('ezpublish.siteaccess.list');
432
        // First build the SiteAccess relation map, indexed by repository and rootLocationId.
433
        foreach ($saList as $sa) {
434
            $repository = $configResolver->getParameter('repository', 'ezsettings', $sa);
435
            if (!isset($saRelationMap[$repository])) {
436
                $saRelationMap[$repository] = array();
437
            }
438
439
            $rootLocationId = $configResolver->getParameter('content.tree_root.location_id', 'ezsettings', $sa);
440
            if (!isset($saRelationMap[$repository][$rootLocationId])) {
441
                $saRelationMap[$repository][$rootLocationId] = array();
442
            }
443
            $saRelationMap[$repository][$rootLocationId][] = $sa;
444
        }
445
        $container->setParameter('ezpublish.siteaccess.relation_map', $saRelationMap);
446
447
        // Now build the related SiteAccesses list, based on the relation map.
448
        foreach ($saList as $sa) {
449
            $repository = $configResolver->getParameter('repository', 'ezsettings', $sa);
450
            $rootLocationId = $configResolver->getParameter('content.tree_root.location_id', 'ezsettings', $sa);
451
            $container->setParameter(
452
                "ezsettings.$sa.related_siteaccesses",
453
                $saRelationMap[$repository][$rootLocationId]
454
            );
455
        }
456
    }
457
458
    /**
459
     * @param array $config
460
     * @param ContainerBuilder $container
461
     * @param FileLoader $loader
462
     */
463
    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...
464
    {
465
        $loader->load('image.yml');
466
    }
467
468
    private function buildPolicyMap(ContainerBuilder $container)
469
    {
470
        $policiesBuilder = new PoliciesConfigBuilder($container);
471
        foreach ($this->policyProviders as $provider) {
472
            $provider->addPolicies($policiesBuilder);
473
        }
474
    }
475
476 View Code Duplication
    public function prepend(ContainerBuilder $container)
477
    {
478
        // Default settings for FOSHttpCacheBundle
479
        $configFile = __DIR__ . '/../Resources/config/fos_http_cache.yml';
480
        $config = Yaml::parse(file_get_contents($configFile));
481
        $container->prependExtensionConfig('fos_http_cache', $config);
482
        $container->addResource(new FileResource($configFile));
483
    }
484
485
    /**
486
     * Adds a new policy provider to the internal collection.
487
     * One can call this method from a bundle `build()` method.
488
     *
489
     * ```php
490
     * public function build(ContainerBuilder $container)
491
     * {
492
     *     $ezExtension = $container->getExtension('ezpublish');
493
     *     $ezExtension->addPolicyProvider($myPolicyProvider);
494
     * }
495
     * ```
496
     *
497
     * @since 6.0
498
     *
499
     * @param PolicyProviderInterface $policyProvider
500
     */
501
    public function addPolicyProvider(PolicyProviderInterface $policyProvider)
502
    {
503
        $this->policyProviders[] = $policyProvider;
504
    }
505
506
    /**
507
     * Adds a new config parser to the internal collection.
508
     * One can call this method from a bundle `build()` method.
509
     *
510
     * ```php
511
     * public function build(ContainerBuilder $container)
512
     * {
513
     *     $ezExtension = $container->getExtension('ezpublish');
514
     *     $ezExtension->addConfigParser($myConfigParser);
515
     * }
516
     * ```
517
     *
518
     * @since 6.0
519
     *
520
     * @param \eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\ParserInterface $configParser
521
     */
522
    public function addConfigParser(ParserInterface $configParser)
523
    {
524
        if ($this->mainConfigParser !== null) {
525
            throw new RuntimeException('Main config parser is already instantiated');
526
        }
527
528
        $this->configParsers[] = $configParser;
529
    }
530
531
    /**
532
     * Adds new default settings to the internal collection.
533
     * One can call this method from a bundle `build()` method.
534
     *
535
     * ```php
536
     * public function build(ContainerBuilder $container)
537
     * {
538
     *     $ezExtension = $container->getExtension('ezpublish');
539
     *     $ezExtension->addDefaultSettings(
540
     *         __DIR__ . '/Resources/config',
541
     *         ['default_settings.yml']
542
     *     );
543
     * }
544
     * ```
545
     *
546
     * @since 6.0
547
     *
548
     * @param string $fileLocation
549
     * @param array $files
550
     */
551
    public function addDefaultSettings($fileLocation, array $files)
552
    {
553
        $this->defaultSettingsCollection[$fileLocation] = $files;
554
    }
555
556
    public function addSiteAccessConfigurationFilter(SiteAccessConfigurationFilter $filter)
557
    {
558
        $this->siteaccessConfigurationFilters[] = $filter;
559
    }
560
561
    private function filterSiteaccessConfiguration(&$siteAccessConfig)
562
    {
563
        foreach ($this->siteaccessConfigurationFilters as $filter) {
564
            $filter->filter($siteAccessConfig);
565
        }
566
    }
567
}
568