Configuration.php 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <?php
  2. declare(strict_types=1);
  3. namespace Doctrine\Bundle\MigrationsBundle\DependencyInjection;
  4. use ReflectionClass;
  5. use Symfony\Component\Config\Definition\Builder\TreeBuilder;
  6. use Symfony\Component\Config\Definition\ConfigurationInterface;
  7. use function array_filter;
  8. use function array_keys;
  9. use function constant;
  10. use function count;
  11. use function in_array;
  12. use function is_string;
  13. use function method_exists;
  14. use function strlen;
  15. use function strpos;
  16. use function strtoupper;
  17. use function substr;
  18. /**
  19. * DoctrineMigrationsExtension configuration structure.
  20. */
  21. class Configuration implements ConfigurationInterface
  22. {
  23. /**
  24. * Generates the configuration tree.
  25. *
  26. * @return TreeBuilder The config tree builder
  27. */
  28. public function getConfigTreeBuilder(): TreeBuilder
  29. {
  30. $treeBuilder = new TreeBuilder('doctrine_migrations');
  31. if (method_exists($treeBuilder, 'getRootNode')) {
  32. $rootNode = $treeBuilder->getRootNode();
  33. } else {
  34. // BC layer for symfony/config 4.1 and older
  35. $rootNode = $treeBuilder->root('doctrine_migrations', 'array');
  36. }
  37. $organizeMigrationModes = $this->getOrganizeMigrationsModes();
  38. $rootNode
  39. ->fixXmlConfig('migration', 'migrations')
  40. ->fixXmlConfig('migrations_path', 'migrations_paths')
  41. ->children()
  42. ->arrayNode('migrations_paths')
  43. ->info('A list of namespace/path pairs where to look for migrations.')
  44. ->defaultValue([])
  45. ->useAttributeAsKey('namespace')
  46. ->prototype('scalar')->end()
  47. ->end()
  48. ->arrayNode('services')
  49. ->info('A set of services to pass to the underlying doctrine/migrations library, allowing to change its behaviour.')
  50. ->useAttributeAsKey('service')
  51. ->defaultValue([])
  52. ->validate()
  53. ->ifTrue(static function ($v): bool {
  54. return count(array_filter(array_keys($v), static function (string $doctrineService): bool {
  55. return strpos($doctrineService, 'Doctrine\Migrations\\') !== 0;
  56. })) !== 0;
  57. })
  58. ->thenInvalid('Valid services for the DoctrineMigrationsBundle must be in the "Doctrine\Migrations" namespace.')
  59. ->end()
  60. ->prototype('scalar')->end()
  61. ->end()
  62. ->arrayNode('factories')
  63. ->info('A set of callables to pass to the underlying doctrine/migrations library as services, allowing to change its behaviour.')
  64. ->useAttributeAsKey('factory')
  65. ->defaultValue([])
  66. ->validate()
  67. ->ifTrue(static function ($v): bool {
  68. return count(array_filter(array_keys($v), static function (string $doctrineService): bool {
  69. return strpos($doctrineService, 'Doctrine\Migrations\\') !== 0;
  70. })) !== 0;
  71. })
  72. ->thenInvalid('Valid callables for the DoctrineMigrationsBundle must be in the "Doctrine\Migrations" namespace.')
  73. ->end()
  74. ->prototype('scalar')->end()
  75. ->end()
  76. ->arrayNode('storage')
  77. ->addDefaultsIfNotSet()
  78. ->info('Storage to use for migration status metadata.')
  79. ->children()
  80. ->arrayNode('table_storage')
  81. ->addDefaultsIfNotSet()
  82. ->info('The default metadata storage, implemented as a table in the database.')
  83. ->children()
  84. ->scalarNode('table_name')->defaultValue(null)->cannotBeEmpty()->end()
  85. ->scalarNode('version_column_name')->defaultValue(null)->end()
  86. ->scalarNode('version_column_length')->defaultValue(null)->end()
  87. ->scalarNode('executed_at_column_name')->defaultValue(null)->end()
  88. ->scalarNode('execution_time_column_name')->defaultValue(null)->end()
  89. ->end()
  90. ->end()
  91. ->end()
  92. ->end()
  93. ->arrayNode('migrations')
  94. ->info('A list of migrations to load in addition to the one discovered via "migrations_paths".')
  95. ->prototype('scalar')->end()
  96. ->defaultValue([])
  97. ->end()
  98. ->scalarNode('connection')
  99. ->info('Connection name to use for the migrations database.')
  100. ->defaultValue(null)
  101. ->end()
  102. ->scalarNode('em')
  103. ->info('Entity manager name to use for the migrations database (available when doctrine/orm is installed).')
  104. ->defaultValue(null)
  105. ->end()
  106. ->scalarNode('all_or_nothing')
  107. ->info('Run all migrations in a transaction.')
  108. ->defaultValue(false)
  109. ->end()
  110. ->scalarNode('check_database_platform')
  111. ->info('Adds an extra check in the generated migrations to allow execution only on the same platform as they were initially generated on.')
  112. ->defaultValue(true)
  113. ->end()
  114. ->scalarNode('custom_template')
  115. ->info('Custom template path for generated migration classes.')
  116. ->defaultValue(null)
  117. ->end()
  118. ->scalarNode('organize_migrations')
  119. ->defaultValue(false)
  120. ->info('Organize migrations mode. Possible values are: "BY_YEAR", "BY_YEAR_AND_MONTH", false')
  121. ->validate()
  122. ->ifTrue(static function ($v) use ($organizeMigrationModes): bool {
  123. if ($v === false) {
  124. return false;
  125. }
  126. return ! is_string($v) || ! in_array(strtoupper($v), $organizeMigrationModes, true);
  127. })
  128. ->thenInvalid('Invalid organize migrations mode value %s')
  129. ->end()
  130. ->validate()
  131. ->ifString()
  132. ->then(static function ($v) {
  133. return constant('Doctrine\Migrations\Configuration\Configuration::VERSIONS_ORGANIZATION_' . strtoupper($v));
  134. })
  135. ->end()
  136. ->end()
  137. ->booleanNode('enable_profiler')
  138. ->info('Use profiler to calculate and visualize migration status.')
  139. ->defaultFalse()
  140. ->end()
  141. ->end();
  142. return $treeBuilder;
  143. }
  144. /**
  145. * Find organize migrations modes for their names
  146. *
  147. * @return string[]
  148. */
  149. private function getOrganizeMigrationsModes(): array
  150. {
  151. $constPrefix = 'VERSIONS_ORGANIZATION_';
  152. $prefixLen = strlen($constPrefix);
  153. $refClass = new ReflectionClass('Doctrine\Migrations\Configuration\Configuration');
  154. $constsArray = $refClass->getConstants();
  155. $namesArray = [];
  156. foreach ($constsArray as $key => $value) {
  157. if (strpos($key, $constPrefix) !== 0) {
  158. continue;
  159. }
  160. $namesArray[] = substr($key, $prefixLen);
  161. }
  162. return $namesArray;
  163. }
  164. }