DoctrineMongoDBExtension.php 18 KB

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