This recipe is compatible with eZ Publish 5.4 / 2014.07
EZP >= 5.4 / 2014.07
Symfony Config component makes it possible to define semantic configuration, exposed to the end-developer. This configuration is validated by rules you define, e.g. validating type (string, array, integer, boolean...). Usually, once validated and processed this semantic configuration is then mapped to internal key/value parameters stored in the
eZ Publish uses this for its core configuration, but adds another configuration level, the SiteAccess. For each defined SiteAccess, we need to be able to use the same configuration tree in order to define SiteAccess specific config. These settings then need to be mapped to SiteAccess aware internal parameters, that one can retrieve via the
ConfigResolver. For this, internal keys need to follow the format
namespace being specific to your app/bundle,
scope being the SiteAccess, SiteAccess group,
parameter_name being the actual setting identifier.
For more information on ConfigResolver, namespaces and scopes, see eZ Publish configuration basics.
Goal of this feature is to make it easy to implement a SiteAccess aware semantic configuration and its mapping to internal config for any eZ bundle developer.
Semantic configuration parsing
Configuration class has been added, simplifying the way to add a SiteAccess settings tree like the following:
Class FQN is
All you have to do is to extend it and use
Default name for the SiteAccess root node is
system, but you can customize it. For this, just pass the name you want to use as a 2nd argument of
Mapping to internal settings
Semantic configuration must always be mapped to internal key/value settings within the
ServiceContainer. This is usually done in the DIC extension.
For SiteAccess aware settings, new
Contextualizer classes have been introduced to ease the process.
You can map simple settings by calling
$processor->mapSetting(), without having to call
$processor->mapConfig() with a callable.
Important: Always ensure you have defined and loaded default settings.
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 made possible by using
$processor->mapConfigArray(), which needs to be called outside the closure (before or after), in order to be called only once.
Consider the following default config:
And then this semantic config:
What we want here, is that keys defined for
foo_setting are merged between default/group/SiteAccess:
Merge from second level
In the example above, entries were merged in respect to the scope order of precedence. However, if we define the
planets key for
sa1, it will completely override the default value since the merge process is done at only 1 level.
You can add another level by passing
ContextualizerInterface::MERGE_FROM_SECOND_LEVEL as an option (3rd argument) to
There is also another option,
ContextualizerInterface::UNIQUE, to be used when you want to ensure your array setting has unique values. It will only work on normal arrays though, not hashes.
A few limitation exist with this scope hash merge:
- Semantic setting name and internal name will be the same (like
foo_settingin the examples above).
- Applicable to 1st level semantic parameter only (i.e. settings right under the SiteAccess name).
- Merge is not recursive. Only 2nd level merge is possible by using
Dedicated mapper object
Instead of passing a callable to
$processor->mapConfig(), an instance of
eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\SiteAccessAware\ConfigurationMapperInterface can be passed.
This can be useful if you have a lot of configuration to map and don't want to pollute your DIC extension class (better for maintenance).
Merging hash values between scopes
As specified above,
$contextualizer->mapConfigArray() is not to be used 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, a dedicated interface can be used:
HookableConfigurationMapperInterface, which defines 2 methods: