Completed
Push — master ( d1d2ef...0e04b4 )
by Kit Loong
04:05
created

SchemaGenerator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
nc 1
nop 3
dl 0
loc 8
ccs 4
cts 4
cp 1
crap 1
rs 10
c 3
b 0
f 0
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: liow.kitloong
5
 */
6
7
namespace KitLoong\MigrationsGenerator\Generators;
8
9
use Doctrine\DBAL\Types\Type;
10
use Illuminate\Support\Collection;
11
use KitLoong\MigrationsGenerator\MigrationsGeneratorSetting;
12
use KitLoong\MigrationsGenerator\Types\DoubleType;
13
use KitLoong\MigrationsGenerator\Types\EnumType;
14
use KitLoong\MigrationsGenerator\Types\GeographyType;
15
use KitLoong\MigrationsGenerator\Types\GeomCollectionType;
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
38
class SchemaGenerator
39
{
40
    /**
41
     * @var FieldGenerator
42
     */
43
    private $fieldGenerator;
44
45
    /**
46
     * @var ForeignKeyGenerator
47
     */
48
    private $foreignKeyGenerator;
49
50
    private $indexGenerator;
51
52
    /**
53
     * Custom doctrine type
54
     * ['class', 'name', 'type']
55
     * @see registerCustomDoctrineType()
56
     *
57
     * @var array
58
     */
59
    private static $customDoctrineTypes = [
60
        [DoubleType::class, 'double', 'double'],
61
        [EnumType::class, 'enum', 'enum'],
62
        [GeometryType::class, 'geometry', 'geometry'],
63
        [GeomCollectionType::class, 'geomcollection', 'geomcollection'],
64
        [GeometryCollectionType::class, 'geometrycollection', 'geometrycollection'],
65
        [LineStringType::class, 'linestring', 'linestring'],
66
        [LongTextType::class, 'longtext', 'longtext'],
67
        [MediumIntegerType::class, 'mediumint', 'mediumint'],
68
        [MediumTextType::class, 'mediumtext', 'mediumtext'],
69
        [MultiLineStringType::class, 'multilinestring', 'multilinestring'],
70
        [MultiPointType::class, 'multipoint', 'multipoint'],
71
        [MultiPolygonType::class, 'multipolygon', 'multipolygon'],
72
        [PointType::class, 'point', 'point'],
73
        [PolygonType::class, 'polygon', 'polygon'],
74
        [SetType::class, 'set', 'set'],
75
        [TimestampType::class, 'timestamp', 'timestamp'],
76
        [TinyIntegerType::class, 'tinyint', 'tinyint'],
77
        [UUIDType::class, 'uuid', 'uuid'],
78
        [YearType::class, 'year', 'year'],
79
80
        // Postgres types
81
        [GeographyType::class, 'geography', 'geography'],
82
        [IpAddressType::class, 'ipaddress', 'inet'],
83
        [JsonbType::class, 'jsonb', 'jsonb'],
84
        [MacAddressType::class, 'macaddress', 'macaddr'],
85
        [TimeTzType::class, 'timetz', 'timetz'],
86
        [TimestampTzType::class, 'timestamptz', 'timestamptz'],
87
    ];
88
89
    /**
90
     * @var \Doctrine\DBAL\Schema\AbstractSchemaManager
91
     */
92
    protected $schema;
93
94 21
    public function __construct(
95
        FieldGenerator $fieldGenerator,
96
        IndexGenerator $indexGenerator,
97
        ForeignKeyGenerator $foreignKeyGenerator
98
    ) {
99 21
        $this->fieldGenerator = $fieldGenerator;
100 21
        $this->indexGenerator = $indexGenerator;
101 21
        $this->foreignKeyGenerator = $foreignKeyGenerator;
102 21
    }
103
104
    /**
105
     * @throws \Doctrine\DBAL\DBALException
106
     */
107 3
    public function initialize()
108
    {
109 3
        $setting = app(MigrationsGeneratorSetting::class);
110
111 3
        foreach (self::$customDoctrineTypes as $doctrineType) {
112 3
            $this->registerCustomDoctrineType(...$doctrineType);
0 ignored issues
show
Bug introduced by
The call to KitLoong\MigrationsGener...terCustomDoctrineType() has too few arguments starting with name. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

112
            $this->/** @scrutinizer ignore-call */ 
113
                   registerCustomDoctrineType(...$doctrineType);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
113
        }
114
115 3
        $this->addNewDoctrineType('bit', 'boolean');
116 3
        $this->addNewDoctrineType('json', 'json');
117
118 3
        switch ($setting->getPlatform()) {
119 3
            case Platform::POSTGRESQL:
120 3
                $this->addNewDoctrineType('_text', 'text');
121 3
                $this->addNewDoctrineType('_int4', 'integer');
122 3
                $this->addNewDoctrineType('_numeric', 'float');
123 3
                $this->addNewDoctrineType('cidr', 'string');
124 3
                break;
125
            default:
126
        }
127
128 3
        $this->schema = $setting->getConnection()->getDoctrineConnection()->getSchemaManager();
129 3
    }
130
131
    /**
132
     * @return string[]
133
     */
134 3
    public function getTables(): array
135
    {
136 3
        return $this->schema->listTableNames();
137
    }
138
139
    /**
140
     * @param  string  $table
141
     * @return array|\Illuminate\Support\Collection[]
142
     * [
143
     *  'single' => Collection of single column indexes, with column name as key
144
     *  'multi' => Collection of multi columns indexes
145
     * ]
146
     */
147 3
    public function getIndexes(string $table): array
148
    {
149 3
        return $this->indexGenerator->generate(
150 2
            $table,
151 3
            $this->schema->listTableIndexes($table),
152 3
            app(MigrationsGeneratorSetting::class)->isIgnoreIndexNames()
153
        );
154
    }
155
156 3
    public function getFields(string $table, Collection $singleColIndexes): array
157
    {
158 3
        return $this->fieldGenerator->generate(
159 2
            $table,
160 3
            $this->schema->listTableColumns($table),
161
            $singleColIndexes
162
        );
163
    }
164
165 3
    public function getForeignKeyConstraints(string $table): array
166
    {
167 3
        return $this->foreignKeyGenerator->generate(
168 2
            $table,
169 3
            $this->schema->listTableForeignKeys($table),
170 3
            app(MigrationsGeneratorSetting::class)->isIgnoreForeignKeyNames()
171
        );
172
    }
173
174
    /**
175
     * Register custom doctrineType
176
     * Will override if exists
177
     *
178
     * @param  string  $class
179
     * @param  string  $name
180
     * @param  string  $type
181
     * @throws \Doctrine\DBAL\DBALException
182
     */
183 6
    protected function registerCustomDoctrineType(string $class, string $name, string $type): void
184
    {
185 6
        if (!Type::hasType($name)) {
186 3
            Type::addType($name, $class);
187
        } else {
188 3
            Type::overrideType($name, $class);
189
        }
190
191 6
        $this->addNewDoctrineType($type, $name);
192 6
    }
193
194
    /**
195
     * @param  string  $type
196
     * @param  string  $name
197
     * @throws \Doctrine\DBAL\DBALException
198
     */
199 9
    protected function addNewDoctrineType(string $type, string $name): void
200
    {
201 9
        app(MigrationsGeneratorSetting::class)->getConnection()
202 9
            ->getDoctrineConnection()
203 9
            ->getDatabasePlatform()
204 9
            ->registerDoctrineTypeMapping($type, $name);
205 9
    }
206
}
207