diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml
index 73008ee..7342612 100644
--- a/.github/workflows/documentation.yml
+++ b/.github/workflows/documentation.yml
@@ -3,7 +3,7 @@ on:
release:
types: [published]
jobs:
- build-documentation:
+ build_documentation:
runs-on: ubuntu-latest
steps:
- name: Checkout
@@ -15,5 +15,43 @@ jobs:
architecture: 'x64'
- name: Install dependencies
run: python -m pip install --upgrade pip mkdocs mkdocs-material
- - name: Deploy documentation
- run: mkdocs gh-deploy --force
\ No newline at end of file
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: docs-artifact
+ path: _site/
+ build_api:
+ needs: build_documentation
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Setup PHP, with composer and extensions
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '8.3'
+ coverage: none
+ - name: Install composer dependencies
+ uses: ramsey/composer-install@v3
+ with:
+ composer-options: "--prefer-dist --optimize-autoloader"
+ - name: Download phpDocumentor phar archive
+ run: wget https://phpdoc.org/phpDocumentor.phar
+ - name: Build the coumentation api
+ run: php phpDocumentor.phar
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: api-artifact
+ path: _site/api/
+ deploy_documentation:
+ needs: [build_documentation,build_api]
+ runs-on: ubuntu-latest
+ steps:
+ - name: Download artifacts
+ uses: actions/download-artifact@v4
+ - name: Deploy documentation to Github Pages
+ uses: peaceiris/actions-gh-pages@v4
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ publish_dir: ./_site
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 7857d7b..7c7a4ee 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -8,7 +8,7 @@ jobs:
fail-fast: false
matrix:
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
- php-versions: ['8.2', '8.3']
+ php-versions: ['8.3', '8.4']
symfony-version: ['6.4', '7.1']
runs-on: ${{ matrix.operating-system }}
steps:
@@ -32,8 +32,10 @@ jobs:
with:
composer-options: "--prefer-dist --optimize-autoloader"
- name: Check coding standard
+ if: matrix.php-versions != '8.4'
run: composer cs:check
- name: Static analysis tool
+ if: matrix.php-versions != '8.4'
run: composer analytics
- name: Test suite
run: composer test
diff --git a/.gitignore b/.gitignore
index a64fced..40a2698 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@ composer.phar
composer.lock
coverage/
vendor/
+_site/
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9d0b46b..0eac6d3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,29 @@ All notable changes to `susina/config-builder` project will be documented in thi
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+### [1.1] - 2025-05-22
+### Added
+- Add `replaces` option to inject an external parameter to resolve. Useful, i.e. to pass
+`kernel_dir` or other parameters.
+- Add [phpdocumentor](https://phpdoc.org/) to generate the documentation api
+### Changed
+- Update the documentation
+
+## [1.0.1] - 2024-11-30
+### Fixed
+- Remove PHP 8.4 deprecations
+
+## [1.0] - 2024-09-16
+### Added
+- Introduce `susina/param-resolver` library
+- Introduce `susina/xml-to-array` library
+### Changed
+- Bump dependencies
+- Update Github Actions
+- Update documentation
+### Removed
+- Remove `.ini` support since it's not suited for complex nested configurations
+
## [0.4] - 2023-02-16
### Added
- `ConfigBuilder::keepFirstXmlTag` method, to include into the configuration array also the first xml tag
diff --git a/docs/methods.md b/docs/methods.md
deleted file mode 100644
index 4f8f86b..0000000
--- a/docs/methods.md
+++ /dev/null
@@ -1,261 +0,0 @@
-The Configuration Builder class can be set up via the following methods:
-
-## addFile
-
-!!! Example "Signature"
- `#!php-inline public function addFile(string|SplFileInfo ...$files): self`
-
-The parameters can contain:
-
-- the name of the configuration file to load
-- the full path name of the configuration file to load
-- SplFileInfo object representing the configuration file to load
-
-
-Use this method to add one or more elements to the list of configuration files to load. I.e.:
-
-```php
-addFile('my-project-config.yaml.dist', 'my-project-config-yml');
-```
-
-
-## setFiles
-
-!!! example "Signature"
- `#!php-inline public function setFiles(array|IteratorAggregate $files): self`
-
-This method receive an array of strings or SplFileInfo objects and set the list of the configuration files to load.
-This method __removes__ all the files previously added.
-
-```php
-setFiles($configFiles);
-```
-
-This method can also accept an iterator, containing strings or SplFileInfo, so you can pass also an instance of a finder object, i.e. [Symfony Finder](https://symfony.com/doc/current/components/finder.html):
-
-```php
-in('app/config')->name('*.json')->files();
-
-$builder->setFiles($finder);
-```
-
-
-## addDirectory
-
-!!! example "Signature"
- `#!php-inline public function addDirectory(string|SplFileInfo ...$dirs): self`
-
-Add one or more directories where to find the configuration files.
-
-The parameters can contain:
-
-- the full path name of the directory
-- SplFileInfo object representing a directory where to find the configuration files
-
-This method check if the passed directories are existent and readable, otherwise throws a `ConfigurationBuilderException`.
-
-
-```php
-addDirectory(__DIR__ . '/app/config', getcwd());
-```
-
-
-## setDirectories
-
-!!! example "Signature"
- `#!php-inline public function setDirectories(array|IteratorAggregate $dirs): self`
-
-This method receive an array of strings or SplFileInfo objects and set the list of the directories where to find the configuration files to load.
-This method __removes__ all the directory previously added.
-
-```php
-setDirectories($dirs);
-```
-
-This method can also accept an iterator, containing strings or SplFileInfo, so you can pass also an instance of a finder object, i.e. [Symfony Finder](https://symfony.com/doc/current/components/finder.html):
-
-```php
-in(getcwd())->name('config')->directories();
-
-$builder->setDirectories($dirs);
-```
-
-
-## setDefinition
-
-!!! example "Signature"
- `#!php-inline public function setDefinition(ConfigurationInterface $definition): self`
-
-Add an instance of `Symfony\Component\Config\Definition\ConfigurationInterface` to process the configuration parameters.
-
-For further information about Symfony Config and how to define a `ConfigurationInterface` class, please see the [official Symfony documentation](https://symfony.com/doc/current/components/config/definition.html).
-
-
-## setConfigurationClass
-
-!!! example "Signature"
- `#!php-inline public function setConfigurationClass(string $configurationClass): self`
-
-Set the configuration class to populate with the processed parameters. If the class does not exist, a `ConfigurationBuilderException` is thrown.
-The method expects to pass an array of parameters to the class constructor.
-
-
-## setInitMethod
-
-!!! example "Signature"
- `#!php-inline public function setInitMethod(string $initMethod): self`
-
-The configuration class, set via [setConfigurationClass](#set-configuration-class) method, could be populated via its constructor or via an _initialization_ method, expecting an array as parameter.
-With `setInitMethod` we set the method to use to populate the configuration class.
-
-
-Suppose you have a configuration class, like the following:
-
-```php
-setConfigurationClass(ConfigurationManager::class)
- ->setInitMethod('setParameters')
- ;
-```
-
-
-## setBeforeParams
-
-!!! example "Signature"
- `#!php-inline public function setBeforeParams(array $beforeParams): self`
-
-Set an array of parameters to merge into your configuration __before__ loading the files.
-
-Note that the value of this parameters _could be overwritten_ by the ones loaded from the configuration files.
-
-
-## setAfterParams
-
-!!! example "Signature"
- `#!php-inline public function setAfterParams(array $afterParams): self`
-
-Set an array of parameters to merge into your configuration __after__ loading the files.
-
-Note that the value of this parameters _could overwrite_ the ones loaded from the configuration files.
-
-## setCacheDirectory
-
-!!! example "Signature"
- `#!php-inline public function setCacheDirectory(string $cache): self`
-
-Set the directory where to save the cache files (see [Cache](usage.md#cache)).
-
-## populateContainer
-
-!!! example "Signature"
-`#!php-inline public function populateContainer(object $container, string $method): void`
-
-Populate a dependency injection container `$container` with the loaded configuration parameters.
-You can retrieve each parameter with a _dot acces_ key (i.e. database.connection.dsn).
-
-## keepFirstXmlTag
-
-!!! example "Signature"
-`#!php-inline public function keepFirstXmlTag(bool $keep = true): self`
-
-When loading XML files, keep the first xml tag as part of the configuration.
-
-Consider the following xml:
-
-```xml
-
-
- bar
- baz
-
-```
-
-it usually results in the following array:
-
-```php
- 'bar',
- 'bar' => 'baz'
- ];
-```
-
-If you call `keepFirstXmTag` then the resulted array is the following:
-
-```php
- [
- 'foo' => 'bar',
- 'bar' => 'baz'
- ]
- ];
-```
diff --git a/docs/usage.md b/docs/usage.md
index 2ae107c..7e29b51 100644
--- a/docs/usage.md
+++ b/docs/usage.md
@@ -23,7 +23,7 @@ $builder = ConfigurationBuilder::create()
;
```
-You can set up the `ConfigurationBuilder` via all the methods explained into [Api Reference](methods.md) document.
+You can set up the `ConfigurationBuilder` via all the methods explained into [Api Reference](api/index.html) document.
## Get The Configuration as an Array
diff --git a/mkdocs.yml b/mkdocs.yml
index f3506c3..7f44dd3 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -12,6 +12,7 @@ edit_uri: ''
copyright: 'Susina Configuration Builder is licensed under Apache 2.0 license'
#Configuration
+site_dir: _site
theme:
name: material
favicon: assets/hammer-and-wrench.png
@@ -28,7 +29,7 @@ nav:
- Installation: installation.md
- Usage: usage.md
- Reference:
- - Api: methods.md
+ - Api: api/index.html
- Parameters reference: parameters.md
- Complete Example: example.md
- About:
diff --git a/phpdoc.dist.xml b/phpdoc.dist.xml
new file mode 100644
index 0000000..7a8c4f0
--- /dev/null
+++ b/phpdoc.dist.xml
@@ -0,0 +1,20 @@
+
+
+
+
+ _site/cache
+
+
+
+
+ src
+
+
+
+
+
\ No newline at end of file
diff --git a/src/ConfigCache.php b/src/ConfigCache.php
index 3456418..7eb8278 100644
--- a/src/ConfigCache.php
+++ b/src/ConfigCache.php
@@ -10,11 +10,22 @@
use Symfony\Component\Config\ConfigCache as BaseConfigCache;
+/**
+ * Specialized class to cache the built configuration.
+ * It extends `Symfony\Component\Config\ConfigCache` class.
+ *
+ * @author Cristiano Cinotti
+ */
class ConfigCache extends BaseConfigCache
{
private string $builderSerial;
private string $serialFile;
+ /**
+ * @param string $file The cache file.
+ * @param bool $debug start/stop debug environment.
+ * @param ConfigurationBuilder $builder The object to save in cache.
+ */
public function __construct(string $file, bool $debug, ConfigurationBuilder $builder)
{
parent::__construct($file, $debug);
@@ -23,6 +34,11 @@ public function __construct(string $file, bool $debug, ConfigurationBuilder $bui
$this->serialFile = dirname($this->getPath()) . DIRECTORY_SEPARATOR . 'config_builder.serial';
}
+ /**
+ * Check if the cache is fresh.
+ *
+ * @return bool
+ */
public function isFresh(): bool
{
if (!file_exists($this->serialFile) || $this->builderSerial !== file_get_contents($this->serialFile)) {
@@ -32,6 +48,12 @@ public function isFresh(): bool
return parent::isFresh();
}
+ /**
+ * Write the data into the cache.
+ *
+ * @param $content The content to write in cache.
+ * @param $metadata An optional array of metadata.
+ */
public function write(string $content, ?array $metadata = null): void
{
parent::write($content, $metadata);
diff --git a/src/ConfigurationBuilder.php b/src/ConfigurationBuilder.php
index 7cfdbf3..dbb7d99 100644
--- a/src/ConfigurationBuilder.php
+++ b/src/ConfigurationBuilder.php
@@ -11,20 +11,28 @@
use IteratorAggregate;
use SplFileInfo;
use Susina\ConfigBuilder\Exception\ConfigurationBuilderException;
-use Susina\ConfigBuilder\Loader\IniFileLoader;
use Susina\ConfigBuilder\Loader\JsonFileLoader;
use Susina\ConfigBuilder\Loader\NeonFileLoader;
use Susina\ConfigBuilder\Loader\PhpFileLoader;
use Susina\ConfigBuilder\Loader\XmlFileLoader;
use Susina\ConfigBuilder\Loader\YamlFileLoader;
+use Susina\ParamResolver\ParamResolver;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\Config\Loader\DelegatingLoader;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\Resource\FileResource;
+/**
+ * Class ConfigurationBuilder.
+ *
+ * @author Cristiano Cinotti
+ */
final class ConfigurationBuilder
{
+ /**
+ * @var string The name of the cache file.
+ */
public const CACHE_FILE = 'susina_config_builder.cache';
/**
@@ -33,7 +41,7 @@ final class ConfigurationBuilder
private array $files = [];
/**
- * @var array The directories where to find the configuration files.
+ * @var string[] The directories where to find the configuration files.
*/
private array $directories = [];
@@ -54,19 +62,27 @@ final class ConfigurationBuilder
private string $initMethod = '';
/**
- * @var array Additional array of parameters to merge BEFORE to load the configuration files.
+ * @var array Additional array of parameters to merge BEFORE loading the configuration files.
*/
private array $beforeParams = [];
/**
- * @var array Additional array of parameters to merge AFTER to load the configuration files.
+ * @var array Additional array of parameters to merge AFTER loading the configuration files.
*/
private array $afterParams = [];
+ /**
+ * @var array An array of key => values elements to replace into the configuration, before parameters resolving and validating.
+ */
+ private array $replaces = [];
+
+ /**
+ * @string The cache directory.
+ */
private string $cacheDirectory = '';
/**
- * @var bool if keep the first xml tag in an xml configuration file
+ * @var bool If keep the first xml tag in an xml configuration file.
*/
private bool $keepFirstXmlTag = false;
@@ -83,8 +99,22 @@ public static function create(): self
/**
* Add one or more file names to the array of configuration files to load.
*
- * @param string|SplFileInfo ...$files
+ * The parameters can contain:
+ * - the name of the configuration file to load
+ * - the full path name of the configuration file to load
+ * - SplFileInfo object representing the configuration file to load
+ *
+ * Use this method to add one or more elements to the list of configuration files to load. I.e.:
+ * ```php
+ * addFile('my-project-config.yaml.dist', 'my-project-config-yml');
+ * ```
*
+ * @param string|SplFileInfo ...$files The files to load.
* @return $this
*/
public function addFile(string|SplFileInfo ...$files): self
@@ -102,11 +132,37 @@ public function addFile(string|SplFileInfo ...$files): self
/**
* Set the name of the configuration files to load.
- * It accepts also an Iterator, so that It's possible to directly pass the result of a finder library
- * (e.g. Symfony Finder)
*
- * @param array|IteratorAggregate $files
+ * This method receives an array of strings or SplFileInfo objects and sets the list of the configuration files to load.
+ * It __removes__ all the files previously added.
*
+ * ```php
+ * setFiles($configFiles);
+ * ```
+ *
+ * This method can also accept an iterator, containing strings or SplFileInfo,
+ * so you can pass also an instance of a finder object, i.e. [Symfony Finder](https://symfony.com/doc/current/components/finder.html):
+ *
+ * ```php
+ * in('app/config')->name('*.json')->files();
+ *
+ * $builder->setFiles($finder);
+ * ```
+ *
+ * @param array|IteratorAggregate $files The files to add.
* @return $this
*/
public function setFiles(array|IteratorAggregate $files): self
@@ -122,10 +178,27 @@ public function setFiles(array|IteratorAggregate $files): self
/**
* Add one or more directories where to find the configuration files.
*
- * @param string|SplFileInfo ...$dirs
+ * Add one or more directories where to find the configuration files.
+ * The parameters can contain:
+ *
+ * - the full path name of the directory
+ * - SplFileInfo object representing a directory where to find the configuration files
+ *
+ * This method check if the passed directories are existent and readable,
+ * otherwise throws a `ConfigurationBuilderException`.
*
+ * ```php
+ * addDirectory(__DIR__ . '/app/config', getcwd());
+ * ```
+ *
+ * @param string|SplFileInfo ...$dirs The directories to add.
* @return $this
- * @throws ConfigurationBuilderException
+ * @throws ConfigurationBuilderException If a directory does not exist or it's not writeable.
*/
public function addDirectory(string|SplFileInfo ...$dirs): self
{
@@ -151,14 +224,40 @@ function (string|SplFileInfo $dir): string {
}
/**
- * Set the name of the directory where to find the configuration files to load.
- * It accepts also an Iterator, so that It's possible to directly pass the result of a finder library
- * (e.g. Symfony Finder)
+ * Set the name of the directories where to find the configuration files to load.
+ *
+ * This method receives an array of strings or SplFileInfo objects and sets the list of the directories
+ * where to find the configuration files to load. It __removes__ all the previously added directories.
+ *
+ * ```php
+ * setDirectories($dirs);
+ * ```
+ *
+ * This method can also accept an iterator, containing strings or SplFileInfo,
+ * so you can pass also an instance of a finder object, i.e. [Symfony Finder](https://symfony.com/doc/current/components/finder.html):
+ *
+ * ```php
+ * in(getcwd())->name('config')->directories();
*
- * @param array|IteratorAggregate $dirs
+ * $builder->setDirectories($dirs);
+ * ```
*
+ * @param array|IteratorAggregate $dirs Se the entire directories array.
* @return $this
- * @throws ConfigurationBuilderException
+ * @throws ConfigurationBuilderException If a directory does not exist or it's not writeable.
*/
public function setDirectories(array|IteratorAggregate $dirs): self
{
@@ -173,8 +272,11 @@ public function setDirectories(array|IteratorAggregate $dirs): self
/**
* Set the object to process the configuration parameters.
*
- * @param ConfigurationInterface $definition
+ * Add an instance of `Symfony\Component\Config\Definition\ConfigurationInterface` to process the configuration parameters.
+ * For further information about Symfony Config and how to define a `ConfigurationInterface` class,
+ * please see the [official Symfony documentation](https://symfony.com/doc/current/components/config/definition.html).
*
+ * @param ConfigurationInterface $definition The configuration definition object.
* @return $this
* @see https://symfony.com/doc/current/components/config/definition.html
*/
@@ -188,10 +290,13 @@ public function setDefinition(ConfigurationInterface $definition): self
/**
* Set the full class name of the configuration object to instantiate.
*
- * @param string $configurationClass
+ * Set the configuration class to populate with the processed parameters. If the class does not exist,
+ * a `ConfigurationBuilderException` is thrown. This method expects to pass an array of parameters to the class constructor.
+ *
+ * @param string $configurationClass The configuration full classname.
*
* @return $this
- * @throws ConfigurationBuilderException
+ * @throws ConfigurationBuilderException If the class does not exist.
*/
public function setConfigurationClass(string $configurationClass): self
{
@@ -206,8 +311,44 @@ public function setConfigurationClass(string $configurationClass): self
/**
* Set the method to use to initialize the configuration object.
*
- * @param string $initMethod
+ * The configuration class, set via [setConfigurationClass](#set-configuration-class) method, could be populated
+ * via its constructor or via an _initialization_ method, expecting an array as parameter.
+ * With `setInitMethod` we set the method to use to populate the configuration class.
+ *
+ * Suppose you have a configuration class, like the following:
+ *
+ * ```php
+ * setConfigurationClass(ConfigurationManager::class)
+ * ->setInitMethod('setParameters');
+ * ```
*
+ * @param string $initMethod The name of the method.
* @return $this
*/
public function setInitMethod(string $initMethod): self
@@ -220,8 +361,13 @@ public function setInitMethod(string $initMethod): self
/**
* Set an array of additional parameters to merge before loading the configuration files.
*
- * @param array $beforeParams
+ * Set an array of parameters to merge into your configuration __before__ loading the files.
+ * These parameters are processed and validated via Symfony\Config, so they must be compatible with
+ * the definition class specified in `$definition` property.
*
+ * > The value of these parameters __could be overwritten__ by the ones loaded from the configuration files.
+ *
+ * @param array $beforeParams The array of parameters to be merged.
* @return $this
*/
public function setBeforeParams(array $beforeParams): self
@@ -234,8 +380,13 @@ public function setBeforeParams(array $beforeParams): self
/**
* Set an array of additional parameters to merge after loading the configuration files.
*
- * @param array $afterParams
+ * Set an array of parameters to merge into your configuration __after__ loading the files.
+ * These parameters are processed and validated via Symfony\Config, so they must be compatible with
+ * the definition class specified in `$definition` property.
+ *
+ * > The value of these parameters __could overwrite__ the ones loaded from the configuration files.
*
+ * @param array $afterParams The array of parameters to be merged.
* @return $this
*/
public function setAfterParams(array $afterParams): self
@@ -249,7 +400,7 @@ public function setAfterParams(array $afterParams): self
* Set the cache directory or the CacheInterface object
*
* @return $this
- * @throws ConfigurationBuilderException
+ * @throws ConfigurationBuilderException If the directory does not exist or it's not readable.
*/
public function setCacheDirectory(string $cache): self
{
@@ -264,11 +415,82 @@ public function setCacheDirectory(string $cache): self
return $this;
}
+ /**
+ * Set an array of parameters to replace.
+ *
+ * This values are useful for parameters replacing and they're removed before processing and validating
+ * the configuration. In this way, you can write some "standard" parameters in your configuration. I.e.:
+ *
+ * ```yaml
+ * cache:
+ * path: %kernel_dir%/cache/my_app.cache
+ * ```
+ *
+ * Now,you can inject the `kernel_dir` parameter to replace it:
+ *
+ * ```php
+ * setReplaces(['kernel_dir' => '/my/absolute/path])
+ * ->getConfigurationArray();
+ *
+ * // $config = [
+ * // 'cache' => [
+ * // 'path' => '/my/absolute/path/my_app.cache'
+ * // ]
+ * //]
+ * ```
+ *
+ * Note that, after replacing, the `kernel_dir` parameter is removed from the configuration.
+ *
+ * @param array $params The parameters to replace
+ * @return $this
+ */
+ public function setReplaces(array $params): self
+ {
+ $this->replaces = $params;
+
+ return $this;
+ }
+
/**
* Keep also the first tag of a xml configuration.
*
- * @param bool $keep
+ * When loading XML files, it keeps the first xml tag as part of the configuration. Consider the following xml:
+ *
+ * ```xml
+ *
+ *
+ * bar
+ * baz
+ *
+ * ```
*
+ * it usually results in the following array:
+ * ```php
+ * 'bar',
+ * 'bar' => 'baz'
+ * ];
+ * ```
+ *
+ * If you call `keepFirstXmTag` then the resulted array is the following:
+ *
+ * ```php
+ * [
+ * 'foo' => 'bar',
+ * 'bar' => 'baz'
+ * ]
+ * ];
+ * ```
+ *
+ * @param bool $keep
* @return $this
*/
public function keepFirstXmlTag(bool $keep = true): self
@@ -282,6 +504,7 @@ public function keepFirstXmlTag(bool $keep = true): self
* Return a populated configuration object.
*
* @return object
+ * @throws ConfigurationBuilderException If not set any configuration classtoinstantiate.
*/
public function getConfiguration(): object
{
@@ -316,10 +539,11 @@ public function getConfigurationArray(): array
/**
* Populate a container object with the configuration values.
*
- * @param object $container The container object
- * @param string $method The container method to add a parameter
- * (i.e. `set` for Php-Di or `setParameter` for Symfony Dependency Injection).
+ * This method populates a dependency injection container `$container` with the loaded configuration parameters.
+ * You can acces the loaded parameters _dot acces_ key reference (i.e. database.connection.dsn).
*
+ * @param object $container The container object
+ * @param string $method The container method to add a parameter (i.e. `set` for Php-Di or `setParameter` for Symfony Dependency Injection).
* @return void
*/
public function populateContainer(object $container, string $method): void
@@ -331,6 +555,14 @@ public function populateContainer(object $container, string $method): void
array_map([$container, $method], array_keys($parameters), array_values($parameters));
}
+ /**
+ * Transform an array in dotted notation.
+ * Useful to populate a di-container.
+ *
+ * @param array $parameters The array to translate in dotted notation.
+ * @param array &$output The array to return.
+ * @param string $affix The optional affix to add to the dotted key.
+ */
private function getDotArray(array $parameters, array &$output, string $keyAffix = ''): void
{
foreach ($parameters as $key => $value) {
@@ -344,6 +576,8 @@ private function getDotArray(array $parameters, array &$output, string $keyAffix
}
/**
+ * Load parameters from the configuration files.
+ *
* @psalm-suppress NamedArgumentNotAllowed
*/
private function loadParameters(): array
@@ -358,9 +592,29 @@ private function loadParameters(): array
]);
$delegatingLoader = new DelegatingLoader($loaderResolver);
- return array_merge_recursive(...array_map([$delegatingLoader, 'load'], $this->files));
+ $parameters = array_merge_recursive(...array_map([$delegatingLoader, 'load'], $this->files));
+
+ //Add replaces to the array...
+ foreach ($this->replaces as $key => $value) {
+ $parameters[$key] = $value;
+ }
+
+ //Param resolver do the job...
+ $parameters = ParamResolver::create()->resolve($parameters);
+
+ //Remove replaces from the array.
+ foreach ($this->replaces as $key => $value) {
+ unset($parameters[$key]);
+ }
+
+ return $parameters;
}
+ /**
+ * Process and validate the configuration.
+ *
+ * @throws ConfigurationBuilderException If the definition file is not set.
+ */
private function loadConfiguration(): array
{
$processor = new Processor();
@@ -376,7 +630,9 @@ private function loadConfiguration(): array
}
/**
- * @return array
+ * Load the configuration from cache.
+ *
+ * @return array The configuration
*
* @psalm-suppress PossiblyInvalidArgument FileLocator::locate() returns a string
* if the 3rd function argument is not set to false
diff --git a/src/Exception/ConfigurationBuilderException.php b/src/Exception/ConfigurationBuilderException.php
index 8e81958..65040d0 100644
--- a/src/Exception/ConfigurationBuilderException.php
+++ b/src/Exception/ConfigurationBuilderException.php
@@ -10,6 +10,10 @@
use RuntimeException;
+/**
+ * Class ConfigurationBuilderException.
+ * Specialized Exception class for Configuration Builder.
+ */
class ConfigurationBuilderException extends RuntimeException
{
}
diff --git a/src/FileLocator.php b/src/FileLocator.php
index e85fea7..334305b 100644
--- a/src/FileLocator.php
+++ b/src/FileLocator.php
@@ -11,8 +11,18 @@
use Susina\ConfigBuilder\Exception\ConfigurationBuilderException;
use Symfony\Component\Config\FileLocator as BaseFileLocator;
+/**
+ * Class to locate the configuration files to load.
+ *
+ * @author Cristiano Cinotti
+ */
class FileLocator extends BaseFileLocator
{
+ /**
+ * @inheritdoc
+ *
+ * @throws ConfigurationBuilderException If the located files are not readable.
+ */
public function locate(string $name, ?string $currentPath = null, bool $first = true): string|array
{
$output = parent::locate($name, $currentPath, $first);
diff --git a/src/Loader/JsonFileLoader.php b/src/Loader/JsonFileLoader.php
index 7e69df1..c80fe09 100644
--- a/src/Loader/JsonFileLoader.php
+++ b/src/Loader/JsonFileLoader.php
@@ -8,22 +8,20 @@
namespace Susina\ConfigBuilder\Loader;
-use Susina\ParamResolver\ParamResolver;
use Symfony\Component\Config\Loader\FileLoader;
/**
* JsonFileLoader loads configuration parameters from json file.
*
- * @author Cristiano Cinotti
+ * @author Cristiano Cinotti
*/
class JsonFileLoader extends FileLoader
{
/**
* Loads a Json file.
*
- * @param mixed $resource The resource
+ * @param mixed $resource The resource to load.
* @param string|null $type The resource type
- *
* @return array
* @throws \JsonException
*
@@ -36,9 +34,7 @@ public function load(mixed $resource, ?string $type = null): array
return [];
}
- $content = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
-
- return ParamResolver::create()->resolve($content); //Resolve parameter placeholders (%name%)
+ return json_decode($json, true, 512, JSON_THROW_ON_ERROR);
}
/**
@@ -46,8 +42,7 @@ public function load(mixed $resource, ?string $type = null): array
*
* @param mixed $resource A resource
* @param string|null $type The resource type
- *
- * @return bool true if this class supports the given resource, false otherwise
+ * @return bool true If this class supports the given resource, false otherwise
*/
public function supports($resource, $type = null): bool
{
diff --git a/src/Loader/NeonFileLoader.php b/src/Loader/NeonFileLoader.php
index 4e33032..dcfae3d 100644
--- a/src/Loader/NeonFileLoader.php
+++ b/src/Loader/NeonFileLoader.php
@@ -9,7 +9,6 @@
namespace Susina\ConfigBuilder\Loader;
use Nette\Neon\Neon;
-use Susina\ParamResolver\ParamResolver;
use Symfony\Component\Config\Loader\FileLoader;
/**
@@ -20,11 +19,10 @@
class NeonFileLoader extends FileLoader
{
/**
- * Loads a Yaml file.
- *
- * @param mixed $resource The resource
- * @param string|null $type The resource type
+ * Loads a Neon file.
*
+ * @param mixed $resource The resource to load.
+ * @param string|null $type The resource type.
* @return array
*
* @psalm-suppress PossiblyInvalidArgument FileLocator::locate() returns string, since 3rd argument isn't false
@@ -33,17 +31,15 @@ public function load(mixed $resource, ?string $type = null): array
{
$content = Neon::decode(file_get_contents($this->getLocator()->locate($resource)));
- return $content === null ? [] : ParamResolver::create()->resolve($content);
+ return $content ?? [];
}
/**
* Returns true if this class supports the given resource.
- * Both 'yml' and 'yaml' extensions are accepted.
- *
- * @param mixed $resource A resource
- * @param string|null $type The resource type
*
- * @return bool true if this class supports the given resource, false otherwise
+ * @param mixed $resource A resource.
+ * @param string|null $type The resource type.
+ * @return bool true If this class supports the given resource, false otherwise.
*/
public function supports($resource, $type = null): bool
{
diff --git a/src/Loader/PhpFileLoader.php b/src/Loader/PhpFileLoader.php
index d7f18da..27a19b4 100644
--- a/src/Loader/PhpFileLoader.php
+++ b/src/Loader/PhpFileLoader.php
@@ -9,7 +9,6 @@
namespace Susina\ConfigBuilder\Loader;
use Susina\ConfigBuilder\Exception\ConfigurationBuilderException;
-use Susina\ParamResolver\ParamResolver;
use Symfony\Component\Config\Loader\FileLoader;
/**
@@ -24,17 +23,15 @@
* );
*
*
- * @author Cristiano Cinotti
+ * @author Cristiano Cinotti
*/
class PhpFileLoader extends FileLoader
{
/**
* Loads a PHP file.
*
- * @param mixed $resource The resource
- * @param string|null $type The resource type
- *
- *
+ * @param mixed $resource The resource to load.
+ * @param string|null $type The resource type.
* @return array
* @throws ConfigurationBuilderException
*
@@ -60,17 +57,16 @@ public function load(mixed $resource, ?string $type = null): array
throw new ConfigurationBuilderException("The configuration file '$resource' has invalid content.");
}
- return ParamResolver::create()->resolve($content); //Resolve parameter placeholders (%name%)
+ return $content;
}
/**
* Returns true if this class supports the given resource.
* It supports both .php and .inc extensions.
*
- * @param mixed $resource A resource
- * @param string|null $type The resource type
- *
- * @return bool true if this class supports the given resource, false otherwise
+ * @param mixed $resource A resource.
+ * @param string|null $type The resource type.
+ * @return bool true if this class supports the given resource, false otherwise.
*/
public function supports(mixed $resource, $type = null): bool
{
diff --git a/src/Loader/XmlFileLoader.php b/src/Loader/XmlFileLoader.php
index c806e16..fde8846 100644
--- a/src/Loader/XmlFileLoader.php
+++ b/src/Loader/XmlFileLoader.php
@@ -9,15 +9,15 @@
namespace Susina\ConfigBuilder\Loader;
use Susina\ConfigBuilder\Exception\ConfigurationBuilderException;
-use Susina\ParamResolver\ParamResolver;
use Susina\XmlToArray\Converter;
+use Susina\XmlToArray\Exception\ConverterException;
use Symfony\Component\Config\FileLocatorInterface;
use Symfony\Component\Config\Loader\FileLoader;
/**
* XmlFileLoader loads configuration parameters from xml file.
*
- * @author Cristiano Cinotti
+ * @author Cristiano Cinotti
*/
class XmlFileLoader extends FileLoader
{
@@ -32,13 +32,11 @@ public function __construct(FileLocatorInterface $fileLocator, bool $keepFirstTa
/**
* Loads a Xml file.
*
- * @param mixed $resource The resource
- * @param string|null $type The resource type
- *
+ * @param mixed $resource The resource to load.
+ * @param string|null $type The resource type.
* @return array
- *
- * @throws ConfigurationBuilderException
- * @throws ConfigurationBuilderException
+ * @throws ConverterException If an error occurs while parsing the xml.
+ * @throws ConfigurationBuilderException If an error occurs while reading the xml file.
*
* @psalm-suppress PossiblyInvalidArgument FileLocator::locate() returns string, since 3rd argument isn't false
*/
@@ -51,18 +49,16 @@ public function load(mixed $resource, ?string $type = null): array
}
$converter = new Converter(['preserveFirstTag' => $this->keepFirstTag]);
- $content = $converter->convert($xmlContent);
- return ParamResolver::create()->resolve($content); //Resolve parameter placeholders (%name%)
+ return $converter->convert($xmlContent);
}
/**
* Returns true if this class supports the given resource.
*
- * @param mixed $resource A resource
- * @param string|null $type The resource type
- *
- * @return bool true if this class supports the given resource, false otherwise
+ * @param mixed $resource A resource.
+ * @param string|null $type The resource type.
+ * @return bool true If this class supports the given resource, false otherwise.
*/
public function supports(mixed $resource, ?string $type = null): bool
{
diff --git a/src/Loader/YamlFileLoader.php b/src/Loader/YamlFileLoader.php
index 3594121..358199f 100644
--- a/src/Loader/YamlFileLoader.php
+++ b/src/Loader/YamlFileLoader.php
@@ -9,7 +9,6 @@
namespace Susina\ConfigBuilder\Loader;
use Susina\ConfigBuilder\Exception\ConfigurationBuilderException;
-use Susina\ParamResolver\ParamResolver;
use Symfony\Component\Config\Loader\FileLoader;
use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Yaml;
@@ -17,7 +16,7 @@
/**
* YamlFileLoader loads configuration parameters from yaml file.
*
- * @author Cristiano Cinotti
+ * @author Cristiano Cinotti
*/
class YamlFileLoader extends FileLoader
{
@@ -26,11 +25,9 @@ class YamlFileLoader extends FileLoader
*
* @param mixed $resource The resource
* @param string|null $type The resource type
- *
* @return array
- *
- * @throws ConfigurationBuilderException
- * @throws ParseException if something goes wrong in parsing file
+ * @throws ConfigurationBuilderException If an error occurs while reading the file.
+ * @throws ParseException If something goes wrong in parsing the file.
*
* @psalm-suppress PossiblyInvalidArgument FileLocator::locate() returns string, since 3rd argument isn't false
*/
@@ -46,17 +43,16 @@ public function load(mixed $resource, ?string $type = null): array
throw new ConfigurationBuilderException('Unable to parse the configuration file: wrong yaml content.');
}
- return ParamResolver::create()->resolve($content);
+ return $content;
}
/**
* Returns true if this class supports the given resource.
* Both 'yml' and 'yaml' extensions are accepted.
*
- * @param mixed $resource A resource
- * @param string|null $type The resource type
- *
- * @return bool true if this class supports the given resource, false otherwise
+ * @param mixed $resource A resource.
+ * @param string|null $type The resource type.
+ * @return bool true If this class supports the given resource, false otherwise.
*/
public function supports($resource, $type = null): bool
{
diff --git a/tests/Functional/FunctionalTest.php b/tests/Functional/FunctionalTest.php
index 2af05a3..bbcc8f2 100644
--- a/tests/Functional/FunctionalTest.php
+++ b/tests/Functional/FunctionalTest.php
@@ -255,3 +255,51 @@
]
);
});
+
+test('Replaces', function () {
+ $file = vfsStream::newFile('config.yml')->at($this->getRoot())->setContent(<< true,
+ 'default_connection' => 'mysql',
+ 'connections' => [
+ 'mysql' => [
+ 'host' => 'localhost',
+ 'driver' => 'mysql',
+ 'username' => 'user',
+ 'password' => 'pass'
+ ],
+ 'sqlite' => [
+ 'host' => 'vfs://root/database.sqlite',
+ 'driver' => 'sqlite',
+ 'username' => 'user',
+ 'password' => 'pass'
+ ]
+ ]
+ ];
+
+ $config = ConfigurationBuilder::create()
+ ->addFile('config.yml')
+ ->addDirectory($this->getRoot()->url())
+ ->setConfigurationClass(ConfigurationConstructor::class)
+ ->setDefinition(new DatabaseConfiguration())
+ ->setReplaces(['kernel_dir' => 'vfs://root'])
+ ->getConfigurationArray()
+ ;
+
+ expect($config)->toBe($expected);
+});