SiteAccess-aware configuration¶
The Symfony Config component makes it possible to define semantic configuration, exposed to the end developer. This configuration is validated by rules you define, for example, validating type (string, array, integer, boolean, and more). Usually, after it's validated and processed, this semantic configuration is then mapped to internal key/value parameters stored in the service container.
Ibexa DXP uses this for its core configuration, but adds another configuration level, the SiteAccess. For each defined SiteAccess, you need to be able to use the same configuration tree to define SiteAccess-specific config.
These settings then need to be mapped to SiteAccess-aware internal parameters that you can retrieve with the ConfigResolver.
For this, internal keys need to follow the format <namespace>.<scope>.<parameter_name>
. where:
namespace
is specific to your app or bundlescope
is the SiteAccess, SiteAccess group,default
orglobal
parameter_name
is the actual setting identifier
For more information about the ConfigResolver, namespaces and scopes, see configuration basics.
Repository-aware configuration
If you need to use different settings per repository, not per SiteAccess, see Repository-aware configuration.
The example below assumes you're using an Acme\ExampleBundle
.
Remember to register the bundle by adding it to config/bundles.php
:
1 |
|
Parsing semantic configuration¶
To parse semantic configuration, create a Configuration
class which extends Ibexa\Bundle\Core\DependencyInjection\Configuration\SiteAccessAware\Configuration
and then extend its generateScopeBaseNode()
method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
Note
Default name for the SiteAccess root node is system
, but you can customize it.
To do this, pass the name you want to use as a second argument of $this->generateScopeBaseNode()
.
This enables you to use the following SiteAccess-aware configuration:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Mapping to internal settings¶
Semantic configuration must always be mapped to internal key/value settings within the service container. You usually do it in the service container extension.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
|
You can also map simple settings by calling $processor->mapSetting()
, without having to call $processor->mapConfig()
with a callable.
1 2 |
|
Important
Always ensure you have defined and loaded default settings.
In @AcmeExampleBundle/Resources/config/default_settings.yaml
:
1 2 3 4 5 6 |
|
Merging hash values between scopes¶
When you define a hash as semantic config, you sometimes don't want the SiteAccess settings to replace the default or group values,
but enrich them by appending new entries.
This is possible by using $processor->mapConfigArray()
, which you must call outside the closure (before or after), so that it's called only once.
1 |
|
Consider the following default config in default_settings.yaml
:
1 2 3 4 5 6 7 |
|
And then this semantic configuration in config/packages/acme.yaml
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
By calling mapConfigArray()
you can get the following end configuration, where keys defined for custom_setting
in default/group/SiteAccess scopes are merged:
1 2 3 4 5 6 7 |
|
Merging from second level¶
In the example above, entries were merged in respect to the scope order of precedence.
However, because you defined the os_types
key for siteaccess1
, it completely overrode the default value, because the merge process is done only at the first level.
You can add another level by passing ContextualizerInterface::MERGE_FROM_SECOND_LEVEL
as the third argument to $contextualizer->mapConfigArray()
:
1 |
|
When you use ContextualizerInterface::MERGE_FROM_SECOND_LEVEL
with the configuration above, you get the following result:
1 2 3 4 5 6 7 |
|
There is also another option, ContextualizerInterface::UNIQUE
, that ensures the array setting has unique values.
It only works on normal arrays, not hashes.
Note
Merge isn't recursive. Only second level merge is possible by using ContextualizerInterface::MERGE_FROM_SECOND_LEVEL
option.
Dedicated mapper object¶
Instead of passing a callable to $processor->mapConfig()
, you can pass an instance of
Ibexa\Bundle\Core\DependencyInjection\Configuration\SiteAccessAware\ConfigurationMapperInterface
.
This can be useful if you have a lot of configuration to map and don't want to pollute your service container extension class (it's better for maintenance).
Merging hash values between scopes¶
You should not use $contextualizer->mapConfigArray()
within the scope loop, like for simple values.
When using a closure/callable, you usually call it before or after $processor->mapConfig()
.
For mapper objects, you can use a dedicated interface: HookableConfigurationMapperInterface
, which defines two methods: preMap()
and postMap()
.