Passed
Pull Request — master (#784)
by Mathias
02:38
created

DiffGenerator::generate()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 37
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 4.0016

Importance

Changes 0
Metric Value
cc 4
eloc 20
nc 4
nop 5
dl 0
loc 37
ccs 20
cts 21
cp 0.9524
crap 4.0016
rs 9.6
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Migrations\Generator;
6
7
use Doctrine\DBAL\Configuration as DBALConfiguration;
8
use Doctrine\DBAL\Platforms\AbstractPlatform;
9
use Doctrine\DBAL\Schema\AbstractSchemaManager;
10
use Doctrine\DBAL\Schema\Schema;
11
use Doctrine\Migrations\Generator\Exception\NoChangesDetected;
12
use Doctrine\Migrations\Provider\SchemaProviderInterface;
13
use function preg_match;
14
use function strpos;
15
use function substr;
16
17
/**
18
 * The DiffGenerator class is responsible for comparing two Doctrine\DBAL\Schema\Schema instances and generating a
19
 * migration class with the SQL statements needed to migrate from one schema to the other.
20
 *
21
 * @internal
22
 */
23
class DiffGenerator
24
{
25
    /** @var DBALConfiguration */
26
    private $dbalConfiguration;
27
28
    /** @var AbstractSchemaManager */
29
    private $schemaManager;
30
31
    /** @var SchemaProviderInterface */
32
    private $schemaProvider;
33
34
    /** @var AbstractPlatform */
35
    private $platform;
36
37
    /** @var Generator */
38
    private $migrationGenerator;
39
40
    /** @var SqlGenerator */
41
    private $migrationSqlGenerator;
42
43 6
    public function __construct(
44
        DBALConfiguration $dbalConfiguration,
45
        AbstractSchemaManager $schemaManager,
46
        SchemaProviderInterface $schemaProvider,
47
        AbstractPlatform $platform,
48
        Generator $migrationGenerator,
49
        SqlGenerator $migrationSqlGenerator
50
    ) {
51 6
        $this->dbalConfiguration     = $dbalConfiguration;
52 6
        $this->schemaManager         = $schemaManager;
53 6
        $this->schemaProvider        = $schemaProvider;
54 6
        $this->platform              = $platform;
55 6
        $this->migrationGenerator    = $migrationGenerator;
56 6
        $this->migrationSqlGenerator = $migrationSqlGenerator;
57 6
    }
58
59
    /**
60
     * @throws NoChangesDetected
61
     */
62 6
    public function generate(
63
        string $versionNumber,
64
        ?string $filterExpression,
65
        bool $formatted = false,
66
        int $lineLength = 120,
67
        bool $checkDbPlatform = true
68
    ) : string {
69 6
        if ($filterExpression !== null) {
70 1
            $this->dbalConfiguration->setFilterSchemaAssetsExpression($filterExpression);
71
        }
72
73 6
        $fromSchema = $this->createFromSchema();
74
75 6
        $toSchema = $this->createToSchema();
76
77 6
        $up = $this->migrationSqlGenerator->generate(
78 6
            $fromSchema->getMigrateToSql($toSchema, $this->platform),
79 6
            $formatted,
80 6
            $lineLength,
81 6
            $checkDbPlatform
82
        );
83
84 6
        $down = $this->migrationSqlGenerator->generate(
85 6
            $fromSchema->getMigrateFromSql($toSchema, $this->platform),
86 6
            $formatted,
87 6
            $lineLength,
88 6
            $checkDbPlatform
89
        );
90
91 6
        if ($up === '' && $down === '') {
92
            throw NoChangesDetected::new();
93
        }
94
95 6
        return $this->migrationGenerator->generateMigration(
96 6
            $versionNumber,
97 6
            $up,
98 6
            $down
99
        );
100
    }
101
102 6
    private function createFromSchema() : Schema
103
    {
104 6
        return $this->schemaManager->createSchema();
105
    }
106
107 6
    private function createToSchema() : Schema
108
    {
109 6
        $toSchema = $this->schemaProvider->createSchema();
110
111 6
        $filterExpression = $this->dbalConfiguration->getFilterSchemaAssetsExpression();
112
113 6
        if ($filterExpression !== null) {
114 3
            foreach ($toSchema->getTables() as $table) {
115 3
                $tableName = $table->getName();
116
117 3
                if (preg_match($filterExpression, $this->resolveTableName($tableName)) === 1) {
118 3
                    continue;
119
                }
120
121 2
                $toSchema->dropTable($tableName);
122
            }
123
        }
124
125 6
        return $toSchema;
126
    }
127
128
    /**
129
     * Resolve a table name from its fully qualified name. The `$name` argument
130
     * comes from Doctrine\DBAL\Schema\Table#getName which can sometimes return
131
     * a namespaced name with the form `{namespace}.{tableName}`. This extracts
132
     * the table name from that.
133
     */
134 3
    private function resolveTableName(string $name) : string
135
    {
136 3
        $pos = strpos($name, '.');
137
138 3
        return $pos === false ? $name : substr($name, $pos + 1);
139
    }
140
}
141