Completed
Pull Request — master (#969)
by Asmir
02:33
created

DependencyFactory   B

Complexity

Total Complexity 50

Size/Duplication

Total Lines 408
Duplicated Lines 0 %

Test Coverage

Coverage 60.1%

Importance

Changes 7
Bugs 1 Features 0
Metric Value
eloc 162
dl 0
loc 408
ccs 119
cts 198
cp 0.601
rs 8.4
c 7
b 1
f 0
wmc 50

39 Methods

Rating   Name   Duplication   Size   Complexity  
A assertNotFrozen() 0 4 2
A freeze() 0 4 1
A hasEntityManager() 0 3 1
A isFrozen() 0 3 1
A getQueryWriter() 0 6 1
A getVersionExecutor() 0 11 1
A getDependency() 0 7 2
A getMigrationStatusCalculator() 0 6 1
A getRollup() 0 6 1
A getVersionAliasResolver() 0 7 1
A getMigrator() 0 9 1
A getMetadataStorage() 0 7 1
A fromEntityManager() 0 10 1
A fromConnection() 0 10 1
A __construct() 0 7 2
A getLogger() 0 4 1
A getFileBuilder() 0 4 1
A getMigrationSqlGenerator() 0 6 1
A getDiffGenerator() 0 10 1
A getSchemaDumper() 0 16 2
A getParameterFormatter() 0 4 1
A getEventDispatcher() 0 6 1
A getSchemaDiffProvider() 0 7 1
A getMigrationGenerator() 0 4 1
A getMigrationsFinder() 0 7 3
A getVersionComparator() 0 4 1
A getConsoleInputMigratorConfigurationFactory() 0 5 1
A getClassNameGenerator() 0 4 1
A getSchemaProvider() 0 4 1
A setConfigurationLoader() 0 4 1
A getConnection() 0 10 3
A getConfiguration() 0 8 2
A getEntityManager() 0 12 3
A getMigrationFactory() 0 4 1
A setService() 0 4 1
A getMigrationRepository() 0 8 1
A getMigrationPlanCalculator() 0 7 1
A getMigrationStatusInfosHelper() 0 10 1
A getStopwatch() 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\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 preg_quote;
52
use function sprintf;
53
54
/**
55
 * The DependencyFactory is responsible for wiring up and managing internal class dependencies.
56
 */
57
class DependencyFactory
58
{
59
    /** @var Configuration */
60
    private $configuration;
61
62
    /** @var object[]|callable[] */
63
    private $dependencies = [];
64
65
    /** @var Connection */
66
    private $connection;
67
68
    /** @var EntityManagerInterface|null */
69
    private $em;
70
71
    /** @var bool */
72
    private $frozen = false;
73
74
    /** @var ConfigurationLoader */
75
    private $configurationLoader;
76
77
    /** @var ConnectionLoader */
78
    private $connectionLoader;
79
80
    /** @var EntityManagerLoader|null */
81
    private $emLoader;
82
83 55
    public static function fromConnection(
84
        ConfigurationLoader $configurationLoader,
85
        ConnectionLoader $connectionLoader,
86
        ?LoggerInterface $logger = null
87
    ) : self {
88 55
        $dependencyFactory                      = new self($logger);
89 55
        $dependencyFactory->configurationLoader = $configurationLoader;
90 55
        $dependencyFactory->connectionLoader    = $connectionLoader;
91
92 55
        return $dependencyFactory;
93
    }
94
95 1
    public static function fromEntityManager(
96
        ConfigurationLoader $configurationLoader,
97
        EntityManagerLoader $emLoader,
98
        ?LoggerInterface $logger = null
99
    ) : self {
100 1
        $dependencyFactory                      = new self($logger);
101 1
        $dependencyFactory->configurationLoader = $configurationLoader;
102 1
        $dependencyFactory->emLoader            = $emLoader;
103
104 1
        return $dependencyFactory;
105
    }
106
107 56
    private function __construct(?LoggerInterface $logger)
108
    {
109 56
        if ($logger === null) {
110 41
            return;
111
        }
112
113 15
        $this->setService(LoggerInterface::class, $logger);
114 15
    }
115
116 51
    public function isFrozen() : bool
117
    {
118 51
        return $this->frozen;
119
    }
120
121 53
    public function freeze() : void
122
    {
123 53
        $this->frozen = true;
124 53
        $this->getConfiguration()->freeze();
125 53
    }
126
127 37
    private function assertNotFrozen() : void
128
    {
129 37
        if ($this->frozen) {
130 1
            throw FrozenDependencies::new();
131
        }
132 36
    }
133
134 31
    public function hasEntityManager() : bool
135
    {
136 31
        return $this->emLoader !== null;
137
    }
138
139 2
    public function setConfigurationLoader(ConfigurationLoader $configurationLoader) : void
140
    {
141 2
        $this->assertNotFrozen();
142 2
        $this->configurationLoader = $configurationLoader;
143 2
    }
144
145 53
    public function getConfiguration() : Configuration
146
    {
147 53
        if ($this->configuration === null) {
148 53
            $this->configuration = $this->configurationLoader->getConfiguration();
149 53
            $this->freeze();
150
        }
151
152 53
        return $this->configuration;
153
    }
154
155 31
    public function getConnection() : Connection
156
    {
157 31
        if ($this->connection === null) {
158 31
            $this->connection = $this->hasEntityManager()
159 1
                ? $this->getEntityManager()->getConnection()
160 30
                : $this->connectionLoader->getConnection();
161 31
            $this->freeze();
162
        }
163
164 31
        return $this->connection;
165
    }
166
167 2
    public function getEntityManager() : EntityManagerInterface
168
    {
169 2
        if ($this->em === null) {
170 2
            if ($this->emLoader === null) {
171 1
                throw MissingDependency::noEntityManager();
172
            }
173
174 1
            $this->em = $this->emLoader->getEntityManager();
175 1
            $this->freeze();
176
        }
177
178 1
        return $this->em;
179
    }
180
181 35
    public function getVersionComparator() : Comparator
182
    {
183
        return $this->getDependency(Comparator::class, static function () : AlphabeticalComparator {
184 35
            return new AlphabeticalComparator();
185 35
        });
186
    }
187
188 34
    public function getLogger() : LoggerInterface
189
    {
190
        return $this->getDependency(LoggerInterface::class, static function () : LoggerInterface {
191 14
            return new NullLogger();
192 34
        });
193
    }
194
195
    public function getEventDispatcher() : EventDispatcher
196
    {
197
        return $this->getDependency(EventDispatcher::class, function () : EventDispatcher {
198
            return new EventDispatcher(
199
                $this->getConnection(),
200
                $this->getConnection()->getEventManager()
201
            );
202
        });
203
    }
204
205
    public function getClassNameGenerator() : ClassNameGenerator
206
    {
207
        return $this->getDependency(ClassNameGenerator::class, static function () : ClassNameGenerator {
208
            return new ClassNameGenerator();
209
        });
210
    }
211
212
    public function getSchemaDumper() : SchemaDumper
213
    {
214
        return $this->getDependency(SchemaDumper::class, function () : SchemaDumper {
215
            $excludedTables = [];
216
217
            $metadataConfig = $this->getConfiguration()->getMetadataStorageConfiguration();
218
            if ($metadataConfig instanceof TableMetadataStorageConfiguration) {
219
                $excludedTables[] = sprintf('/^%s$/', preg_quote($metadataConfig->getTableName(), '/'));
220
            }
221
222
            return new SchemaDumper(
223
                $this->getConnection()->getDatabasePlatform(),
224
                $this->getConnection()->getSchemaManager(),
225
                $this->getMigrationGenerator(),
226
                $this->getMigrationSqlGenerator(),
227
                $excludedTables
228
            );
229
        });
230
    }
231
232
    private function getSchemaProvider() : SchemaProvider
233
    {
234
        return $this->getDependency(SchemaProvider::class, function () : SchemaProvider {
235
            return new OrmSchemaProvider($this->getEntityManager());
236
        });
237
    }
238
239
    public function getDiffGenerator() : DiffGenerator
240
    {
241
        return $this->getDependency(DiffGenerator::class, function () : DiffGenerator {
242
            return new DiffGenerator(
243
                $this->getConnection()->getConfiguration(),
244
                $this->getConnection()->getSchemaManager(),
245
                $this->getSchemaProvider(),
246
                $this->getConnection()->getDatabasePlatform(),
247
                $this->getMigrationGenerator(),
248
                $this->getMigrationSqlGenerator()
249
            );
250
        });
251
    }
252
253
    public function getSchemaDiffProvider() : SchemaDiffProvider
254
    {
255
        return $this->getDependency(SchemaDiffProvider::class, function () : LazySchemaDiffProvider {
256
            return LazySchemaDiffProvider::fromDefaultProxyFactoryConfiguration(
257
                new DBALSchemaDiffProvider(
258
                    $this->getConnection()->getSchemaManager(),
259
                    $this->getConnection()->getDatabasePlatform()
260
                )
261
            );
262
        });
263
    }
264
265
    private function getFileBuilder() : FileBuilder
266
    {
267
        return $this->getDependency(FileBuilder::class, static function () : FileBuilder {
268
            return new ConcatenationFileBuilder();
269
        });
270
    }
271
272
    private function getParameterFormatter() : ParameterFormatter
273
    {
274
        return $this->getDependency(ParameterFormatter::class, function () : ParameterFormatter {
275
            return new InlineParameterFormatter($this->getConnection());
276
        });
277
    }
278
279 32
    public function getMigrationsFinder() : MigrationFinder
280
    {
281
        return $this->getDependency(MigrationFinder::class, function () : MigrationFinder {
282 32
            $configs              = $this->getConfiguration();
283 32
            $needsRecursiveFinder = $configs->areMigrationsOrganizedByYear() || $configs->areMigrationsOrganizedByYearAndMonth();
284
285 32
            return $needsRecursiveFinder ? new RecursiveRegexFinder() : new GlobFinder();
286 32
        });
287
    }
288
289 42
    public function getMigrationRepository() : MigrationRepository
290
    {
291
        return $this->getDependency(MigrationRepository::class, function () : MigrationRepository {
292 29
            return new MigrationRepository(
293 29
                $this->getConfiguration()->getMigrationClasses(),
294 29
                $this->getConfiguration()->getMigrationDirectories(),
295 29
                $this->getMigrationsFinder(),
296 29
                $this->getMigrationFactory()
297
            );
298 42
        });
299
    }
300
301 29
    public function getMigrationFactory() : MigrationFactory
302
    {
303
        return $this->getDependency(MigrationFactory::class, function () : MigrationFactory {
304 29
            return new DbalMigrationFactory($this->getConnection(), $this->getLogger());
305 29
        });
306
    }
307
308
    /**
309
     * @param object|callable $service
310
     */
311 36
    public function setService(string $id, $service) : void
312
    {
313 36
        $this->assertNotFrozen();
314 35
        $this->dependencies[$id] = $service;
315 35
    }
316
317 42
    public function getMetadataStorage() : MetadataStorage
318
    {
319
        return $this->getDependency(MetadataStorage::class, function () : MetadataStorage {
320 29
            return new TableMetadataStorage(
321 29
                $this->getConnection(),
322 29
                $this->getConfiguration()->getMetadataStorageConfiguration(),
323 29
                $this->getMigrationRepository()
324
            );
325 42
        });
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 4
    public function getQueryWriter() : QueryWriter
344
    {
345
        return $this->getDependency(QueryWriter::class, function () : QueryWriter {
346
            return new FileQueryWriter(
347
                $this->getFileBuilder(),
348
                $this->getLogger()
349
            );
350 4
        });
351
    }
352
353 20
    public function getVersionAliasResolver() : AliasResolver
354
    {
355
        return $this->getDependency(AliasResolver::class, function () : AliasResolver {
356 20
            return new DefaultAliasResolver(
357 20
                $this->getMigrationPlanCalculator(),
358 20
                $this->getMetadataStorage(),
359 20
                $this->getMigrationStatusCalculator()
360
            );
361 20
        });
362
    }
363
364 26
    public function getMigrationStatusCalculator() : MigrationStatusCalculator
365
    {
366
        return $this->getDependency(MigrationStatusCalculator::class, function () : MigrationStatusCalculator {
367 26
            return new CurrentMigrationStatusCalculator(
368 26
                $this->getMigrationPlanCalculator(),
369 26
                $this->getMetadataStorage()
370
            );
371 26
        });
372
    }
373
374 40
    public function getMigrationPlanCalculator() : MigrationPlanCalculator
375
    {
376
        return $this->getDependency(MigrationPlanCalculator::class, function () : MigrationPlanCalculator {
377 35
            return new SortedMigrationPlanCalculator(
378 35
                $this->getMigrationRepository(),
379 35
                $this->getMetadataStorage(),
380 35
                $this->getVersionComparator()
381
            );
382 40
        });
383
    }
384
385
    public function getMigrationGenerator() : Generator
386
    {
387
        return $this->getDependency(Generator::class, function () : Generator {
388
            return new Generator($this->getConfiguration());
389
        });
390
    }
391
392
    public function getMigrationSqlGenerator() : SqlGenerator
393
    {
394
        return $this->getDependency(SqlGenerator::class, function () : SqlGenerator {
395
            return new SqlGenerator(
396
                $this->getConfiguration(),
397
                $this->getConnection()->getDatabasePlatform()
398
            );
399
        });
400
    }
401
402 15
    public function getConsoleInputMigratorConfigurationFactory() : MigratorConfigurationFactory
403
    {
404
        return $this->getDependency(MigratorConfigurationFactory::class, function () : MigratorConfigurationFactory {
405 15
            return new ConsoleInputMigratorConfigurationFactory(
406 15
                $this->getConfiguration()
407
            );
408 15
        });
409
    }
410
411 3
    public function getMigrationStatusInfosHelper() : MigrationStatusInfosHelper
412
    {
413
        return $this->getDependency(MigrationStatusInfosHelper::class, function () : MigrationStatusInfosHelper {
414 3
            return new MigrationStatusInfosHelper(
415 3
                $this->getConfiguration(),
416 3
                $this->getConnection(),
417 3
                $this->getVersionAliasResolver(),
418 3
                $this->getMigrationPlanCalculator(),
419 3
                $this->getMigrationStatusCalculator(),
420 3
                $this->getMetadataStorage()
421
            );
422 3
        });
423
    }
424
425 12
    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->getLogger(),
433
                $this->getStopwatch()
434
            );
435 12
        });
436
    }
437
438
    public function getStopwatch() : Stopwatch
439
    {
440
        return $this->getDependency(Stopwatch::class, static function () : Stopwatch {
441
            return new Stopwatch(true);
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->getMigrationPlanCalculator()
451
            );
452
        });
453
    }
454
455
    /**
456
     * @return mixed
457
     */
458 50
    private function getDependency(string $id, callable $callback)
459
    {
460 50
        if (! array_key_exists($id, $this->dependencies)) {
461 48
            $this->dependencies[$id] = $callback();
462
        }
463
464 50
        return $this->dependencies[$id];
465
    }
466
}
467