Completed
Pull Request — master (#927)
by
unknown
02:50
created

DependencyFactory   B

Complexity

Total Complexity 50

Size/Duplication

Total Lines 407
Duplicated Lines 0 %

Test Coverage

Coverage 58.33%

Importance

Changes 6
Bugs 1 Features 0
Metric Value
eloc 158
c 6
b 1
f 0
dl 0
loc 407
ccs 112
cts 192
cp 0.5833
rs 8.4
wmc 50

39 Methods

Rating   Name   Duplication   Size   Complexity  
A fromEntityManager() 0 10 1
A fromConnection() 0 10 1
A assertNotFrozen() 0 4 2
A getLogger() 0 4 1
A getConnection() 0 9 3
A getFileBuilder() 0 4 1
A getConfiguration() 0 7 2
A getMigrationSqlGenerator() 0 6 1
A freeze() 0 4 1
A getMigrationFactory() 0 4 1
A setService() 0 4 1
A getDiffGenerator() 0 10 1
A getMigrationRepository() 0 9 1
A getSchemaDumper() 0 16 2
A getParameterFormatter() 0 4 1
A getMigrationStatusInfosHelper() 0 9 1
A getStopwatch() 0 6 1
A getEventDispatcher() 0 6 1
A getSchemaDiffProvider() 0 7 1
A getQueryWriter() 0 6 1
A getMigrationGenerator() 0 4 1
A getVersionExecutor() 0 11 1
A getMigrationsFinder() 0 7 3
A getEntityManager() 0 11 3
A hasEntityManager() 0 3 1
A getVersionComparator() 0 4 1
A getDependency() 0 7 2
A getMigrationStatusCalculator() 0 6 1
A __construct() 0 4 2
A getRollup() 0 6 1
A getMetadataStorage() 0 6 1
A getConsoleInputMigratorConfigurationFactory() 0 5 1
A getClassNameGenerator() 0 4 1
A isFrozen() 0 3 1
A getMigrationPlanCalculator() 0 6 1
A getMigrator() 0 9 1
A getVersionAliasResolver() 0 7 1
A getSchemaProvider() 0 4 1
A getMetadataStorageConfiguration() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like DependencyFactory often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DependencyFactory, and based on these observations, apply Extract Interface, too.

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
        if ($logger !== null) {
0 ignored issues
show
introduced by
Use early exit to reduce code nesting.
Loading history...
114 13
            $this->setService(LoggerInterface::class, $logger);
115
        }
116 42
    }
117
118 36
    public function isFrozen() : bool
119
    {
120 36
        return $this->frozen;
121
    }
122
123 36
    public function freeze() : void
124
    {
125 36
        $this->frozen = true;
126 36
        $this->getConfiguration()->freeze();
127 36
    }
128
129 37
    private function assertNotFrozen() : void
130
    {
131 37
        if ($this->frozen) {
132 1
            throw FrozenDependencies::new();
133
        }
134 36
    }
135
136 37
    public function hasEntityManager() : bool
137
    {
138 37
        return $this->emLoader !== null;
139
    }
140
141 39
    public function getConfiguration() : Configuration
142
    {
143 39
        if ($this->configuration === null) {
144 39
            $this->configuration = $this->configurationLoader->getConfiguration();
145
        }
146
147 39
        return $this->configuration;
148
    }
149
150 37
    public function getConnection() : Connection
151
    {
152 37
        if ($this->connection === null) {
153 37
            $this->connection = $this->hasEntityManager()
154 1
                ? $this->getEntityManager()->getConnection()
155 36
                : $this->connectionLoader->getConnection();
156
        }
157
158 37
        return $this->connection;
159
    }
160
161 2
    public function getEntityManager() : EntityManagerInterface
162
    {
163 2
        if ($this->em === null) {
164 2
            if ($this->emLoader === null) {
165 1
                throw MissingDependency::noEntityManager();
166
            }
167
168 1
            $this->em = $this->emLoader->getEntityManager();
169
        }
170
171 1
        return $this->em;
172
    }
173
174 35
    public function getVersionComparator() : Comparator
175
    {
176
        return $this->getDependency(Comparator::class, static function () : AlphabeticalComparator {
177 35
            return new AlphabeticalComparator();
178 35
        });
179
    }
180
181 35
    public function getLogger() : LoggerInterface
182
    {
183
        return $this->getDependency(LoggerInterface::class, static function () : LoggerInterface {
184 21
            return new NullLogger();
185 35
        });
186
    }
187
188
    public function getEventDispatcher() : EventDispatcher
189
    {
190
        return $this->getDependency(EventDispatcher::class, function () : EventDispatcher {
191
            return new EventDispatcher(
192
                $this->getConnection(),
193
                $this->getConnection()->getEventManager()
194
            );
195
        });
196
    }
197
198
    public function getClassNameGenerator() : ClassNameGenerator
199
    {
200
        return $this->getDependency(ClassNameGenerator::class, static function () : ClassNameGenerator {
201
            return new ClassNameGenerator();
202
        });
203
    }
204
205
    public function getSchemaDumper() : SchemaDumper
206
    {
207
        return $this->getDependency(SchemaDumper::class, function () : SchemaDumper {
208
            $excludedTables = [];
209
210
            $metadataConfig = $this->getConfiguration()->getMetadataStorageConfiguration();
211
            if ($metadataConfig instanceof TableMetadataStorageConfiguration) {
212
                $excludedTables[] = sprintf('/^%s$/', preg_quote($metadataConfig->getTableName(), '/'));
213
            }
214
215
            return new SchemaDumper(
216
                $this->getConnection()->getDatabasePlatform(),
217
                $this->getConnection()->getSchemaManager(),
218
                $this->getMigrationGenerator(),
219
                $this->getMigrationSqlGenerator(),
220
                $excludedTables
221
            );
222
        });
223
    }
224
225
    private function getSchemaProvider() : SchemaProvider
226
    {
227
        return $this->getDependency(SchemaProvider::class, function () : SchemaProvider {
228
            return new OrmSchemaProvider($this->getEntityManager());
229
        });
230
    }
231
232
    public function getDiffGenerator() : DiffGenerator
233
    {
234
        return $this->getDependency(DiffGenerator::class, function () : DiffGenerator {
235
            return new DiffGenerator(
236
                $this->getConnection()->getConfiguration(),
237
                $this->getConnection()->getSchemaManager(),
238
                $this->getSchemaProvider(),
239
                $this->getConnection()->getDatabasePlatform(),
240
                $this->getMigrationGenerator(),
241
                $this->getMigrationSqlGenerator()
242
            );
243
        });
244
    }
245
246
    public function getSchemaDiffProvider() : SchemaDiffProvider
247
    {
248
        return $this->getDependency(SchemaDiffProvider::class, function () : LazySchemaDiffProvider {
249
            return LazySchemaDiffProvider::fromDefaultProxyFactoryConfiguration(
250
                new DBALSchemaDiffProvider(
251
                    $this->getConnection()->getSchemaManager(),
252
                    $this->getConnection()->getDatabasePlatform()
253
                )
254
            );
255
        });
256
    }
257
258
    private function getFileBuilder() : FileBuilder
259
    {
260
        return $this->getDependency(FileBuilder::class, static function () : FileBuilder {
261
            return new ConcatenationFileBuilder();
262
        });
263
    }
264
265
    private function getParameterFormatter() : ParameterFormatter
266
    {
267
        return $this->getDependency(ParameterFormatter::class, function () : ParameterFormatter {
268
            return new InlineParameterFormatter($this->getConnection());
269
        });
270
    }
271
272 38
    public function getMigrationsFinder() : MigrationFinder
273
    {
274
        return $this->getDependency(MigrationFinder::class, function () : MigrationFinder {
275 38
            $configs              = $this->getConfiguration();
276 38
            $needsRecursiveFinder = $configs->areMigrationsOrganizedByYear() || $configs->areMigrationsOrganizedByYearAndMonth();
277
278 38
            return $needsRecursiveFinder ? new RecursiveRegexFinder() : new GlobFinder();
279 38
        });
280
    }
281
282 35
    public function getMigrationRepository() : MigrationRepository
283
    {
284
        return $this->getDependency(MigrationRepository::class, function () : MigrationRepository {
285 35
            return new MigrationRepository(
286 35
                $this->getConfiguration()->getMigrationClasses(),
287 35
                $this->getConfiguration()->getMigrationDirectories(),
288 35
                $this->getMigrationsFinder(),
289 35
                $this->getMigrationFactory(),
290 35
                $this->getVersionComparator()
291
            );
292 35
        });
293
    }
294
295 35
    public function getMigrationFactory() : MigrationFactory
296
    {
297
        return $this->getDependency(MigrationFactory::class, function () : MigrationFactory {
298 35
            return new DbalMigrationFactory($this->getConnection(), $this->getLogger());
299 35
        });
300
    }
301
302
    /**
303
     * @param object|callable $service
304
     */
305 37
    public function setService(string $id, $service) : void
306
    {
307 37
        $this->assertNotFrozen();
308 36
        $this->dependencies[$id] = $service;
309 36
    }
310
311 35
    private function getMetadataStorageConfiguration() : MetadataStorageConfiguration
312
    {
313
        return $this->getDependency(MetadataStorageConfiguration::class, static function () : MetadataStorageConfiguration {
314 35
            return new TableMetadataStorageConfiguration();
315 35
        });
316
    }
317
318 35
    public function getMetadataStorage() : MetadataStorage
319
    {
320
        return $this->getDependency(MetadataStorage::class, function () : MetadataStorage {
321 35
            return new TableMetadataStorage(
322 35
                $this->getConnection(),
323 35
                $this->getMetadataStorageConfiguration()
324
            );
325 35
        });
326
    }
327
328
    private function getVersionExecutor() : Executor
329
    {
330
        return $this->getDependency(Executor::class, function () : Executor {
331
            return new DbalExecutor(
332
                $this->getMetadataStorage(),
333
                $this->getEventDispatcher(),
334
                $this->getConnection(),
335
                $this->getSchemaDiffProvider(),
336
                $this->getLogger(),
337
                $this->getParameterFormatter(),
338
                $this->getStopwatch()
339
            );
340
        });
341
    }
342
343 2
    public function getQueryWriter() : QueryWriter
344
    {
345
        return $this->getDependency(QueryWriter::class, function () : QueryWriter {
346
            return new FileQueryWriter(
347
                $this->getFileBuilder(),
348
                $this->logger
349
            );
350 2
        });
351
    }
352
353 16
    public function getVersionAliasResolver() : AliasResolver
354
    {
355
        return $this->getDependency(AliasResolver::class, function () : AliasResolver {
356 16
            return new DefaultAliasResolver(
357 16
                $this->getMigrationRepository(),
358 16
                $this->getMetadataStorage(),
359 16
                $this->getMigrationStatusCalculator()
360
            );
361 16
        });
362
    }
363
364 22
    public function getMigrationStatusCalculator() : MigrationStatusCalculator
365
    {
366
        return $this->getDependency(MigrationStatusCalculator::class, function () : MigrationStatusCalculator {
367 22
            return new CurrentMigrationStatusCalculator(
368 22
                $this->getMigrationRepository(),
369 22
                $this->getMetadataStorage()
370
            );
371 22
        });
372
    }
373
374 10
    public function getMigrationPlanCalculator() : MigrationPlanCalculator
375
    {
376
        return $this->getDependency(MigrationPlanCalculator::class, function () : MigrationPlanCalculator {
377 10
            return new SortedMigrationPlanCalculator(
378 10
                $this->getMigrationRepository(),
379 10
                $this->getMetadataStorage()
380
            );
381 10
        });
382
    }
383
384
    public function getMigrationGenerator() : Generator
385
    {
386
        return $this->getDependency(Generator::class, function () : Generator {
387
            return new Generator($this->getConfiguration());
388
        });
389
    }
390
391
    public function getMigrationSqlGenerator() : SqlGenerator
392
    {
393
        return $this->getDependency(SqlGenerator::class, function () : SqlGenerator {
394
            return new SqlGenerator(
395
                $this->getConfiguration(),
396
                $this->getConnection()->getDatabasePlatform()
397
            );
398
        });
399
    }
400
401 14
    public function getConsoleInputMigratorConfigurationFactory() : MigratorConfigurationFactory
402
    {
403
        return $this->getDependency(MigratorConfigurationFactory::class, function () : MigratorConfigurationFactory {
404 14
            return new ConsoleInputMigratorConfigurationFactory(
405 14
                $this->getConfiguration()
406
            );
407 14
        });
408
    }
409
410 3
    public function getMigrationStatusInfosHelper() : MigrationStatusInfosHelper
411
    {
412
        return $this->getDependency(MigrationStatusInfosHelper::class, function () : MigrationStatusInfosHelper {
413 3
            return new MigrationStatusInfosHelper(
414 3
                $this->getConfiguration(),
415 3
                $this->getConnection(),
416 3
                $this->getVersionAliasResolver(),
417 3
                $this->getMigrationRepository(),
418 3
                $this->getMetadataStorage()
419
            );
420 3
        });
421
    }
422
423 6
    public function getMigrator() : Migrator
424
    {
425
        return $this->getDependency(Migrator::class, function () : Migrator {
426
            return new DbalMigrator(
427
                $this->getConnection(),
428
                $this->getEventDispatcher(),
429
                $this->getVersionExecutor(),
430
                $this->logger,
431
                $this->getStopwatch()
432
            );
433 6
        });
434
    }
435
436
    public function getStopwatch() : Stopwatch
437
    {
438
        return $this->getDependency(Stopwatch::class, static function () : Stopwatch {
439
            $symfonyStopwatch = new SymfonyStopwatch(true);
440
441
            return new Stopwatch($symfonyStopwatch);
442
        });
443
    }
444
445
    public function getRollup() : Rollup
446
    {
447
        return $this->getDependency(Rollup::class, function () : Rollup {
448
            return new Rollup(
449
                $this->getMetadataStorage(),
450
                $this->getMigrationRepository()
451
            );
452
        });
453
    }
454
455
    /**
456
     * @return mixed
457
     */
458 43
    private function getDependency(string $id, callable $callback)
459
    {
460 43
        if (! array_key_exists($id, $this->dependencies)) {
461 43
            $this->dependencies[$id] = $callback();
462
        }
463
464 43
        return $this->dependencies[$id];
465
    }
466
}
467