vendor/doctrine/doctrine-bundle/DependencyInjection/Configuration.php line 345

Open in your IDE?
  1. <?php
  2. namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection;
  3. use Doctrine\ORM\EntityManager;
  4. use ReflectionClass;
  5. use Symfony\Component\Config\Definition\BaseNode;
  6. use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
  7. use Symfony\Component\Config\Definition\Builder\NodeDefinition;
  8. use Symfony\Component\Config\Definition\Builder\TreeBuilder;
  9. use Symfony\Component\Config\Definition\ConfigurationInterface;
  10. use Symfony\Component\DependencyInjection\Exception\LogicException;
  11. use function array_key_exists;
  12. use function assert;
  13. use function class_exists;
  14. use function constant;
  15. use function in_array;
  16. use function is_array;
  17. use function is_bool;
  18. use function is_int;
  19. use function is_string;
  20. use function key;
  21. use function method_exists;
  22. use function reset;
  23. use function strlen;
  24. use function strpos;
  25. use function strtoupper;
  26. use function substr;
  27. use function trigger_error;
  28. use const E_USER_DEPRECATED;
  29. /**
  30.  * This class contains the configuration information for the bundle
  31.  *
  32.  * This information is solely responsible for how the different configuration
  33.  * sections are normalized, and merged.
  34.  */
  35. class Configuration implements ConfigurationInterface
  36. {
  37.     /** @var bool */
  38.     private $debug;
  39.     /**
  40.      * @param bool $debug Whether to use the debug mode
  41.      */
  42.     public function __construct(bool $debug)
  43.     {
  44.         $this->debug $debug;
  45.     }
  46.     public function getConfigTreeBuilder(): TreeBuilder
  47.     {
  48.         $treeBuilder = new TreeBuilder('doctrine');
  49.         $rootNode    $treeBuilder->getRootNode();
  50.         $this->addDbalSection($rootNode);
  51.         $this->addOrmSection($rootNode);
  52.         return $treeBuilder;
  53.     }
  54.     /**
  55.      * Add DBAL section to configuration tree
  56.      */
  57.     private function addDbalSection(ArrayNodeDefinition $node): void
  58.     {
  59.         $node
  60.             ->children()
  61.             ->arrayNode('dbal')
  62.                 ->beforeNormalization()
  63.                     ->ifTrue(static function ($v) {
  64.                         return is_array($v) && ! array_key_exists('connections'$v) && ! array_key_exists('connection'$v);
  65.                     })
  66.                     ->then(static function ($v) {
  67.                         // Key that should not be rewritten to the connection config
  68.                         $excludedKeys = ['default_connection' => true'types' => true'type' => true];
  69.                         $connection   = [];
  70.                         foreach ($v as $key => $value) {
  71.                             if (isset($excludedKeys[$key])) {
  72.                                 continue;
  73.                             }
  74.                             $connection[$key] = $v[$key];
  75.                             unset($v[$key]);
  76.                         }
  77.                         $v['default_connection'] = isset($v['default_connection']) ? (string) $v['default_connection'] : 'default';
  78.                         $v['connections']        = [$v['default_connection'] => $connection];
  79.                         return $v;
  80.                     })
  81.                 ->end()
  82.                 ->children()
  83.                     ->scalarNode('default_connection')->end()
  84.                 ->end()
  85.                 ->fixXmlConfig('type')
  86.                 ->children()
  87.                     ->arrayNode('types')
  88.                         ->useAttributeAsKey('name')
  89.                         ->prototype('array')
  90.                             ->beforeNormalization()
  91.                                 ->ifString()
  92.                                 ->then(static function ($v) {
  93.                                     return ['class' => $v];
  94.                                 })
  95.                             ->end()
  96.                             ->children()
  97.                                 ->scalarNode('class')->isRequired()->end()
  98.                                 ->booleanNode('commented')
  99.                                     ->setDeprecated(
  100.                                         ...$this->getDeprecationMsg('The doctrine-bundle type commenting features were removed; the corresponding config parameter was deprecated in 2.0 and will be dropped in 3.0.''2.0')
  101.                                     )
  102.                                 ->end()
  103.                             ->end()
  104.                         ->end()
  105.                     ->end()
  106.                 ->end()
  107.                 ->fixXmlConfig('connection')
  108.                 ->append($this->getDbalConnectionsNode())
  109.             ->end();
  110.     }
  111.     /**
  112.      * Return the dbal connections node
  113.      */
  114.     private function getDbalConnectionsNode(): ArrayNodeDefinition
  115.     {
  116.         $treeBuilder = new TreeBuilder('connections');
  117.         $node        $treeBuilder->getRootNode();
  118.         $connectionNode $node
  119.             ->requiresAtLeastOneElement()
  120.             ->useAttributeAsKey('name')
  121.             ->prototype('array');
  122.         assert($connectionNode instanceof ArrayNodeDefinition);
  123.         $this->configureDbalDriverNode($connectionNode);
  124.         $connectionNode
  125.             ->fixXmlConfig('option')
  126.             ->fixXmlConfig('mapping_type')
  127.             ->fixXmlConfig('slave')
  128.             ->fixXmlConfig('replica')
  129.             ->fixXmlConfig('shard')
  130.             ->fixXmlConfig('default_table_option')
  131.             ->children()
  132.                 ->scalarNode('driver')->defaultValue('pdo_mysql')->end()
  133.                 ->scalarNode('platform_service')->end()
  134.                 ->booleanNode('auto_commit')->end()
  135.                 ->scalarNode('schema_filter')->end()
  136.                 ->booleanNode('logging')->defaultValue($this->debug)->end()
  137.                 ->booleanNode('profiling')->defaultValue($this->debug)->end()
  138.                 ->booleanNode('profiling_collect_backtrace')
  139.                     ->defaultValue(false)
  140.                     ->info('Enables collecting backtraces when profiling is enabled')
  141.                 ->end()
  142.                 ->booleanNode('profiling_collect_schema_errors')
  143.                     ->defaultValue(true)
  144.                     ->info('Enables collecting schema errors when profiling is enabled')
  145.                 ->end()
  146.                 ->scalarNode('server_version')->end()
  147.                 ->scalarNode('driver_class')->end()
  148.                 ->scalarNode('wrapper_class')->end()
  149.                 ->scalarNode('shard_manager_class')->end()
  150.                 ->scalarNode('shard_choser')->end()
  151.                 ->scalarNode('shard_choser_service')->end()
  152.                 ->booleanNode('keep_slave')
  153.                     ->setDeprecated(
  154.                         ...$this->getDeprecationMsg('The "keep_slave" configuration key is deprecated since doctrine-bundle 2.2. Use the "keep_replica" configuration key instead.''2.2')
  155.                     )
  156.                 ->end()
  157.                 ->booleanNode('keep_replica')->end()
  158.                 ->arrayNode('options')
  159.                     ->useAttributeAsKey('key')
  160.                     ->prototype('variable')->end()
  161.                 ->end()
  162.                 ->arrayNode('mapping_types')
  163.                     ->useAttributeAsKey('name')
  164.                     ->prototype('scalar')->end()
  165.                 ->end()
  166.                 ->arrayNode('default_table_options')
  167.                     ->info("This option is used by the schema-tool and affects generated SQL. Possible keys include 'charset','collate', and 'engine'.")
  168.                     ->useAttributeAsKey('name')
  169.                     ->prototype('scalar')->end()
  170.                 ->end()
  171.             ->end();
  172.         // dbal < 2.11
  173.         $slaveNode $connectionNode
  174.             ->children()
  175.                 ->arrayNode('slaves')
  176.                     ->setDeprecated(
  177.                         ...$this->getDeprecationMsg('The "slaves" configuration key will be renamed to "replicas" in doctrine-bundle 3.0. "slaves" is deprecated since doctrine-bundle 2.2.''2.2')
  178.                     )
  179.                     ->useAttributeAsKey('name')
  180.                     ->prototype('array');
  181.         $this->configureDbalDriverNode($slaveNode);
  182.         // dbal >= 2.11
  183.         $replicaNode $connectionNode
  184.             ->children()
  185.                 ->arrayNode('replicas')
  186.                     ->useAttributeAsKey('name')
  187.                     ->prototype('array');
  188.         $this->configureDbalDriverNode($replicaNode);
  189.         $shardNode $connectionNode
  190.             ->children()
  191.                 ->arrayNode('shards')
  192.                     ->prototype('array');
  193.         // TODO: Remove when https://github.com/psalm/psalm-plugin-symfony/pull/168 is released
  194.         assert($shardNode instanceof ArrayNodeDefinition);
  195.         $shardNode
  196.             ->children()
  197.                 ->integerNode('id')
  198.                     ->min(1)
  199.                     ->isRequired()
  200.                 ->end()
  201.             ->end();
  202.         $this->configureDbalDriverNode($shardNode);
  203.         return $node;
  204.     }
  205.     /**
  206.      * Adds config keys related to params processed by the DBAL drivers
  207.      *
  208.      * These keys are available for replica configurations too.
  209.      */
  210.     private function configureDbalDriverNode(ArrayNodeDefinition $node): void
  211.     {
  212.         $node
  213.             ->children()
  214.                 ->scalarNode('url')->info('A URL with connection information; any parameter value parsed from this string will override explicitly set parameters')->end()
  215.                 ->scalarNode('dbname')->end()
  216.                 ->scalarNode('host')->info('Defaults to "localhost" at runtime.')->end()
  217.                 ->scalarNode('port')->info('Defaults to null at runtime.')->end()
  218.                 ->scalarNode('user')->info('Defaults to "root" at runtime.')->end()
  219.                 ->scalarNode('password')->info('Defaults to null at runtime.')->end()
  220.                 ->booleanNode('override_url')->defaultValue(false)->info('Allows overriding parts of the "url" parameter with dbname, host, port, user, and/or password parameters.')->end()
  221.                 ->scalarNode('application_name')->end()
  222.                 ->scalarNode('charset')->end()
  223.                 ->scalarNode('path')->end()
  224.                 ->booleanNode('memory')->end()
  225.                 ->scalarNode('unix_socket')->info('The unix socket to use for MySQL')->end()
  226.                 ->booleanNode('persistent')->info('True to use as persistent connection for the ibm_db2 driver')->end()
  227.                 ->scalarNode('protocol')->info('The protocol to use for the ibm_db2 driver (default to TCPIP if omitted)')->end()
  228.                 ->booleanNode('service')
  229.                     ->info('True to use SERVICE_NAME as connection parameter instead of SID for Oracle')
  230.                 ->end()
  231.                 ->scalarNode('servicename')
  232.                     ->info(
  233.                         'Overrules dbname parameter if given and used as SERVICE_NAME or SID connection parameter ' .
  234.                         'for Oracle depending on the service parameter.'
  235.                     )
  236.                 ->end()
  237.                 ->scalarNode('sessionMode')
  238.                     ->info('The session mode to use for the oci8 driver')
  239.                 ->end()
  240.                 ->scalarNode('server')
  241.                     ->info('The name of a running database server to connect to for SQL Anywhere.')
  242.                 ->end()
  243.                 ->scalarNode('default_dbname')
  244.                     ->info(
  245.                         'Override the default database (postgres) to connect to for PostgreSQL connexion.'
  246.                     )
  247.                 ->end()
  248.                 ->scalarNode('sslmode')
  249.                     ->info(
  250.                         'Determines whether or with what priority a SSL TCP/IP connection will be negotiated with ' .
  251.                         'the server for PostgreSQL.'
  252.                     )
  253.                 ->end()
  254.                 ->scalarNode('sslrootcert')
  255.                     ->info(
  256.                         'The name of a file containing SSL certificate authority (CA) certificate(s). ' .
  257.                         'If the file exists, the server\'s certificate will be verified to be signed by one of these authorities.'
  258.                     )
  259.                 ->end()
  260.                 ->scalarNode('sslcert')
  261.                     ->info(
  262.                         'The path to the SSL client certificate file for PostgreSQL.'
  263.                     )
  264.                 ->end()
  265.                 ->scalarNode('sslkey')
  266.                     ->info(
  267.                         'The path to the SSL client key file for PostgreSQL.'
  268.                     )
  269.                 ->end()
  270.                 ->scalarNode('sslcrl')
  271.                     ->info(
  272.                         'The file name of the SSL certificate revocation list for PostgreSQL.'
  273.                     )
  274.                 ->end()
  275.                 ->booleanNode('pooled')->info('True to use a pooled server with the oci8/pdo_oracle driver')->end()
  276.                 ->booleanNode('MultipleActiveResultSets')->info('Configuring MultipleActiveResultSets for the pdo_sqlsrv driver')->end()
  277.                 ->booleanNode('use_savepoints')->info('Use savepoints for nested transactions')->end()
  278.                 ->scalarNode('instancename')
  279.                 ->info(
  280.                     'Optional parameter, complete whether to add the INSTANCE_NAME parameter in the connection.' .
  281.                     ' It is generally used to connect to an Oracle RAC server to select the name' .
  282.                     ' of a particular instance.'
  283.                 )
  284.                 ->end()
  285.                 ->scalarNode('connectstring')
  286.                 ->info(
  287.                     'Complete Easy Connect connection descriptor, see https://docs.oracle.com/database/121/NETAG/naming.htm.' .
  288.                     'When using this option, you will still need to provide the user and password parameters, but the other ' .
  289.                     'parameters will no longer be used. Note that when using this parameter, the getHost and getPort methods' .
  290.                     ' from Doctrine\DBAL\Connection will no longer function as expected.'
  291.                 )
  292.                 ->end()
  293.             ->end()
  294.             ->beforeNormalization()
  295.                 ->ifTrue(static function ($v) {
  296.                     return ! isset($v['sessionMode']) && isset($v['session_mode']);
  297.                 })
  298.                 ->then(static function ($v) {
  299.                     $v['sessionMode'] = $v['session_mode'];
  300.                     unset($v['session_mode']);
  301.                     return $v;
  302.                 })
  303.             ->end()
  304.             ->beforeNormalization()
  305.                 ->ifTrue(static function ($v) {
  306.                     return ! isset($v['MultipleActiveResultSets']) && isset($v['multiple_active_result_sets']);
  307.                 })
  308.                 ->then(static function ($v) {
  309.                     $v['MultipleActiveResultSets'] = $v['multiple_active_result_sets'];
  310.                     unset($v['multiple_active_result_sets']);
  311.                     return $v;
  312.                 })
  313.             ->end()
  314.             ->beforeNormalization()
  315.                 ->ifTrue(static function ($v) {
  316.                     return empty($v['override_url']) && isset($v['url']);
  317.                 })
  318.                 ->then(static function ($v) {
  319.                     @trigger_error('Not setting doctrine.dbal.override_url to true is deprecated. True is the only value that will be supported in doctrine-bundle 3.0.'E_USER_DEPRECATED);
  320.                     return $v;
  321.                 })
  322.             ->end();
  323.     }
  324.     /**
  325.      * Add the ORM section to configuration tree
  326.      */
  327.     private function addOrmSection(ArrayNodeDefinition $node): void
  328.     {
  329.         $node
  330.             ->children()
  331.                 ->arrayNode('orm')
  332.                     ->beforeNormalization()
  333.                         ->ifTrue(static function ($v) {
  334.                             if (! empty($v) && ! class_exists(EntityManager::class)) {
  335.                                 throw new LogicException('The doctrine/orm package is required when the doctrine.orm config is set.');
  336.                             }
  337.                             return $v === null || (is_array($v) && ! array_key_exists('entity_managers'$v) && ! array_key_exists('entity_manager'$v));
  338.                         })
  339.                         ->then(static function ($v) {
  340.                             $v = (array) $v;
  341.                             // Key that should not be rewritten to the connection config
  342.                             $excludedKeys  = [
  343.                                 'default_entity_manager' => true,
  344.                                 'auto_generate_proxy_classes' => true,
  345.                                 'proxy_dir' => true,
  346.                                 'proxy_namespace' => true,
  347.                                 'resolve_target_entities' => true,
  348.                                 'resolve_target_entity' => true,
  349.                             ];
  350.                             $entityManager = [];
  351.                             foreach ($v as $key => $value) {
  352.                                 if (isset($excludedKeys[$key])) {
  353.                                     continue;
  354.                                 }
  355.                                 $entityManager[$key] = $v[$key];
  356.                                 unset($v[$key]);
  357.                             }
  358.                             $v['default_entity_manager'] = isset($v['default_entity_manager']) ? (string) $v['default_entity_manager'] : 'default';
  359.                             $v['entity_managers']        = [$v['default_entity_manager'] => $entityManager];
  360.                             return $v;
  361.                         })
  362.                     ->end()
  363.                     ->children()
  364.                         ->scalarNode('default_entity_manager')->end()
  365.                         ->scalarNode('auto_generate_proxy_classes')->defaultValue(false)
  366.                             ->info('Auto generate mode possible values are: "NEVER", "ALWAYS", "FILE_NOT_EXISTS", "EVAL"')
  367.                             ->validate()
  368.                                 ->ifTrue(function ($v) {
  369.                                     $generationModes $this->getAutoGenerateModes();
  370.                                     if (is_int($v) && in_array($v$generationModes['values']/*array(0, 1, 2, 3)*/)) {
  371.                                         return false;
  372.                                     }
  373.                                     if (is_bool($v)) {
  374.                                         return false;
  375.                                     }
  376.                                     if (is_string($v)) {
  377.                                         if (in_array(strtoupper($v), $generationModes['names']/*array('NEVER', 'ALWAYS', 'FILE_NOT_EXISTS', 'EVAL')*/)) {
  378.                                             return false;
  379.                                         }
  380.                                     }
  381.                                     return true;
  382.                                 })
  383.                                 ->thenInvalid('Invalid auto generate mode value %s')
  384.                             ->end()
  385.                             ->validate()
  386.                                 ->ifString()
  387.                                 ->then(static function ($v) {
  388.                                     return constant('Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_' strtoupper($v));
  389.                                 })
  390.                             ->end()
  391.                         ->end()
  392.                         ->scalarNode('proxy_dir')->defaultValue('%kernel.cache_dir%/doctrine/orm/Proxies')->end()
  393.                         ->scalarNode('proxy_namespace')->defaultValue('Proxies')->end()
  394.                     ->end()
  395.                     ->fixXmlConfig('entity_manager')
  396.                     ->append($this->getOrmEntityManagersNode())
  397.                     ->fixXmlConfig('resolve_target_entity''resolve_target_entities')
  398.                     ->append($this->getOrmTargetEntityResolverNode())
  399.                 ->end()
  400.             ->end();
  401.     }
  402.     /**
  403.      * Return ORM target entity resolver node
  404.      */
  405.     private function getOrmTargetEntityResolverNode(): NodeDefinition
  406.     {
  407.         $treeBuilder = new TreeBuilder('resolve_target_entities');
  408.         $node        $treeBuilder->getRootNode();
  409.         $node
  410.             ->useAttributeAsKey('interface')
  411.             ->prototype('scalar')
  412.                 ->cannotBeEmpty()
  413.             ->end();
  414.         return $node;
  415.     }
  416.     /**
  417.      * Return ORM entity listener node
  418.      */
  419.     private function getOrmEntityListenersNode(): NodeDefinition
  420.     {
  421.         $treeBuilder = new TreeBuilder('entity_listeners');
  422.         $node        $treeBuilder->getRootNode();
  423.         $normalizer = static function ($mappings) {
  424.             $entities = [];
  425.             foreach ($mappings as $entityClass => $mapping) {
  426.                 $listeners = [];
  427.                 foreach ($mapping as $listenerClass => $listenerEvent) {
  428.                     $events = [];
  429.                     foreach ($listenerEvent as $eventType => $eventMapping) {
  430.                         if ($eventMapping === null) {
  431.                             $eventMapping = [null];
  432.                         }
  433.                         foreach ($eventMapping as $method) {
  434.                             $events[] = [
  435.                                 'type' => $eventType,
  436.                                 'method' => $method,
  437.                             ];
  438.                         }
  439.                     }
  440.                     $listeners[] = [
  441.                         'class' => $listenerClass,
  442.                         'event' => $events,
  443.                     ];
  444.                 }
  445.                 $entities[] = [
  446.                     'class' => $entityClass,
  447.                     'listener' => $listeners,
  448.                 ];
  449.             }
  450.             return ['entities' => $entities];
  451.         };
  452.         $node
  453.             ->beforeNormalization()
  454.                 // Yaml normalization
  455.                 ->ifTrue(static function ($v) {
  456.                     return is_array(reset($v)) && is_string(key(reset($v)));
  457.                 })
  458.                 ->then($normalizer)
  459.             ->end()
  460.             ->fixXmlConfig('entity''entities')
  461.             ->children()
  462.                 ->arrayNode('entities')
  463.                     ->useAttributeAsKey('class')
  464.                     ->prototype('array')
  465.                         ->fixXmlConfig('listener')
  466.                         ->children()
  467.                             ->arrayNode('listeners')
  468.                                 ->useAttributeAsKey('class')
  469.                                 ->prototype('array')
  470.                                     ->fixXmlConfig('event')
  471.                                     ->children()
  472.                                         ->arrayNode('events')
  473.                                             ->prototype('array')
  474.                                                 ->children()
  475.                                                     ->scalarNode('type')->end()
  476.                                                     ->scalarNode('method')->defaultNull()->end()
  477.                                                 ->end()
  478.                                             ->end()
  479.                                         ->end()
  480.                                     ->end()
  481.                                 ->end()
  482.                             ->end()
  483.                         ->end()
  484.                     ->end()
  485.                 ->end()
  486.             ->end();
  487.         return $node;
  488.     }
  489.     /**
  490.      * Return ORM entity manager node
  491.      */
  492.     private function getOrmEntityManagersNode(): ArrayNodeDefinition
  493.     {
  494.         $treeBuilder = new TreeBuilder('entity_managers');
  495.         $node        $treeBuilder->getRootNode();
  496.         $node
  497.             ->requiresAtLeastOneElement()
  498.             ->useAttributeAsKey('name')
  499.             ->prototype('array')
  500.                 ->addDefaultsIfNotSet()
  501.                 ->append($this->getOrmCacheDriverNode('query_cache_driver'))
  502.                 ->append($this->getOrmCacheDriverNode('metadata_cache_driver'))
  503.                 ->append($this->getOrmCacheDriverNode('result_cache_driver'))
  504.                 ->append($this->getOrmEntityListenersNode())
  505.                 ->children()
  506.                     ->scalarNode('connection')->end()
  507.                     ->scalarNode('class_metadata_factory_name')->defaultValue('Doctrine\ORM\Mapping\ClassMetadataFactory')->end()
  508.                     ->scalarNode('default_repository_class')->defaultValue('Doctrine\ORM\EntityRepository')->end()
  509.                     ->scalarNode('auto_mapping')->defaultFalse()->end()
  510.                     ->scalarNode('naming_strategy')->defaultValue('doctrine.orm.naming_strategy.default')->end()
  511.                     ->scalarNode('quote_strategy')->defaultValue('doctrine.orm.quote_strategy.default')->end()
  512.                     ->scalarNode('entity_listener_resolver')->defaultNull()->end()
  513.                     ->scalarNode('repository_factory')->defaultValue('doctrine.orm.container_repository_factory')->end()
  514.                 ->end()
  515.                 ->children()
  516.                     ->arrayNode('second_level_cache')
  517.                         ->children()
  518.                             ->append($this->getOrmCacheDriverNode('region_cache_driver'))
  519.                             ->scalarNode('region_lock_lifetime')->defaultValue(60)->end()
  520.                             ->booleanNode('log_enabled')->defaultValue($this->debug)->end()
  521.                             ->scalarNode('region_lifetime')->defaultValue(3600)->end()
  522.                             ->booleanNode('enabled')->defaultValue(true)->end()
  523.                             ->scalarNode('factory')->end()
  524.                         ->end()
  525.                         ->fixXmlConfig('region')
  526.                         ->children()
  527.                             ->arrayNode('regions')
  528.                                 ->useAttributeAsKey('name')
  529.                                 ->prototype('array')
  530.                                     ->children()
  531.                                         ->append($this->getOrmCacheDriverNode('cache_driver'))
  532.                                         ->scalarNode('lock_path')->defaultValue('%kernel.cache_dir%/doctrine/orm/slc/filelock')->end()
  533.                                         ->scalarNode('lock_lifetime')->defaultValue(60)->end()
  534.                                         ->scalarNode('type')->defaultValue('default')->end()
  535.                                         ->scalarNode('lifetime')->defaultValue(0)->end()
  536.                                         ->scalarNode('service')->end()
  537.                                         ->scalarNode('name')->end()
  538.                                     ->end()
  539.                                 ->end()
  540.                             ->end()
  541.                         ->end()
  542.                         ->fixXmlConfig('logger')
  543.                         ->children()
  544.                             ->arrayNode('loggers')
  545.                                 ->useAttributeAsKey('name')
  546.                                 ->prototype('array')
  547.                                     ->children()
  548.                                         ->scalarNode('name')->end()
  549.                                         ->scalarNode('service')->end()
  550.                                     ->end()
  551.                                 ->end()
  552.                             ->end()
  553.                         ->end()
  554.                     ->end()
  555.                 ->end()
  556.                 ->fixXmlConfig('hydrator')
  557.                 ->children()
  558.                     ->arrayNode('hydrators')
  559.                         ->useAttributeAsKey('name')
  560.                         ->prototype('scalar')->end()
  561.                     ->end()
  562.                 ->end()
  563.                 ->fixXmlConfig('mapping')
  564.                 ->children()
  565.                     ->arrayNode('mappings')
  566.                         ->useAttributeAsKey('name')
  567.                         ->prototype('array')
  568.                             ->beforeNormalization()
  569.                                 ->ifString()
  570.                                 ->then(static function ($v) {
  571.                                     return ['type' => $v];
  572.                                 })
  573.                             ->end()
  574.                             ->treatNullLike([])
  575.                             ->treatFalseLike(['mapping' => false])
  576.                             ->performNoDeepMerging()
  577.                             ->children()
  578.                                 ->scalarNode('mapping')->defaultValue(true)->end()
  579.                                 ->scalarNode('type')->end()
  580.                                 ->scalarNode('dir')->end()
  581.                                 ->scalarNode('alias')->end()
  582.                                 ->scalarNode('prefix')->end()
  583.                                 ->booleanNode('is_bundle')->end()
  584.                             ->end()
  585.                         ->end()
  586.                     ->end()
  587.                     ->arrayNode('dql')
  588.                         ->fixXmlConfig('string_function')
  589.                         ->fixXmlConfig('numeric_function')
  590.                         ->fixXmlConfig('datetime_function')
  591.                         ->children()
  592.                             ->arrayNode('string_functions')
  593.                                 ->useAttributeAsKey('name')
  594.                                 ->prototype('scalar')->end()
  595.                             ->end()
  596.                             ->arrayNode('numeric_functions')
  597.                                 ->useAttributeAsKey('name')
  598.                                 ->prototype('scalar')->end()
  599.                             ->end()
  600.                             ->arrayNode('datetime_functions')
  601.                                 ->useAttributeAsKey('name')
  602.                                 ->prototype('scalar')->end()
  603.                             ->end()
  604.                         ->end()
  605.                     ->end()
  606.                 ->end()
  607.                 ->fixXmlConfig('filter')
  608.                 ->children()
  609.                     ->arrayNode('filters')
  610.                         ->info('Register SQL Filters in the entity manager')
  611.                         ->useAttributeAsKey('name')
  612.                         ->prototype('array')
  613.                             ->beforeNormalization()
  614.                                 ->ifString()
  615.                                 ->then(static function ($v) {
  616.                                     return ['class' => $v];
  617.                                 })
  618.                             ->end()
  619.                             ->beforeNormalization()
  620.                                 // The content of the XML node is returned as the "value" key so we need to rename it
  621.                                 ->ifTrue(static function ($v) {
  622.                                     return is_array($v) && isset($v['value']);
  623.                                 })
  624.                                 ->then(static function ($v) {
  625.                                     $v['class'] = $v['value'];
  626.                                     unset($v['value']);
  627.                                     return $v;
  628.                                 })
  629.                             ->end()
  630.                             ->fixXmlConfig('parameter')
  631.                             ->children()
  632.                                 ->scalarNode('class')->isRequired()->end()
  633.                                 ->booleanNode('enabled')->defaultFalse()->end()
  634.                                 ->arrayNode('parameters')
  635.                                     ->useAttributeAsKey('name')
  636.                                     ->prototype('variable')->end()
  637.                                 ->end()
  638.                             ->end()
  639.                         ->end()
  640.                     ->end()
  641.                 ->end()
  642.             ->end();
  643.         return $node;
  644.     }
  645.     /**
  646.      * Return a ORM cache driver node for an given entity manager
  647.      */
  648.     private function getOrmCacheDriverNode(string $name): ArrayNodeDefinition
  649.     {
  650.         $treeBuilder = new TreeBuilder($name);
  651.         $node        $treeBuilder->getRootNode();
  652.         $node
  653.             ->addDefaultsIfNotSet()
  654.             ->beforeNormalization()
  655.                 ->ifString()
  656.                 ->then(static function ($v): array {
  657.                     return ['type' => $v];
  658.                 })
  659.             ->end()
  660.             ->children()
  661.                 ->scalarNode('type')->defaultNull()->end()
  662.                 ->scalarNode('id')->end()
  663.                 ->scalarNode('pool')->end()
  664.             ->end();
  665.         if ($name === 'metadata_cache_driver') {
  666.             $node->setDeprecated(...$this->getDeprecationMsg(
  667.                 'The "metadata_cache_driver" configuration key is deprecated. PHP Array cache is now automatically registered when %kernel.debug% is false.',
  668.                 '2.3'
  669.             ));
  670.         }
  671.         return $node;
  672.     }
  673.     /**
  674.      * Find proxy auto generate modes for their names and int values
  675.      *
  676.      * @return array{names: list<string>, values: list<int>}
  677.      */
  678.     private function getAutoGenerateModes(): array
  679.     {
  680.         $constPrefix 'AUTOGENERATE_';
  681.         $prefixLen   strlen($constPrefix);
  682.         $refClass    = new ReflectionClass('Doctrine\Common\Proxy\AbstractProxyFactory');
  683.         $constsArray $refClass->getConstants();
  684.         $namesArray  = [];
  685.         $valuesArray = [];
  686.         foreach ($constsArray as $key => $value) {
  687.             if (strpos($key$constPrefix) !== 0) {
  688.                 continue;
  689.             }
  690.             $namesArray[]  = substr($key$prefixLen);
  691.             $valuesArray[] = (int) $value;
  692.         }
  693.         return [
  694.             'names' => $namesArray,
  695.             'values' => $valuesArray,
  696.         ];
  697.     }
  698.     /**
  699.      * Returns the correct deprecation param's as an array for setDeprecated.
  700.      *
  701.      * Symfony/Config v5.1 introduces a deprecation notice when calling
  702.      * setDeprecation() with less than 3 args and the getDeprecation method was
  703.      * introduced at the same time. By checking if getDeprecation() exists,
  704.      * we can determine the correct param count to use when calling setDeprecated.
  705.      *
  706.      * @return list<string>|array{0:string, 1: numeric-string, string}
  707.      */
  708.     private function getDeprecationMsg(string $messagestring $version): array
  709.     {
  710.         if (method_exists(BaseNode::class, 'getDeprecation')) {
  711.             return [
  712.                 'doctrine/doctrine-bundle',
  713.                 $version,
  714.                 $message,
  715.             ];
  716.         }
  717.         return [$message];
  718.     }
  719. }