Completed
Push — master ( ab7ebf...740609 )
by Grégoire
02:23
created

DependencyFactory   B

Complexity

Total Complexity 49

Size/Duplication

Total Lines 395
Duplicated Lines 0 %

Test Coverage

Coverage 56.76%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 153
dl 0
loc 395
ccs 105
cts 185
cp 0.5676
rs 8.48
c 4
b 0
f 0
wmc 49

38 Methods

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