Completed
Push — http_cache_mvc ( 5374b9 )
by
unknown
27:11
created

EzPublishCoreExtension::buildPolicyMap()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
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 Symfony\Component\Config\Resource\FileResource;
19
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
20
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
21
use Symfony\Component\DependencyInjection\ContainerBuilder;
22
use Symfony\Component\DependencyInjection\Loader;
23
use Symfony\Component\DependencyInjection\Loader\FileLoader;
24
use Symfony\Component\Config\FileLocator;
25
use InvalidArgumentException;
26
use Symfony\Component\Yaml\Yaml;
27
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\ParserInterface;
28
use RuntimeException;
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
    public function __construct(array $configParsers = array())
61
    {
62
        $this->configParsers = $configParsers;
63
        $this->suggestionCollector = new SuggestionCollector();
64
    }
65
66
    public function getAlias()
67
    {
68
        return 'ezpublish';
69
    }
70
71
    /**
72
     * Loads a specific configuration.
73
     *
74
     * @param mixed[] $configs An array of configuration values
75
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container A ContainerBuilder instance
76
     *
77
     * @throws \InvalidArgumentException When provided tag is not defined in this extension
78
     *
79
     * @api
80
     */
81
    public function load(array $configs, ContainerBuilder $container)
82
    {
83
        $loader = new Loader\YamlFileLoader(
84
            $container,
85
            new FileLocator(__DIR__ . '/../Resources/config')
86
        );
87
88
        $configuration = $this->getConfiguration($configs, $container);
89
90
        // Note: this is where the transformation occurs
91
        $config = $this->processConfiguration($configuration, $configs);
92
93
        // Base services and services overrides
94
        $loader->load('services.yml');
95
        // Security services
96
        $loader->load('security.yml');
97
        // Slots
98
        $loader->load('slot.yml');
99
100
        // Default settings
101
        $this->handleDefaultSettingsLoading($container, $loader);
102
103
        $this->registerRepositoriesConfiguration($config, $container);
104
        $this->registerSiteAccessConfiguration($config, $container);
105
        $this->registerImageMagickConfiguration($config, $container);
106
        $this->registerPageConfiguration($config, $container);
107
108
        // Routing
109
        $this->handleRouting($config, $container, $loader);
110
        // Public API loading
111
        $this->handleApiLoading($container, $loader);
112
        $this->handleTemplating($container, $loader);
113
        $this->handleSessionLoading($container, $loader);
114
        $this->handleCache($config, $container, $loader);
115
        $this->handleLocale($config, $container, $loader);
116
        $this->handleHelpers($config, $container, $loader);
117
        $this->handleImage($config, $container, $loader);
118
        $this->handleViewCache($config, $container, $loader);
119
120
        // Map settings
121
        $processor = new ConfigurationProcessor($container, 'ezsettings');
122
        $processor->mapConfig($config, $this->getMainConfigParser());
123
124
        if ($this->suggestionCollector->hasSuggestions()) {
125
            $message = '';
126
            $suggestionFormatter = new YamlSuggestionFormatter();
127
            foreach ($this->suggestionCollector->getSuggestions() as $suggestion) {
128
                $message .= $suggestionFormatter->format($suggestion) . "\n\n";
129
            }
130
131
            throw new InvalidArgumentException($message);
132
        }
133
134
        $this->handleSiteAccessesRelation($container);
135
        $this->buildPolicyMap($container);
136
    }
137
138
    /**
139
     * @param array $config
140
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
141
     *
142
     * @return \eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration
143
     */
144
    public function getConfiguration(array $config, ContainerBuilder $container)
145
    {
146
        return new Configuration($this->getMainConfigParser(), $this->suggestionCollector);
147
    }
148
149
    /**
150
     * @return \eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\ParserInterface
151
     */
152
    private function getMainConfigParser()
153
    {
154
        if ($this->mainConfigParser === null) {
155
            foreach ($this->configParsers as $parser) {
156
                if ($parser instanceof SuggestionCollectorAwareInterface) {
157
                    $parser->setSuggestionCollector($this->suggestionCollector);
158
                }
159
            }
160
161
            $this->mainConfigParser = new ConfigParser($this->configParsers);
162
        }
163
164
        return $this->mainConfigParser;
165
    }
166
167
    /**
168
     * Handle default settings.
169
     *
170
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
171
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
172
     */
173
    private function handleDefaultSettingsLoading(ContainerBuilder $container, FileLoader $loader)
174
    {
175
        $loader->load('default_settings.yml');
176
177
        foreach ($this->defaultSettingsCollection as $fileLocation => $files) {
178
            $externalLoader = new Loader\YamlFileLoader($container, new FileLocator($fileLocation));
179
            foreach ($files as $file) {
180
                $externalLoader->load($file);
181
            }
182
        }
183
    }
184
185
    private function registerRepositoriesConfiguration(array $config, ContainerBuilder $container)
186
    {
187
        if (!isset($config['repositories'])) {
188
            $config['repositories'] = array();
189
        }
190
191
        $container->setParameter('ezpublish.repositories', $config['repositories']);
192
    }
193
194
    private function registerSiteAccessConfiguration(array $config, ContainerBuilder $container)
195
    {
196
        if (!isset($config['siteaccess'])) {
197
            $config['siteaccess'] = array();
198
            $config['siteaccess']['list'] = array('setup');
199
            $config['siteaccess']['default_siteaccess'] = 'setup';
200
            $config['siteaccess']['groups'] = array();
201
            $config['siteaccess']['match'] = null;
202
        }
203
204
        $container->setParameter('ezpublish.siteaccess.list', $config['siteaccess']['list']);
205
        ConfigurationProcessor::setAvailableSiteAccesses($config['siteaccess']['list']);
206
        $container->setParameter('ezpublish.siteaccess.default', $config['siteaccess']['default_siteaccess']);
207
        $container->setParameter('ezpublish.siteaccess.match_config', $config['siteaccess']['match']);
208
209
        // Register siteaccess groups + reverse
210
        $container->setParameter('ezpublish.siteaccess.groups', $config['siteaccess']['groups']);
211
        $groupsBySiteaccess = array();
212 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...
213
            foreach ($groupMembers as $member) {
214
                if (!isset($groupsBySiteaccess[$member])) {
215
                    $groupsBySiteaccess[$member] = array();
216
                }
217
218
                $groupsBySiteaccess[$member][] = $groupName;
219
            }
220
        }
221
        $container->setParameter('ezpublish.siteaccess.groups_by_siteaccess', $groupsBySiteaccess);
222
        ConfigurationProcessor::setGroupsBySiteAccess($groupsBySiteaccess);
223
    }
224
225
    private function registerImageMagickConfiguration(array $config, ContainerBuilder $container)
226
    {
227
        if (isset($config['imagemagick'])) {
228
            $container->setParameter('ezpublish.image.imagemagick.enabled', $config['imagemagick']['enabled']);
229
            if ($config['imagemagick']['enabled']) {
230
                $container->setParameter('ezpublish.image.imagemagick.executable_path', dirname($config['imagemagick']['path']));
231
                $container->setParameter('ezpublish.image.imagemagick.executable', basename($config['imagemagick']['path']));
232
            }
233
        }
234
235
        $filters = isset($config['imagemagick']['filters']) ? $config['imagemagick']['filters'] : array();
236
        $filters = $filters + $container->getParameter('ezpublish.image.imagemagick.filters');
237
        $container->setParameter('ezpublish.image.imagemagick.filters', $filters);
238
    }
239
240
    private function registerPageConfiguration(array $config, ContainerBuilder $container)
241
    {
242
        if (isset($config['ezpage']['layouts'])) {
243
            $container->setParameter(
244
                'ezpublish.ezpage.layouts',
245
                $config['ezpage']['layouts'] + $container->getParameter('ezpublish.ezpage.layouts')
246
            );
247
        }
248
        if (isset($config['ezpage']['blocks'])) {
249
            $container->setParameter(
250
                'ezpublish.ezpage.blocks',
251
                $config['ezpage']['blocks'] + $container->getParameter('ezpublish.ezpage.blocks')
252
            );
253
        }
254
        if (isset($config['ezpage']['enabledLayouts'])) {
255
            $container->setParameter(
256
                'ezpublish.ezpage.enabledLayouts',
257
                $config['ezpage']['enabledLayouts'] + $container->getParameter('ezpublish.ezpage.enabledLayouts')
258
            );
259
        }
260
        if (isset($config['ezpage']['enabledBlocks'])) {
261
            $container->setParameter(
262
                'ezpublish.ezpage.enabledBlocks',
263
                $config['ezpage']['enabledBlocks'] + $container->getParameter('ezpublish.ezpage.enabledBlocks')
264
            );
265
        }
266
    }
267
268
    /**
269
     * Handle routing parameters.
270
     *
271
     * @param array $config
272
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
273
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
274
     */
275
    private function handleRouting(array $config, ContainerBuilder $container, FileLoader $loader)
276
    {
277
        $loader->load('routing.yml');
278
        $container->setAlias('router', 'ezpublish.chain_router');
279
280
        if (isset($config['router']['default_router']['non_siteaccess_aware_routes'])) {
281
            $container->setParameter(
282
                'ezpublish.default_router.non_siteaccess_aware_routes',
283
                array_merge(
284
                    $container->getParameter('ezpublish.default_router.non_siteaccess_aware_routes'),
285
                    $config['router']['default_router']['non_siteaccess_aware_routes']
286
                )
287
            );
288
        }
289
    }
290
291
    /**
292
     * Handle public API loading.
293
     *
294
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
295
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
296
     */
297
    private function handleApiLoading(ContainerBuilder $container, FileLoader $loader)
298
    {
299
        // Loading configuration from Core/settings
300
        $coreLoader = new Loader\YamlFileLoader(
301
            $container,
302
            new FileLocator(__DIR__ . '/../../../Publish/Core/settings')
303
        );
304
        $coreLoader->load('repository.yml');
305
        $coreLoader->load('fieldtype_external_storages.yml');
306
        $coreLoader->load('fieldtypes.yml');
307
        $coreLoader->load('indexable_fieldtypes.yml');
308
        $coreLoader->load('roles.yml');
309
        $coreLoader->load('storage_engines/common.yml');
310
        $coreLoader->load('storage_engines/cache.yml');
311
        $coreLoader->load('storage_engines/legacy.yml');
312
        $coreLoader->load('storage_engines/shortcuts.yml');
313
        $coreLoader->load('search_engines/common.yml');
314
        $coreLoader->load('utils.yml');
315
        $coreLoader->load('io.yml');
316
317
        // Public API services
318
        $loader->load('papi.yml');
319
320
        // Built-in field types
321
        $loader->load('fieldtype_services.yml');
322
323
        // Storage engine
324
        $loader->load('storage_engines.yml');
325
    }
326
327
    /**
328
     * Handle templating parameters.
329
     *
330
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
331
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
332
     */
333
    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...
334
    {
335
        $loader->load('templating.yml');
336
    }
337
338
    /**
339
     * Handle session parameters.
340
     *
341
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
342
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
343
     */
344
    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...
345
    {
346
        $loader->load('session.yml');
347
    }
348
349
    /**
350
     * Handle cache parameters.
351
     *
352
     * @param array $config
353
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
354
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
355
     *
356
     * @throws \InvalidArgumentException
357
     */
358
    private function handleCache(array $config, ContainerBuilder $container, FileLoader $loader)
359
    {
360
        $loader->load('cache.yml');
361
362
        if (isset($config['http_cache']['purge_type'])) {
363
            switch ($config['http_cache']['purge_type']) {
364
                case 'local':
365
                    $purgeService = 'ezpublish.http_cache.purge_client.local';
366
                    break;
367
                case 'http':
368
                    $purgeService = 'ezpublish.http_cache.purge_client.fos';
369
                    break;
370
                default:
371
                    if (!$container->has($config['http_cache']['purge_type'])) {
372
                        throw new \InvalidArgumentException("Invalid ezpublish.http_cache.purge_type. Can be 'single', 'multiple' or a valid service identifier implementing PurgeClientInterface.");
373
                    }
374
375
                    $purgeService = $config['http_cache']['purge_type'];
376
            }
377
378
            $container->setAlias('ezpublish.http_cache.purge_client', $purgeService);
379
        }
380
    }
381
382
    /**
383
     * Handle locale parameters.
384
     *
385
     * @param array $config
386
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
387
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
388
     */
389
    private function handleLocale(array $config, ContainerBuilder $container, FileLoader $loader)
390
    {
391
        $loader->load('locale.yml');
392
        $container->setParameter(
393
            'ezpublish.locale.conversion_map',
394
            $config['locale_conversion'] + $container->getParameter('ezpublish.locale.conversion_map')
395
        );
396
    }
397
398
    /**
399
     * Handle helpers.
400
     *
401
     * @param array $config
402
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
403
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
404
     */
405
    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...
406
    {
407
        $loader->load('helpers.yml');
408
    }
409
410
    private function handleViewCache(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('view_cache.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 View Code Duplication
    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
        if ($this->mainConfigParser !== null) {
521
            throw new RuntimeException('Main config parser is already instantiated');
522
        }
523
524
        $this->configParsers[] = $configParser;
525
    }
526
527
    /**
528
     * Adds new default settings to the internal collection.
529
     * One can call this method from a bundle `build()` method.
530
     *
531
     * ```php
532
     * public function build(ContainerBuilder $container)
533
     * {
534
     *     $ezExtension = $container->getExtension('ezpublish');
535
     *     $ezExtension->addDefaultSettings(
536
     *         __DIR__ . '/Resources/config',
537
     *         ['default_settings.yml']
538
     *     );
539
     * }
540
     * ```
541
     *
542
     * @since 6.0
543
     *
544
     * @param string $fileLocation
545
     * @param array $files
546
     */
547
    public function addDefaultSettings($fileLocation, array $files)
548
    {
549
        $this->defaultSettingsCollection[$fileLocation] = $files;
550
    }
551
}
552