Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
50.00% covered (danger)
50.00%
11 / 22
75.00% covered (warning)
75.00%
3 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
CacheFactory
50.00% covered (danger)
50.00%
11 / 22
75.00% covered (warning)
75.00%
3 / 4
13.12
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 create
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 createFilesystemAdapter
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 createRedisAdapter
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3/**
4 * Factory for creating cache adapters based on configuration.
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public License,
7 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
8 * obtain one at https://mozilla.org/MPL/2.0/.
9 *
10 * @package   phpMyFAQ
11 * @author    Thorsten Rinne <thorsten@phpmyfaq.de>
12 * @copyright 2026 phpMyFAQ Team
13 * @license   https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
14 * @link      https://www.phpmyfaq.de
15 * @since     2026-03-16
16 */
17
18declare(strict_types=1);
19
20namespace phpMyFAQ\Cache;
21
22use phpMyFAQ\Configuration;
23use phpMyFAQ\Configuration\Storage\DatabaseConfigurationStore;
24use RuntimeException;
25use Symfony\Component\Cache\Adapter\FilesystemAdapter;
26use Symfony\Component\Cache\Adapter\RedisAdapter;
27use Symfony\Contracts\Cache\CacheInterface;
28
29readonly class CacheFactory
30{
31    public function __construct(
32        private Configuration $configuration,
33        private string $cacheDir,
34    ) {
35    }
36
37    public function create(): CacheInterface
38    {
39        $resolver = new CacheSettingsResolver(new DatabaseConfigurationStore($this->configuration->getDb()));
40        $settings = $resolver->resolve();
41
42        return match ($settings->adapter) {
43            'redis' => $this->createRedisAdapter($settings),
44            default => $this->createFilesystemAdapter($settings),
45        };
46    }
47
48    private function createFilesystemAdapter(CacheSettings $settings): FilesystemAdapter
49    {
50        return new FilesystemAdapter(
51            namespace: 'pmf',
52            defaultLifetime: $settings->defaultTtl,
53            directory: $this->cacheDir,
54        );
55    }
56
57    private function createRedisAdapter(CacheSettings $settings): RedisAdapter
58    {
59        if (!extension_loaded('redis')) {
60            throw new RuntimeException(
61                'The "redis" PHP extension is required when using the Redis cache adapter. '
62                . 'Please install ext-redis or change storage.cacheAdapter to "filesystem".',
63            );
64        }
65
66        $connection = RedisAdapter::createConnection($settings->redisDsn, ['timeout' => $settings->connectTimeout]);
67
68        return new RedisAdapter(
69            redis: $connection,
70            namespace: $settings->redisPrefix,
71            defaultLifetime: $settings->defaultTtl,
72        );
73    }
74}