Completed
Pull Request — master (#917)
by Asmir
02:37
created

DependencyFactory::getQueryWriter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1.4218

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
nc 1
nop 0
dl 0
loc 6
ccs 1
cts 4
cp 0.25
crap 1.4218
rs 10
c 1
b 0
f 0
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 41
    public static function fromConnection(
87
        ConfigurationLoader $configurationLoader,
88
        ConnectionLoader $connectionLoader,
89
        ?LoggerInterface $logger = null
90
    ) : self {
91 41
        $dependencyFactory                      = new self($logger);
92 41
        $dependencyFactory->configurationLoader = $configurationLoader;
93 41
        $dependencyFactory->connectionLoader    = $connectionLoader;
94
95 41
        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 42
    private function __construct(?LoggerInterface $logger)
111
    {
112 42
        $this->logger = $logger ?: new NullLogger();
113 42
    }
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 37
    private function assertNotFrozen() : void
127
    {
128 37
        if ($this->frozen) {
129 1
            throw FrozenDependencies::new();
130
        }
131 36
    }
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 35
    public function getVersionComparator() : Comparator
172
    {
173
        return $this->getDependency(Comparator::class, static function () : AlphabeticalComparator {
174 35
            return new AlphabeticalComparator();
175 35
        });
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 35
    private function getMetadataStorageConfiguration() : MetadataStorageConfiguration
300
    {
301
        return $this->getDependency(MetadataStorageConfiguration::class, static function () : MetadataStorageConfiguration {
302 35
            return new TableMetadataStorageConfiguration();
303 35
        });
304
    }
305
306 35
    public function getMetadataStorage() : MetadataStorage
307
    {
308
        return $this->getDependency(MetadataStorage::class, function () : MetadataStorage {
309 35
            return new TableMetadataStorage(
310 35
                $this->getConnection(),
311 35
                $this->getMetadataStorageConfiguration()
312
            );
313 35
        });
314
    }
315
316
    public function getVersionExecutor() : Executor
317
    {
318
        return $this->getDependency(Executor::class, function () : Executor {
319
            return new DbalExecutor(
320
                $this->getMetadataStorage(),
321
                $this->getEventDispatcher(),
322
                $this->getConnection(),
323
                $this->getSchemaDiffProvider(),
324
                $this->getLogger(),
325
                $this->getParameterFormatter(),
326
                $this->getStopwatch()
327
            );
328
        });
329
    }
330
331 2
    public function getQueryWriter() : QueryWriter
332
    {
333
        return $this->getDependency(QueryWriter::class, function () : QueryWriter {
334
            return new FileQueryWriter(
335
                $this->getFileBuilder(),
336
                $this->logger
337
            );
338 2
        });
339
    }
340
341 16
    public function getVersionAliasResolver() : AliasResolver
342
    {
343
        return $this->getDependency(AliasResolver::class, function () : AliasResolver {
344 16
            return new DefaultAliasResolver(
345 16
                $this->getMigrationRepository(),
346 16
                $this->getMetadataStorage(),
347 16
                $this->getMigrationStatusCalculator()
348
            );
349 16
        });
350
    }
351
352 22
    public function getMigrationStatusCalculator() : MigrationStatusCalculator
353
    {
354
        return $this->getDependency(MigrationStatusCalculator::class, function () : MigrationStatusCalculator {
355 22
            return new CurrentMigrationStatusCalculator(
356 22
                $this->getMigrationRepository(),
357 22
                $this->getMetadataStorage()
358
            );
359 22
        });
360
    }
361
362 10
    public function getMigrationPlanCalculator() : MigrationPlanCalculator
363
    {
364
        return $this->getDependency(MigrationPlanCalculator::class, function () : MigrationPlanCalculator {
365 10
            return new SortedMigrationPlanCalculator(
366 10
                $this->getMigrationRepository(),
367 10
                $this->getMetadataStorage()
368
            );
369 10
        });
370
    }
371
372
    public function getMigrationGenerator() : Generator
373
    {
374
        return $this->getDependency(Generator::class, function () : Generator {
375
            return new Generator($this->getConfiguration());
376
        });
377
    }
378
379
    public function getMigrationSqlGenerator() : SqlGenerator
380
    {
381
        return $this->getDependency(SqlGenerator::class, function () : SqlGenerator {
382
            return new SqlGenerator(
383
                $this->getConfiguration(),
384
                $this->getConnection()->getDatabasePlatform()
385
            );
386
        });
387
    }
388
389 14
    public function getConsoleInputMigratorConfigurationFactory() : MigratorConfigurationFactory
390
    {
391
        return $this->getDependency(MigratorConfigurationFactory::class, function () : MigratorConfigurationFactory {
392 14
            return new ConsoleInputMigratorConfigurationFactory(
393 14
                $this->getConfiguration()
394
            );
395 14
        });
396
    }
397
398 3
    public function getMigrationStatusInfosHelper() : MigrationStatusInfosHelper
399
    {
400
        return $this->getDependency(MigrationStatusInfosHelper::class, function () : MigrationStatusInfosHelper {
401 3
            return new MigrationStatusInfosHelper(
402 3
                $this->getConfiguration(),
403 3
                $this->getConnection(),
404 3
                $this->getVersionAliasResolver(),
405 3
                $this->getMigrationRepository(),
406 3
                $this->getMetadataStorage()
407
            );
408 3
        });
409
    }
410
411 6
    public function getMigrator() : Migrator
412
    {
413
        return $this->getDependency(Migrator::class, function () : Migrator {
414
            return new DbalMigrator(
415
                $this->getConnection(),
416
                $this->getEventDispatcher(),
417
                $this->getVersionExecutor(),
418
                $this->logger,
419
                $this->getStopwatch()
420
            );
421 6
        });
422
    }
423
424
    public function getStopwatch() : Stopwatch
425
    {
426
        return $this->getDependency(Stopwatch::class, static function () : Stopwatch {
427
            $symfonyStopwatch = new SymfonyStopwatch(true);
428
429
            return new Stopwatch($symfonyStopwatch);
430
        });
431
    }
432
433
    public function getRollup() : Rollup
434
    {
435
        return $this->getDependency(Rollup::class, function () : Rollup {
436
            return new Rollup(
437
                $this->getMetadataStorage(),
438
                $this->getMigrationRepository()
439
            );
440
        });
441
    }
442
443
    /**
444
     * @return mixed
445
     */
446 43
    private function getDependency(string $id, callable $callback)
447
    {
448 43
        if (! array_key_exists($id, $this->dependencies)) {
449 43
            $this->dependencies[$id] = $callback();
450
        }
451
452 43
        return $this->dependencies[$id];
453
    }
454
}
455