DoctrineBundle.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. <?php
  2. namespace Doctrine\Bundle\DoctrineBundle;
  3. use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\CacheSchemaSubscriberPass;
  4. use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DbalSchemaFilterPass;
  5. use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\EntityListenerPass;
  6. use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\IdGeneratorPass;
  7. use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\ServiceRepositoryCompilerPass;
  8. use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\WellKnownSchemaFilterPass;
  9. use Doctrine\Common\Util\ClassUtils;
  10. use Doctrine\ORM\EntityManagerInterface;
  11. use Doctrine\ORM\Proxy\Autoloader;
  12. use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\DoctrineValidationPass;
  13. use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\RegisterEventListenersAndSubscribersPass;
  14. use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\RegisterUidTypePass;
  15. use Symfony\Bridge\Doctrine\DependencyInjection\Security\UserProvider\EntityFactory;
  16. use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;
  17. use Symfony\Component\Console\Application;
  18. use Symfony\Component\DependencyInjection\Compiler\PassConfig;
  19. use Symfony\Component\DependencyInjection\ContainerBuilder;
  20. use Symfony\Component\HttpKernel\Bundle\Bundle;
  21. use function assert;
  22. use function class_exists;
  23. use function clearstatcache;
  24. use function spl_autoload_unregister;
  25. class DoctrineBundle extends Bundle
  26. {
  27. /** @var callable|null */
  28. private $autoloader;
  29. /**
  30. * {@inheritDoc}
  31. */
  32. public function build(ContainerBuilder $container)
  33. {
  34. parent::build($container);
  35. $container->addCompilerPass(new RegisterEventListenersAndSubscribersPass('doctrine.connections', 'doctrine.dbal.%s_connection.event_manager', 'doctrine'), PassConfig::TYPE_BEFORE_OPTIMIZATION);
  36. if ($container->hasExtension('security')) {
  37. $security = $container->getExtension('security');
  38. if ($security instanceof SecurityExtension) {
  39. $security->addUserProviderFactory(new EntityFactory('entity', 'doctrine.orm.security.user.provider'));
  40. }
  41. }
  42. $container->addCompilerPass(new DoctrineValidationPass('orm'));
  43. $container->addCompilerPass(new EntityListenerPass());
  44. $container->addCompilerPass(new ServiceRepositoryCompilerPass());
  45. $container->addCompilerPass(new IdGeneratorPass());
  46. $container->addCompilerPass(new WellKnownSchemaFilterPass());
  47. $container->addCompilerPass(new DbalSchemaFilterPass());
  48. $container->addCompilerPass(new CacheSchemaSubscriberPass(), PassConfig::TYPE_BEFORE_REMOVING, -10);
  49. if (! class_exists(RegisterUidTypePass::class)) {
  50. return;
  51. }
  52. $container->addCompilerPass(new RegisterUidTypePass());
  53. }
  54. /**
  55. * {@inheritDoc}
  56. */
  57. public function boot()
  58. {
  59. // Register an autoloader for proxies to avoid issues when unserializing them
  60. // when the ORM is used.
  61. if (! $this->container->hasParameter('doctrine.orm.proxy_namespace')) {
  62. return;
  63. }
  64. $namespace = (string) $this->container->getParameter('doctrine.orm.proxy_namespace');
  65. $dir = (string) $this->container->getParameter('doctrine.orm.proxy_dir');
  66. $proxyGenerator = null;
  67. if ($this->container->getParameter('doctrine.orm.auto_generate_proxy_classes')) {
  68. // See https://github.com/symfony/symfony/pull/3419 for usage of references
  69. $container = &$this->container;
  70. $proxyGenerator = static function ($proxyDir, $proxyNamespace, $class) use (&$container): void {
  71. $originalClassName = ClassUtils::getRealClass($class);
  72. $registry = $container->get('doctrine');
  73. assert($registry instanceof Registry);
  74. foreach ($registry->getManagers() as $em) {
  75. assert($em instanceof EntityManagerInterface);
  76. if (! $em->getConfiguration()->getAutoGenerateProxyClasses()) {
  77. continue;
  78. }
  79. $metadataFactory = $em->getMetadataFactory();
  80. if ($metadataFactory->isTransient($originalClassName)) {
  81. continue;
  82. }
  83. $classMetadata = $metadataFactory->getMetadataFor($originalClassName);
  84. $em->getProxyFactory()->generateProxyClasses([$classMetadata]);
  85. clearstatcache(true, Autoloader::resolveFile($proxyDir, $proxyNamespace, $class));
  86. break;
  87. }
  88. };
  89. }
  90. $this->autoloader = Autoloader::register($dir, $namespace, $proxyGenerator);
  91. }
  92. /**
  93. * {@inheritDoc}
  94. */
  95. public function shutdown()
  96. {
  97. if ($this->autoloader !== null) {
  98. spl_autoload_unregister($this->autoloader);
  99. $this->autoloader = null;
  100. }
  101. // Clear all entity managers to clear references to entities for GC
  102. if ($this->container->hasParameter('doctrine.entity_managers')) {
  103. foreach ($this->container->getParameter('doctrine.entity_managers') as $id) {
  104. if (! $this->container->initialized($id)) {
  105. continue;
  106. }
  107. $this->container->get($id)->clear();
  108. }
  109. }
  110. // Close all connections to avoid reaching too many connections in the process when booting again later (tests)
  111. if (! $this->container->hasParameter('doctrine.connections')) {
  112. return;
  113. }
  114. foreach ($this->container->getParameter('doctrine.connections') as $id) {
  115. if (! $this->container->initialized($id)) {
  116. continue;
  117. }
  118. $this->container->get($id)->close();
  119. }
  120. }
  121. /**
  122. * {@inheritDoc}
  123. */
  124. public function registerCommands(Application $application)
  125. {
  126. }
  127. }