Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
CachedConfig
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
4 / 4
7
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __invoke
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 set
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 remove
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5/**
6 * This file is part of php-fast-forward/config.
7 *
8 * This source file is subject to the license bundled
9 * with this source code in the file LICENSE.
10 *
11 * @copyright Copyright (c) 2025-2026 Felipe SayĆ£o Lobato Abreu <github@mentordosnerds.com>
12 * @license   https://opensource.org/licenses/MIT MIT License
13 *
14 * @see       https://github.com/php-fast-forward/config
15 * @see       https://github.com/php-fast-forward
16 * @see       https://datatracker.ietf.org/doc/html/rfc2119
17 */
18
19namespace FastForward\Config;
20
21use Psr\SimpleCache\CacheInterface;
22use Psr\SimpleCache\InvalidArgumentException;
23
24/**
25 * Class CachedConfig.
26 *
27 * Provides a cached implementation of a configuration source.
28 * This class MUST cache the configuration output of the decorated ConfigInterface instance.
29 * It SHALL lazily initialize and retrieve cached configuration data upon invocation.
30 */
31 class CachedConfig implements ConfigInterface
32{
33    use LazyLoadConfigTrait;
34
35    /**
36     * Constructs a CachedConfig wrapper.
37     *
38     * This constructor SHALL accept a PSR-16 cache implementation and a configuration instance
39     * to be cached. It MUST defer reading and writing the configuration until invoked.
40     *
41     * @param CacheInterface $cache the cache implementation used for storing configuration data
42     * @param ConfigInterface $defaultConfig the configuration source to be cached
43     * @param bool $persistent whether the cache should be persistent or not
44     * @param string|null $cacheKey the cache key to use for storing the configuration data
45     */
46    public function __construct(
47        private  CacheInterface $cache,
48        private  ConfigInterface $defaultConfig,
49        private  bool $persistent = false,
50        private ?string $cacheKey = null,
51    ) {
52        $this->cacheKey ??= $this->defaultConfig::class;
53    }
54
55    /**
56     * Invokes the configuration and returns the cached configuration data.
57     *
58     * If the configuration has not yet been cached, it MUST be stored in the cache upon first invocation.
59     * This method MUST return a ConfigInterface implementation containing the cached configuration data.
60     *
61     * @return ConfigInterface a ConfigInterface implementation containing the cached configuration data
62     *
63     * @throws InvalidArgumentException if the cache key is invalid
64     */
65    public function __invoke(): ConfigInterface
66    {
67        if (! $this->cache->has($this->cacheKey)) {
68            $this->cache->set($this->cacheKey, $this->defaultConfig->toArray());
69        }
70
71        return new ArrayConfig($this->cache->get($this->cacheKey));
72    }
73
74    /**
75     * Sets configuration data.
76     *
77     * This method MUST update the cached configuration data in the cache if the persistent flag is set to true.
78     *
79     * @param array|ConfigInterface|string $key the configuration key or an array of key-value pairs to set
80     * @param mixed $value the value to set for the specified key
81     *
82     * @return void
83     *
84     * @throws InvalidArgumentException if the key is invalid
85     */
86    public function set(array|ConfigInterface|string $key, mixed $value = null): void
87    {
88        $config = $this->getConfig();
89        $config->set($key, $value);
90
91        if ($this->persistent) {
92            $this->cache->set($this->cacheKey, $config->toArray());
93        }
94    }
95
96    /**
97     * Retrieves a configuration value by key.
98     *
99     * This method MUST return the cached value if it exists, or the default value if not found.
100     *
101     * @param string $key the configuration key to retrieve
102     *
103     * @return mixed the configuration value or the default value
104     */
105    public function remove(mixed $key): void
106    {
107        $config = $this->getConfig();
108        $config->remove($key);
109
110        if ($this->persistent) {
111            $this->cache->set($this->cacheKey, $config->toArray());
112        }
113    }
114}