Skip to content

Commit

Permalink
BREAKING: Refactor charcoal-config
Browse files Browse the repository at this point in the history
- Remove separator and delegates from AbstractEntity
  - Still available in AbstractConfig
- Move Separator and Delegates features to their own Interface / Trait
- getter() and setter() methods removed from AbstractEntity
- Rewrote separator access method
- Optimize camelize method (see https://3v4l.org/WbpFv)
- Unit tests++
  • Loading branch information
mducharme committed Nov 20, 2017
1 parent 300c6dd commit 8b6eacc
Show file tree
Hide file tree
Showing 24 changed files with 1,216 additions and 639 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ script:
- ./vendor/bin/phpcs --config-set ignore_warnings_on_exit 1;./vendor/bin/phpcs -ps --colors --standard=phpcs.xml src/

## Run PHPUnit Tests
- phpunit --configuration ./tests/phpunit.xml --coverage-text --coverage-clover build/logs/clover.xml
- ./vendor/bin/phpunit --configuration ./tests/phpunit.xml --coverage-text --coverage-clover build/logs/clover.xml

after_script:
- php vendor/bin/coveralls -v
Expand Down
107 changes: 31 additions & 76 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ Configuration container for all things Charcoal.
This package provides easy hierarchical configuration container (for config storage and access).
`Charcoal\Config` acts as a configuration registry / repository.

## Entity and Config

There are 2 main concepts in this package: `Entity` and `Config`.

_Entities_ are simple data container, which implements `ArrayAccess`, `JsonSerializable` and `Serializable`. It also provides the `keys()`, `setData()`, `data()`, `set()`, `get()` and `has()` methods.

_Config_ are _entities_ that also implements the `IteratorAggregate`, `\Interop\Container\ContainerInterface`, `\Charcoal\Config\SeparatorAwareInterface` and `\Charcoal\Config\DelegatesAwareInterface`. On top of those interfaces and _entity_'s methods, it provides the `merge()`, `defaults()`, `addFile()` and `loadFile()` methods. Config are meant to hold application configuraion data as well as any other object configuration.


## Main features

- [Load data from ini, json, php or yaml files.](#supported-file-formats)
Expand All @@ -19,7 +28,7 @@ This package provides easy hierarchical configuration container (for config stor

## Supported file formats

There are currently 4 supported file formats: `ini`, `json`, `php` and `yaml`.
The _config_ container currently supports 4 file formats: `ini`, `json`, `php` and `yaml`.

To load configuration from a file, simply use the `addFile($filename)` method. The file's extension will be used to determine how to load the file.

Expand All @@ -41,6 +50,8 @@ It is also possible to load a config file directly from the constructor, by pass
$config = new \Charcoal\GenericConfig('../config/my-config.json');
```

Note that file loading is not supported on the base _entity_ container. This is a _config_-only feature.

### JSON configuration

For the JSON file (ex: `config/my-config.json`):
Expand Down Expand Up @@ -111,11 +122,11 @@ echo $config['example.foo'];
> $this->addFile('./config/more-config.json');
> ```
>
> The recommended way of use a _Config_ object is to include a single `config/config.php` file (that is outside of the document root) that takes care of loading required configuration (json or PHP) files.
> The recommended way of use a root / app _Config_ object is to include a single `config/config.php` file (that is outside of the document root) that takes care of loading required configuration (json or PHP) files.
### Yaml configuration

To be able to use the yaml loader, make sure `symfony/yaml` is included in your project composer dependencies:
> 👉 To be able to use the yaml loader, make sure `symfony/yaml` is included (required) in your project composer dependencies:
```shell
$ composer require symfony/yaml
Expand All @@ -141,9 +152,11 @@ echo $config['exampe.foo'];
## Separators

It is possible to fetch embedded _array-ish_ values recursively in a single call with the help of _separators_.
It is possible to fetch embedded _array-ish_ values recursively on _config_ containers in a single call with the help of _separators_.

In `config` objects, the default separator is `.` (it can be retrieved with `separator()`) but it can be changed easily with `setSeparator()`.

The default separator is `.` (it can be retrieved with `separator()`) but it can be changed easily with `setSeparator()`.
Separator is not available in _entity_ container. This is a _config_-only feature.

> 👉 Separator must be a single character. An exception will be thrown if trying to call `setSeparator()` with a longer string.
Expand All @@ -152,7 +165,7 @@ The default separator is `.` (it can be retrieved with `separator()`) but it can
```php
$config = new \Charcoal\GenericConfig();
$config->setSeparator('/'); // Default is "."
$config->merge([
$config->setData([
'foo', [
'baz'=>example,
'bar'=>42
Expand All @@ -164,9 +177,9 @@ echo $config->get('foo/bar');

## Delegates

It is possible to "chain" configuration containers with the help of _delegates_.
It is possible to "chain" _config_ containers with the help of _delegates_.

If one or more delegates are added to a class, they will be used as _fallback_ when trying to fetch a key that isn't set in the config.
If one or more delegates are added to a class, they will be used as _fallback_ when trying to fetch a key that isn't set in the config's data.

```php
$config = new \Charcoal\Config\GenericConfig([
Expand Down Expand Up @@ -195,17 +208,19 @@ Delegates can be set with:
- `addDelegate()` to add a config object at the end of the delegate list.
- `prependDelegate()` to add a config object at the beginning of the delegate list.

It is also possible to set delegates by passing them (as an array of ConfigInterface) to the constructor:
On _config_ containers, it is also possible to set delegates by passing them as the 2nd argument to the constructor:

```php
$config = new \Charcoal\Config\GenericConfig('../config/my-config.json', [$delegate1, $delegate2]);
```

> 👉 The order of the delegates is important. They are looked in the order they are added, so the first match is returned. Use `prependDelegate()` to add a config at the beginning of the stack (top priority).
> 👉 The order of the delegates is important. They are looked in the order they are added, so the first match is returned. Use `prependDelegate()` to add a delegate at the beginning of the stack (top priority).
Delegates are not available on _entity_ containers. This is a _config_-only feature.

## Array Access

The config class implements the `ArrayAccess` interface and therefore can be used with array style:
The _entity_ container implements the `ArrayAccess` interface and therefore can be used with array style:

```php
$config = new \Charcoal\Config\GenericConfig();
Expand All @@ -228,7 +243,7 @@ unset($config['foobar']);

## Interoperability

The `\Charcoal\Config` container implements the `container-interop` interface.
The `\Charcoal\Config` entity container implements the `container-interop` interface.

See [https://github.com/container-interop/container-interop](https://github.com/container-interop/container-interop).

Expand Down Expand Up @@ -293,8 +308,8 @@ $foo->setConfig([
]);

// echo 42
$foo_config = $foo->config();
echo $foo_config['bar.baz'];
$fooConfig = $foo->config();
echo $fooConfig['bar.baz'];

// Also echo 42
echo $foo->config('bar.baz');
Expand Down Expand Up @@ -340,72 +355,12 @@ The Charcoal-Config module follows the Charcoal coding-style:

> Coding style validation / enforcement can be performed with `composer phpcs`. An auto-fixer is also available with `composer phpcbf`.
> This module should also throw no error when running `phpstan analyse -l7 src/` 👍.
## Authors

- Mathieu Ducharme <mat@locomotive.ca>

## Changelog

### 0.6
_Released on 2016-05-10_

- Support for Yaml files.

### 0.5.1
_Released on 2016-05-09_

- Minor internal changes.

### 0.5
_Released on 2016-02-02_

- Split the base config class into AbstractEntity.
- AbstractEntity is the default data container that implements ArrayAccess, Container Interface and serialization.

### 0.4
_Released on 2016-01-16_

This release breaks compatibility.

- Move to camelCase, for 100% PSR-1 compliance.

### 0.3
_Released on 2016-01-15_

This releases breaks compatibility

- AbstractConfig constructor is now final.
- `set_data()` has been renamed to `merge()`.
- `merge()` (previously set_data) can now accept any `Traversable` objects, as well as array.
- `default_data()` has been renamed to `defaults()`
- Added a new `load_file()` method, to return the content of a config file.
- Added the `keys()` method, to retrieve the list of keys of the config file.
- Added the `data()` method, to retrieve the config as an array data, now that we have `keys()`.
- Config now inherits `IteratorAggregate` / `Traversable` (made possible with `data()`).
- Config is now `serializable` AND `jsonSerializable`.
- Setter rules can be overridden in children classes (for PSR2-style setter, for example).
- ConfigurableInterface / Trait `config()` method now accepts an optional `$key` argument.

### 0.2
_Released on 2015-12-09_

- Added the "delegates" feature.
- Setting value with a separator now tries to set as array.
- Implements the container-interop interface.

### 0.1.1
_Released on 2015-12-02_

- Removed the second argument for the constructor (currently unused).
- Clearer error message on invalid JSON files.
- Fix composer.json and the autoloader.
- Various internal changes (PSR2 compliancy, _with psr1 exception_).

### 0.1
_Released on 2015-08-25_

- Initial release of `charcoal-config`

# License

**The MIT License (MIT)**
Expand Down
2 changes: 1 addition & 1 deletion build/travis/apigen_ghpages.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# echo "TRAVIS_BRANCH: $TRAVIS_BRANCH"
# echo "TRAVIS_BUILD_NUMBER: $TRAVIS_BUILD_NUMBER"

if [ "$TRAVIS_REPO_SLUG" == "locomotivemtl/charcoal-config" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_PHP_VERSION" == "5.6" ]; then
if [ "$TRAVIS_REPO_SLUG" == "locomotivemtl/charcoal-config" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_PHP_VERSION" == "7.1" ]; then

echo -e "Publishing ApiGen to Github Pages...\n";

Expand Down
2 changes: 1 addition & 1 deletion build/travis/phpdoc_ghpages.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# echo "TRAVIS_BRANCH: $TRAVIS_BRANCH"
# echo "TRAVIS_BUILD_NUMBER: $TRAVIS_BUILD_NUMBER"

if [ "$TRAVIS_REPO_SLUG" == "locomotivemtl/charcoal-config" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_PHP_VERSION" == "5.6" ]; then
if [ "$TRAVIS_REPO_SLUG" == "locomotivemtl/charcoal-config" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_PHP_VERSION" == "7.1" ]; then

echo -e "Publishing PHPDoc to Github Pages...\n"

Expand Down

0 comments on commit 8b6eacc

Please sign in to comment.