DoctrineMongoDBExtension.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Bundle\DoctrineMongoDBBundle\DependencyInjection;
  11. use Symfony\Component\DependencyInjection\Extension\Extension;
  12. use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
  13. use Symfony\Component\DependencyInjection\ContainerBuilder;
  14. use Symfony\Component\DependencyInjection\Alias;
  15. use Symfony\Component\DependencyInjection\Reference;
  16. use Symfony\Component\DependencyInjection\Definition;
  17. use Symfony\Component\DependencyInjection\Resource\FileResource;
  18. use Symfony\Bundle\DoctrineAbstractBundle\DependencyInjection\AbstractDoctrineExtension;
  19. /**
  20. * Doctrine MongoDB ODM extension.
  21. *
  22. * @author Bulat Shakirzyanov <bulat@theopenskyproject.com>
  23. * @author Kris Wallsmith <kris.wallsmith@symfony-project.com>
  24. * @author Jonathan H. Wage <jonwage@gmail.com>
  25. */
  26. class DoctrineMongoDBExtension extends AbstractDoctrineExtension
  27. {
  28. /**
  29. * Loads the MongoDB ODM configuration.
  30. *
  31. * Usage example:
  32. *
  33. * <doctrine:mongodb server="mongodb://localhost:27017" />
  34. *
  35. * @param array $config An array of configuration settings
  36. * @param ContainerBuilder $container A ContainerBuilder instance
  37. */
  38. public function mongodbLoad($config, ContainerBuilder $container)
  39. {
  40. $this->loadDefaults($config, $container);
  41. $this->loadConnections($config, $container);
  42. $this->loadDocumentManagers($config, $container);
  43. $this->loadConstraints($config, $container);
  44. }
  45. /**
  46. * Loads the default configuration.
  47. *
  48. * @param array $config An array of configuration settings
  49. * @param ContainerBuilder $container A ContainerBuilder instance
  50. */
  51. protected function loadDefaults(array $config, ContainerBuilder $container)
  52. {
  53. if (!$container->hasDefinition('doctrine.odm.mongodb.metadata.annotation')) {
  54. // Load DoctrineMongoDBBundle/Resources/config/mongodb.xml
  55. $loader = new XmlFileLoader($container, __DIR__.'/../Resources/config');
  56. $loader->load('mongodb.xml');
  57. }
  58. // Allow these application configuration options to override the defaults
  59. $options = array(
  60. 'default_document_manager',
  61. 'default_connection',
  62. 'cache_driver',
  63. 'metadata_cache_driver',
  64. 'proxy_namespace',
  65. 'auto_generate_proxy_classes',
  66. 'hydrator_namespace',
  67. 'auto_generate_hydrator_classes',
  68. 'default_database',
  69. );
  70. foreach ($options as $key) {
  71. if (isset($config[$key])) {
  72. $container->setParameter('doctrine.odm.mongodb.'.$key, $config[$key]);
  73. }
  74. $nKey = str_replace('_', '-', $key);
  75. if (isset($config[$nKey])) {
  76. $container->setParameter('doctrine.odm.mongodb.'.$key, $config[$nKey]);
  77. }
  78. }
  79. }
  80. /**
  81. * Loads the document managers configuration.
  82. *
  83. * @param array $config An array of configuration settings
  84. * @param ContainerBuilder $container A ContainerBuilder instance
  85. */
  86. protected function loadDocumentManagers(array $config, ContainerBuilder $container)
  87. {
  88. $documentManagers = $this->getDocumentManagers($config, $container);
  89. foreach ($documentManagers as $name => $documentManager) {
  90. $documentManager['name'] = $name;
  91. $this->loadDocumentManager($documentManager, $container);
  92. }
  93. }
  94. /**
  95. * Loads a document manager configuration.
  96. *
  97. * @param array $documentManager A document manager configuration array
  98. * @param ContainerBuilder $container A ContainerBuilder instance
  99. */
  100. protected function loadDocumentManager(array $documentManager, ContainerBuilder $container)
  101. {
  102. $defaultDocumentManager = $container->getParameter('doctrine.odm.mongodb.default_document_manager');
  103. $defaultDatabase = isset($documentManager['default_database']) ? $documentManager['default_database'] : $container->getParameter('doctrine.odm.mongodb.default_database');
  104. $proxyCacheDir = $container->getParameter('kernel.cache_dir').'/doctrine/odm/mongodb/Proxies';
  105. $hydratorCacheDir = $container->getParameter('kernel.cache_dir').'/doctrine/odm/mongodb/Hydrators';
  106. $configServiceName = sprintf('doctrine.odm.mongodb.%s_configuration', $documentManager['name']);
  107. if ($container->hasDefinition($configServiceName)) {
  108. $odmConfigDef = $container->getDefinition($configServiceName);
  109. } else {
  110. $odmConfigDef = new Definition('%doctrine.odm.mongodb.configuration_class%');
  111. $container->setDefinition($configServiceName, $odmConfigDef);
  112. }
  113. $this->loadDocumentManagerBundlesMappingInformation($documentManager, $odmConfigDef, $container);
  114. $this->loadDocumentManagerMetadataCacheDriver($documentManager, $container);
  115. $methods = array(
  116. 'setMetadataCacheImpl' => new Reference(sprintf('doctrine.odm.mongodb.%s_metadata_cache', $documentManager['name'])),
  117. 'setMetadataDriverImpl' => new Reference(sprintf('doctrine.odm.mongodb.%s_metadata_driver', $documentManager['name'])),
  118. 'setProxyDir' => $proxyCacheDir,
  119. 'setProxyNamespace' => $container->getParameter('doctrine.odm.mongodb.proxy_namespace'),
  120. 'setAutoGenerateProxyClasses' => $container->getParameter('doctrine.odm.mongodb.auto_generate_proxy_classes'),
  121. 'setHydratorDir' => $hydratorCacheDir,
  122. 'setHydratorNamespace' => $container->getParameter('doctrine.odm.mongodb.hydrator_namespace'),
  123. 'setAutoGenerateHydratorClasses' => $container->getParameter('doctrine.odm.mongodb.auto_generate_hydrator_classes'),
  124. 'setDefaultDB' => $defaultDatabase,
  125. 'setLoggerCallable' => array(new Reference('doctrine.odm.mongodb.logger'), 'logQuery'),
  126. );
  127. foreach ($methods as $method => $arg) {
  128. if ($odmConfigDef->hasMethodCall($method)) {
  129. $odmConfigDef->removeMethodCall($method);
  130. }
  131. $odmConfigDef->addMethodCall($method, array($arg));
  132. }
  133. // event manager
  134. $eventManagerName = isset($documentManager['event_manager']) ? $documentManager['event_manager'] : $documentManager['name'];
  135. $eventManagerId = sprintf('doctrine.odm.mongodb.%s_event_manager', $eventManagerName);
  136. if (!$container->hasDefinition($eventManagerId)) {
  137. $eventManagerDef = new Definition('%doctrine.odm.mongodb.event_manager_class%');
  138. $eventManagerDef->addTag('doctrine.odm.mongodb.event_manager');
  139. $eventManagerDef->setPublic(false);
  140. $container->setDefinition($eventManagerId, $eventManagerDef);
  141. }
  142. $odmDmArgs = array(
  143. new Reference(sprintf('doctrine.odm.mongodb.%s_connection', isset($documentManager['connection']) ? $documentManager['connection'] : $documentManager['name'])),
  144. new Reference(sprintf('doctrine.odm.mongodb.%s_configuration', $documentManager['name'])),
  145. new Reference($eventManagerId),
  146. );
  147. $odmDmDef = new Definition('%doctrine.odm.mongodb.document_manager_class%', $odmDmArgs);
  148. $odmDmDef->setFactoryMethod('create');
  149. $odmDmDef->addTag('doctrine.odm.mongodb.document_manager');
  150. $container->setDefinition(sprintf('doctrine.odm.mongodb.%s_document_manager', $documentManager['name']), $odmDmDef);
  151. if ($documentManager['name'] == $defaultDocumentManager) {
  152. $container->setAlias(
  153. 'doctrine.odm.mongodb.document_manager',
  154. new Alias(sprintf('doctrine.odm.mongodb.%s_document_manager', $documentManager['name']))
  155. );
  156. $container->setAlias(
  157. 'doctrine.odm.mongodb.event_manager',
  158. new Alias(sprintf('doctrine.odm.mongodb.%s_event_manager', $documentManager['name']))
  159. );
  160. }
  161. }
  162. /**
  163. * Gets the configured document managers.
  164. *
  165. * @param array $config An array of configuration settings
  166. * @param ContainerBuilder $container A ContainerBuilder instance
  167. */
  168. protected function getDocumentManagers(array $config, ContainerBuilder $container)
  169. {
  170. $defaultDocumentManager = $container->getParameter('doctrine.odm.mongodb.default_document_manager');
  171. $documentManagers = array();
  172. if (isset($config['document-managers'])) {
  173. $config['document_managers'] = $config['document-managers'];
  174. }
  175. if (isset($config['document_managers'])) {
  176. $configDocumentManagers = $config['document_managers'];
  177. if (isset($config['document_managers']['document-manager'])) {
  178. $config['document_managers']['document_manager'] = $config['document_managers']['document-manager'];
  179. }
  180. if (isset($config['document_managers']['document_manager']) && isset($config['document_managers']['document_manager'][0])) {
  181. // Multiple document managers
  182. $configDocumentManagers = $config['document_managers']['document_manager'];
  183. }
  184. foreach ($configDocumentManagers as $name => $documentManager) {
  185. $documentManagers[isset($documentManager['id']) ? $documentManager['id'] : $name] = $documentManager;
  186. }
  187. } else {
  188. $documentManagers = array($defaultDocumentManager => $config);
  189. }
  190. return $documentManagers;
  191. }
  192. /**
  193. * Loads the configured document manager metadata cache driver.
  194. *
  195. * @param array $config A configured document manager array
  196. * @param ContainerBuilder $container A ContainerBuilder instance
  197. */
  198. protected function loadDocumentManagerMetadataCacheDriver(array $documentManager, ContainerBuilder $container)
  199. {
  200. $metadataCacheDriver = $container->getParameter('doctrine.odm.mongodb.metadata_cache_driver');
  201. $dmMetadataCacheDriver = isset($documentManager['metadata-cache-driver']) ? $documentManager['metadata-cache-driver'] : (isset($documentManager['metadata_cache_driver']) ? $documentManager['metadata_cache_driver'] : $metadataCacheDriver);
  202. $type = is_array($dmMetadataCacheDriver) && isset($dmMetadataCacheDriver['type']) ? $dmMetadataCacheDriver['type'] : $dmMetadataCacheDriver;
  203. if ('memcache' === $type) {
  204. $memcacheClass = isset($dmMetadataCacheDriver['class']) ? $dmMetadataCacheDriver['class'] : sprintf('%%doctrine.odm.mongodb.cache.%s_class%%', $type);
  205. $cacheDef = new Definition($memcacheClass);
  206. $memcacheHost = isset($dmMetadataCacheDriver['host']) ? $dmMetadataCacheDriver['host'] : '%doctrine.odm.mongodb.cache.memcache_host%';
  207. $memcachePort = isset($dmMetadataCacheDriver['port']) ? $dmMetadataCacheDriver['port'] : '%doctrine.odm.mongodb.cache.memcache_port%';
  208. $memcacheInstanceClass = isset($dmMetadataCacheDriver['instance-class']) ? $dmMetadataCacheDriver['instance-class'] : (isset($dmMetadataCacheDriver['instance_class']) ? $dmMetadataCacheDriver['instance_class'] : '%doctrine.odm.mongodb.cache.memcache_instance_class%');
  209. $memcacheInstance = new Definition($memcacheInstanceClass);
  210. $memcacheInstance->addMethodCall('connect', array($memcacheHost, $memcachePort));
  211. $container->setDefinition(sprintf('doctrine.odm.mongodb.%s_memcache_instance', $documentManager['name']), $memcacheInstance);
  212. $cacheDef->addMethodCall('setMemcache', array(new Reference(sprintf('doctrine.odm.mongodb.%s_memcache_instance', $documentManager['name']))));
  213. } else {
  214. $cacheDef = new Definition(sprintf('%%doctrine.odm.mongodb.cache.%s_class%%', $type));
  215. }
  216. $container->setDefinition(sprintf('doctrine.odm.mongodb.%s_metadata_cache', $documentManager['name']), $cacheDef);
  217. }
  218. /**
  219. * Loads the configured connections.
  220. *
  221. * @param array $config An array of configuration settings
  222. * @param ContainerBuilder $container A ContainerBuilder instance
  223. */
  224. protected function loadConnections(array $config, ContainerBuilder $container)
  225. {
  226. $connections = $this->getConnections($config, $container);
  227. foreach ($connections as $name => $connection) {
  228. $odmConnArgs = array(
  229. isset($connection['server']) ? $connection['server'] : null,
  230. isset($connection['options']) ? $connection['options'] : array(),
  231. new Reference(sprintf('doctrine.odm.mongodb.%s_configuration', $name))
  232. );
  233. $odmConnDef = new Definition('%doctrine.odm.mongodb.connection_class%', $odmConnArgs);
  234. $container->setDefinition(sprintf('doctrine.odm.mongodb.%s_connection', $name), $odmConnDef);
  235. }
  236. }
  237. /**
  238. * Gets the configured connections.
  239. *
  240. * @param array $config An array of configuration settings
  241. * @param ContainerBuilder $container A ContainerBuilder instance
  242. */
  243. protected function getConnections(array $config, ContainerBuilder $container)
  244. {
  245. $defaultConnection = $container->getParameter('doctrine.odm.mongodb.default_connection');
  246. $connections = array();
  247. if (isset($config['connections'])) {
  248. $configConnections = $config['connections'];
  249. if (isset($config['connections']['connection']) && isset($config['connections']['connection'][0])) {
  250. // Multiple connections
  251. $configConnections = $config['connections']['connection'];
  252. }
  253. foreach ($configConnections as $name => $connection) {
  254. $connections[isset($connection['id']) ? $connection['id'] : $name] = $connection;
  255. }
  256. } else {
  257. $connections = array($defaultConnection => $config);
  258. }
  259. return $connections;
  260. }
  261. /**
  262. * Loads an ODM document managers bundle mapping information.
  263. *
  264. * There are two distinct configuration possibilities for mapping information:
  265. *
  266. * 1. Specifiy a bundle and optionally details where the entity and mapping information reside.
  267. * 2. Specifiy an arbitrary mapping location.
  268. *
  269. * @example
  270. *
  271. * doctrine.orm:
  272. * mappings:
  273. * MyBundle1: ~
  274. * MyBundle2: yml
  275. * MyBundle3: { type: annotation, dir: Documents/ }
  276. * MyBundle4: { type: xml, dir: Resources/config/doctrine/mapping }
  277. * MyBundle5:
  278. * type: yml
  279. * dir: [bundle-mappings1/, bundle-mappings2/]
  280. * alias: BundleAlias
  281. * arbitrary_key:
  282. * type: xml
  283. * dir: %kernel.dir%/../src/vendor/DoctrineExtensions/lib/DoctrineExtensions/Documents
  284. * prefix: DoctrineExtensions\Documents\
  285. * alias: DExt
  286. *
  287. * In the case of bundles everything is really optional (which leads to autodetection for this bundle) but
  288. * in the mappings key everything except alias is a required argument.
  289. *
  290. * @param array $documentManager A configured ODM entity manager.
  291. * @param Definition A Definition instance
  292. * @param ContainerBuilder $container A ContainerBuilder instance
  293. */
  294. protected function loadDocumentManagerBundlesMappingInformation(array $documentManager, Definition $odmConfigDef, ContainerBuilder $container)
  295. {
  296. // reset state of drivers and alias map. They are only used by this methods and children.
  297. $this->drivers = array();
  298. $this->aliasMap = array();
  299. $this->loadMappingInformation($documentManager, $container);
  300. $this->registerMappingDrivers($documentManager, $container);
  301. if ($odmConfigDef->hasMethodCall('setDocumentNamespaces')) {
  302. // TODO: Can we make a method out of it on Definition? replaceMethodArguments() or something.
  303. $calls = $odmConfigDef->getMethodCalls();
  304. foreach ($calls AS $call) {
  305. if ($call[0] == 'setDocumentNamespaces') {
  306. $this->aliasMap = array_merge($call[1][0], $this->aliasMap);
  307. }
  308. }
  309. $method = $odmConfigDef->removeMethodCall('setDocumentNamespaces');
  310. }
  311. $odmConfigDef->addMethodCall('setDocumentNamespaces', array($this->aliasMap));
  312. }
  313. protected function loadConstraints($config, ContainerBuilder $container)
  314. {
  315. if ($container->hasParameter('validator.annotations.namespaces')) {
  316. $container->setParameter('validator.annotations.namespaces', array_merge(
  317. $container->getParamter('validator.annotations.namespaces'),
  318. array('Symfony\Bundle\DoctrineMongoDBBundle\Validator\Constraints\\')
  319. ));
  320. }
  321. }
  322. protected function getObjectManagerElementName($name)
  323. {
  324. return 'doctrine.odm.mongodb.' . $name;
  325. }
  326. protected function getMappingObjectDefaultName()
  327. {
  328. return 'Document';
  329. }
  330. protected function getMappingResourceConfigDirectory()
  331. {
  332. return 'Resources/config/doctrine/metadata/mongodb';
  333. }
  334. /**
  335. * Returns the namespace to be used for this extension (XML namespace).
  336. *
  337. * @return string The XML namespace
  338. */
  339. public function getNamespace()
  340. {
  341. return 'http://www.symfony-project.org/schema/dic/doctrine/odm/mongodb';
  342. }
  343. /**
  344. * @return string
  345. */
  346. public function getXsdValidationBasePath()
  347. {
  348. return __DIR__.'/../Resources/config/schema';
  349. }
  350. /**
  351. * Returns the recommended alias to use in XML.
  352. *
  353. * This alias is also the mandatory prefix to use when using YAML.
  354. *
  355. * @return string The alias
  356. */
  357. public function getAlias()
  358. {
  359. return 'doctrine_odm';
  360. }
  361. }