Completed
Pull Request — master (#975)
by Asmir
02:12
created

DependencyFactory::setDefinition()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

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