Configuration.php 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. <?php
  2. /*
  3. * This file is part of the Doctrine Bundle
  4. *
  5. * The code was originally distributed inside the Symfony framework.
  6. *
  7. * (c) Fabien Potencier <fabien@symfony.com>
  8. * (c) Doctrine Project, Benjamin Eberlei <kontakt@beberlei.de>
  9. *
  10. * For the full copyright and license information, please view the LICENSE
  11. * file that was distributed with this source code.
  12. */
  13. namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection;
  14. use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
  15. use Symfony\Component\Config\Definition\Builder\TreeBuilder;
  16. use Symfony\Component\Config\Definition\ConfigurationInterface;
  17. /**
  18. * This class contains the configuration information for the bundle
  19. *
  20. * This information is solely responsible for how the different configuration
  21. * sections are normalized, and merged.
  22. *
  23. * @author Christophe Coevoet <stof@notk.org>
  24. */
  25. class Configuration implements ConfigurationInterface
  26. {
  27. private $debug;
  28. /**
  29. * Constructor
  30. *
  31. * @param Boolean $debug Whether to use the debug mode
  32. */
  33. public function __construct($debug)
  34. {
  35. $this->debug = (Boolean) $debug;
  36. }
  37. /**
  38. * {@inheritDoc}
  39. */
  40. public function getConfigTreeBuilder()
  41. {
  42. $treeBuilder = new TreeBuilder();
  43. $rootNode = $treeBuilder->root('doctrine');
  44. $this->addDbalSection($rootNode);
  45. $this->addOrmSection($rootNode);
  46. return $treeBuilder;
  47. }
  48. /**
  49. * Add DBAL section to configuration tree
  50. *
  51. * @param ArrayNodeDefinition $node
  52. */
  53. private function addDbalSection(ArrayNodeDefinition $node)
  54. {
  55. $node
  56. ->children()
  57. ->arrayNode('dbal')
  58. ->beforeNormalization()
  59. ->ifTrue(function ($v) { return is_array($v) && !array_key_exists('connections', $v) && !array_key_exists('connection', $v); })
  60. ->then(function ($v) {
  61. // Key that should not be rewritten to the connection config
  62. $excludedKeys = array('default_connection' => true, 'types' => true, 'type' => true);
  63. $connection = array();
  64. foreach ($v as $key => $value) {
  65. if (isset($excludedKeys[$key])) {
  66. continue;
  67. }
  68. $connection[$key] = $v[$key];
  69. unset($v[$key]);
  70. }
  71. $v['default_connection'] = isset($v['default_connection']) ? (string) $v['default_connection'] : 'default';
  72. $v['connections'] = array($v['default_connection'] => $connection);
  73. return $v;
  74. })
  75. ->end()
  76. ->children()
  77. ->scalarNode('default_connection')->end()
  78. ->end()
  79. ->fixXmlConfig('type')
  80. ->children()
  81. ->arrayNode('types')
  82. ->useAttributeAsKey('name')
  83. ->prototype('array')
  84. ->beforeNormalization()
  85. ->ifString()
  86. ->then(function($v) { return array('class' => $v); })
  87. ->end()
  88. ->children()
  89. ->scalarNode('class')->isRequired()->end()
  90. ->booleanNode('commented')->defaultTrue()->end()
  91. ->end()
  92. ->end()
  93. ->end()
  94. ->end()
  95. ->fixXmlConfig('connection')
  96. ->append($this->getDbalConnectionsNode())
  97. ->end()
  98. ;
  99. }
  100. /**
  101. * Return the dbal connections node
  102. *
  103. * @return ArrayNodeDefinition
  104. */
  105. private function getDbalConnectionsNode()
  106. {
  107. $treeBuilder = new TreeBuilder();
  108. $node = $treeBuilder->root('connections');
  109. /** @var $connectionNode ArrayNodeDefinition */
  110. $connectionNode = $node
  111. ->requiresAtLeastOneElement()
  112. ->useAttributeAsKey('name')
  113. ->prototype('array')
  114. ;
  115. $this->configureDbalDriverNode($connectionNode);
  116. $connectionNode
  117. ->fixXmlConfig('option')
  118. ->fixXmlConfig('mapping_type')
  119. ->fixXmlConfig('slave')
  120. ->children()
  121. ->scalarNode('driver')->defaultValue('pdo_mysql')->end()
  122. ->scalarNode('platform_service')->end()
  123. ->scalarNode('schema_filter')->end()
  124. ->booleanNode('logging')->defaultValue($this->debug)->end()
  125. ->booleanNode('profiling')->defaultValue($this->debug)->end()
  126. ->scalarNode('driver_class')->end()
  127. ->scalarNode('wrapper_class')->end()
  128. ->booleanNode('keep_slave')->end()
  129. ->arrayNode('options')
  130. ->useAttributeAsKey('key')
  131. ->prototype('scalar')->end()
  132. ->end()
  133. ->arrayNode('mapping_types')
  134. ->useAttributeAsKey('name')
  135. ->prototype('scalar')->end()
  136. ->end()
  137. ->end()
  138. ;
  139. $slaveNode = $connectionNode
  140. ->children()
  141. ->arrayNode('slaves')
  142. ->useAttributeAsKey('name')
  143. ->prototype('array')
  144. ;
  145. $this->configureDbalDriverNode($slaveNode);
  146. return $node;
  147. }
  148. /**
  149. * Adds config keys related to params processed by the DBAL drivers
  150. *
  151. * These keys are available for slave configurations too.
  152. *
  153. * @param ArrayNodeDefinition $node
  154. */
  155. private function configureDbalDriverNode(ArrayNodeDefinition $node)
  156. {
  157. $node
  158. ->children()
  159. ->scalarNode('dbname')->end()
  160. ->scalarNode('host')->defaultValue('localhost')->end()
  161. ->scalarNode('port')->defaultNull()->end()
  162. ->scalarNode('user')->defaultValue('root')->end()
  163. ->scalarNode('password')->defaultNull()->end()
  164. ->scalarNode('charset')->end()
  165. ->scalarNode('path')->end()
  166. ->booleanNode('memory')->end()
  167. ->scalarNode('unix_socket')->info('The unix socket to use for MySQL')->end()
  168. ->booleanNode('persistent')->info('True to use as persistent connection for the ibm_db2 driver')->end()
  169. ->scalarNode('protocol')->info('The protocol to use for the ibm_db2 driver (default to TCPIP if ommited)')->end()
  170. ->booleanNode('service')->info('True to use dbname as service name instead of SID for Oracle')->end()
  171. ->scalarNode('sessionMode')
  172. ->info('The session mode to use for the oci8 driver')
  173. ->end()
  174. ->booleanNode('pooled')->info('True to use a pooled server with the oci8 driver')->end()
  175. ->booleanNode('MultipleActiveResultSets')->info('Configuring MultipleActiveResultSets for the pdo_sqlsrv driver')->end()
  176. ->end()
  177. ->beforeNormalization()
  178. ->ifTrue(function($v) {return !isset($v['sessionMode']) && isset($v['session_mode']);})
  179. ->then(function($v) {
  180. $v['sessionMode'] = $v['session_mode'];
  181. unset($v['session_mode']);
  182. return $v;
  183. })
  184. ->end()
  185. ->beforeNormalization()
  186. ->ifTrue(function($v) {return !isset($v['MultipleActiveResultSets']) && isset($v['multiple_active_result_sets']);})
  187. ->then(function($v) {
  188. $v['MultipleActiveResultSets'] = $v['multiple_active_result_sets'];
  189. unset($v['multiple_active_result_sets']);
  190. return $v;
  191. })
  192. ->end()
  193. ;
  194. }
  195. /**
  196. * Add the ORM section to configuration tree
  197. *
  198. * @param ArrayNodeDefinition $node
  199. */
  200. private function addOrmSection(ArrayNodeDefinition $node)
  201. {
  202. $node
  203. ->children()
  204. ->arrayNode('orm')
  205. ->beforeNormalization()
  206. ->ifTrue(function ($v) { return null === $v || (is_array($v) && !array_key_exists('entity_managers', $v) && !array_key_exists('entity_manager', $v)); })
  207. ->then(function ($v) {
  208. $v = (array) $v;
  209. // Key that should not be rewritten to the connection config
  210. $excludedKeys = array(
  211. 'default_entity_manager' => true, 'auto_generate_proxy_classes' => true,
  212. 'proxy_dir' => true, 'proxy_namespace' => true, 'resolve_target_entities' => true,
  213. 'resolve_target_entity' => true,
  214. );
  215. $entityManager = array();
  216. foreach ($v as $key => $value) {
  217. if (isset($excludedKeys[$key])) {
  218. continue;
  219. }
  220. $entityManager[$key] = $v[$key];
  221. unset($v[$key]);
  222. }
  223. $v['default_entity_manager'] = isset($v['default_entity_manager']) ? (string) $v['default_entity_manager'] : 'default';
  224. $v['entity_managers'] = array($v['default_entity_manager'] => $entityManager);
  225. return $v;
  226. })
  227. ->end()
  228. ->children()
  229. ->scalarNode('default_entity_manager')->end()
  230. ->booleanNode('auto_generate_proxy_classes')->defaultFalse()->end()
  231. ->scalarNode('proxy_dir')->defaultValue('%kernel.cache_dir%/doctrine/orm/Proxies')->end()
  232. ->scalarNode('proxy_namespace')->defaultValue('Proxies')->end()
  233. ->end()
  234. ->fixXmlConfig('entity_manager')
  235. ->append($this->getOrmEntityManagersNode())
  236. ->fixXmlConfig('resolve_target_entity', 'resolve_target_entities')
  237. ->append($this->getOrmTargetEntityResolverNode())
  238. ->end()
  239. ->end()
  240. ;
  241. }
  242. /**
  243. * Return ORM target entity resolver node
  244. *
  245. * @return \Symfony\Component\Config\Definition\Builder\NodeDefinition
  246. */
  247. private function getOrmTargetEntityResolverNode()
  248. {
  249. $treeBuilder = new TreeBuilder();
  250. $node = $treeBuilder->root('resolve_target_entities');
  251. $node
  252. ->useAttributeAsKey('interface')
  253. ->prototype('scalar')
  254. ->cannotBeEmpty()
  255. ->end()
  256. ;
  257. return $node;
  258. }
  259. /**
  260. * Return ORM entity manager node
  261. *
  262. * @return ArrayNodeDefinition
  263. */
  264. private function getOrmEntityManagersNode()
  265. {
  266. $treeBuilder = new TreeBuilder();
  267. $node = $treeBuilder->root('entity_managers');
  268. $node
  269. ->requiresAtLeastOneElement()
  270. ->useAttributeAsKey('name')
  271. ->prototype('array')
  272. ->addDefaultsIfNotSet()
  273. ->append($this->getOrmCacheDriverNode('query_cache_driver'))
  274. ->append($this->getOrmCacheDriverNode('metadata_cache_driver'))
  275. ->append($this->getOrmCacheDriverNode('result_cache_driver'))
  276. ->children()
  277. ->scalarNode('connection')->end()
  278. ->scalarNode('class_metadata_factory_name')->defaultValue('Doctrine\ORM\Mapping\ClassMetadataFactory')->end()
  279. ->scalarNode('default_repository_class')->defaultValue('Doctrine\ORM\EntityRepository')->end()
  280. ->scalarNode('auto_mapping')->defaultFalse()->end()
  281. ->scalarNode('naming_strategy')->defaultValue('doctrine.orm.naming_strategy.default')->end()
  282. ->end()
  283. ->fixXmlConfig('hydrator')
  284. ->children()
  285. ->arrayNode('hydrators')
  286. ->useAttributeAsKey('name')
  287. ->prototype('scalar')->end()
  288. ->end()
  289. ->end()
  290. ->fixXmlConfig('mapping')
  291. ->children()
  292. ->arrayNode('mappings')
  293. ->useAttributeAsKey('name')
  294. ->prototype('array')
  295. ->beforeNormalization()
  296. ->ifString()
  297. ->then(function($v) { return array('type' => $v); })
  298. ->end()
  299. ->treatNullLike(array())
  300. ->treatFalseLike(array('mapping' => false))
  301. ->performNoDeepMerging()
  302. ->children()
  303. ->scalarNode('mapping')->defaultValue(true)->end()
  304. ->scalarNode('type')->end()
  305. ->scalarNode('dir')->end()
  306. ->scalarNode('alias')->end()
  307. ->scalarNode('prefix')->end()
  308. ->booleanNode('is_bundle')->end()
  309. ->end()
  310. ->end()
  311. ->end()
  312. ->arrayNode('dql')
  313. ->fixXmlConfig('string_function')
  314. ->fixXmlConfig('numeric_function')
  315. ->fixXmlConfig('datetime_function')
  316. ->children()
  317. ->arrayNode('string_functions')
  318. ->useAttributeAsKey('name')
  319. ->prototype('scalar')->end()
  320. ->end()
  321. ->arrayNode('numeric_functions')
  322. ->useAttributeAsKey('name')
  323. ->prototype('scalar')->end()
  324. ->end()
  325. ->arrayNode('datetime_functions')
  326. ->useAttributeAsKey('name')
  327. ->prototype('scalar')->end()
  328. ->end()
  329. ->end()
  330. ->end()
  331. ->end()
  332. ->fixXmlConfig('filter')
  333. ->children()
  334. ->arrayNode('filters')
  335. ->info('Register SQL Filters in the entity manager')
  336. ->useAttributeAsKey('name')
  337. ->prototype('array')
  338. ->beforeNormalization()
  339. ->ifString()
  340. ->then(function($v) { return array('class' => $v); })
  341. ->end()
  342. ->beforeNormalization()
  343. // The content of the XML node is returned as the "value" key so we need to rename it
  344. ->ifTrue(function($v) {return is_array($v) && isset($v['value']); })
  345. ->then(function($v) {
  346. $v['class'] = $v['value'];
  347. unset($v['value']);
  348. return $v;
  349. })
  350. ->end()
  351. ->children()
  352. ->scalarNode('class')->isRequired()->end()
  353. ->booleanNode('enabled')->defaultFalse()->end()
  354. ->end()
  355. ->end()
  356. ->end()
  357. ->end()
  358. ->end()
  359. ;
  360. return $node;
  361. }
  362. /**
  363. * Return a ORM cache driver node for an given entity manager
  364. *
  365. * @param string $name
  366. *
  367. * @return ArrayNodeDefinition
  368. */
  369. private function getOrmCacheDriverNode($name)
  370. {
  371. $treeBuilder = new TreeBuilder();
  372. $node = $treeBuilder->root($name);
  373. $node
  374. ->addDefaultsIfNotSet()
  375. ->beforeNormalization()
  376. ->ifString()
  377. ->then(function($v) { return array('type' => $v); })
  378. ->end()
  379. ->children()
  380. ->scalarNode('type')->defaultValue('array')->end()
  381. ->scalarNode('host')->end()
  382. ->scalarNode('port')->end()
  383. ->scalarNode('instance_class')->end()
  384. ->scalarNode('class')->end()
  385. ->scalarNode('id')->end()
  386. ->end()
  387. ;
  388. return $node;
  389. }
  390. }