SonataCacheExtension::configureServers()   A
last analyzed

Complexity

Conditions 2
Paths 1

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.8333
c 0
b 0
f 0
cc 2
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\CacheBundle\DependencyInjection;
15
16
use Symfony\Component\Config\Definition\Processor;
17
use Symfony\Component\Config\FileLocator;
18
use Symfony\Component\DependencyInjection\ContainerBuilder;
19
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
20
use Symfony\Component\DependencyInjection\Reference;
21
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
22
23
/**
24
 * @author     Thomas Rabaix <[email protected]>
25
 */
26
class SonataCacheExtension extends Extension
27
{
28
    public function load(array $configs, ContainerBuilder $container): void
29
    {
30
        $processor = new Processor();
31
        $configuration = new Configuration();
32
        $config = $processor->processConfiguration($configuration, $configs);
33
34
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
35
        $loader->load('cache.xml');
36
        $loader->load('counter.xml');
37
        $loader->load('command.xml');
38
39
        $useOrm = 'auto' === $config['cache_invalidation']['orm_listener'] ?
40
            class_exists('Doctrine\\ORM\\Version') :
41
            $config['cache_invalidation']['orm_listener'];
42
43
        if ($useOrm) {
44
            $loader->load('orm.xml');
45
        }
46
47
        $usePhpcrOdm = 'auto' === $config['cache_invalidation']['phpcr_odm_listener'] ?
48
            class_exists('Doctrine\\ODM\\PHPCR\\Version') :
49
            $config['cache_invalidation']['phpcr_odm_listener'];
50
        if ($usePhpcrOdm) {
51
            $loader->load('phpcr_odm.xml');
52
        }
53
54
        $this->configureInvalidation($container, $config);
55
        if ($useOrm) {
56
            $this->configureORM($container, $config);
57
        }
58
        if ($usePhpcrOdm) {
59
            $this->configurePHPCRODM($container, $config);
60
        }
61
        $this->configureCache($container, $config);
62
        $this->configureCounter($container, $config);
63
    }
64
65
    public function configureInvalidation(ContainerBuilder $container, array $config): void
66
    {
67
        $cacheManager = $container->getDefinition('sonata.cache.manager');
68
69
        $cacheManager->replaceArgument(0, new Reference($config['cache_invalidation']['service']));
70
71
        $recorder = $container->getDefinition('sonata.cache.model_identifier');
72
        foreach ($config['cache_invalidation']['classes'] as $class => $method) {
73
            $recorder->addMethodCall('addClass', [$class, $method]);
74
        }
75
76
        $cacheManager->addMethodCall('setRecorder', [new Reference($config['cache_invalidation']['recorder'])]);
77
    }
78
79
    public function configureORM(ContainerBuilder $container, array $config): void
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...
80
    {
81
        $container->getDefinition('sonata.cache.orm.event_subscriber')
82
            ->addTag('doctrine.event_subscriber')
83
        ;
84
    }
85
86
    public function configurePHPCRODM(ContainerBuilder $container, array $config): void
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...
87
    {
88
        $container->getDefinition('sonata.cache.phpcr_odm.event_subscriber')
89
            ->addTag('doctrine_phpcr.event_subscriber')
90
        ;
91
    }
92
93
    /**
94
     * @throws \RuntimeException
95
     */
96
    public function configureCache(ContainerBuilder $container, array $config): void
97
    {
98
        if ($config['default_cache']) {
99
            $container->setAlias('sonata.cache', $config['default_cache']);
100
        }
101
102
        if (isset($config['caches']['esi'])) {
103
            $container
104
                ->getDefinition('sonata.cache.esi')
105
                ->replaceArgument(0, $config['caches']['esi']['token'])
106
                ->replaceArgument(1, $config['caches']['esi']['servers'])
107
                ->replaceArgument(3, 3 === $config['caches']['esi']['version'] ? 'ban' : 'purge');
108
        } else {
109
            $container->removeDefinition('sonata.cache.esi');
110
        }
111
112
        if (isset($config['caches']['ssi'])) {
113
            $container
114
                ->getDefinition('sonata.cache.ssi')
115
                ->replaceArgument(0, $config['caches']['ssi']['token'])
116
            ;
117
        } else {
118
            $container->removeDefinition('sonata.cache.ssi');
119
        }
120
121
        if (isset($config['caches']['mongo'])) {
122
            $this->checkMongo();
123
124
            $database = $config['caches']['mongo']['database'];
125
            $servers = [];
126
            foreach ($config['caches']['mongo']['servers'] as $server) {
127
                if ($server['user']) {
128
                    $servers[] = sprintf(
129
                        '%s:%s@%s:%s/%s',
130
                        $server['user'],
131
                        $server['password'],
132
                        $server['host'],
133
                        $server['port'],
134
                        $database
135
                    );
136
                } else {
137
                    $servers[] = sprintf('%s:%s', $server['host'], $server['port']);
138
                }
139
            }
140
141
            $container
142
                ->getDefinition('sonata.cache.mongo')
143
                ->replaceArgument(0, $servers)
144
                ->replaceArgument(1, $database)
145
                ->replaceArgument(2, $config['caches']['mongo']['collection'])
146
            ;
147
        } else {
148
            $container->removeDefinition('sonata.cache.mongo');
149
        }
150
151
        if (isset($config['caches']['memcached'])) {
152
            $this->checkMemcached();
153
154
            $container
155
                ->getDefinition('sonata.cache.memcached')
156
                ->replaceArgument(0, $config['caches']['memcached']['prefix'])
157
                ->replaceArgument(1, $config['caches']['memcached']['servers'])
158
            ;
159
        } else {
160
            $container->removeDefinition('sonata.cache.memcached');
161
        }
162
163
        if (isset($config['caches']['predis'])) {
164
            $this->checkPRedis();
165
166
            $container
167
                ->getDefinition('sonata.cache.predis')
168
                ->replaceArgument(0, $config['caches']['predis']['servers'])
169
            ;
170
        } else {
171
            $container->removeDefinition('sonata.cache.predis');
172
        }
173
174
        if (isset($config['caches']['apc'])) {
175
            $this->checkApc();
176
177
            $container
178
                ->getDefinition('sonata.cache.apc')
179
                ->replaceArgument(1, $config['caches']['apc']['token'])
180
                ->replaceArgument(2, $config['caches']['apc']['prefix'])
181
                ->replaceArgument(3, $this->configureServers($config['caches']['apc']['servers']))
182
                ->replaceArgument(4, $config['caches']['apc']['timeout'])
183
            ;
184
        } else {
185
            $container->removeDefinition('sonata.cache.apc');
186
        }
187
188
        if (isset($config['caches']['symfony'])) {
189
            $container
190
                ->getDefinition('sonata.cache.symfony')
191
                ->replaceArgument(3, $config['caches']['symfony']['token'])
192
                ->replaceArgument(4, $config['caches']['symfony']['php_cache_enabled'])
193
                ->replaceArgument(5, $config['caches']['symfony']['types'])
194
                ->replaceArgument(6, $this->configureServers($config['caches']['symfony']['servers']))
195
                ->replaceArgument(7, $config['caches']['symfony']['timeout'])
196
            ;
197
        } else {
198
            $container->removeDefinition('sonata.cache.symfony');
199
        }
200
    }
201
202
    /**
203
     * @throws \RuntimeException
204
     */
205
    public function configureCounter(ContainerBuilder $container, array $config): void
206
    {
207
        if ($config['default_counter']) {
208
            $container->setAlias('sonata.counter', $config['default_counter']);
209
        }
210
211
        if (isset($config['counters']['mongo'])) {
212
            $this->checkMongo();
213
214
            $servers = [];
215
            foreach ($config['counters']['mongo']['servers'] as $server) {
216
                if ($server['user']) {
217
                    $servers[] = sprintf(
218
                        '%s:%s@%s:%s',
219
                        $server['user'],
220
                        $server['password'],
221
                        $server['host'],
222
                        $server['port']
223
                    );
224
                } else {
225
                    $servers[] = sprintf('%s:%s', $server['host'], $server['port']);
226
                }
227
            }
228
229
            $container
230
                ->getDefinition('sonata.cache.counter.mongo')
231
                ->replaceArgument(0, $servers)
232
                ->replaceArgument(1, $config['counters']['mongo']['database'])
233
                ->replaceArgument(2, $config['counters']['mongo']['collection'])
234
            ;
235
        } else {
236
            $container->removeDefinition('sonata.cache.counter.mongo');
237
        }
238
239
        if (isset($config['counters']['memcached'])) {
240
            $this->checkMemcached();
241
242
            $container
243
                ->getDefinition('sonata.cache.counter.memcached')
244
                ->replaceArgument(0, $config['counters']['memcached']['prefix'])
245
                ->replaceArgument(1, $config['counters']['memcached']['servers'])
246
            ;
247
        } else {
248
            $container->removeDefinition('sonata.cache.counter.memcached');
249
        }
250
251
        if (isset($config['counters']['predis'])) {
252
            $this->checkPRedis();
253
254
            $container
255
                ->getDefinition('sonata.cache.counter.predis')
256
                ->replaceArgument(0, $config['counters']['predis']['servers'])
257
            ;
258
        } else {
259
            $container->removeDefinition('sonata.cache.counter.predis');
260
        }
261
262
        if (isset($config['counters']['apc'])) {
263
            $this->checkApc();
264
265
            $container
266
                ->getDefinition('sonata.cache.counter.apc')
267
                ->replaceArgument(0, $config['counters']['apc']['prefix'])
268
            ;
269
        } else {
270
            $container->removeDefinition('sonata.cache.counter.apc');
271
        }
272
    }
273
274
    /**
275
     * Returns servers list with hash for basic auth computed if provided.
276
     */
277
    public function configureServers(array $servers): array
278
    {
279
        return array_map(
280
            static function ($item) {
281
                if ($item['basic']) {
282
                    $item['basic'] = base64_encode($item['basic']);
283
                }
284
285
                return $item;
286
            },
287
            $servers
288
        );
289
    }
290
291
    protected function checkMemcached(): void
292
    {
293
        if (!class_exists('\Memcached', true)) {
294
            throw new \RuntimeException(
295
                <<<'HELP'
296
The `sonata.cache.memcached` service is configured, however the Memcached class is not available.
297
298
To resolve this issue, please install the related library : http://php.net/manual/en/book.memcached.php
299
or remove the memcached cache settings from the configuration file.
300
HELP
301
            );
302
        }
303
    }
304
305
    protected function checkApc(): void
306
    {
307
        if (!\function_exists('apc_fetch')) {
308
            throw new \RuntimeException(
309
                <<<'HELP'
310
The `sonata.cache.apc` service is configured, however the apc_* functions are not available.
311
312
To resolve this issue, please install the related library : http://php.net/manual/en/book.apc.php
313
or remove the APC cache settings from the configuration file.
314
HELP
315
            );
316
        }
317
    }
318
319
    protected function checkMongo(): void
320
    {
321
        if (!class_exists('\Mongo', true)) {
322
            throw new \RuntimeException(
323
                <<<'HELP'
324
The `sonata.cache.mongo` service is configured, however the Mongo class is not available.
325
326
To resolve this issue, please install the related library : http://php.net/manual/en/book.mongo.php
327
or remove the mongo cache settings from the configuration file.
328
HELP
329
            );
330
        }
331
    }
332
333
    protected function checkPRedis(): void
334
    {
335
        if (!class_exists('\Predis\Client', true)) {
336
            throw new \RuntimeException(
337
                <<<HELP
338
The `sonata.cache.predis` service is configured, however the Predis\Client class is not available.
339
340
Please add the lib in your composer.json file: "predis/predis": "~0.8".
341
HELP
342
            );
343
        }
344
    }
345
}
346