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

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