Passed
Pull Request — master (#927)
by Grégoire
02:20
created

DependencyFactory   B

Complexity

Total Complexity 50

Size/Duplication

Total Lines 409
Duplicated Lines 0 %

Test Coverage

Coverage 58.55%

Importance

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