Completed
Pull Request — master (#926)
by Asmir
02:58
created

DependencyFactory   B

Complexity

Total Complexity 50

Size/Duplication

Total Lines 402
Duplicated Lines 0 %

Test Coverage

Coverage 58.12%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 156
dl 0
loc 402
ccs 111
cts 191
cp 0.5812
rs 8.4
c 4
b 0
f 0
wmc 50

39 Methods

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