Failed Conditions
Pull Request — master (#298)
by Asmir
07:36
created

php$0 ➔ getContainerBuilder()   A

Complexity

Conditions 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Bundle\MigrationsBundle\Tests\DependencyInjection;
6
7
use Doctrine\Bundle\MigrationsBundle\DependencyInjection\CompilerPass\ConfigureDependencyFactoryPass;
8
use Doctrine\Bundle\MigrationsBundle\DependencyInjection\DoctrineMigrationsExtension;
9
use Doctrine\Bundle\MigrationsBundle\Tests\Fixtures\CustomEntityManager;
10
use Doctrine\DBAL\Connection;
11
use Doctrine\Migrations\Configuration\Configuration;
12
use Doctrine\Migrations\DependencyFactory;
13
use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
14
use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
15
use Doctrine\Migrations\Version\Comparator;
16
use Doctrine\Migrations\Version\Version;
17
use Doctrine\ORM\EntityManager;
18
use InvalidArgumentException;
19
use PHPUnit\Framework\TestCase;
20
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
21
use Symfony\Component\Config\FileLocator;
22
use Symfony\Component\DependencyInjection\Alias;
23
use Symfony\Component\DependencyInjection\ContainerBuilder;
24
use Symfony\Component\DependencyInjection\Definition;
25
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
26
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
27
use function assert;
28
use function method_exists;
29
use function sys_get_temp_dir;
30
31
class DoctrineMigrationsExtensionTest extends TestCase
32
{
33
    public function testXmlConfigs() : void
34
    {
35
        $container = $this->getContainerBuilder();
36
37
        $conn = $this->createMock(Connection::class);
38
        $container->set('doctrine.dbal.default_connection', $conn);
39
40
        $container->registerExtension(new DoctrineMigrationsExtension());
41
        $container->setAlias('doctrine.migrations.configuration.test', new Alias('doctrine.migrations.configuration', true));
42
43
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Fixtures'));
44
        $loader->load('conf.xml');
45
46
        $container->compile();
47
48
        $config = $container->get('doctrine.migrations.configuration.test');
49
        $this->assertConfigs($config);
50
    }
51
52
    public function testFullConfig() : void
53
    {
54
        $config = [
55
            'name' => 'Doctrine Sandbox Migrations',
56
            'storage' => [
57
                'table_storage' => [
58
                    'table_name'                 => 'doctrine_migration_versions_test',
59
                    'version_column_name'        => 'doctrine_migration_column_test',
60
                    'version_column_length'      => 2000,
61
                    'executed_at_column_name'    => 'doctrine_migration_executed_at_column_test',
62
                    'execution_time_column_name' => 'doctrine_migration_execution_time_column_test',
63
                ],
64
            ],
65
66
            'migrations_paths' => [
67
                'DoctrineMigrationsTest' => 'a',
68
                'DoctrineMigrationsTest2' => 'b',
69
            ],
70
71
            'migrations' => ['Foo', 'Bar'],
72
73
            'organize_migrations' => 'BY_YEAR_AND_MONTH',
74
75
            'all_or_nothing'            => true,
76
            'check_database_platform'   => true,
77
        ];
78
        $container = $this->getContainer($config);
79
80
        $conn = $this->createMock(Connection::class);
81
        $container->set('doctrine.dbal.default_connection', $conn);
82
83
        $container->compile();
84
85
        $config = $container->get('doctrine.migrations.configuration');
86
87
        $this->assertConfigs($config);
88
    }
89
90
    public function testNoConfig() : void
91
    {
92
        $this->expectException(InvalidConfigurationException::class);
93
        $this->expectExceptionMessage('The child node "migrations_paths" at path "doctrine_migrations" must be configured.');
94
95
        $container = $this->getContainer([]);
96
97
        $conn = $this->createMock(Connection::class);
98
        $container->set('doctrine.dbal.default_connection', $conn);
99
        $container->compile();
100
101
        $container->get('doctrine.migrations.configuration');
102
    }
103
104
105
    private function assertConfigs(?object $config) : void
106
    {
107
        self::assertInstanceOf(Configuration::class, $config);
108
        self::assertSame('Doctrine Sandbox Migrations', $config->getName());
0 ignored issues
show
Bug introduced by
The method getName() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

108
        self::assertSame('Doctrine Sandbox Migrations', $config->/** @scrutinizer ignore-call */ getName());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
109
        self::assertSame([
110
            'DoctrineMigrationsTest' => 'a',
111
            'DoctrineMigrationsTest2' => 'b',
112
113
        ], $config->getMigrationDirectories());
114
115
        self::assertSame(['Foo', 'Bar'], $config->getMigrationClasses());
116
        self::assertTrue($config->isAllOrNothing());
117
        self::assertTrue($config->isDatabasePlatformChecked());
118
        self::assertTrue($config->areMigrationsOrganizedByYearAndMonth());
119
120
        $storage = $config->getMetadataStorageConfiguration();
121
        self::assertInstanceOf(TableMetadataStorageConfiguration::class, $storage);
122
123
        self::assertSame('doctrine_migration_versions_test', $storage->getTableName());
124
        self::assertSame('doctrine_migration_column_test', $storage->getVersionColumnName());
125
        self::assertSame(2000, $storage->getVersionColumnLength());
126
        self::assertSame('doctrine_migration_execution_time_column_test', $storage->getExecutionTimeColumnName());
127
        self::assertSame('doctrine_migration_executed_at_column_test', $storage->getExecutedAtColumnName());
128
    }
129
130
    public function testCustomSorter() : void
131
    {
132
        $config    = [
133
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
134
            'services' => [Comparator::class => 'my_sorter'],
135
        ];
136
        $container = $this->getContainer($config);
137
138
        $conn = $this->createMock(Connection::class);
139
        $container->set('doctrine.dbal.default_connection', $conn);
140
141
        $sorter = new class() implements Comparator{
142
            public function compare(Version $a, Version $b) : int
143
            {
144
            }
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...
145
        };
146
        $container->set('my_sorter', $sorter);
147
148
        $container->compile();
149
150
        $di = $container->get('doctrine.migrations.dependency_factory');
151
        self::assertInstanceOf(DependencyFactory::class, $di);
152
        self::assertSame($sorter, $di->getVersionComparator());
153
    }
154
155
    public function testCustomConnection() : void
156
    {
157
        $config    = [
158
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
159
            'connection' => 'custom',
160
        ];
161
        $container = $this->getContainer($config);
162
163
        $conn = $this->createMock(Connection::class);
164
        $container->set('doctrine.dbal.custom_connection', $conn);
165
166
        $container->compile();
167
168
        $di = $container->get('doctrine.migrations.dependency_factory');
169
        self::assertInstanceOf(DependencyFactory::class, $di);
170
        self::assertSame($conn, $di->getConnection());
171
    }
172
173
174
    public function testPrefersEntityManagerOverConnection() : void
175
    {
176
        $config    = [
177
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
178
        ];
179
        $container = $this->getContainer($config);
180
181
        $em = $this->createMock(EntityManager::class);
182
        $container->set('doctrine.orm.default_entity_manager', $em);
183
184
        $container->compile();
185
186
        $di = $container->get('doctrine.migrations.dependency_factory');
187
188
        self::assertInstanceOf(DependencyFactory::class, $di);
189
        self::assertSame($em, $di->getEntityManager());
190
    }
191
192
    public function testCustomEntityManager() : void
193
    {
194
        $config    = [
195
            'em' => 'custom',
196
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
197
        ];
198
        $container = $this->getContainer($config);
199
200
        $em = new Definition(CustomEntityManager::class);
201
        $container->setDefinition('doctrine.orm.custom_entity_manager', $em);
202
203
        $container->compile();
204
205
        $di = $container->get('doctrine.migrations.dependency_factory');
206
        self::assertInstanceOf(DependencyFactory::class, $di);
207
208
        $em = $di->getEntityManager();
209
        self::assertInstanceOf(CustomEntityManager::class, $em);
210
211
        assert(method_exists($di->getConnection(), 'getEm'));
212
        self::assertInstanceOf(CustomEntityManager::class, $di->getConnection()->getEm());
213
        self::assertSame($em, $di->getConnection()->getEm());
214
    }
215
216
    public function testCustomMetadataStorage() : void
217
    {
218
        $config = [
219
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
220
            'services' => [MetadataStorage::class => 'mock_storage_service'],
221
        ];
222
223
        $container = $this->getContainer($config);
224
225
        $mockStorage = $this->createMock(MetadataStorage::class);
226
        $container->set('mock_storage_service', $mockStorage);
227
228
        $conn = $this->createMock(Connection::class);
229
        $container->set('doctrine.dbal.default_connection', $conn);
230
231
        $container->compile();
232
233
        $di = $container->get('doctrine.migrations.dependency_factory');
234
        self::assertInstanceOf(DependencyFactory::class, $di);
235
        self::assertSame($mockStorage, $di->getMetadataStorage());
236
    }
237
238
    public function testInvalidService() : void
239
    {
240
        $this->expectException(InvalidConfigurationException::class);
241
        $this->expectExceptionMessage('Invalid configuration for path "doctrine_migrations.services": Valid services for the DoctrineMigrationsBundle must be in the "Doctrine\Migrations" namespace.');
242
243
        $config    = [
244
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
245
            'services' => ['foo' => 'mock_storage_service'],
246
        ];
247
        $container = $this->getContainer($config);
248
249
        $conn = $this->createMock(Connection::class);
250
        $container->set('doctrine.dbal.default_connection', $conn);
251
252
        $container->compile();
253
    }
254
255
    public function testCanNotSpecifyBothEmAndConnection() : void
256
    {
257
        $this->expectExceptionMessage('You cannot specify both "connection" and "em" in the DoctrineMigrationsBundle configurations');
258
        $this->expectException(InvalidArgumentException::class);
259
260
        $config = [
261
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
262
            'em' => 'custom',
263
            'connection' => 'custom',
264
        ];
265
266
        $container = $this->getContainer($config);
267
268
        $container->compile();
269
    }
270
271
    /**
272
     * @param mixed $config
273
     */
274
    public function getContainer($config) : ContainerBuilder
275
    {
276
        $container = $this->getContainerBuilder();
277
        $container->addCompilerPass(new ConfigureDependencyFactoryPass());
278
279
        $extension = new DoctrineMigrationsExtension();
280
281
        $extension->load(['doctrine_migrations' => $config], $container);
282
283
        $container->getDefinition('doctrine.migrations.dependency_factory')->setPublic(true);
284
        $container->getDefinition('doctrine.migrations.configuration')->setPublic(true);
285
286
        return $container;
287
    }
288
289
    private function getContainerBuilder() : ContainerBuilder
290
    {
291
        return new ContainerBuilder(new ParameterBag([
292
            'kernel.debug' => false,
293
            'kernel.bundles' => [],
294
            'kernel.cache_dir' => sys_get_temp_dir(),
295
            'kernel.environment' => 'test',
296
            'kernel.project_dir' => __DIR__ . '/../',
297
        ]));
298
    }
299
}
300