Completed
Pull Request — master (#925)
by Asmir
02:17
created

DependencyFactory::getMigrationFactory()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Migrations;
6
7
use Doctrine\DBAL\Connection;
8
use Doctrine\Migrations\Configuration\Configuration;
9
use Doctrine\Migrations\Configuration\Connection\ConnectionLoader;
10
use Doctrine\Migrations\Configuration\EntityManager\EntityManagerLoader;
11
use Doctrine\Migrations\Configuration\Migration\ConfigurationLoader;
12
use Doctrine\Migrations\Exception\FrozenDependencies;
13
use Doctrine\Migrations\Exception\MissingDependency;
14
use Doctrine\Migrations\Finder\GlobFinder;
15
use Doctrine\Migrations\Finder\MigrationFinder;
16
use Doctrine\Migrations\Finder\RecursiveRegexFinder;
17
use Doctrine\Migrations\Generator\ClassNameGenerator;
18
use Doctrine\Migrations\Generator\ConcatenationFileBuilder;
19
use Doctrine\Migrations\Generator\DiffGenerator;
20
use Doctrine\Migrations\Generator\FileBuilder;
21
use Doctrine\Migrations\Generator\Generator;
22
use Doctrine\Migrations\Generator\SqlGenerator;
23
use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
24
use Doctrine\Migrations\Metadata\Storage\MetadataStorageConfiguration;
25
use Doctrine\Migrations\Metadata\Storage\TableMetadataStorage;
26
use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
27
use Doctrine\Migrations\Provider\DBALSchemaDiffProvider;
28
use Doctrine\Migrations\Provider\LazySchemaDiffProvider;
29
use Doctrine\Migrations\Provider\OrmSchemaProvider;
30
use Doctrine\Migrations\Provider\SchemaDiffProvider;
31
use Doctrine\Migrations\Provider\SchemaProvider;
32
use Doctrine\Migrations\Tools\Console\ConsoleInputMigratorConfigurationFactory;
33
use Doctrine\Migrations\Tools\Console\Helper\MigrationStatusInfosHelper;
34
use Doctrine\Migrations\Tools\Console\MigratorConfigurationFactory;
35
use Doctrine\Migrations\Version\AliasResolver;
36
use Doctrine\Migrations\Version\AlphabeticalComparator;
37
use Doctrine\Migrations\Version\Comparator;
38
use Doctrine\Migrations\Version\CurrentMigrationStatusCalculator;
39
use Doctrine\Migrations\Version\DbalExecutor;
40
use Doctrine\Migrations\Version\DbalMigrationFactory;
41
use Doctrine\Migrations\Version\DefaultAliasResolver;
42
use Doctrine\Migrations\Version\Executor;
43
use Doctrine\Migrations\Version\MigrationFactory;
44
use Doctrine\Migrations\Version\MigrationPlanCalculator;
45
use Doctrine\Migrations\Version\MigrationStatusCalculator;
46
use Doctrine\Migrations\Version\SortedMigrationPlanCalculator;
47
use Doctrine\ORM\EntityManagerInterface;
48
use Psr\Log\LoggerInterface;
49
use Psr\Log\NullLogger;
50
use Symfony\Component\Stopwatch\Stopwatch as SymfonyStopwatch;
51
use function array_key_exists;
52
use function preg_quote;
53
use function sprintf;
54
55
/**
56
 * The DependencyFactory is responsible for wiring up and managing internal class dependencies.
57
 */
58
class DependencyFactory
59
{
60
    /** @var Configuration */
61
    private $configuration;
62
63
    /** @var object[]|callable[] */
64
    private $dependencies = [];
65
66
    /** @var LoggerInterface */
67
    private $logger;
68
69
    /** @var Connection */
70
    private $connection;
71
72
    /** @var EntityManagerInterface|null */
73
    private $em;
74
75
    /** @var bool */
76
    private $frozen = false;
77
78
    /** @var ConfigurationLoader */
79
    private $configurationLoader;
80
81
    /** @var ConnectionLoader */
82
    private $connectionLoader;
83
84
    /** @var EntityManagerLoader|null */
85
    private $emLoader;
86
87 41
    public static function fromConnection(
88
        ConfigurationLoader $configurationLoader,
89
        ConnectionLoader $connectionLoader,
90
        ?LoggerInterface $logger = null
91
    ) : self {
92 41
        $dependencyFactory                      = new self($logger);
93 41
        $dependencyFactory->configurationLoader = $configurationLoader;
94 41
        $dependencyFactory->connectionLoader    = $connectionLoader;
95
96 41
        return $dependencyFactory;
97
    }
98
99 1
    public static function fromEntityManager(
100
        ConfigurationLoader $configurationLoader,
101
        EntityManagerLoader $emLoader,
102
        ?LoggerInterface $logger = null
103
    ) : self {
104 1
        $dependencyFactory                      = new self($logger);
105 1
        $dependencyFactory->configurationLoader = $configurationLoader;
106 1
        $dependencyFactory->emLoader            = $emLoader;
107
108 1
        return $dependencyFactory;
109
    }
110
111 42
    private function __construct(?LoggerInterface $logger)
112
    {
113 42
        $this->logger = $logger ?: new NullLogger();
114 42
    }
115
116 36
    public function isFrozen() : bool
117
    {
118 36
        return $this->frozen;
119
    }
120
121 36
    public function freeze() : void
122
    {
123 36
        $this->frozen = true;
124 36
        $this->getConfiguration()->freeze();
125 36
    }
126
127 37
    private function assertNotFrozen() : void
128
    {
129 37
        if ($this->frozen) {
130 1
            throw FrozenDependencies::new();
131
        }
132 36
    }
133
134 37
    public function hasEntityManager() : bool
135
    {
136 37
        return $this->emLoader !== null;
137
    }
138
139 39
    public function getConfiguration() : Configuration
140
    {
141 39
        if ($this->configuration === null) {
142 39
            $this->configuration = $this->configurationLoader->getConfiguration();
143
        }
144
145 39
        return $this->configuration;
146
    }
147
148 37
    public function getConnection() : Connection
149
    {
150 37
        if ($this->connection === null) {
151 37
            $this->connection = $this->hasEntityManager()
152 1
                ? $this->getEntityManager()->getConnection()
153 36
                : $this->connectionLoader->getConnection();
154
        }
155
156 37
        return $this->connection;
157
    }
158
159 2
    public function getEntityManager() : EntityManagerInterface
160
    {
161 2
        if ($this->em === null) {
162 2
            if ($this->emLoader === null) {
163 1
                throw MissingDependency::noEntityManager();
164
            }
165
166 1
            $this->em = $this->emLoader->getEntityManager();
167
        }
168
169 1
        return $this->em;
170
    }
171
172 35
    public function getVersionComparator() : Comparator
173
    {
174
        return $this->getDependency(Comparator::class, static function () : AlphabeticalComparator {
175 35
            return new AlphabeticalComparator();
176 35
        });
177
    }
178
179 35
    public function getLogger() : LoggerInterface
180
    {
181 35
        return $this->logger;
182
    }
183
184
    public function getEventDispatcher() : EventDispatcher
185
    {
186
        return $this->getDependency(EventDispatcher::class, function () : EventDispatcher {
187
            return new EventDispatcher(
188
                $this->getConnection(),
189
                $this->getConnection()->getEventManager()
190
            );
191
        });
192
    }
193
194
    public function getClassNameGenerator() : ClassNameGenerator
195
    {
196
        return $this->getDependency(ClassNameGenerator::class, static function () : ClassNameGenerator {
197
            return new ClassNameGenerator();
198
        });
199
    }
200
201
    public function getSchemaDumper() : SchemaDumper
202
    {
203
        return $this->getDependency(SchemaDumper::class, function () : SchemaDumper {
204
            $excludedTables = [];
205
206
            $metadataConfig = $this->getConfiguration()->getMetadataStorageConfiguration();
207
            if ($metadataConfig instanceof TableMetadataStorageConfiguration) {
208
                $excludedTables[] = sprintf('/^%s$/', preg_quote($metadataConfig->getTableName(), '/'));
209
            }
210
211
            return new SchemaDumper(
212
                $this->getConnection()->getDatabasePlatform(),
213
                $this->getConnection()->getSchemaManager(),
214
                $this->getMigrationGenerator(),
215
                $this->getMigrationSqlGenerator(),
216
                $excludedTables
217
            );
218
        });
219
    }
220
221
    private function getSchemaProvider() : SchemaProvider
222
    {
223
        return $this->getDependency(SchemaProvider::class, function () : SchemaProvider {
224
            return new OrmSchemaProvider($this->getEntityManager());
225
        });
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
            );
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
254
    private function getFileBuilder() : FileBuilder
255
    {
256
        return $this->getDependency(FileBuilder::class, static function () : FileBuilder {
257
            return new ConcatenationFileBuilder();
258
        });
259
    }
260
261
    private function getParameterFormatter() : ParameterFormatter
262
    {
263
        return $this->getDependency(ParameterFormatter::class, function () : ParameterFormatter {
264
            return new InlineParameterFormatter($this->getConnection());
265
        });
266
    }
267
268 38
    public function getMigrationsFinder() : MigrationFinder
269
    {
270
        return $this->getDependency(MigrationFinder::class, function () : MigrationFinder {
271 38
            $configs              = $this->getConfiguration();
272 38
            $needsRecursiveFinder = $configs->areMigrationsOrganizedByYear() || $configs->areMigrationsOrganizedByYearAndMonth();
273
274 38
            return $needsRecursiveFinder ? new RecursiveRegexFinder() : new GlobFinder();
275 38
        });
276
    }
277
278 35
    public function getMigrationRepository() : MigrationRepository
279
    {
280
        return $this->getDependency(MigrationRepository::class, function () : MigrationRepository {
281 35
            return new MigrationRepository(
282 35
                $this->getConfiguration()->getMigrationClasses(),
283 35
                $this->getConfiguration()->getMigrationDirectories(),
284 35
                $this->getMigrationsFinder(),
285 35
                $this->getMigrationFactory(),
286 35
                $this->getVersionComparator()
287
            );
288 35
        });
289
    }
290
291 35
    private function getMigrationFactory() : MigrationFactory
292
    {
293
        return $this->getDependency(MigrationFactory::class, function () : MigrationFactory {
294 35
            return new DbalMigrationFactory($this->getConnection(), $this->getLogger());
295 35
        });
296
    }
297
298
    /**
299
     * @param object|callable $service
300
     */
301 37
    public function setService(string $id, $service) : void
302
    {
303 37
        $this->assertNotFrozen();
304 36
        $this->dependencies[$id] = $service;
305 36
    }
306
307 35
    private function getMetadataStorageConfiguration() : MetadataStorageConfiguration
308
    {
309
        return $this->getDependency(MetadataStorageConfiguration::class, static function () : MetadataStorageConfiguration {
310 35
            return new TableMetadataStorageConfiguration();
311 35
        });
312
    }
313
314 35
    public function getMetadataStorage() : MetadataStorage
315
    {
316
        return $this->getDependency(MetadataStorage::class, function () : MetadataStorage {
317 35
            return new TableMetadataStorage(
318 35
                $this->getConnection(),
319 35
                $this->getMetadataStorageConfiguration()
320
            );
321 35
        });
322
    }
323
324
    private function getVersionExecutor() : Executor
325
    {
326
        return $this->getDependency(Executor::class, function () : Executor {
327
            return new DbalExecutor(
328
                $this->getMetadataStorage(),
329
                $this->getEventDispatcher(),
330
                $this->getConnection(),
331
                $this->getSchemaDiffProvider(),
332
                $this->getLogger(),
333
                $this->getParameterFormatter(),
334
                $this->getStopwatch()
335
            );
336
        });
337
    }
338
339 2
    public function getQueryWriter() : QueryWriter
340
    {
341
        return $this->getDependency(QueryWriter::class, function () : QueryWriter {
342
            return new FileQueryWriter(
343
                $this->getFileBuilder(),
344
                $this->logger
345
            );
346 2
        });
347
    }
348
349 16
    public function getVersionAliasResolver() : AliasResolver
350
    {
351
        return $this->getDependency(AliasResolver::class, function () : AliasResolver {
352 16
            return new DefaultAliasResolver(
353 16
                $this->getMigrationRepository(),
354 16
                $this->getMetadataStorage(),
355 16
                $this->getMigrationStatusCalculator()
356
            );
357 16
        });
358
    }
359
360 22
    public function getMigrationStatusCalculator() : MigrationStatusCalculator
361
    {
362
        return $this->getDependency(MigrationStatusCalculator::class, function () : MigrationStatusCalculator {
363 22
            return new CurrentMigrationStatusCalculator(
364 22
                $this->getMigrationRepository(),
365 22
                $this->getMetadataStorage()
366
            );
367 22
        });
368
    }
369
370 10
    public function getMigrationPlanCalculator() : MigrationPlanCalculator
371
    {
372
        return $this->getDependency(MigrationPlanCalculator::class, function () : MigrationPlanCalculator {
373 10
            return new SortedMigrationPlanCalculator(
374 10
                $this->getMigrationRepository(),
375 10
                $this->getMetadataStorage()
376
            );
377 10
        });
378
    }
379
380
    public function getMigrationGenerator() : Generator
381
    {
382
        return $this->getDependency(Generator::class, function () : Generator {
383
            return new Generator($this->getConfiguration());
384
        });
385
    }
386
387
    public function getMigrationSqlGenerator() : SqlGenerator
388
    {
389
        return $this->getDependency(SqlGenerator::class, function () : SqlGenerator {
390
            return new SqlGenerator(
391
                $this->getConfiguration(),
392
                $this->getConnection()->getDatabasePlatform()
393
            );
394
        });
395
    }
396
397 14
    public function getConsoleInputMigratorConfigurationFactory() : MigratorConfigurationFactory
398
    {
399
        return $this->getDependency(MigratorConfigurationFactory::class, function () : MigratorConfigurationFactory {
400 14
            return new ConsoleInputMigratorConfigurationFactory(
401 14
                $this->getConfiguration()
402
            );
403 14
        });
404
    }
405
406 3
    public function getMigrationStatusInfosHelper() : MigrationStatusInfosHelper
407
    {
408
        return $this->getDependency(MigrationStatusInfosHelper::class, function () : MigrationStatusInfosHelper {
409 3
            return new MigrationStatusInfosHelper(
410 3
                $this->getConfiguration(),
411 3
                $this->getConnection(),
412 3
                $this->getVersionAliasResolver(),
413 3
                $this->getMigrationRepository(),
414 3
                $this->getMetadataStorage()
415
            );
416 3
        });
417
    }
418
419 6
    public function getMigrator() : Migrator
420
    {
421
        return $this->getDependency(Migrator::class, function () : Migrator {
422
            return new DbalMigrator(
423
                $this->getConnection(),
424
                $this->getEventDispatcher(),
425
                $this->getVersionExecutor(),
426
                $this->logger,
427
                $this->getStopwatch()
428
            );
429 6
        });
430
    }
431
432
    public function getStopwatch() : Stopwatch
433
    {
434
        return $this->getDependency(Stopwatch::class, static function () : Stopwatch {
435
            $symfonyStopwatch = new SymfonyStopwatch(true);
436
437
            return new Stopwatch($symfonyStopwatch);
438
        });
439
    }
440
441
    public function getRollup() : Rollup
442
    {
443
        return $this->getDependency(Rollup::class, function () : Rollup {
444
            return new Rollup(
445
                $this->getMetadataStorage(),
446
                $this->getMigrationRepository()
447
            );
448
        });
449
    }
450
451
    /**
452
     * @return mixed
453
     */
454 43
    private function getDependency(string $id, callable $callback)
455
    {
456 43
        if (! array_key_exists($id, $this->dependencies)) {
457 43
            $this->dependencies[$id] = $callback();
458
        }
459
460 43
        return $this->dependencies[$id];
461
    }
462
}
463