Completed
Push — master ( f804ac...7bb34e )
by
unknown
22:59 queued 08:44
created

EzPublishCoreExtension::handleCache()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 15
nc 5
nop 3
dl 0
loc 23
rs 8.5906
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
        $configuration = new Configuration($this->getMainConfigParser(), $this->suggestionCollector);
152
        $configuration->setSiteAccessConfigurationFilters($this->siteaccessConfigurationFilters);
153
154
        return $configuration;
155
    }
156
157
    /**
158
     * @return \eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\ParserInterface
159
     */
160
    private function getMainConfigParser()
161
    {
162
        if ($this->mainConfigParser === null) {
163
            foreach ($this->configParsers as $parser) {
164
                if ($parser instanceof SuggestionCollectorAwareInterface) {
165
                    $parser->setSuggestionCollector($this->suggestionCollector);
166
                }
167
            }
168
169
            $this->mainConfigParser = new ConfigParser($this->configParsers);
170
        }
171
172
        return $this->mainConfigParser;
173
    }
174
175
    /**
176
     * Handle default settings.
177
     *
178
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
179
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
180
     */
181
    private function handleDefaultSettingsLoading(ContainerBuilder $container, FileLoader $loader)
182
    {
183
        $loader->load('default_settings.yml');
184
185
        foreach ($this->defaultSettingsCollection as $fileLocation => $files) {
186
            $externalLoader = new Loader\YamlFileLoader($container, new FileLocator($fileLocation));
187
            foreach ($files as $file) {
188
                $externalLoader->load($file);
189
            }
190
        }
191
    }
192
193
    private function registerRepositoriesConfiguration(array $config, ContainerBuilder $container)
194
    {
195
        if (!isset($config['repositories'])) {
196
            $config['repositories'] = array();
197
        }
198
199
        $container->setParameter('ezpublish.repositories', $config['repositories']);
200
    }
201
202
    private function registerSiteAccessConfiguration(array $config, ContainerBuilder $container)
203
    {
204
        if (!isset($config['siteaccess'])) {
205
            $config['siteaccess'] = array();
206
            $config['siteaccess']['list'] = array('setup');
207
            $config['siteaccess']['default_siteaccess'] = 'setup';
208
            $config['siteaccess']['groups'] = array();
209
            $config['siteaccess']['match'] = null;
210
        }
211
212
        $container->setParameter('ezpublish.siteaccess.list', $config['siteaccess']['list']);
213
        ConfigurationProcessor::setAvailableSiteAccesses($config['siteaccess']['list']);
214
        $container->setParameter('ezpublish.siteaccess.default', $config['siteaccess']['default_siteaccess']);
215
        $container->setParameter('ezpublish.siteaccess.match_config', $config['siteaccess']['match']);
216
217
        // Register siteaccess groups + reverse
218
        $container->setParameter('ezpublish.siteaccess.groups', $config['siteaccess']['groups']);
219
        $groupsBySiteaccess = array();
220 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...
221
            foreach ($groupMembers as $member) {
222
                if (!isset($groupsBySiteaccess[$member])) {
223
                    $groupsBySiteaccess[$member] = array();
224
                }
225
226
                $groupsBySiteaccess[$member][] = $groupName;
227
            }
228
        }
229
        $container->setParameter('ezpublish.siteaccess.groups_by_siteaccess', $groupsBySiteaccess);
230
        ConfigurationProcessor::setGroupsBySiteAccess($groupsBySiteaccess);
231
    }
232
233
    private function registerImageMagickConfiguration(array $config, ContainerBuilder $container)
234
    {
235
        if (isset($config['imagemagick'])) {
236
            $container->setParameter('ezpublish.image.imagemagick.enabled', $config['imagemagick']['enabled']);
237
            if ($config['imagemagick']['enabled']) {
238
                $container->setParameter('ezpublish.image.imagemagick.executable_path', dirname($config['imagemagick']['path']));
239
                $container->setParameter('ezpublish.image.imagemagick.executable', basename($config['imagemagick']['path']));
240
            }
241
        }
242
243
        $filters = isset($config['imagemagick']['filters']) ? $config['imagemagick']['filters'] : array();
244
        $filters = $filters + $container->getParameter('ezpublish.image.imagemagick.filters');
245
        $container->setParameter('ezpublish.image.imagemagick.filters', $filters);
246
    }
247
248
    private function registerPageConfiguration(array $config, ContainerBuilder $container)
249
    {
250
        if (isset($config['ezpage']['layouts'])) {
251
            $container->setParameter(
252
                'ezpublish.ezpage.layouts',
253
                $config['ezpage']['layouts'] + $container->getParameter('ezpublish.ezpage.layouts')
254
            );
255
        }
256
        if (isset($config['ezpage']['blocks'])) {
257
            $container->setParameter(
258
                'ezpublish.ezpage.blocks',
259
                $config['ezpage']['blocks'] + $container->getParameter('ezpublish.ezpage.blocks')
260
            );
261
        }
262
        if (isset($config['ezpage']['enabledLayouts'])) {
263
            $container->setParameter(
264
                'ezpublish.ezpage.enabledLayouts',
265
                $config['ezpage']['enabledLayouts'] + $container->getParameter('ezpublish.ezpage.enabledLayouts')
266
            );
267
        }
268
        if (isset($config['ezpage']['enabledBlocks'])) {
269
            $container->setParameter(
270
                'ezpublish.ezpage.enabledBlocks',
271
                $config['ezpage']['enabledBlocks'] + $container->getParameter('ezpublish.ezpage.enabledBlocks')
272
            );
273
        }
274
    }
275
276
    /**
277
     * Handle routing parameters.
278
     *
279
     * @param array $config
280
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
281
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
282
     */
283
    private function handleRouting(array $config, ContainerBuilder $container, FileLoader $loader)
284
    {
285
        $loader->load('routing.yml');
286
        $container->setAlias('router', 'ezpublish.chain_router');
287
288
        if (isset($config['router']['default_router']['non_siteaccess_aware_routes'])) {
289
            $container->setParameter(
290
                'ezpublish.default_router.non_siteaccess_aware_routes',
291
                array_merge(
292
                    $container->getParameter('ezpublish.default_router.non_siteaccess_aware_routes'),
293
                    $config['router']['default_router']['non_siteaccess_aware_routes']
294
                )
295
            );
296
        }
297
    }
298
299
    /**
300
     * Handle public API loading.
301
     *
302
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
303
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
304
     */
305
    private function handleApiLoading(ContainerBuilder $container, FileLoader $loader)
306
    {
307
        // Loading configuration from Core/settings
308
        $coreLoader = new Loader\YamlFileLoader(
309
            $container,
310
            new FileLocator(__DIR__ . '/../../../Publish/Core/settings')
311
        );
312
        $coreLoader->load('repository.yml');
313
        $coreLoader->load('repository/inner.yml');
314
        $coreLoader->load('repository/signalslot.yml');
315
        $coreLoader->load('fieldtype_external_storages.yml');
316
        $coreLoader->load('fieldtypes.yml');
317
        $coreLoader->load('indexable_fieldtypes.yml');
318
        $coreLoader->load('roles.yml');
319
        $coreLoader->load('storage_engines/common.yml');
320
        $coreLoader->load('storage_engines/cache.yml');
321
        $coreLoader->load('storage_engines/legacy.yml');
322
        $coreLoader->load('storage_engines/shortcuts.yml');
323
        $coreLoader->load('search_engines/common.yml');
324
        $coreLoader->load('utils.yml');
325
        $coreLoader->load('io.yml');
326
327
        // Public API services
328
        $loader->load('papi.yml');
329
330
        // Built-in field types
331
        $loader->load('fieldtype_services.yml');
332
333
        // Storage engine
334
        $loader->load('storage_engines.yml');
335
    }
336
337
    /**
338
     * Handle templating parameters.
339
     *
340
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
341
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
342
     */
343
    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...
344
    {
345
        $loader->load('templating.yml');
346
    }
347
348
    /**
349
     * Handle session parameters.
350
     *
351
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
352
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
353
     */
354
    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...
355
    {
356
        $loader->load('session.yml');
357
    }
358
359
    /**
360
     * Handle cache parameters.
361
     *
362
     * @param array $config
363
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
364
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
365
     *
366
     * @throws \InvalidArgumentException
367
     */
368
    private function handleCache(array $config, ContainerBuilder $container, FileLoader $loader)
369
    {
370
        $loader->load('cache.yml');
371
372
        if (isset($config['http_cache']['purge_type'])) {
373
            switch ($config['http_cache']['purge_type']) {
374
                case 'local':
375
                    $purgeService = 'ezpublish.http_cache.purge_client.local';
376
                    break;
377
                case 'http':
378
                    $purgeService = 'ezpublish.http_cache.purge_client.fos';
379
                    break;
380
                default:
381
                    if (!$container->has($config['http_cache']['purge_type'])) {
382
                        throw new \InvalidArgumentException("Invalid ezpublish.http_cache.purge_type. Can be 'single', 'multiple' or a valid service identifier implementing PurgeClientInterface.");
383
                    }
384
385
                    $purgeService = $config['http_cache']['purge_type'];
386
            }
387
388
            $container->setAlias('ezpublish.http_cache.purge_client', $purgeService);
389
        }
390
    }
391
392
    /**
393
     * Handle locale parameters.
394
     *
395
     * @param array $config
396
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
397
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
398
     */
399
    private function handleLocale(array $config, ContainerBuilder $container, FileLoader $loader)
400
    {
401
        $loader->load('locale.yml');
402
        $container->setParameter(
403
            'ezpublish.locale.conversion_map',
404
            $config['locale_conversion'] + $container->getParameter('ezpublish.locale.conversion_map')
405
        );
406
    }
407
408
    /**
409
     * Handle helpers.
410
     *
411
     * @param array $config
412
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
413
     * @param \Symfony\Component\DependencyInjection\Loader\FileLoader $loader
414
     */
415
    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...
416
    {
417
        $loader->load('helpers.yml');
418
    }
419
420
    /**
421
     * Handles relation between SiteAccesses.
422
     * Related SiteAccesses share the same repository and root location id.
423
     *
424
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
425
     */
426
    private function handleSiteAccessesRelation(ContainerBuilder $container)
427
    {
428
        $configResolver = $container->get('ezpublish.config.resolver.core');
429
        $configResolver->setContainer($container);
430
431
        $saRelationMap = array();
432
        $saList = $container->getParameter('ezpublish.siteaccess.list');
433
        // First build the SiteAccess relation map, indexed by repository and rootLocationId.
434
        foreach ($saList as $sa) {
435
            $repository = $configResolver->getParameter('repository', 'ezsettings', $sa);
436
            if (!isset($saRelationMap[$repository])) {
437
                $saRelationMap[$repository] = array();
438
            }
439
440
            $rootLocationId = $configResolver->getParameter('content.tree_root.location_id', 'ezsettings', $sa);
441
            if (!isset($saRelationMap[$repository][$rootLocationId])) {
442
                $saRelationMap[$repository][$rootLocationId] = array();
443
            }
444
            $saRelationMap[$repository][$rootLocationId][] = $sa;
445
        }
446
        $container->setParameter('ezpublish.siteaccess.relation_map', $saRelationMap);
447
448
        // Now build the related SiteAccesses list, based on the relation map.
449
        foreach ($saList as $sa) {
450
            $repository = $configResolver->getParameter('repository', 'ezsettings', $sa);
451
            $rootLocationId = $configResolver->getParameter('content.tree_root.location_id', 'ezsettings', $sa);
452
            $container->setParameter(
453
                "ezsettings.$sa.related_siteaccesses",
454
                $saRelationMap[$repository][$rootLocationId]
455
            );
456
        }
457
    }
458
459
    /**
460
     * @param array $config
461
     * @param ContainerBuilder $container
462
     * @param FileLoader $loader
463
     */
464
    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...
465
    {
466
        $loader->load('image.yml');
467
    }
468
469
    private function buildPolicyMap(ContainerBuilder $container)
470
    {
471
        $policiesBuilder = new PoliciesConfigBuilder($container);
472
        foreach ($this->policyProviders as $provider) {
473
            $provider->addPolicies($policiesBuilder);
474
        }
475
    }
476
477 View Code Duplication
    public function prepend(ContainerBuilder $container)
478
    {
479
        // Default settings for FOSHttpCacheBundle
480
        $configFile = __DIR__ . '/../Resources/config/fos_http_cache.yml';
481
        $config = Yaml::parse(file_get_contents($configFile));
482
        $container->prependExtensionConfig('fos_http_cache', $config);
483
        $container->addResource(new FileResource($configFile));
484
    }
485
486
    /**
487
     * Adds a new policy provider to the internal collection.
488
     * One can call this method from a bundle `build()` method.
489
     *
490
     * ```php
491
     * public function build(ContainerBuilder $container)
492
     * {
493
     *     $ezExtension = $container->getExtension('ezpublish');
494
     *     $ezExtension->addPolicyProvider($myPolicyProvider);
495
     * }
496
     * ```
497
     *
498
     * @since 6.0
499
     *
500
     * @param PolicyProviderInterface $policyProvider
501
     */
502
    public function addPolicyProvider(PolicyProviderInterface $policyProvider)
503
    {
504
        $this->policyProviders[] = $policyProvider;
505
    }
506
507
    /**
508
     * Adds a new config parser to the internal collection.
509
     * One can call this method from a bundle `build()` method.
510
     *
511
     * ```php
512
     * public function build(ContainerBuilder $container)
513
     * {
514
     *     $ezExtension = $container->getExtension('ezpublish');
515
     *     $ezExtension->addConfigParser($myConfigParser);
516
     * }
517
     * ```
518
     *
519
     * @since 6.0
520
     *
521
     * @param \eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\ParserInterface $configParser
522
     */
523
    public function addConfigParser(ParserInterface $configParser)
524
    {
525
        if ($this->mainConfigParser !== null) {
526
            throw new RuntimeException('Main config parser is already instantiated');
527
        }
528
529
        $this->configParsers[] = $configParser;
530
    }
531
532
    /**
533
     * Adds new default settings to the internal collection.
534
     * One can call this method from a bundle `build()` method.
535
     *
536
     * ```php
537
     * public function build(ContainerBuilder $container)
538
     * {
539
     *     $ezExtension = $container->getExtension('ezpublish');
540
     *     $ezExtension->addDefaultSettings(
541
     *         __DIR__ . '/Resources/config',
542
     *         ['default_settings.yml']
543
     *     );
544
     * }
545
     * ```
546
     *
547
     * @since 6.0
548
     *
549
     * @param string $fileLocation
550
     * @param array $files
551
     */
552
    public function addDefaultSettings($fileLocation, array $files)
553
    {
554
        $this->defaultSettingsCollection[$fileLocation] = $files;
555
    }
556
557
    public function addSiteAccessConfigurationFilter(SiteAccessConfigurationFilter $filter)
558
    {
559
        $this->siteaccessConfigurationFilters[] = $filter;
560
    }
561
}
562