Completed
Pull Request — master (#1005)
by Asmir
06:55
created

DiffGenerator::generate()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 47

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 5.1024

Importance

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