Failed Conditions
Push — master ( f9b4c0...25e0b2 )
by Asmir
41s queued 11s
created

testBundleRelativePathResolution()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 14
c 0
b 0
f 0
dl 0
loc 22
rs 9.7998
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Bundle\MigrationsBundle\Tests\DependencyInjection;
6
7
use Doctrine\Bundle\MigrationsBundle\DependencyInjection\DoctrineMigrationsExtension;
8
use Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle;
9
use Doctrine\Bundle\MigrationsBundle\Tests\Fixtures\CustomEntityManager;
10
use Doctrine\Bundle\MigrationsBundle\Tests\Fixtures\TestBundle\TestBundle;
11
use Doctrine\DBAL\Connection;
12
use Doctrine\Migrations\Configuration\Configuration;
13
use Doctrine\Migrations\DependencyFactory;
14
use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
15
use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
16
use Doctrine\Migrations\Version\Comparator;
17
use Doctrine\Migrations\Version\Version;
18
use Doctrine\ORM\EntityManager;
19
use InvalidArgumentException;
20
use PHPUnit\Framework\TestCase;
21
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
22
use Symfony\Component\Config\FileLocator;
23
use Symfony\Component\DependencyInjection\Alias;
24
use Symfony\Component\DependencyInjection\ContainerBuilder;
25
use Symfony\Component\DependencyInjection\Definition;
26
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
27
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
28
use function assert;
29
use function method_exists;
30
use function sys_get_temp_dir;
31
32
class DoctrineMigrationsExtensionTest extends TestCase
33
{
34
    public function testXmlConfigs() : void
35
    {
36
        $container = $this->getContainerBuilder();
37
38
        $conn = $this->createMock(Connection::class);
39
        $container->set('doctrine.dbal.default_connection', $conn);
40
41
        $container->registerExtension(new DoctrineMigrationsExtension());
42
43
        $container->setAlias('doctrine.migrations.configuration.test', new Alias('doctrine.migrations.configuration', true));
44
45
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Fixtures'));
46
        $loader->load('conf.xml');
47
48
        $container->compile();
49
50
        $config = $container->get('doctrine.migrations.configuration.test');
51
        $this->assertConfigs($config);
52
    }
53
54
    public function testFullConfig() : void
55
    {
56
        $config = [
57
            'storage' => [
58
                'table_storage' => [
59
                    'table_name'                 => 'doctrine_migration_versions_test',
60
                    'version_column_name'        => 'doctrine_migration_column_test',
61
                    'version_column_length'      => 2000,
62
                    'executed_at_column_name'    => 'doctrine_migration_executed_at_column_test',
63
                    'execution_time_column_name' => 'doctrine_migration_execution_time_column_test',
64
                ],
65
            ],
66
67
            'migrations_paths' => [
68
                'DoctrineMigrationsTest' => 'a',
69
                'DoctrineMigrationsTest2' => 'b',
70
            ],
71
72
            'migrations' => ['Foo', 'Bar'],
73
74
            'organize_migrations' => 'BY_YEAR_AND_MONTH',
75
76
            'all_or_nothing'            => true,
77
            'check_database_platform'   => true,
78
        ];
79
        $container = $this->getContainer($config);
80
81
        $conn = $this->createMock(Connection::class);
82
        $container->set('doctrine.dbal.default_connection', $conn);
83
84
        $container->compile();
85
86
        $config = $container->get('doctrine.migrations.configuration');
87
88
        $this->assertConfigs($config);
89
    }
90
91
    public function testNoConfigsAreNeeded() : void
92
    {
93
        $container = $this->getContainer([]);
94
95
        $conn = $this->createMock(Connection::class);
96
        $container->set('doctrine.dbal.default_connection', $conn);
97
        $container->compile();
98
99
        $config = $container->get('doctrine.migrations.configuration');
100
101
        self::assertInstanceOf(Configuration::class, $config);
102
        self::assertSame([], $config->getMigrationDirectories());
103
    }
104
105
    public function testBundleRelativePathResolution() : void
106
    {
107
        $container = $this->getContainer([
108
            'migrations_paths' => [
109
                'DoctrineMigrationsTest' => '@TestBundle',
110
                'DoctrineMigrationsTestAnother' => '@TestBundle/another-path',
111
            ],
112
        ]);
113
114
        $conn = $this->createMock(Connection::class);
115
        $container->set('doctrine.dbal.default_connection', $conn);
116
        $container->compile();
117
118
        $config = $container->get('doctrine.migrations.configuration');
119
        $bundle = new TestBundle();
120
121
        self::assertInstanceOf(Configuration::class, $config);
122
        self::assertSame([
123
            'DoctrineMigrationsTest' => $bundle->getPath(),
124
            'DoctrineMigrationsTestAnother' => $bundle->getPath() . '/another-path',
125
126
        ], $config->getMigrationDirectories());
127
    }
128
129
    private function assertConfigs(?object $config) : void
130
    {
131
        self::assertInstanceOf(Configuration::class, $config);
132
        self::assertSame([
133
            'DoctrineMigrationsTest' => 'a',
134
            'DoctrineMigrationsTest2' => 'b',
135
136
        ], $config->getMigrationDirectories());
137
138
        self::assertSame(['Foo', 'Bar'], $config->getMigrationClasses());
139
        self::assertTrue($config->isAllOrNothing());
140
        self::assertTrue($config->isDatabasePlatformChecked());
141
        self::assertTrue($config->areMigrationsOrganizedByYearAndMonth());
142
143
        $storage = $config->getMetadataStorageConfiguration();
144
        self::assertInstanceOf(TableMetadataStorageConfiguration::class, $storage);
145
146
        self::assertSame('doctrine_migration_versions_test', $storage->getTableName());
147
        self::assertSame('doctrine_migration_column_test', $storage->getVersionColumnName());
148
        self::assertSame(2000, $storage->getVersionColumnLength());
149
        self::assertSame('doctrine_migration_execution_time_column_test', $storage->getExecutionTimeColumnName());
150
        self::assertSame('doctrine_migration_executed_at_column_test', $storage->getExecutedAtColumnName());
151
    }
152
153
    public function testCustomSorter() : void
154
    {
155
        $config    = [
156
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
157
            'services' => [Comparator::class => 'my_sorter'],
158
        ];
159
        $container = $this->getContainer($config);
160
161
        $conn = $this->createMock(Connection::class);
162
        $container->set('doctrine.dbal.default_connection', $conn);
163
164
        $sorter = new class() implements Comparator{
165
            public function compare(Version $a, Version $b) : int
166
            {
167
            }
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return integer. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
168
        };
169
        $container->set('my_sorter', $sorter);
170
171
        $container->compile();
172
173
        $di = $container->get('doctrine.migrations.dependency_factory');
174
        self::assertInstanceOf(DependencyFactory::class, $di);
175
        self::assertSame($sorter, $di->getVersionComparator());
176
    }
177
178
    public function testCustomConnection() : void
179
    {
180
        $config    = [
181
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
182
            'connection' => 'custom',
183
        ];
184
        $container = $this->getContainer($config);
185
186
        $conn = $this->createMock(Connection::class);
187
        $container->set('doctrine.dbal.custom_connection', $conn);
188
189
        $container->compile();
190
191
        $di = $container->get('doctrine.migrations.dependency_factory');
192
        self::assertInstanceOf(DependencyFactory::class, $di);
193
        self::assertSame($conn, $di->getConnection());
194
    }
195
196
197
    public function testPrefersEntityManagerOverConnection() : void
198
    {
199
        $config    = [
200
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
201
        ];
202
        $container = $this->getContainer($config);
203
204
        $em = $this->createMock(EntityManager::class);
205
        $container->set('doctrine.orm.default_entity_manager', $em);
206
207
        $container->compile();
208
209
        $di = $container->get('doctrine.migrations.dependency_factory');
210
211
        self::assertInstanceOf(DependencyFactory::class, $di);
212
        self::assertSame($em, $di->getEntityManager());
213
    }
214
215
    public function testCustomEntityManager() : void
216
    {
217
        $config    = [
218
            'em' => 'custom',
219
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
220
        ];
221
        $container = $this->getContainer($config);
222
223
        $em = new Definition(CustomEntityManager::class);
224
        $container->setDefinition('doctrine.orm.custom_entity_manager', $em);
225
226
        $container->compile();
227
228
        $di = $container->get('doctrine.migrations.dependency_factory');
229
        self::assertInstanceOf(DependencyFactory::class, $di);
230
231
        $em = $di->getEntityManager();
232
        self::assertInstanceOf(CustomEntityManager::class, $em);
233
234
        assert(method_exists($di->getConnection(), 'getEm'));
235
        self::assertInstanceOf(CustomEntityManager::class, $di->getConnection()->getEm());
236
        self::assertSame($em, $di->getConnection()->getEm());
237
    }
238
239
    public function testCustomMetadataStorage() : void
240
    {
241
        $config = [
242
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
243
            'services' => [MetadataStorage::class => 'mock_storage_service'],
244
        ];
245
246
        $container = $this->getContainer($config);
247
248
        $mockStorage = $this->createMock(MetadataStorage::class);
249
        $container->set('mock_storage_service', $mockStorage);
250
251
        $conn = $this->createMock(Connection::class);
252
        $container->set('doctrine.dbal.default_connection', $conn);
253
254
        $container->compile();
255
256
        $di = $container->get('doctrine.migrations.dependency_factory');
257
        self::assertInstanceOf(DependencyFactory::class, $di);
258
        self::assertSame($mockStorage, $di->getMetadataStorage());
259
    }
260
261
    public function testInvalidService() : void
262
    {
263
        $this->expectException(InvalidConfigurationException::class);
264
        $this->expectExceptionMessage('Invalid configuration for path "doctrine_migrations.services": Valid services for the DoctrineMigrationsBundle must be in the "Doctrine\Migrations" namespace.');
265
266
        $config    = [
267
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
268
            'services' => ['foo' => 'mock_storage_service'],
269
        ];
270
        $container = $this->getContainer($config);
271
272
        $conn = $this->createMock(Connection::class);
273
        $container->set('doctrine.dbal.default_connection', $conn);
274
275
        $container->compile();
276
    }
277
278
    public function testCanNotSpecifyBothEmAndConnection() : void
279
    {
280
        $this->expectExceptionMessage('You cannot specify both "connection" and "em" in the DoctrineMigrationsBundle configurations');
281
        $this->expectException(InvalidArgumentException::class);
282
283
        $config = [
284
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
285
            'em' => 'custom',
286
            'connection' => 'custom',
287
        ];
288
289
        $container = $this->getContainer($config);
290
291
        $container->compile();
292
    }
293
294
    /**
295
     * @param mixed[] $config
296
     */
297
    private function getContainer(array $config) : ContainerBuilder
298
    {
299
        $container = $this->getContainerBuilder();
300
301
        $bundle = new DoctrineMigrationsBundle();
302
        $bundle->build($container);
303
304
        $extension = new DoctrineMigrationsExtension();
305
306
        $extension->load(['doctrine_migrations' => $config], $container);
307
308
        $container->getDefinition('doctrine.migrations.dependency_factory')->setPublic(true);
309
        $container->getDefinition('doctrine.migrations.configuration')->setPublic(true);
310
311
        return $container;
312
    }
313
314
    private function getContainerBuilder() : ContainerBuilder
315
    {
316
        $bundle = new TestBundle();
317
        return new ContainerBuilder(new ParameterBag([
318
            'kernel.debug' => false,
319
            'kernel.bundles' => [$bundle->getName() => TestBundle::class],
320
            'kernel.bundles_metadata' => [
321
                $bundle->getName() => [
322
                    'path' => $bundle->getPath(),
323
                    'namespace' => $bundle->getNamespace(),
324
                ],
325
            ],
326
            'kernel.cache_dir' => sys_get_temp_dir(),
327
            'kernel.environment' => 'test',
328
            'kernel.project_dir' => __DIR__ . '/../',
329
        ]));
330
    }
331
}
332