Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
4 / 4
CRAP
n/a
0 / 0
FastForward\Config\config
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
9
FastForward\Config\configCache
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
FastForward\Config\configDir
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
FastForward\Config\configProvider
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
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;
22
23/**
24 * Creates a unified configuration object from various sources.
25 *
26 * This function SHALL normalize and aggregate mixed input types such as arrays,
27 * directories, and Laminas configuration providers into a single configuration instance.
28 *
29 * @param array|ConfigInterface|string ...$configs The configuration sources.
30 *
31 * @return ConfigInterface the aggregated configuration instance
32 */
33function config(array|ConfigInterface|string ...$configs): ConfigInterface
34{
35    foreach ($configs as $index => $config) {
36        if (\is_array($config)) {
37            $configs[$index] = new ArrayConfig($config);
38        }
39
40        if (\is_string($config) && is_dir($config) && is_readable($config)) {
41            $configs[$index] = configDir($config, true);
42        }
43
44        if (\is_string($config)
45            && class_exists($config)
46            && method_exists($config, '__invoke')
47        ) {
48            $configs[$index] = configProvider([$config]);
49        }
50    }
51
52    return new AggregateConfig(...$configs);
53}
54
55/**
56 * Creates a cached configuration object from various sources.
57 *
58 * This function SHALL wrap the configuration in a caching layer using PSR-16 CacheInterface.
59 *
60 * @param CacheInterface $cache the cache pool for storing configuration data
61 * @param array|ConfigInterface|string ...$configs The configuration sources.
62 *
63 * @return ConfigInterface the cached configuration instance
64 */
65function configCache(CacheInterface $cache, array|ConfigInterface|string ...$configs): ConfigInterface
66{
67    return new CachedConfig(cache: $cache, defaultConfig: config(...$configs));
68}
69
70/**
71 * Creates a directory-based configuration provider.
72 *
73 * If the recursive flag is TRUE, nested directories SHALL be included in the scan.
74 * Configuration files MUST follow the PHP file format.
75 *
76 * @param string $rootDirectory the directory to load configuration files from
77 * @param bool $recursive whether to include files in subdirectories recursively
78 * @param string|null $cachedConfigFile optional path to a cache file for the configuration
79 *
80 * @return ConfigInterface the resulting configuration provider instance
81 */
82function configDir(
83    string $rootDirectory,
84    bool $recursive = false,
85    ?string $cachedConfigFile = null,
86): ConfigInterface {
87    $configClass = $recursive
88        ? RecursiveDirectoryConfig::class
89        : DirectoryConfig::class;
90
91    return new $configClass($rootDirectory, $cachedConfigFile);
92}
93
94/**
95 * Creates a configuration from a list of Laminas-style configuration providers.
96 *
97 * Each provider MUST be invokable and return an array or configuration structure.
98 *
99 * @param iterable $providers a list of configuration providers
100 * @param string|null $cachedConfigFile optional path to a cache file for the configuration
101 *
102 * @return ConfigInterface the resulting configuration instance
103 */
104function configProvider(iterable $providers, ?string $cachedConfigFile = null): ConfigInterface
105{
106    return new LamiasConfigAggregatorConfig(providers: $providers, cachedConfigFile: $cachedConfigFile);
107}