Test Failed
Pull Request — master (#95)
by Dallas
06:01
created

src/Schema/Blueprint.php (1 issue)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Umbrellio\Postgres\Schema;
6
7
use Doctrine\DBAL\DriverManager;
8
use Illuminate\Database\Schema\Blueprint as BaseBlueprint;
9
use Illuminate\Database\Schema\ColumnDefinition;
10
use Illuminate\Support\Facades\Schema;
11
use Illuminate\Support\Fluent;
12
use Umbrellio\Postgres\Schema\Builders\Constraints\Check\CheckBuilder;
13
use Umbrellio\Postgres\Schema\Builders\Constraints\Exclude\ExcludeBuilder;
14
use Umbrellio\Postgres\Schema\Builders\Indexes\Unique\UniqueBuilder;
15
use Umbrellio\Postgres\Schema\Definitions\AttachPartitionDefinition;
16
use Umbrellio\Postgres\Schema\Definitions\CheckDefinition;
17
use Umbrellio\Postgres\Schema\Definitions\ExcludeDefinition;
18
use Umbrellio\Postgres\Schema\Definitions\LikeDefinition;
19
use Umbrellio\Postgres\Schema\Definitions\UniqueDefinition;
20
use Umbrellio\Postgres\Schema\Definitions\ViewDefinition;
21
use Umbrellio\Postgres\Schema\Types\DateRangeType;
22
use Umbrellio\Postgres\Schema\Types\TsRangeType;
23
use Umbrellio\Postgres\Schema\Types\TsTzRangeType;
24
25
class Blueprint extends BaseBlueprint
26
{
27
    protected $commands = [];
28
29
    public function setTable(string $table): self
30
    {
31
        $this->table = $table;
0 ignored issues
show
Bug Best Practice introduced by
The property table does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
32 4
        return $this;
33
    }
34 4
35
    /**
36
     * @return AttachPartitionDefinition|Fluent
37 1
     */
38
    public function attachPartition(string $partition): Fluent
39 1
    {
40
        return $this->addCommand('attachPartition', compact('partition'));
41
    }
42
43
    public function detachPartition(string $partition): void
44
    {
45
        $this->addCommand('detachPartition', compact('partition'));
46
    }
47
48
    /**
49
     * @codeCoverageIgnore
50
     * @return LikeDefinition|Fluent
51
     */
52
    public function like(string $table): Fluent
53
    {
54
        return $this->addCommand('like', compact('table'));
55
    }
56
57
    /**
58
     * @codeCoverageIgnore
59
     */
60
    public function ifNotExists(): Fluent
61
    {
62
        return $this->addCommand('ifNotExists');
63 13
    }
64
65 13
    /**
66
     * @param array|string $columns
67 13
     * @return UniqueDefinition|UniqueBuilder
68
     */
69 13
    public function uniquePartial($columns, ?string $index = null, ?string $algorithm = null): Fluent
70 13
    {
71 13
        $columns = (array) $columns;
72 13
73 13
        $index = $index ?: $this->createIndexName('unique', $columns);
74
75
        return $this->addExtendedCommand(
76 12
            UniqueBuilder::class,
77
            'uniquePartial',
78 12
            compact('columns', 'index', 'algorithm')
79
        );
80
    }
81
82
    public function dropUniquePartial($index): Fluent
83
    {
84
        return $this->dropIndexCommand('dropIndex', 'unique', $index);
85 6
    }
86
87 6
    /**
88
     * @param array|string $columns
89 6
     * @return ExcludeDefinition|ExcludeBuilder
90
     */
91 6
    public function exclude($columns, ?string $index = null): Fluent
92
    {
93
        $columns = (array) $columns;
94
95
        $index = $index ?: $this->createIndexName('excl', $columns);
96
97
        return $this->addExtendedCommand(ExcludeBuilder::class, 'exclude', compact('columns', 'index'));
98 3
    }
99
100 3
    /**
101
     * @param array|string $columns
102 3
     * @return CheckDefinition|CheckBuilder
103
     */
104 3
    public function check($columns, ?string $index = null): Fluent
105
    {
106
        $columns = (array) $columns;
107 1
108
        $index = $index ?: $this->createIndexName('chk', $columns);
109 1
110
        return $this->addExtendedCommand(CheckBuilder::class, 'check', compact('columns', 'index'));
111
    }
112 1
113
    public function dropExclude($index): Fluent
114 1
    {
115
        return $this->dropIndexCommand('dropUnique', 'excl', $index);
116
    }
117
118
    public function dropCheck($index): Fluent
119
    {
120
        return $this->dropIndexCommand('dropUnique', 'chk', $index);
121
    }
122
123
    /**
124
     * @codeCoverageIgnore
125
     */
126
    public function hasIndex($index, bool $unique = false): bool
127
    {
128
        if (is_array($index)) {
129
            $index = $this->createIndexName($unique === false ? 'index' : 'unique', $index);
130
        }
131
132
        return array_key_exists($index, $this->getSchemaManager()->listTableIndexes($this->getTable()));
133
    }
134
135
    /**
136
     * @codeCoverageIgnore
137
     * @return ViewDefinition|Fluent
138
     */
139
    public function createView(string $view, string $select, bool $materialize = false): Fluent
140
    {
141
        return $this->addCommand('createView', compact('view', 'select', 'materialize'));
142
    }
143
144
    /**
145
     * @codeCoverageIgnore
146
     */
147
    public function dropView(string $view): Fluent
148
    {
149
        return $this->addCommand('dropView', compact('view'));
150
    }
151 3
152
    /**
153 3
     * Almost like 'decimal' type, but can be with variable precision (by default)
154
     *
155
     * @return Fluent|ColumnDefinition
156
     */
157
    public function numeric(string $column, ?int $precision = null, ?int $scale = null): Fluent
158
    {
159 1
        return $this->addColumn('numeric', $column, compact('precision', 'scale'));
160
    }
161 1
162
    /**
163
     * @return Fluent|ColumnDefinition
164
     */
165
    public function tsrange(string $column): Fluent
166
    {
167 1
        return $this->addColumn(TsRangeType::TYPE_NAME, $column);
168
    }
169 1
170
    /**
171
     * @return Fluent|ColumnDefinition
172
     */
173
    public function tstzrange(string $column): Fluent
174
    {
175 1
        return $this->addColumn(TsTzRangeType::TYPE_NAME, $column);
176
    }
177 1
178
    /**
179
     * @return Fluent|ColumnDefinition
180
     */
181
    public function daterange(string $column): Fluent
182
    {
183
        return $this->addColumn(DateRangeType::TYPE_NAME, $column);
184
    }
185
186
    /**
187
     * @codeCoverageIgnore
188
     */
189
    protected function getSchemaManager()
190
    {
191 22
        /** @scrutinizer ignore-call */
192
        $connection = Schema::getConnection();
193 22
        $doctrineConnection = DriverManager::getConnection($connection->getConfig());
194 22
        return $doctrineConnection->getSchemaManager();
195 22
    }
196
197
    private function addExtendedCommand(string $fluent, string $name, array $parameters = []): Fluent
198
    {
199
        $command = new $fluent(array_merge(compact('name'), $parameters));
200
        $this->commands[] = $command;
201
        return $command;
202
    }
203
}
204