[FrameworkBundle] Integrate Configuration\Builder class for config merging and normalization
This fixes some BC problems introduced in f9138d313b
. Some top-level can now be simply enabled by providing true/null in PHP/YAML. Additionally, the Configuration\Builder allows options to be unset by providing "false" (helpful for overriding activation in a previous config file). All options supporting these behaviors can be found in the Configuration.php file (look for canBeUnset() and treatNull/TrueLike()).
Major changes:
* Removed "enabled" option for profiler config. Profiler is now enabled if its config is true, null or a map.
* Restore original config structure for validation namespaces. In PHP/YAML, namespaces are defined under annotations as an alternative to false (disabled) and true/null (enabled). For XML, annotation remains a boolean attribute for validation and a one or more optional namespace tags may appear within <app:validation />. During config normalization, namespace tags under validation will be moved to annotations to conform to the PHP/YAML structure (this occurs transparently to the user).
* Restore behavior for router/templating config sections being optional (as shown in changes to session/validation test fixtures). If either top-level section is unset in the configuration, neither feature will be enabled and the user will no longer receive exceptions due to missing a resource option (router) or engines (templating). Resource/engines will still be properly required if the respective feature is enabled.
* Remove unused router type option from XML config XSD. Type is only relevant for import statements, so this option is likely useless.
Additional small changes:
* Added isset()'s, since config options may be unset
* Wrap registerXxxConfiguration() calls in isset() checks
* Load translation.xml in configLoad(), since it's always required
* Default cache_warmer value (!kernel.debug) is determined via Configuration class
Things to be fixed:
* Configuration\Builder doesn't seem to respect isRequired() and requiresAtLeastOneElement() (or I haven't set it properly); this should replace the need for FrameworkExtension to throw exceptions for bad router/templating configs
* The config nodes for session options don't have the "pdo." prefix, as dots are not allowed in node names. To preserve BC for now, the "pdo." prefix is still allowed (and mandated by XSD) in configuration files. In the future, we may just want to do away with the "pdo." prefix.
* Translator has an "enabled" option. If there's no use case for setting "fallback" independently (when "enabled" is false), perhaps "enabled" should be removed entirely and translator should function like profiler currently does.
* Profiler matcher merging might need to be adjusted so multiple configs simply overwrite matcher instead of merging its array keys.
This commit is contained in:
parent
2b256a0804
commit
099b9dee1f
@ -0,0 +1,220 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Configuration\Builder\NodeBuilder;
|
||||
use Symfony\Component\DependencyInjection\Configuration\Builder\TreeBuilder;
|
||||
|
||||
/**
|
||||
* FrameworkExtension configuration structure.
|
||||
*
|
||||
* @author Jeremy Mikola <jmikola@gmail.com>
|
||||
*/
|
||||
class Configuration
|
||||
{
|
||||
/**
|
||||
* Generates the configuration tree.
|
||||
*
|
||||
* @param boolean $kernelDebug The kernel.debug DIC parameter
|
||||
* @return \Symfony\Component\DependencyInjection\Configuration\NodeInterface
|
||||
*/
|
||||
public function getConfigTree($kernelDebug)
|
||||
{
|
||||
$treeBuilder = new TreeBuilder();
|
||||
$rootNode = $treeBuilder->root('app:config', 'array');
|
||||
|
||||
$rootNode
|
||||
->scalarNode('cache_warmer')->defaultValue(!$kernelDebug)->end()
|
||||
->scalarNode('charset')->end()
|
||||
->scalarNode('document_root')->end()
|
||||
->scalarNode('error_handler')->end()
|
||||
->scalarNode('ide')->end()
|
||||
->booleanNode('test')->end()
|
||||
;
|
||||
|
||||
$this->addCsrfProtectionSection($rootNode);
|
||||
$this->addEsiSection($rootNode);
|
||||
$this->addProfilerSection($rootNode);
|
||||
$this->addRouterSection($rootNode);
|
||||
$this->addSessionSection($rootNode);
|
||||
$this->addTemplatingSection($rootNode);
|
||||
$this->addTranslatorSection($rootNode);
|
||||
$this->addValidationSection($rootNode);
|
||||
|
||||
return $treeBuilder->buildTree();
|
||||
}
|
||||
|
||||
private function addCsrfProtectionSection(NodeBuilder $rootNode)
|
||||
{
|
||||
$rootNode
|
||||
->arrayNode('csrf_protection')
|
||||
->canBeUnset()
|
||||
->treatNullLike(array('enabled' => true))
|
||||
->treatTrueLike(array('enabled' => true))
|
||||
->booleanNode('enabled')->end()
|
||||
->scalarNode('field_name')->end()
|
||||
->scalarNode('secret')->end()
|
||||
->end()
|
||||
;
|
||||
}
|
||||
|
||||
private function addEsiSection(NodeBuilder $rootNode)
|
||||
{
|
||||
$rootNode
|
||||
->arrayNode('esi')
|
||||
->canBeUnset()
|
||||
->treatNullLike(array('enabled' => true))
|
||||
->treatTrueLike(array('enabled' => true))
|
||||
->booleanNode('enabled')->end()
|
||||
->end()
|
||||
;
|
||||
}
|
||||
|
||||
private function addProfilerSection(NodeBuilder $rootNode)
|
||||
{
|
||||
$rootNode
|
||||
->arrayNode('profiler')
|
||||
->canBeUnset()
|
||||
->treatNullLike(array())
|
||||
->treatTrueLike(array())
|
||||
->booleanNode('only_exceptions')->end()
|
||||
->arrayNode('matcher')
|
||||
->canBeUnset()
|
||||
->scalarNode('ip')->end()
|
||||
->scalarNode('path')->end()
|
||||
->scalarNode('service')->end()
|
||||
->end()
|
||||
->end()
|
||||
;
|
||||
}
|
||||
|
||||
private function addRouterSection(NodeBuilder $rootNode)
|
||||
{
|
||||
$rootNode
|
||||
->arrayNode('router')
|
||||
->canBeUnset()
|
||||
->scalarNode('cache_warmer')->end()
|
||||
->scalarNode('resource')->isRequired()->end()
|
||||
->end()
|
||||
;
|
||||
}
|
||||
|
||||
private function addSessionSection(NodeBuilder $rootNode)
|
||||
{
|
||||
$rootNode
|
||||
->arrayNode('session')
|
||||
->canBeUnset()
|
||||
->treatNullLike(array())
|
||||
->treatTrueLike(array())
|
||||
// Strip "pdo." prefix from option keys, since dots cannot appear in node names
|
||||
->beforeNormalization()
|
||||
->ifArray()
|
||||
->then(function($v){
|
||||
foreach ($v as $key => $value) {
|
||||
if (0 === strncmp('pdo.', $key, 4)) {
|
||||
$v[substr($key, 4)] = $value;
|
||||
unset($v[$key]);
|
||||
}
|
||||
}
|
||||
return $v;
|
||||
})
|
||||
->end()
|
||||
->booleanNode('auto_start')->end()
|
||||
->scalarNode('class')->end()
|
||||
->scalarNode('default_locale')->end()
|
||||
->scalarNode('storage_id')->defaultValue('native')->end()
|
||||
// NativeSessionStorage options
|
||||
->scalarNode('name')->end()
|
||||
->scalarNode('lifetime')->end()
|
||||
->scalarNode('path')->end()
|
||||
->scalarNode('domain')->end()
|
||||
->booleanNode('secure')->end()
|
||||
->booleanNode('httponly')->end()
|
||||
// PdoSessionStorage options
|
||||
->scalarNode('db_table')->end()
|
||||
->scalarNode('db_id_col')->end()
|
||||
->scalarNode('db_data_col')->end()
|
||||
->scalarNode('db_time_col')->end()
|
||||
->end()
|
||||
;
|
||||
}
|
||||
|
||||
private function addTemplatingSection(NodeBuilder $rootNode)
|
||||
{
|
||||
$rootNode
|
||||
->arrayNode('templating')
|
||||
->canBeUnset()
|
||||
->scalarNode('assets_version')->end()
|
||||
->scalarNode('assets_base_urls')->end()
|
||||
->scalarNode('cache')->end()
|
||||
->scalarNode('cache_warmer')->end()
|
||||
->fixXmlConfig('engine')
|
||||
->arrayNode('engines')
|
||||
->requiresAtLeastOneElement()
|
||||
->beforeNormalization()
|
||||
->ifTrue(function($v){ return !is_array($v); })
|
||||
->then(function($v){ return array($v); })
|
||||
->end()
|
||||
->prototype('scalar')
|
||||
->beforeNormalization()
|
||||
->ifTrue(function($v) { return is_array($v) && isset($v['id']); })
|
||||
->then(function($v){ return $v['id']; })
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->fixXmlConfig('loader')
|
||||
->arrayNode('loaders')
|
||||
->beforeNormalization()
|
||||
->ifTrue(function($v){ return !is_array($v); })
|
||||
->then(function($v){ return array($v); })
|
||||
->end()
|
||||
->prototype('scalar')->end()
|
||||
->end()
|
||||
->end()
|
||||
;
|
||||
}
|
||||
|
||||
private function addTranslatorSection(NodeBuilder $rootNode)
|
||||
{
|
||||
$rootNode
|
||||
->arrayNode('translator')
|
||||
->canBeUnset()
|
||||
->booleanNode('enabled')->defaultTrue()->end()
|
||||
->scalarNode('fallback')->end()
|
||||
->end()
|
||||
;
|
||||
}
|
||||
|
||||
private function addValidationSection(NodeBuilder $rootNode)
|
||||
{
|
||||
$rootNode
|
||||
->arrayNode('validation')
|
||||
->canBeUnset()
|
||||
// For XML, namespace is a child of validation, so it must be moved under annotations
|
||||
->beforeNormalization()
|
||||
->ifTrue(function($v) { return is_array($v) && !empty($v['annotations']) && !empty($v['namespace']); })
|
||||
->then(function($v){
|
||||
$v['annotations'] = array('namespace' => $v['namespace']);
|
||||
return $v;
|
||||
})
|
||||
->end()
|
||||
->booleanNode('enabled')->end()
|
||||
->arrayNode('annotations')
|
||||
->canBeUnset()
|
||||
->treatNullLike(array())
|
||||
->treatTrueLike(array())
|
||||
->fixXmlConfig('namespace')
|
||||
->arrayNode('namespaces')
|
||||
->containsNameValuePairsWithKeyAttribute('prefix')
|
||||
->prototype('scalar')
|
||||
->beforeNormalization()
|
||||
->ifTrue(function($v) { return is_array($v) && isset($v['namespace']); })
|
||||
->then(function($v){ return $v['namespace']; })
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
;
|
||||
}
|
||||
}
|
@ -15,10 +15,10 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Parameter;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\Configuration\Processor;
|
||||
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
|
||||
use Symfony\Component\DependencyInjection\Resource\FileResource;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\HttpFoundation\RequestMatcher;
|
||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||
|
||||
/**
|
||||
@ -43,16 +43,23 @@ class FrameworkExtension extends Extension
|
||||
$loader->load('form.xml');
|
||||
$loader->load('services.xml');
|
||||
|
||||
// A translator must always be registered (as support is included by
|
||||
// default in the Form component). If disabled, an identity translator
|
||||
// will be used and everything will still work as expected.
|
||||
$loader->load('translation.xml');
|
||||
|
||||
if ($container->getParameter('kernel.debug')) {
|
||||
$loader->load('debug.xml');
|
||||
$container->setDefinition('event_dispatcher', $container->findDefinition('debug.event_dispatcher'));
|
||||
$container->setAlias('debug.event_dispatcher', 'event_dispatcher');
|
||||
}
|
||||
|
||||
$config = $this->mergeConfigs($configs);
|
||||
$processor = new Processor();
|
||||
$configuration = new Configuration();
|
||||
|
||||
$warmer = isset($config['cache_warmer']) ? $config['cache_warmer'] : !$container->getParameter('kernel.debug');
|
||||
$container->setParameter('kernel.cache_warmup', $warmer);
|
||||
$config = $processor->process($configuration->getConfigTree($container->getParameter('kernel.debug')), $configs);
|
||||
|
||||
$container->setParameter('kernel.cache_warmup', $config['cache_warmer']);
|
||||
|
||||
if (isset($config['charset'])) {
|
||||
$container->setParameter('kernel.charset', $config['charset']);
|
||||
@ -80,19 +87,42 @@ class FrameworkExtension extends Extension
|
||||
$container->setParameter('debug.file_link_format', $pattern);
|
||||
}
|
||||
|
||||
if ($config['test']) {
|
||||
if (isset($config['test']) && $config['test']) {
|
||||
$loader->load('test.xml');
|
||||
$config['session']['storage_id'] = 'array';
|
||||
}
|
||||
|
||||
$this->registerCsrfProtectionConfiguration($config['csrf_protection'], $container);
|
||||
$this->registerEsiConfiguration($config['esi'], $loader);
|
||||
$this->registerProfilerConfiguration($config['profiler'], $container, $loader);
|
||||
$this->registerRouterConfiguration($config['router'], $container, $loader);
|
||||
$this->registerSessionConfiguration($config['session'], $container, $loader);
|
||||
$this->registerTemplatingConfiguration($config['templating'], $container, $loader);
|
||||
$this->registerTranslatorConfiguration($config['translator'], $container, $loader);
|
||||
$this->registerValidationConfiguration($config['validation'], $container, $loader);
|
||||
if (isset($config['csrf_protection'])) {
|
||||
$this->registerCsrfProtectionConfiguration($config['csrf_protection'], $container);
|
||||
}
|
||||
|
||||
if (isset($config['esi'])) {
|
||||
$this->registerEsiConfiguration($config['esi'], $loader);
|
||||
}
|
||||
|
||||
if (isset($config['profiler'])) {
|
||||
$this->registerProfilerConfiguration($config['profiler'], $container, $loader);
|
||||
}
|
||||
|
||||
if (isset($config['router'])) {
|
||||
$this->registerRouterConfiguration($config['router'], $container, $loader);
|
||||
}
|
||||
|
||||
if (isset($config['session'])) {
|
||||
$this->registerSessionConfiguration($config['session'], $container, $loader);
|
||||
}
|
||||
|
||||
if (isset($config['templating'])) {
|
||||
$this->registerTemplatingConfiguration($config['templating'], $container, $loader);
|
||||
}
|
||||
|
||||
if (isset($config['translator'])) {
|
||||
$this->registerTranslatorConfiguration($config['translator'], $container);
|
||||
}
|
||||
|
||||
if (isset($config['validation'])) {
|
||||
$this->registerValidationConfiguration($config['validation'], $container, $loader);
|
||||
}
|
||||
|
||||
$this->addClassesToCompile(array(
|
||||
'Symfony\\Component\\HttpFoundation\\ParameterBag',
|
||||
@ -119,195 +149,13 @@ class FrameworkExtension extends Extension
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges a set of configuration arrays and returns the result.
|
||||
*
|
||||
* This method internally specifies the available options and their
|
||||
* default values. Given an array of configuration arrays, this method
|
||||
* intelligently merges those configuration values and returns the final,
|
||||
* flattened product.
|
||||
*
|
||||
* @param array $configs An array of configuration arrays to merge
|
||||
* @return array The merged configuration array
|
||||
*/
|
||||
protected function mergeConfigs(array $configs)
|
||||
{
|
||||
$defaultOptions = array(
|
||||
'cache_warmer' => null,
|
||||
'charset' => null,
|
||||
'csrf_protection' => array(
|
||||
'enabled' => null,
|
||||
'field_name' => null,
|
||||
'secret' => null,
|
||||
),
|
||||
'document_root' => null,
|
||||
'error_handler' => null,
|
||||
// TODO: consolidate into a scalar unless future options are planned
|
||||
'esi' => array(
|
||||
'enabled' => null,
|
||||
),
|
||||
'ide' => null,
|
||||
'profiler' => array(
|
||||
'enabled' => false,
|
||||
'only_exceptions' => null,
|
||||
'matcher' => array(
|
||||
'ip' => null,
|
||||
'path' => null,
|
||||
'service' => null,
|
||||
),
|
||||
),
|
||||
'router' => array(
|
||||
'cache_warmer' => null,
|
||||
'resource' => null,
|
||||
),
|
||||
'session' => array(
|
||||
'auto_start' => null,
|
||||
'class' => null,
|
||||
'default_locale' => null,
|
||||
'storage_id' => 'native',
|
||||
// NativeSessionStorage options
|
||||
'name' => null,
|
||||
'lifetime' => null,
|
||||
'path' => null,
|
||||
'domain' => null,
|
||||
'secure' => null,
|
||||
'httponly' => null,
|
||||
// PdoSessionStorage options
|
||||
'pdo.db_table' => null,
|
||||
'pdo.db_id_col' => null,
|
||||
'pdo.db_data_col' => null,
|
||||
'pdo.db_time_col' => null,
|
||||
),
|
||||
'templating' => array(
|
||||
'assets_version' => null,
|
||||
'assets_base_urls' => null,
|
||||
'cache' => null,
|
||||
'cache_warmer' => null,
|
||||
'engines' => array(),
|
||||
'loaders' => array(),
|
||||
),
|
||||
'test' => null,
|
||||
'translator' => array(
|
||||
'enabled' => null,
|
||||
'fallback' => null,
|
||||
),
|
||||
'validation' => array(
|
||||
'enabled' => null,
|
||||
'annotations' => null,
|
||||
'namespaces' => array(),
|
||||
),
|
||||
);
|
||||
|
||||
$mergedConfig = $defaultOptions;
|
||||
|
||||
foreach ($configs as $config) {
|
||||
$config = $this->normalizeKeys($config);
|
||||
|
||||
if (isset($config['profiler'])) {
|
||||
$config['profiler']['enabled'] = true;
|
||||
}
|
||||
|
||||
if (isset($config['templating']) && is_array($config['templating'])) {
|
||||
$config['templating']['engines'] = $this->normalizeConfig($config['templating'], 'engine');
|
||||
$config['templating']['loaders'] = $this->normalizeConfig($config['templating'], 'loader');
|
||||
unset($config['templating']['engine'], $config['templating']['loader']);
|
||||
}
|
||||
|
||||
if (isset($config['validation']) && is_array($config['validation'])) {
|
||||
$config['validation']['namespaces'] = $this->normalizeConfig($config['validation'], 'namespace');
|
||||
unset($config['validation']['namespace']);
|
||||
}
|
||||
|
||||
$mergedConfig = $this->mergeOptions($mergedConfig, $config, $defaultOptions);
|
||||
}
|
||||
|
||||
return $mergedConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges a single level of configuration options.
|
||||
*
|
||||
* @param array $current The value of the options before merging
|
||||
* @param array $new The new values to be merged
|
||||
* @param array $default The corresponding default values for the option level
|
||||
* @param string $basePath Base property path for the option level
|
||||
* @return array The merged options
|
||||
* @throws InvalidArgumentException When an unsupported is found
|
||||
*/
|
||||
protected function mergeOptions(array $current, array $new, array $default, $basePath = null)
|
||||
{
|
||||
if ($unsupportedOptions = array_diff_key($new, $default)) {
|
||||
throw new \InvalidArgumentException('The following options are not supported: '.implode(', ', array_keys($unsupportedOptions)));
|
||||
}
|
||||
|
||||
foreach ($default as $key => $defaultValue) {
|
||||
if (array_key_exists($key, $new)) {
|
||||
$optionPath = $basePath ? $basePath.'.'.$key : $key;
|
||||
$current[$key] = $this->mergeOptionValue($current[$key], $new[$key], $defaultValue, $optionPath);
|
||||
}
|
||||
}
|
||||
|
||||
return $current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges an option value.
|
||||
*
|
||||
* @param mixed $current The value of the option before merging
|
||||
* @param mixed $new The new value to be merged
|
||||
* @param mixed $default The corresponding default value for the option
|
||||
* @param string $optionPath Property path for the option
|
||||
* @return mixed The merged value
|
||||
* @throws InvalidArgumentException When an invalid option is found
|
||||
*/
|
||||
protected function mergeOptionValue($current, $new, $defaultValue, $optionPath)
|
||||
{
|
||||
// Allow profiler.matcher array to be overridden with any value. This
|
||||
// option requires no merge logic and would not benefit from the type
|
||||
// validation below.
|
||||
if ('profiler.matcher' === $optionPath) {
|
||||
return $new;
|
||||
}
|
||||
|
||||
// Ensure that the new value's type is an array if expected
|
||||
if (is_array($defaultValue) && !is_array($new)) {
|
||||
throw new \InvalidArgumentException(sprintf('Expected array type for option "%s", %s given', $optionPath, gettype($new)));
|
||||
}
|
||||
|
||||
switch ($optionPath) {
|
||||
// Engine options are arrays of strings, although XML configurations
|
||||
// store the engine ID in an attribute. Dedupe after merging.
|
||||
case 'templating.engines':
|
||||
$new = array_map(function($engine) { return is_array($engine) ? $engine['id'] : $engine; }, $new);
|
||||
return array_unique(array_merge($current, $new));
|
||||
|
||||
// Loader options are arrays of strings, so dedupe after merging
|
||||
case 'templating.loaders':
|
||||
return array_unique(array_merge($current, $new));
|
||||
|
||||
// The namespace options' keys are used for the annotation prefix
|
||||
// and are significant, so do not dedupe array values. Be mindful
|
||||
// of XML configurations, which store the prefix in an attribute.
|
||||
case 'validation.namespaces':
|
||||
foreach ($new as $prefix => $namespace) {
|
||||
if (is_array($namespace)) {
|
||||
$new[$namespace['prefix']] = $namespace['namespace'];
|
||||
unset($new[$prefix]);
|
||||
}
|
||||
}
|
||||
return array_merge($current, $new);
|
||||
}
|
||||
|
||||
return is_array($defaultValue) ? $this->mergeOptions($current, $new, $defaultValue, $optionPath) : $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the CSRF protection configuration.
|
||||
*
|
||||
* @param array $config A CSRF protection configuration array
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||
*/
|
||||
protected function registerCsrfProtectionConfiguration(array $config, ContainerBuilder $container)
|
||||
private function registerCsrfProtectionConfiguration(array $config, ContainerBuilder $container)
|
||||
{
|
||||
foreach (array('enabled', 'field_name', 'secret') as $key) {
|
||||
if (isset($config[$key])) {
|
||||
@ -322,9 +170,9 @@ class FrameworkExtension extends Extension
|
||||
* @param array $config An ESI configuration array
|
||||
* @param XmlFileLoader $loader An XmlFileLoader instance
|
||||
*/
|
||||
protected function registerEsiConfiguration(array $config, XmlFileLoader $loader)
|
||||
private function registerEsiConfiguration(array $config, XmlFileLoader $loader)
|
||||
{
|
||||
if ($config['enabled']) {
|
||||
if (isset($config['enabled']) && $config['enabled']) {
|
||||
$loader->load('esi.xml');
|
||||
}
|
||||
}
|
||||
@ -336,12 +184,8 @@ class FrameworkExtension extends Extension
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||
* @param XmlFileLoader $loader An XmlFileLoader instance
|
||||
*/
|
||||
protected function registerProfilerConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
private function registerProfilerConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
{
|
||||
if (!$config['enabled']) {
|
||||
return;
|
||||
}
|
||||
|
||||
$loader->load('profiling.xml');
|
||||
$loader->load('collectors.xml');
|
||||
|
||||
@ -349,7 +193,7 @@ class FrameworkExtension extends Extension
|
||||
$container->setParameter('profiler_listener.only_exceptions', $config['only_exceptions']);
|
||||
}
|
||||
|
||||
if ($config['matcher']) {
|
||||
if (isset($config['matcher'])) {
|
||||
if (isset($config['matcher']['service'])) {
|
||||
$container->setAlias('profiler.request_matcher', $config['matcher']['service']);
|
||||
} elseif (isset($config['matcher']['ip']) || isset($config['matcher']['path'])) {
|
||||
@ -373,8 +217,9 @@ class FrameworkExtension extends Extension
|
||||
* @param array $config A router configuration array
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||
* @param XmlFileLoader $loader An XmlFileLoader instance
|
||||
* @throws \InvalidArgumentException if resource option is not set
|
||||
*/
|
||||
protected function registerRouterConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
private function registerRouterConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
{
|
||||
$loader->load('routing.xml');
|
||||
|
||||
@ -384,7 +229,7 @@ class FrameworkExtension extends Extension
|
||||
|
||||
$container->setParameter('routing.resource', $config['resource']);
|
||||
|
||||
if ($config['cache_warmer']) {
|
||||
if (isset($config['cache_warmer']) && $config['cache_warmer']) {
|
||||
$container->getDefinition('router.cache_warmer')->addTag('kernel.cache_warmer');
|
||||
$container->setAlias('router', 'router.cached');
|
||||
}
|
||||
@ -395,7 +240,7 @@ class FrameworkExtension extends Extension
|
||||
'Symfony\\Component\\Routing\\Matcher\\UrlMatcher',
|
||||
'Symfony\\Component\\Routing\\Generator\\UrlGeneratorInterface',
|
||||
'Symfony\\Component\\Routing\\Generator\\UrlGenerator',
|
||||
$container->findDefinition('router')->getClass()
|
||||
$container->findDefinition('router')->getClass(),
|
||||
));
|
||||
}
|
||||
|
||||
@ -406,11 +251,11 @@ class FrameworkExtension extends Extension
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||
* @param XmlFileLoader $loader An XmlFileLoader instance
|
||||
*/
|
||||
protected function registerSessionConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
private function registerSessionConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
{
|
||||
$loader->load('session.xml');
|
||||
|
||||
if ($config['auto_start']) {
|
||||
if (isset($config['auto_start']) && $config['auto_start']) {
|
||||
$container->getDefinition('session')->addMethodCall('start');
|
||||
}
|
||||
|
||||
@ -425,9 +270,9 @@ class FrameworkExtension extends Extension
|
||||
$container->setAlias('session.storage', 'session.storage.'.$config['storage_id']);
|
||||
|
||||
$options = $container->getParameter('session.storage.'.$config['storage_id'].'.options');
|
||||
foreach (array('name', 'lifetime', 'path', 'domain', 'secure', 'httponly', 'pdo.db_table', 'pdo.db_id_col', 'pdo.db_data_col', 'pdo.db_time_col') as $key) {
|
||||
foreach (array('name', 'lifetime', 'path', 'domain', 'secure', 'httponly', 'db_table', 'db_id_col', 'db_data_col', 'db_time_col') as $key) {
|
||||
if (isset($config[$key])) {
|
||||
$options[str_replace('pdo.', '', $key)] = $config[$key];
|
||||
$options[$key] = $config[$key];
|
||||
}
|
||||
}
|
||||
$container->setParameter('session.storage.'.$config['storage_id'].'.options', $options);
|
||||
@ -445,8 +290,9 @@ class FrameworkExtension extends Extension
|
||||
* @param array $config A templating configuration array
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||
* @param XmlFileLoader $loader An XmlFileLoader instance
|
||||
* @throws \LogicException if no engines are defined
|
||||
*/
|
||||
protected function registerTemplatingConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
private function registerTemplatingConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
{
|
||||
$loader->load('templating.xml');
|
||||
$loader->load('templating_php.xml');
|
||||
@ -463,7 +309,7 @@ class FrameworkExtension extends Extension
|
||||
$container->setParameter('templating.assets.base_urls', $config['assets_base_urls']);
|
||||
}
|
||||
|
||||
if ($config['loaders']) {
|
||||
if (isset($config['loaders'])) {
|
||||
$loaders = array_map(function($loader) { return new Reference($loader); }, $config['loaders']);
|
||||
|
||||
// Use a deligation unless only a single loader was registered
|
||||
@ -475,7 +321,7 @@ class FrameworkExtension extends Extension
|
||||
}
|
||||
}
|
||||
|
||||
if ($config['cache']) {
|
||||
if (isset($config['cache'])) {
|
||||
// Wrap the existing loader with cache (must happen after loaders are registered)
|
||||
$container->setDefinition('templating.loader.wrapped', $container->findDefinition('templating.loader'));
|
||||
$container->setDefinition('templating.loader', $container->getDefinition('templating.loader.cache'));
|
||||
@ -484,12 +330,12 @@ class FrameworkExtension extends Extension
|
||||
$container->setParameter('templating.loader.cache.path', null);
|
||||
}
|
||||
|
||||
if ($config['cache_warmer']) {
|
||||
if (isset($config['cache_warmer'])) {
|
||||
$container->getDefinition('templating.cache_warmer.template_paths')->addTag('kernel.cache_warmer');
|
||||
$container->setAlias('templating.locator', 'templating.locator.cached');
|
||||
}
|
||||
|
||||
if (!$config['engines']) {
|
||||
if (empty($config['engines'])) {
|
||||
throw new \LogicException('You must register at least one templating engine.');
|
||||
}
|
||||
|
||||
@ -523,26 +369,17 @@ class FrameworkExtension extends Extension
|
||||
$container->getDefinition('templating.engine.delegating')->setArgument(1, $engines);
|
||||
$container->setAlias('templating', 'templating.engine.delegating');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the translator configuration.
|
||||
*
|
||||
* A translator must always be registered (as support is included by default
|
||||
* in the forms component). If disabled, an identity translator will be
|
||||
* used and everything will still work as expected.
|
||||
*
|
||||
* @param array $config A translator configuration array
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||
* @param XmlFileLoader $loader An XmlFileLoader instance
|
||||
*/
|
||||
protected function registerTranslatorConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
private function registerTranslatorConfiguration(array $config, ContainerBuilder $container)
|
||||
{
|
||||
$loader->load('translation.xml');
|
||||
|
||||
if ($config['enabled']) {
|
||||
if (isset($config['enabled']) && $config['enabled']) {
|
||||
// Use the "real" translator instead of the identity default
|
||||
$container->setDefinition('translator', $container->findDefinition('translator.real'));
|
||||
|
||||
@ -585,65 +422,67 @@ class FrameworkExtension extends Extension
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||
* @param XmlFileLoader $loader An XmlFileLoader instance
|
||||
*/
|
||||
protected function registerValidationConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
private function registerValidationConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
{
|
||||
if ($config['enabled']) {
|
||||
$loader->load('validator.xml');
|
||||
if (empty($config['enabled'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$xmlMappingFiles = array();
|
||||
$yamlMappingFiles = array();
|
||||
$loader->load('validator.xml');
|
||||
|
||||
// Include default entries from the framework
|
||||
$xmlMappingFiles[] = __DIR__.'/../../../Component/Form/Resources/config/validation.xml';
|
||||
$xmlMappingFiles = array();
|
||||
$yamlMappingFiles = array();
|
||||
|
||||
foreach ($container->getParameter('kernel.bundles') as $bundle) {
|
||||
$reflection = new \ReflectionClass($bundle);
|
||||
if (file_exists($file = dirname($reflection->getFilename()).'/Resources/config/validation.xml')) {
|
||||
$xmlMappingFiles[] = realpath($file);
|
||||
}
|
||||
if (file_exists($file = dirname($reflection->getFilename()).'/Resources/config/validation.yml')) {
|
||||
$yamlMappingFiles[] = realpath($file);
|
||||
}
|
||||
// Include default entries from the framework
|
||||
$xmlMappingFiles[] = __DIR__.'/../../../Component/Form/Resources/config/validation.xml';
|
||||
|
||||
foreach ($container->getParameter('kernel.bundles') as $bundle) {
|
||||
$reflection = new \ReflectionClass($bundle);
|
||||
if (file_exists($file = dirname($reflection->getFilename()).'/Resources/config/validation.xml')) {
|
||||
$xmlMappingFiles[] = realpath($file);
|
||||
}
|
||||
if (file_exists($file = dirname($reflection->getFilename()).'/Resources/config/validation.yml')) {
|
||||
$yamlMappingFiles[] = realpath($file);
|
||||
}
|
||||
}
|
||||
|
||||
$xmlFilesLoader = new Definition('%validator.mapping.loader.xml_files_loader.class%', array($xmlMappingFiles));
|
||||
$xmlFilesLoader->setPublic(false);
|
||||
|
||||
$yamlFilesLoader = new Definition('%validator.mapping.loader.yaml_files_loader.class%', array($yamlMappingFiles));
|
||||
$yamlFilesLoader->setPublic(false);
|
||||
|
||||
$container->setDefinition('validator.mapping.loader.xml_files_loader', $xmlFilesLoader);
|
||||
$container->setDefinition('validator.mapping.loader.yaml_files_loader', $yamlFilesLoader);
|
||||
|
||||
foreach ($xmlMappingFiles as $file) {
|
||||
$container->addResource(new FileResource($file));
|
||||
}
|
||||
|
||||
foreach ($yamlMappingFiles as $file) {
|
||||
$container->addResource(new FileResource($file));
|
||||
}
|
||||
|
||||
if (isset($config['annotations'])) {
|
||||
// Register prefixes for constraint namespaces
|
||||
if (!empty($config['annotations']['namespaces'])) {
|
||||
$container->setParameter('validator.annotations.namespaces', array_merge(
|
||||
$container->getParameter('validator.annotations.namespaces'),
|
||||
$config['annotations']['namespaces']
|
||||
));
|
||||
}
|
||||
|
||||
$xmlFilesLoader = new Definition('%validator.mapping.loader.xml_files_loader.class%', array($xmlMappingFiles));
|
||||
$xmlFilesLoader->setPublic(false);
|
||||
// Register annotation loader
|
||||
$annotationLoader = new Definition('%validator.mapping.loader.annotation_loader.class%');
|
||||
$annotationLoader->setPublic(false);
|
||||
$annotationLoader->addArgument(new Parameter('validator.annotations.namespaces'));
|
||||
|
||||
$yamlFilesLoader = new Definition('%validator.mapping.loader.yaml_files_loader.class%', array($yamlMappingFiles));
|
||||
$yamlFilesLoader->setPublic(false);
|
||||
$container->setDefinition('validator.mapping.loader.annotation_loader', $annotationLoader);
|
||||
|
||||
$container->setDefinition('validator.mapping.loader.xml_files_loader', $xmlFilesLoader);
|
||||
$container->setDefinition('validator.mapping.loader.yaml_files_loader', $yamlFilesLoader);
|
||||
|
||||
foreach ($xmlMappingFiles as $file) {
|
||||
$container->addResource(new FileResource($file));
|
||||
}
|
||||
|
||||
foreach ($yamlMappingFiles as $file) {
|
||||
$container->addResource(new FileResource($file));
|
||||
}
|
||||
|
||||
if ($config['annotations']) {
|
||||
// Register prefixes for constraint namespaces
|
||||
if ($namespaces = $config['namespaces']) {
|
||||
$container->setParameter('validator.annotations.namespaces', array_merge(
|
||||
$container->getParameter('validator.annotations.namespaces'),
|
||||
$namespaces
|
||||
));
|
||||
}
|
||||
|
||||
// Register annotation loader
|
||||
$annotationLoader = new Definition('%validator.mapping.loader.annotation_loader.class%');
|
||||
$annotationLoader->setPublic(false);
|
||||
$annotationLoader->addArgument(new Parameter('validator.annotations.namespaces'));
|
||||
|
||||
$container->setDefinition('validator.mapping.loader.annotation_loader', $annotationLoader);
|
||||
|
||||
$loaderChain = $container->getDefinition('validator.mapping.loader.loader_chain');
|
||||
$arguments = $loaderChain->getArguments();
|
||||
array_unshift($arguments[0], new Reference('validator.mapping.loader.annotation_loader'));
|
||||
$loaderChain->setArguments($arguments);
|
||||
}
|
||||
$loaderChain = $container->getDefinition('validator.mapping.loader.loader_chain');
|
||||
$arguments = $loaderChain->getArguments();
|
||||
array_unshift($arguments[0], new Reference('validator.mapping.loader.annotation_loader'));
|
||||
$loaderChain->setArguments($arguments);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,6 @@
|
||||
|
||||
<xsd:complexType name="router">
|
||||
<xsd:attribute name="resource" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="cache-warmer" type="cache_warmer" />
|
||||
</xsd:complexType>
|
||||
|
||||
|
@ -1,9 +1,6 @@
|
||||
<?php
|
||||
|
||||
$container->loadFromExtension('app', 'config', array(
|
||||
'router' => array(
|
||||
'resource' => '%kernel.root_dir%/config/routing.xml',
|
||||
),
|
||||
'session' => array(
|
||||
'storage_id' => 'pdo',
|
||||
'pdo.db_table' => 'table',
|
||||
@ -11,7 +8,4 @@ $container->loadFromExtension('app', 'config', array(
|
||||
'pdo.db_data_col' => 'data',
|
||||
'pdo.db_time_col' => 'time',
|
||||
),
|
||||
'templating' => array(
|
||||
'engine' => 'php'
|
||||
),
|
||||
));
|
||||
|
@ -1,17 +1,12 @@
|
||||
<?php
|
||||
|
||||
$container->loadFromExtension('app', 'config', array(
|
||||
'router' => array(
|
||||
'resource' => '%kernel.root_dir%/config/routing.xml',
|
||||
),
|
||||
'validation' => array(
|
||||
'enabled' => true,
|
||||
'annotations' => true,
|
||||
'namespaces' => array(
|
||||
'app' => 'Application\\Validator\\Constraints\\',
|
||||
'annotations' => array(
|
||||
'namespaces' => array(
|
||||
'app' => 'Application\\Validator\\Constraints\\',
|
||||
),
|
||||
),
|
||||
),
|
||||
'templating' => array(
|
||||
'engine' => 'php'
|
||||
),
|
||||
));
|
||||
|
@ -7,10 +7,6 @@
|
||||
http://www.symfony-project.org/schema/dic/symfony http://www.symfony-project.org/schema/dic/symfony/symfony-1.0.xsd">
|
||||
|
||||
<app:config>
|
||||
<app:router resource="%kernel.root_dir%/config/routing.xml" />
|
||||
<app:session storage-id="pdo" pdo.db-table="table" pdo.db-id-col="id" pdo.db-data-col="data" pdo.db-time-col="time" />
|
||||
<app:templating>
|
||||
<app:engine id="php" />
|
||||
</app:templating>
|
||||
</app:config>
|
||||
</container>
|
||||
|
@ -7,12 +7,8 @@
|
||||
http://www.symfony-project.org/schema/dic/symfony http://www.symfony-project.org/schema/dic/symfony/symfony-1.0.xsd">
|
||||
|
||||
<app:config>
|
||||
<app:router resource="%kernel.root_dir%/config/routing.xml" />
|
||||
<app:validation enabled="true" annotations="true">
|
||||
<app:namespace prefix="app" namespace="Application\Validator\Constraints\" />
|
||||
</app:validation>
|
||||
<app:templating>
|
||||
<app:engine id="php" />
|
||||
</app:templating>
|
||||
</app:config>
|
||||
</container>
|
||||
|
@ -28,7 +28,7 @@ app.config:
|
||||
engines: [php, twig]
|
||||
loader: [loader.foo, loader.bar]
|
||||
translator:
|
||||
enabled: true,
|
||||
enabled: true
|
||||
fallback: fr
|
||||
validation:
|
||||
enabled: true
|
||||
|
@ -1,11 +1,7 @@
|
||||
app.config:
|
||||
router:
|
||||
resource: %kernel.root_dir%/config/routing.xml
|
||||
session:
|
||||
storage_id: pdo
|
||||
pdo.db_table: table
|
||||
pdo.db_id_col: id
|
||||
pdo.db_data_col: data
|
||||
pdo.db_time_col: time
|
||||
templating:
|
||||
engine: php
|
||||
|
@ -1,10 +1,6 @@
|
||||
app.config:
|
||||
router:
|
||||
resource: %kernel.root_dir%/config/routing.xml
|
||||
validation:
|
||||
enabled: true
|
||||
annotations: true
|
||||
namespaces:
|
||||
app: Application\Validator\Constraints\
|
||||
templating:
|
||||
engine: php
|
||||
annotations:
|
||||
namespaces:
|
||||
app: Application\Validator\Constraints\
|
||||
|
Reference in New Issue
Block a user