Skip to content

Commit ddcc1c5

Browse files
authored
Merge pull request #294 from goetas/forward-compat-v3
Forward compatibility layer for v3.x
2 parents 856437e + 54598cd commit ddcc1c5

File tree

5 files changed

+202
-26
lines changed

5 files changed

+202
-26
lines changed

.doctrine-project.json

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,49 @@
11
{
2-
"name": "Doctrine Migrations Bundle",
3-
"shortName": "DoctrineMigrationsBundle",
4-
"slug": "doctrine-migrations-bundle",
5-
"versions": [
6-
{
7-
"name": "2.0",
8-
"branchName": "2.0",
9-
"slug": "2.0",
10-
"current": true
11-
},
12-
{
13-
"name": "1.3",
14-
"branchName": "1.3",
15-
"slug": "1.3"
16-
}
17-
]
2+
"name": "Doctrine Migrations Bundle",
3+
"shortName": "DoctrineMigrationsBundle",
4+
"slug": "doctrine-migrations-bundle",
5+
"versions": [
6+
{
7+
"name": "2.2",
8+
"branchName": "master",
9+
"slug": "2.2",
10+
"upcoming": true
11+
},
12+
{
13+
"name": "2.1",
14+
"branchName": "2.1.x",
15+
"slug": "2.1",
16+
"current": true
17+
},
18+
{
19+
"name": "2.0",
20+
"branchName": "2.0.x",
21+
"slug": "2.0",
22+
"maintained": false
23+
},
24+
{
25+
"name": "1.3",
26+
"branchName": "1.3",
27+
"slug": "1.3",
28+
"maintained": false
29+
},
30+
{
31+
"name": "1.2",
32+
"branchName": "1.2",
33+
"slug": "1.2",
34+
"maintained": false
35+
},
36+
{
37+
"name": "1.1",
38+
"branchName": "1.1",
39+
"slug": "1.1",
40+
"maintained": false
41+
},
42+
{
43+
"name": "1.0",
44+
"branchName": "1.0",
45+
"slug": "1.0",
46+
"maintained": false
47+
}
48+
]
1849
}

DependencyInjection/Configuration.php

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
99
use Symfony\Component\Config\Definition\ConfigurationInterface;
1010
use function constant;
11+
use function count;
1112
use function in_array;
1213
use function is_string;
1314
use function method_exists;
@@ -41,14 +42,78 @@ public function getConfigTreeBuilder() : TreeBuilder
4142

4243
$rootNode
4344
->children()
44-
->scalarNode('dir_name')->defaultValue('%kernel.root_dir%/DoctrineMigrations')->cannotBeEmpty()->end()
45-
->scalarNode('namespace')->defaultValue('Application\Migrations')->cannotBeEmpty()->end()
46-
->scalarNode('table_name')->defaultValue('migration_versions')->cannotBeEmpty()->end()
47-
->scalarNode('column_name')->defaultValue('version')->end()
48-
->scalarNode('column_length')->defaultValue(14)->end()
49-
->scalarNode('executed_at_column_name')->defaultValue('executed_at')->end()
45+
->scalarNode('name')
46+
->setDeprecated('The "%node%" option is deprecated.')
47+
->defaultValue('Application Migrations')
48+
->end()
49+
50+
// 3.x forward compatibility layer
51+
->arrayNode('migrations_paths')
52+
->info('A list of pairs namespace/path where to look for migrations.')
53+
->useAttributeAsKey('name')
54+
->defaultValue([])
55+
->prototype('scalar')->end()
56+
->validate()
57+
->ifTrue(static function ($v) : bool {
58+
return count($v) === 0;
59+
})
60+
->thenInvalid('At least one migration path must be specified.')
61+
62+
->ifTrue(static function ($v) : bool {
63+
return count($v) > 1;
64+
})
65+
->thenInvalid('Maximum one migration path can be specified with the 2.x version.')
66+
->end()
67+
->end()
68+
69+
->arrayNode('storage')
70+
->info('Storage to use for migration status metadata.')
71+
->children()
72+
->arrayNode('table_storage')
73+
->info('The default metadata storage, implemented as database table.')
74+
->children()
75+
->scalarNode('table_name')->defaultValue(null)->cannotBeEmpty()->end()
76+
->scalarNode('version_column_name')->defaultValue(null)->end()
77+
->scalarNode('version_column_length')
78+
->defaultValue(null)
79+
->validate()
80+
->ifTrue(static function ($v) : bool {
81+
return $v < 1024;
82+
})
83+
->thenInvalid('The minimum length for the version column is 1024.')
84+
->end()
85+
->end()
86+
->scalarNode('executed_at_column_name')->defaultValue(null)->end()
87+
->end()
88+
->end()
89+
->end()
90+
->end()
91+
92+
->scalarNode('dir_name')
93+
->defaultValue('%kernel.root_dir%/DoctrineMigrations')->cannotBeEmpty()
94+
->setDeprecated('The "%node%" option is deprecated. Use "migrations_paths" instead.')
95+
->end()
96+
->scalarNode('namespace')
97+
->defaultValue('Application\Migrations')->cannotBeEmpty()
98+
->setDeprecated('The "%node%" option is deprecated. Use "migrations_paths" instead.')
99+
->end()
100+
->scalarNode('table_name')
101+
->defaultValue('migration_versions')->cannotBeEmpty()
102+
->setDeprecated('The "%node%" option is deprecated. Use "storage.table_storage.table_name" instead.')
103+
->end()
104+
->scalarNode('column_name')
105+
->defaultValue('version')
106+
->setDeprecated('The "%node%" option is deprecated. Use "storage.table_storage.version_column_name" instead.')
107+
->end()
108+
->scalarNode('column_length')
109+
->defaultValue(14)
110+
->setDeprecated('The "%node%" option is deprecated. Use "storage.table_storage.version_column_length" instead.')
111+
->end()
112+
->scalarNode('executed_at_column_name')
113+
->defaultValue('executed_at')
114+
->setDeprecated('The "%node%" option is deprecated. Use "storage.table_storage.executed_at_column_name" instead.')
115+
->end()
50116
->scalarNode('all_or_nothing')->defaultValue(false)->end()
51-
->scalarNode('name')->defaultValue('Application Migrations')->end()
52117
->scalarNode('custom_template')->defaultValue(null)->end()
53118
->scalarNode('organize_migrations')->defaultValue(false)
54119
->info('Organize migrations mode. Possible values are: "BY_YEAR", "BY_YEAR_AND_MONTH", false')

DependencyInjection/DoctrineMigrationsExtension.php

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
use Symfony\Component\DependencyInjection\ContainerBuilder;
99
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
1010
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
11+
use function count;
12+
use function current;
13+
use function key;
1114

1215
/**
1316
* DoctrineMigrationsExtension.
@@ -17,14 +20,38 @@ class DoctrineMigrationsExtension extends Extension
1720
/**
1821
* Responds to the migrations configuration parameter.
1922
*
20-
* @param string[][] $configs
23+
* @param string[][]|array<string, array<string, array<string, string>|string>>> $configs
2124
*/
2225
public function load(array $configs, ContainerBuilder $container) : void
2326
{
2427
$configuration = new Configuration();
2528

2629
$config = $this->processConfiguration($configuration, $configs);
2730

31+
// 3.x forward compatibility layer
32+
if (isset($config['migrations_paths']) && count($config['migrations_paths'])>0) {
33+
$config['namespace'] = key($config['migrations_paths']);
34+
$config['dir_name'] = current($config['migrations_paths']);
35+
unset($config['migrations_paths']);
36+
}
37+
38+
if (isset($config['storage']['table_storage'])) {
39+
$storageConfig = $config['storage']['table_storage'];
40+
if (isset($storageConfig['table_name'])) {
41+
$config['table_name'] = $storageConfig['table_name'];
42+
}
43+
if (isset($storageConfig['version_column_name'])) {
44+
$config['column_name'] = $storageConfig['version_column_name'];
45+
}
46+
if (isset($storageConfig['version_column_length'])) {
47+
$config['column_length'] = $storageConfig['version_column_length'];
48+
}
49+
if (isset($storageConfig['executed_at_column_name'])) {
50+
$config['executed_at_column_name'] = $storageConfig['executed_at_column_name'];
51+
}
52+
unset($config['storage']);
53+
}
54+
2855
foreach ($config as $key => $value) {
2956
$container->setParameter($this->getAlias() . '.' . $key, $value);
3057
}

Resources/doc/index.rst

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,36 @@ application:
4141
4242
# config/packages/doctrine_migrations.yaml
4343
doctrine_migrations:
44+
name: 'Application Migrations'
45+
46+
# Namespace/path to search for migrations
47+
migrations_paths:
48+
'DoctrineMigrations': '%kernel.project_dir%/src/Migrations'
49+
50+
# Deprecated since v2.2, use "migrations_paths" instead (array value)
4451
dir_name: '%kernel.project_dir%/src/Migrations'
52+
53+
# Deprecated since v2.2, use "migrations_paths" instead (array key)
4554
namespace: DoctrineMigrations
55+
56+
storage:
57+
# Default (SQL table) metadata storage configuration
58+
table_storage:
59+
table_name: 'migration_versions'
60+
version_column_name: 'version'
61+
version_column_length: 1024
62+
executed_at_column_name: 'executed_at'
63+
execution_time_column_name: 'execution_time'
64+
65+
# Deprecated since v2.2, use "storage.table_storage.table_name" instead
4666
table_name: 'migration_versions'
67+
# Deprecated since v2.2, use "storage.table_storage.version_column_name" instead
4768
column_name: 'version'
69+
# Deprecated since v2.2, use "storage.table_storage.version_column_length" instead (minimum value has to be at least 1024)
4870
column_length: 14
71+
# Deprecated since v2.2, use "storage.table_storage.execution_time_column_name" instead
4972
executed_at_column_name: 'executed_at'
50-
name: 'Application Migrations'
73+
5174
# available in version >= 1.2. Possible values: "BY_YEAR", "BY_YEAR_AND_MONTH", false
5275
organize_migrations: false
5376
# available in version >= 1.3. Path to your custom migrations template
@@ -192,7 +215,7 @@ fill in the ``up()`` and ``down()`` methods), see the official Doctrine Migratio
192215

193216
.. tip::
194217

195-
If you need to use another database connection to execute migrations you may use option ``--db="doctrine-connection-name"``
218+
If you need to use another database connection to execute migrations you may use option ``--db="doctrine-connection-name"``
196219
where ``doctrine-connection-name`` is valid Doctrine connection defined in doctrine.yaml
197220

198221
Running Migrations during Deployment

Tests/DependencyInjection/DoctrineMigrationsExtensionTest.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,36 @@ public function testOrganizeMigrations() : void
2828
);
2929
}
3030

31+
public function testForwardCompatibilityLayer() : void
32+
{
33+
$container = $this->getContainer();
34+
$extension = new DoctrineMigrationsExtension();
35+
36+
$config = [
37+
'storage' => [
38+
'table_storage' => [
39+
'table_name' => 'doctrine_migration_versions_test',
40+
'version_column_name' => 'doctrine_migration_column_test',
41+
'version_column_length' => '2000',
42+
'executed_at_column_name' => 'doctrine_migration_executed_at_column_test',
43+
],
44+
],
45+
46+
'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
47+
48+
];
49+
50+
$extension->load(['doctrine_migrations' => $config], $container);
51+
52+
$this->assertEquals('a', $container->getParameter('doctrine_migrations.dir_name'));
53+
$this->assertEquals('DoctrineMigrationsTest', $container->getParameter('doctrine_migrations.namespace'));
54+
$this->assertEquals('doctrine_migration_versions_test', $container->getParameter('doctrine_migrations.table_name'));
55+
$this->assertEquals('doctrine_migration_column_test', $container->getParameter('doctrine_migrations.column_name'));
56+
$this->assertEquals(2000, $container->getParameter('doctrine_migrations.column_length'));
57+
$this->assertEquals(2000, $container->getParameter('doctrine_migrations.column_length'));
58+
$this->assertEquals('doctrine_migration_executed_at_column_test', $container->getParameter('doctrine_migrations.executed_at_column_name'));
59+
}
60+
3161
private function getContainer() : ContainerBuilder
3262
{
3363
return new ContainerBuilder(new ParameterBag([

0 commit comments

Comments
 (0)