Completed
Push — 4.x ( 0f520e...4acd94 )
by Kit Loong
01:32
created

SchemaGenerator   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 176
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 9

Importance

Changes 0
Metric Value
wmc 11
lcom 2
cbo 9
dl 0
loc 176
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A initialize() 0 30 3
A getTables() 0 4 1
A getTable() 0 4 1
A getIndexes() 0 4 1
A getFields() 0 4 1
A getForeignKeyConstraints() 0 4 1
A registerCustomDoctrineType() 0 14 2
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: liow.kitloong
5
 */
6
7
namespace KitLoong\MigrationsGenerator\Generators;
8
9
use Doctrine\DBAL\Schema\Table;
10
use Doctrine\DBAL\Types\Type;
11
use Illuminate\Support\Collection;
12
use Illuminate\Support\Facades\DB;
13
use KitLoong\MigrationsGenerator\MigrationGeneratorSetting;
14
use KitLoong\MigrationsGenerator\Types\DoubleType;
15
use KitLoong\MigrationsGenerator\Types\EnumType;
16
use KitLoong\MigrationsGenerator\Types\GeometryCollectionType;
17
use KitLoong\MigrationsGenerator\Types\GeometryType;
18
use KitLoong\MigrationsGenerator\Types\IpAddressType;
19
use KitLoong\MigrationsGenerator\Types\JsonbType;
20
use KitLoong\MigrationsGenerator\Types\LineStringType;
21
use KitLoong\MigrationsGenerator\Types\LongTextType;
22
use KitLoong\MigrationsGenerator\Types\MacAddressType;
23
use KitLoong\MigrationsGenerator\Types\MediumIntegerType;
24
use KitLoong\MigrationsGenerator\Types\MediumTextType;
25
use KitLoong\MigrationsGenerator\Types\MultiLineStringType;
26
use KitLoong\MigrationsGenerator\Types\MultiPointType;
27
use KitLoong\MigrationsGenerator\Types\MultiPolygonType;
28
use KitLoong\MigrationsGenerator\Types\PointType;
29
use KitLoong\MigrationsGenerator\Types\PolygonType;
30
use KitLoong\MigrationsGenerator\Types\SetType;
31
use KitLoong\MigrationsGenerator\Types\TimestampType;
32
use KitLoong\MigrationsGenerator\Types\TimestampTzType;
33
use KitLoong\MigrationsGenerator\Types\TimeTzType;
34
use KitLoong\MigrationsGenerator\Types\TinyIntegerType;
35
use KitLoong\MigrationsGenerator\Types\UUIDType;
36
use KitLoong\MigrationsGenerator\Types\YearType;
37
use Xethron\MigrationsGenerator\Generators\ForeignKeyGenerator;
38
39
class SchemaGenerator
40
{
41
    /**
42
     * @var \Doctrine\DBAL\Schema\AbstractSchemaManager
43
     */
44
    private $schema;
45
46
    /**
47
     * @var FieldGenerator
48
     */
49
    private $fieldGenerator;
50
51
    /**
52
     * @var ForeignKeyGenerator
53
     */
54
    private $foreignKeyGenerator;
55
56
    private $indexGenerator;
57
58
    /**
59
     * @var string
60
     */
61
    protected $database;
62
63
    /**
64
     * @var bool
65
     */
66
    private $ignoreIndexNames;
67
68
    /**
69
     * @var bool
70
     */
71
    private $ignoreForeignKeyNames;
72
73
    /**
74
     * Custom doctrine type
75
     * ['class', 'name', 'type']
76
     * @see registerCustomDoctrineType()
77
     *
78
     * @var array
79
     */
80
    private static $customDoctrineTypes = [
81
        [DoubleType::class, 'double', 'double'],
82
        [EnumType::class, 'enum', 'enum'],
83
        [GeometryType::class, 'geometry', 'geometry'],
84
        [GeometryCollectionType::class, 'geometrycollection', 'geometrycollection'],
85
        [LineStringType::class, 'linestring', 'linestring'],
86
        [LongTextType::class, 'longtext', 'longtext'],
87
        [MediumIntegerType::class, 'mediumint', 'mediumint'],
88
        [MediumTextType::class, 'mediumtext', 'mediumtext'],
89
        [MultiLineStringType::class, 'multilinestring', 'multilinestring'],
90
        [MultiPointType::class, 'multipoint', 'multipoint'],
91
        [MultiPolygonType::class, 'multipolygon', 'multipolygon'],
92
        [PointType::class, 'point', 'point'],
93
        [PolygonType::class, 'polygon', 'polygon'],
94
        [SetType::class, 'set', 'set'],
95
        [TimestampType::class, 'timestamp', 'timestamp'],
96
        [TinyIntegerType::class, 'tinyint', 'tinyint'],
97
        [UUIDType::class, 'uuid', 'uuid'],
98
        [YearType::class, 'year', 'year'],
99
100
        // Postgres types
101
        [IpAddressType::class, 'ipaddress', 'inet'],
102
        [JsonbType::class, 'jsonb', 'jsonb'],
103
        [MacAddressType::class, 'macaddress', 'macaddr'],
104
        [TimeTzType::class, 'timetz', 'timetz'],
105
        [TimestampTzType::class, 'timestamptz', 'timestamptz'],
106
    ];
107
108
    public function __construct(
109
        FieldGenerator $fieldGenerator,
110
        IndexGenerator $indexGenerator,
111
        ForeignKeyGenerator $foreignKeyGenerator
112
    ) {
113
        $this->fieldGenerator = $fieldGenerator;
114
        $this->indexGenerator = $indexGenerator;
115
        $this->foreignKeyGenerator = $foreignKeyGenerator;
116
    }
117
118
    /**
119
     * @param  string  $database
120
     * @param  bool  $ignoreIndexNames
121
     * @param  bool  $ignoreForeignKeyNames
122
     * @throws \Doctrine\DBAL\DBALException
123
     */
124
    public function initialize(string $database, bool $ignoreIndexNames, bool $ignoreForeignKeyNames)
125
    {
126
        foreach (self::$customDoctrineTypes as $doctrineType) {
127
            $this->registerCustomDoctrineType(...$doctrineType);
0 ignored issues
show
Bug introduced by
The call to registerCustomDoctrineType() misses some required arguments starting with $name.
Loading history...
128
        }
129
130
        /** @var \Doctrine\DBAL\Connection $connection */
131
        $connection = DB::connection($database)->getDoctrineConnection();
132
133
        $connection->getDatabasePlatform()->registerDoctrineTypeMapping('bit', 'boolean');
134
        $connection->getDatabasePlatform()->registerDoctrineTypeMapping('json', 'json');
135
136
        /** @var MigrationGeneratorSetting $setting */
137
        $setting = resolve(MigrationGeneratorSetting::class);
138
139
        switch ($setting->getPlatform()) {
140
            case Platform::POSTGRESQL:
141
                $connection->getDatabasePlatform()->registerDoctrineTypeMapping('_text', 'text');
142
                $connection->getDatabasePlatform()->registerDoctrineTypeMapping('_int4', 'integer');
143
                $connection->getDatabasePlatform()->registerDoctrineTypeMapping('_numeric', 'float');
144
                $connection->getDatabasePlatform()->registerDoctrineTypeMapping('cidr', 'string');
145
                break;
146
            default:
147
        }
148
149
        $this->schema = $connection->getSchemaManager();
150
151
        $this->ignoreIndexNames = $ignoreIndexNames;
152
        $this->ignoreForeignKeyNames = $ignoreForeignKeyNames;
153
    }
154
155
    /**
156
     * @return string[]
157
     */
158
    public function getTables(): array
159
    {
160
        return $this->schema->listTableNames();
161
    }
162
163
    public function getTable(string $tableName): Table
164
    {
165
        return $this->schema->listTableDetails($tableName);
166
    }
167
168
    /**
169
     * @param  Table  $table
170
     * @return array|\Illuminate\Support\Collection[]
171
     * [
172
     *  'single' => Collection of single column indexes, with column name as key
173
     *  'multi' => Collection of multi columns indexes
174
     * ]
175
     */
176
    public function getIndexes(Table $table): array
177
    {
178
        return $this->indexGenerator->generate($table, $this->ignoreIndexNames);
179
    }
180
181
    public function getFields(Table $table, Collection $singleColIndexes): array
182
    {
183
        return $this->fieldGenerator->generate($table, $singleColIndexes);
184
    }
185
186
    public function getForeignKeyConstraints(string $table): array
187
    {
188
        return $this->foreignKeyGenerator->generate($table, $this->schema, $this->ignoreForeignKeyNames);
189
    }
190
191
    /**
192
     * Register custom doctrineType
193
     * Will override if exists
194
     *
195
     * @param $class
196
     * @param $name
197
     * @param $type
198
     * @throws \Doctrine\DBAL\DBALException
199
     */
200
    public function registerCustomDoctrineType($class, $name, $type)
201
    {
202
        /** @var MigrationGeneratorSetting $setting */
203
        $setting = resolve(MigrationGeneratorSetting::class);
204
205
        if (!Type::hasType($name)) {
206
            Type::addType($name, $class);
207
        } else {
208
            Type::overrideType($name, $class);
209
        }
210
211
        $setting->getDatabasePlatform()
212
            ->registerDoctrineTypeMapping($type, $name);
213
    }
214
}
215