vendor/doctrine/migrations/lib/Doctrine/Migrations/DependencyFactory.php line 485

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Doctrine\Migrations;
  4. use Doctrine\DBAL\Connection;
  5. use Doctrine\Migrations\Configuration\Configuration;
  6. use Doctrine\Migrations\Configuration\Connection\ConnectionLoader;
  7. use Doctrine\Migrations\Configuration\EntityManager\EntityManagerLoader;
  8. use Doctrine\Migrations\Configuration\Migration\ConfigurationLoader;
  9. use Doctrine\Migrations\Exception\FrozenDependencies;
  10. use Doctrine\Migrations\Exception\MissingDependency;
  11. use Doctrine\Migrations\Finder\GlobFinder;
  12. use Doctrine\Migrations\Finder\MigrationFinder;
  13. use Doctrine\Migrations\Finder\RecursiveRegexFinder;
  14. use Doctrine\Migrations\Generator\ClassNameGenerator;
  15. use Doctrine\Migrations\Generator\ConcatenationFileBuilder;
  16. use Doctrine\Migrations\Generator\DiffGenerator;
  17. use Doctrine\Migrations\Generator\FileBuilder;
  18. use Doctrine\Migrations\Generator\Generator;
  19. use Doctrine\Migrations\Generator\SqlGenerator;
  20. use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
  21. use Doctrine\Migrations\Metadata\Storage\TableMetadataStorage;
  22. use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
  23. use Doctrine\Migrations\Provider\DBALSchemaDiffProvider;
  24. use Doctrine\Migrations\Provider\EmptySchemaProvider;
  25. use Doctrine\Migrations\Provider\LazySchemaDiffProvider;
  26. use Doctrine\Migrations\Provider\OrmSchemaProvider;
  27. use Doctrine\Migrations\Provider\SchemaDiffProvider;
  28. use Doctrine\Migrations\Provider\SchemaProvider;
  29. use Doctrine\Migrations\Tools\Console\ConsoleInputMigratorConfigurationFactory;
  30. use Doctrine\Migrations\Tools\Console\Helper\MigrationStatusInfosHelper;
  31. use Doctrine\Migrations\Tools\Console\MigratorConfigurationFactory;
  32. use Doctrine\Migrations\Version\AliasResolver;
  33. use Doctrine\Migrations\Version\AlphabeticalComparator;
  34. use Doctrine\Migrations\Version\Comparator;
  35. use Doctrine\Migrations\Version\CurrentMigrationStatusCalculator;
  36. use Doctrine\Migrations\Version\DbalExecutor;
  37. use Doctrine\Migrations\Version\DbalMigrationFactory;
  38. use Doctrine\Migrations\Version\DefaultAliasResolver;
  39. use Doctrine\Migrations\Version\Executor;
  40. use Doctrine\Migrations\Version\MigrationFactory;
  41. use Doctrine\Migrations\Version\MigrationPlanCalculator;
  42. use Doctrine\Migrations\Version\MigrationStatusCalculator;
  43. use Doctrine\Migrations\Version\SortedMigrationPlanCalculator;
  44. use Doctrine\ORM\EntityManagerInterface;
  45. use Psr\Log\LoggerInterface;
  46. use Psr\Log\NullLogger;
  47. use Symfony\Component\Stopwatch\Stopwatch;
  48. use function array_key_exists;
  49. use function call_user_func;
  50. use function preg_quote;
  51. use function sprintf;
  52. /**
  53.  * The DependencyFactory is responsible for wiring up and managing internal class dependencies.
  54.  */
  55. class DependencyFactory
  56. {
  57.     /** @psalm-var array<string, bool> */
  58.     private $inResolution = [];
  59.     private ?Configuration $configuration null;
  60.     /** @var object[]|callable[] */
  61.     private array $dependencies = [];
  62.     private ?Connection $connection null;
  63.     private ?EntityManagerInterface $em null;
  64.     private bool $frozen false;
  65.     private ConfigurationLoader $configurationLoader;
  66.     private ConnectionLoader $connectionLoader;
  67.     private ?EntityManagerLoader $emLoader null;
  68.     /** @var callable[] */
  69.     private array $factories = [];
  70.     public static function fromConnection(
  71.         ConfigurationLoader $configurationLoader,
  72.         ConnectionLoader $connectionLoader,
  73.         ?LoggerInterface $logger null
  74.     ): self {
  75.         $dependencyFactory                      = new self($logger);
  76.         $dependencyFactory->configurationLoader $configurationLoader;
  77.         $dependencyFactory->connectionLoader    $connectionLoader;
  78.         return $dependencyFactory;
  79.     }
  80.     public static function fromEntityManager(
  81.         ConfigurationLoader $configurationLoader,
  82.         EntityManagerLoader $emLoader,
  83.         ?LoggerInterface $logger null
  84.     ): self {
  85.         $dependencyFactory                      = new self($logger);
  86.         $dependencyFactory->configurationLoader $configurationLoader;
  87.         $dependencyFactory->emLoader            $emLoader;
  88.         return $dependencyFactory;
  89.     }
  90.     private function __construct(?LoggerInterface $logger)
  91.     {
  92.         if ($logger === null) {
  93.             return;
  94.         }
  95.         $this->setDefinition(LoggerInterface::class, static function () use ($logger): LoggerInterface {
  96.             return $logger;
  97.         });
  98.     }
  99.     public function isFrozen(): bool
  100.     {
  101.         return $this->frozen;
  102.     }
  103.     public function freeze(): void
  104.     {
  105.         $this->frozen true;
  106.     }
  107.     private function assertNotFrozen(): void
  108.     {
  109.         if ($this->frozen) {
  110.             throw FrozenDependencies::new();
  111.         }
  112.     }
  113.     public function hasEntityManager(): bool
  114.     {
  115.         return $this->emLoader !== null;
  116.     }
  117.     public function setConfigurationLoader(ConfigurationLoader $configurationLoader): void
  118.     {
  119.         $this->assertNotFrozen();
  120.         $this->configurationLoader $configurationLoader;
  121.     }
  122.     public function getConfiguration(): Configuration
  123.     {
  124.         if ($this->configuration === null) {
  125.             $this->configuration $this->configurationLoader->getConfiguration();
  126.             $this->freeze();
  127.         }
  128.         return $this->configuration;
  129.     }
  130.     public function getConnection(): Connection
  131.     {
  132.         if ($this->connection === null) {
  133.             $this->connection $this->hasEntityManager()
  134.                 ? $this->getEntityManager()->getConnection()
  135.                 : $this->connectionLoader->getConnection($this->getConfiguration()->getConnectionName());
  136.             $this->freeze();
  137.         }
  138.         return $this->connection;
  139.     }
  140.     public function getEntityManager(): EntityManagerInterface
  141.     {
  142.         if ($this->em === null) {
  143.             if ($this->emLoader === null) {
  144.                 throw MissingDependency::noEntityManager();
  145.             }
  146.             $this->em $this->emLoader->getEntityManager($this->getConfiguration()->getEntityManagerName());
  147.             $this->freeze();
  148.         }
  149.         return $this->em;
  150.     }
  151.     public function getVersionComparator(): Comparator
  152.     {
  153.         return $this->getDependency(Comparator::class, static function (): AlphabeticalComparator {
  154.             return new AlphabeticalComparator();
  155.         });
  156.     }
  157.     public function getLogger(): LoggerInterface
  158.     {
  159.         return $this->getDependency(LoggerInterface::class, static function (): LoggerInterface {
  160.             return new NullLogger();
  161.         });
  162.     }
  163.     public function getEventDispatcher(): EventDispatcher
  164.     {
  165.         return $this->getDependency(EventDispatcher::class, function (): EventDispatcher {
  166.             return new EventDispatcher(
  167.                 $this->getConnection(),
  168.                 $this->getConnection()->getEventManager()
  169.             );
  170.         });
  171.     }
  172.     public function getClassNameGenerator(): ClassNameGenerator
  173.     {
  174.         return $this->getDependency(ClassNameGenerator::class, static function (): ClassNameGenerator {
  175.             return new ClassNameGenerator();
  176.         });
  177.     }
  178.     public function getSchemaDumper(): SchemaDumper
  179.     {
  180.         return $this->getDependency(SchemaDumper::class, function (): SchemaDumper {
  181.             $excludedTables = [];
  182.             $metadataConfig $this->getConfiguration()->getMetadataStorageConfiguration();
  183.             if ($metadataConfig instanceof TableMetadataStorageConfiguration) {
  184.                 $excludedTables[] = sprintf('/^%s$/'preg_quote($metadataConfig->getTableName(), '/'));
  185.             }
  186.             return new SchemaDumper(
  187.                 $this->getConnection()->getDatabasePlatform(),
  188.                 $this->getConnection()->createSchemaManager(),
  189.                 $this->getMigrationGenerator(),
  190.                 $this->getMigrationSqlGenerator(),
  191.                 $excludedTables
  192.             );
  193.         });
  194.     }
  195.     private function getEmptySchemaProvider(): SchemaProvider
  196.     {
  197.         return $this->getDependency(EmptySchemaProvider::class, function (): SchemaProvider {
  198.             return new EmptySchemaProvider($this->connection->createSchemaManager());
  199.         });
  200.     }
  201.     public function hasSchemaProvider(): bool
  202.     {
  203.         try {
  204.             $this->getSchemaProvider();
  205.         } catch (MissingDependency $exception) {
  206.             return false;
  207.         }
  208.         return true;
  209.     }
  210.     public function getSchemaProvider(): SchemaProvider
  211.     {
  212.         return $this->getDependency(SchemaProvider::class, function (): SchemaProvider {
  213.             if ($this->hasEntityManager()) {
  214.                 return new OrmSchemaProvider($this->getEntityManager());
  215.             }
  216.             throw MissingDependency::noSchemaProvider();
  217.         });
  218.     }
  219.     public function getDiffGenerator(): DiffGenerator
  220.     {
  221.         return $this->getDependency(DiffGenerator::class, function (): DiffGenerator {
  222.             return new DiffGenerator(
  223.                 $this->getConnection()->getConfiguration(),
  224.                 $this->getConnection()->createSchemaManager(),
  225.                 $this->getSchemaProvider(),
  226.                 $this->getConnection()->getDatabasePlatform(),
  227.                 $this->getMigrationGenerator(),
  228.                 $this->getMigrationSqlGenerator(),
  229.                 $this->getEmptySchemaProvider()
  230.             );
  231.         });
  232.     }
  233.     public function getSchemaDiffProvider(): SchemaDiffProvider
  234.     {
  235.         return $this->getDependency(SchemaDiffProvider::class, function (): LazySchemaDiffProvider {
  236.             return LazySchemaDiffProvider::fromDefaultProxyFactoryConfiguration(
  237.                 new DBALSchemaDiffProvider(
  238.                     $this->getConnection()->createSchemaManager(),
  239.                     $this->getConnection()->getDatabasePlatform()
  240.                 )
  241.             );
  242.         });
  243.     }
  244.     private function getFileBuilder(): FileBuilder
  245.     {
  246.         return $this->getDependency(FileBuilder::class, static function (): FileBuilder {
  247.             return new ConcatenationFileBuilder();
  248.         });
  249.     }
  250.     private function getParameterFormatter(): ParameterFormatter
  251.     {
  252.         return $this->getDependency(ParameterFormatter::class, function (): ParameterFormatter {
  253.             return new InlineParameterFormatter($this->getConnection());
  254.         });
  255.     }
  256.     public function getMigrationsFinder(): MigrationFinder
  257.     {
  258.         return $this->getDependency(MigrationFinder::class, function (): MigrationFinder {
  259.             $configs              $this->getConfiguration();
  260.             $needsRecursiveFinder $configs->areMigrationsOrganizedByYear() || $configs->areMigrationsOrganizedByYearAndMonth();
  261.             return $needsRecursiveFinder ? new RecursiveRegexFinder() : new GlobFinder();
  262.         });
  263.     }
  264.     public function getMigrationRepository(): MigrationsRepository
  265.     {
  266.         return $this->getDependency(MigrationsRepository::class, function (): MigrationsRepository {
  267.             return new FilesystemMigrationsRepository(
  268.                 $this->getConfiguration()->getMigrationClasses(),
  269.                 $this->getConfiguration()->getMigrationDirectories(),
  270.                 $this->getMigrationsFinder(),
  271.                 $this->getMigrationFactory()
  272.             );
  273.         });
  274.     }
  275.     public function getMigrationFactory(): MigrationFactory
  276.     {
  277.         return $this->getDependency(MigrationFactory::class, function (): MigrationFactory {
  278.             return new DbalMigrationFactory($this->getConnection(), $this->getLogger());
  279.         });
  280.     }
  281.     /**
  282.      * @param object|callable $service
  283.      */
  284.     public function setService(string $id$service): void
  285.     {
  286.         $this->assertNotFrozen();
  287.         $this->dependencies[$id] = $service;
  288.     }
  289.     public function getMetadataStorage(): MetadataStorage
  290.     {
  291.         return $this->getDependency(MetadataStorage::class, function (): MetadataStorage {
  292.             return new TableMetadataStorage(
  293.                 $this->getConnection(),
  294.                 $this->getVersionComparator(),
  295.                 $this->getConfiguration()->getMetadataStorageConfiguration(),
  296.                 $this->getMigrationRepository()
  297.             );
  298.         });
  299.     }
  300.     private function getVersionExecutor(): Executor
  301.     {
  302.         return $this->getDependency(Executor::class, function (): Executor {
  303.             return new DbalExecutor(
  304.                 $this->getMetadataStorage(),
  305.                 $this->getEventDispatcher(),
  306.                 $this->getConnection(),
  307.                 $this->getSchemaDiffProvider(),
  308.                 $this->getLogger(),
  309.                 $this->getParameterFormatter(),
  310.                 $this->getStopwatch()
  311.             );
  312.         });
  313.     }
  314.     public function getQueryWriter(): QueryWriter
  315.     {
  316.         return $this->getDependency(QueryWriter::class, function (): QueryWriter {
  317.             return new FileQueryWriter(
  318.                 $this->getFileBuilder(),
  319.                 $this->getLogger()
  320.             );
  321.         });
  322.     }
  323.     public function getVersionAliasResolver(): AliasResolver
  324.     {
  325.         return $this->getDependency(AliasResolver::class, function (): AliasResolver {
  326.             return new DefaultAliasResolver(
  327.                 $this->getMigrationPlanCalculator(),
  328.                 $this->getMetadataStorage(),
  329.                 $this->getMigrationStatusCalculator()
  330.             );
  331.         });
  332.     }
  333.     public function getMigrationStatusCalculator(): MigrationStatusCalculator
  334.     {
  335.         return $this->getDependency(MigrationStatusCalculator::class, function (): MigrationStatusCalculator {
  336.             return new CurrentMigrationStatusCalculator(
  337.                 $this->getMigrationPlanCalculator(),
  338.                 $this->getMetadataStorage()
  339.             );
  340.         });
  341.     }
  342.     public function getMigrationPlanCalculator(): MigrationPlanCalculator
  343.     {
  344.         return $this->getDependency(MigrationPlanCalculator::class, function (): MigrationPlanCalculator {
  345.             return new SortedMigrationPlanCalculator(
  346.                 $this->getMigrationRepository(),
  347.                 $this->getMetadataStorage(),
  348.                 $this->getVersionComparator()
  349.             );
  350.         });
  351.     }
  352.     public function getMigrationGenerator(): Generator
  353.     {
  354.         return $this->getDependency(Generator::class, function (): Generator {
  355.             return new Generator($this->getConfiguration());
  356.         });
  357.     }
  358.     public function getMigrationSqlGenerator(): SqlGenerator
  359.     {
  360.         return $this->getDependency(SqlGenerator::class, function (): SqlGenerator {
  361.             return new SqlGenerator(
  362.                 $this->getConfiguration(),
  363.                 $this->getConnection()->getDatabasePlatform()
  364.             );
  365.         });
  366.     }
  367.     public function getConsoleInputMigratorConfigurationFactory(): MigratorConfigurationFactory
  368.     {
  369.         return $this->getDependency(MigratorConfigurationFactory::class, function (): MigratorConfigurationFactory {
  370.             return new ConsoleInputMigratorConfigurationFactory(
  371.                 $this->getConfiguration()
  372.             );
  373.         });
  374.     }
  375.     public function getMigrationStatusInfosHelper(): MigrationStatusInfosHelper
  376.     {
  377.         return $this->getDependency(MigrationStatusInfosHelper::class, function (): MigrationStatusInfosHelper {
  378.             return new MigrationStatusInfosHelper(
  379.                 $this->getConfiguration(),
  380.                 $this->getConnection(),
  381.                 $this->getVersionAliasResolver(),
  382.                 $this->getMigrationPlanCalculator(),
  383.                 $this->getMigrationStatusCalculator(),
  384.                 $this->getMetadataStorage()
  385.             );
  386.         });
  387.     }
  388.     public function getMigrator(): Migrator
  389.     {
  390.         return $this->getDependency(Migrator::class, function (): Migrator {
  391.             return new DbalMigrator(
  392.                 $this->getConnection(),
  393.                 $this->getEventDispatcher(),
  394.                 $this->getVersionExecutor(),
  395.                 $this->getLogger(),
  396.                 $this->getStopwatch()
  397.             );
  398.         });
  399.     }
  400.     public function getStopwatch(): Stopwatch
  401.     {
  402.         return $this->getDependency(Stopwatch::class, static function (): Stopwatch {
  403.             return new Stopwatch(true);
  404.         });
  405.     }
  406.     public function getRollup(): Rollup
  407.     {
  408.         return $this->getDependency(Rollup::class, function (): Rollup {
  409.             return new Rollup(
  410.                 $this->getMetadataStorage(),
  411.                 $this->getMigrationRepository()
  412.             );
  413.         });
  414.     }
  415.     /**
  416.      * @return mixed
  417.      */
  418.     private function getDependency(string $id, callable $callback)
  419.     {
  420.         if (! isset($this->inResolution[$id]) && array_key_exists($id$this->factories) && ! array_key_exists($id$this->dependencies)) {
  421.             $this->inResolution[$id] = true;
  422.             $this->dependencies[$id] = call_user_func($this->factories[$id], $this);
  423.             unset($this->inResolution);
  424.         }
  425.         if (! array_key_exists($id$this->dependencies)) {
  426.             $this->dependencies[$id] = $callback();
  427.         }
  428.         return $this->dependencies[$id];
  429.     }
  430.     public function setDefinition(string $id, callable $service): void
  431.     {
  432.         $this->assertNotFrozen();
  433.         $this->factories[$id] = $service;
  434.     }
  435. }