Passed
Pull Request — next (#84)
by Bas
15:17 queued 11:12
created

Indexes::dropIndex()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 6
nc 1
nop 1
dl 0
loc 9
ccs 7
cts 7
cp 1
crap 1
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace LaravelFreelancerNL\Aranguent\Schema\Concerns;
4
5
use ArangoClient\Exceptions\ArangoException;
6
use Illuminate\Support\Fluent;
7
8
trait Indexes
9
{
10
    /**
11
     * Add a new index command to the blueprint.
12
     *
13
     * @param  string|array<string>|null  $columns
14
     */
15 10
    protected function indexCommand(
16
        string $type = '',
17
        array|string $columns = null,
18
        string $name = null,
19
        array $indexOptions = []
20
    ): Fluent {
21 10
        if ($type == '') {
22
            $type = $this->mapIndexAlgorithm('persistent');
23
        }
24
25 10
        if ($columns === null) {
26 5
            $columns = end($this->columns);
27
        }
28
29 10
        if (is_string($columns)) {
30 5
            $columns = [$columns];
31
        }
32
33 10
        $indexOptions['name'] = $name ?: $this->createIndexName($type, $columns, $indexOptions);
34
35 10
        return $this->addCommand('index', compact('type', 'columns', 'indexOptions'));
0 ignored issues
show
Bug introduced by
It seems like addCommand() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

35
        return $this->/** @scrutinizer ignore-call */ addCommand('index', compact('type', 'columns', 'indexOptions'));
Loading history...
36
    }
37
38
    /**
39
     * Specify an index for the table.
40
     *
41
     * @param  string|array  $columns
42
     * @param  string  $name
43
     * @param  string|null  $algorithm
44
     * @return Fluent
45
     */
46 6
    public function index($columns = null, $name = null, $algorithm = null)
47
    {
48 6
        $type = $this->mapIndexAlgorithm($algorithm);
49
50 6
        return $this->indexCommand($type, $columns, $name);
51
    }
52
53
    /**
54
     * Create a hash index for fast exact matching.
55
     *
56
     * @param  null  $columns
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $columns is correct as it would always require null to be passed?
Loading history...
57
     * @param  array  $indexOptions
58
     * @return Fluent
59
     */
60
    public function hashIndex($columns = null, $indexOptions = [])
61
    {
62
        return $this->indexCommand('hash', $columns, $indexOptions);
0 ignored issues
show
Bug introduced by
$indexOptions of type array is incompatible with the type null|string expected by parameter $name of LaravelFreelancerNL\Aran...Indexes::indexCommand(). ( Ignorable by Annotation )

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

62
        return $this->indexCommand('hash', $columns, /** @scrutinizer ignore-type */ $indexOptions);
Loading history...
63
    }
64
65
    /**
66
     * @param  null|string  $column
67
     * @param  string  $name
68
     * @param  array  $indexOptions
69
     * @return Fluent
70
     */
71
    public function fulltextIndex($column = null, $name = null, $indexOptions = [])
72
    {
73
        return $this->indexCommand('fulltext', $column, $name, $indexOptions);
74
    }
75
76
    /**
77
     *  Specify a spatial index for the table.
78
     *
79
     * @param  array<mixed>|null  $columns
80
     * @param  null  $name
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $name is correct as it would always require null to be passed?
Loading history...
81
     * @param  array  $indexOptions
82
     * @return Fluent
83
     */
84
    public function geoIndex(array $columns = null, $name = null, $indexOptions = [])
85
    {
86
        return $this->indexCommand('geo', $columns, $name, $indexOptions);
87
    }
88
89
    /**
90
     *  Specify a inverted index for the table.
91
     *
92
     * @param  array<mixed>|null  $columns
93
     * @param  null  $name
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $name is correct as it would always require null to be passed?
Loading history...
94
     * @param  array  $indexOptions
95
     * @return Fluent
96
     */
97 1
    public function invertedIndex(array $columns = null, $name = null, $indexOptions = [])
98
    {
99 1
        return $this->indexCommand('inverted', $columns, $name, $indexOptions);
100
    }
101
102
    /**
103
     * Specify a spatial index for the table.
104
     *
105
     * @param  string|array  $columns
106
     * @param  string  $name
107
     * @return Fluent
108
     */
109
    public function spatialIndex($columns, $name = null)
110
    {
111
        return $this->geoIndex($columns, $name);
0 ignored issues
show
Bug introduced by
It seems like $name can also be of type string; however, parameter $name of LaravelFreelancerNL\Aran...rns\Indexes::geoIndex() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

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

111
        return $this->geoIndex($columns, /** @scrutinizer ignore-type */ $name);
Loading history...
Bug introduced by
It seems like $columns can also be of type string; however, parameter $columns of LaravelFreelancerNL\Aran...rns\Indexes::geoIndex() does only seem to accept array|null, maybe add an additional type check? ( Ignorable by Annotation )

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

111
        return $this->geoIndex(/** @scrutinizer ignore-type */ $columns, $name);
Loading history...
112
    }
113
114
    /**
115
     * @param array<mixed>|null$columns
116
     * @param  string|null  $name
117
     * @param  array  $indexOptions
118
     * @return Fluent
119
     */
120
    public function skiplistIndex(array $columns = null, $name = null, $indexOptions = [])
121
    {
122
        return $this->indexCommand('skiplist', $columns, $name, $indexOptions);
123
    }
124
125
    public function persistentIndex(array $columns = null, string $name = null, array $indexOptions = []): Fluent
126
    {
127
        return $this->indexCommand('persistent', $columns, $name, $indexOptions);
128
    }
129
130
    /**
131
     * Create a TTL index for the table.
132
     *
133
     * @param  array<string>|null  $columns
134
     * @param  null  $name
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $name is correct as it would always require null to be passed?
Loading history...
135
     * @param  array  $indexOptions
136
     */
137
    public function ttlIndex(array $columns = null, $name = null, $indexOptions = []): Fluent
138
    {
139
        return $this->indexCommand('ttl', $columns, $name, $indexOptions);
140
    }
141
142
    /**
143
     * Specify a unique index for the table.
144
     *
145
     * @param  string|array  $columns
146
     * @param  string  $name
147
     * @param  string|null  $algorithm
148
     */
149 3
    public function unique($columns = null, $name = null, $algorithm = null): Fluent
150
    {
151 3
        $type = $this->mapIndexAlgorithm($algorithm);
152
153 3
        $indexOptions = [];
154 3
        $indexOptions['unique'] = true;
155
156 3
        return $this->indexCommand($type, $columns, $name, $indexOptions);
157
    }
158
159
    /**
160
     * @throws ArangoException
161
     */
162 10
    public function executeIndexCommand(Fluent $command)
163
    {
164 10
        if ($this->connection->pretending()) {
165
            $this->connection->logQuery('/* ' . $command->explanation . " */\n", []);
166
167
            return;
168
        }
169
170 10
        $options = [
171 10
            'type' => $command->type,
172 10
            'fields' => $command->columns,
173 10
            'unique' => $command->unique,
174 10
            'options' => $command->indexOptions,
175 10
        ];
176
177 10
        if (isset($command->indexOptions) && is_array($command->indexOptions)) {
0 ignored issues
show
introduced by
The condition is_array($command->indexOptions) is always false.
Loading history...
178 10
            $options = array_merge($options, $command->indexOptions);
179
        }
180
181 10
        $this->schemaManager->createIndex($this->table, $options);
182
    }
183
184
    /**
185
     * Indicate that the given index should be dropped.
186
     */
187 3
    public function dropIndex(string $name): Fluent
188
    {
189 3
        $parameters = [];
190 3
        $parameters['name'] = 'dropIndex';
191 3
        $parameters['index'] = $name;
192 3
        $parameters['explanation'] = "Drop the '" . $name . "' index on the {$this->table} table.";
193 3
        $parameters['handler'] = 'collection';
194
195 3
        return $this->addCommand('dropIndex', $parameters);
196
    }
197
198
    /**
199
     * Drop the index by first getting all the indexes on the table; then selecting the matching one
200
     * by name.
201
     */
202 3
    public function executeDropIndexCommand(Fluent $command)
203
    {
204 3
        if ($this->connection->pretending()) {
205
            $this->connection->logQuery('/* ' . $command->explanation . " */\n", []); // @phpstan-ignore-line
206
207
            return;
208
        }
209 3
        $indexes = $this->schemaManager->getIndexes($this->table);
210 3
        $arrayIndex = array_search($command->index, array_column($indexes, 'name'), true);
211 3
        $indexId = $indexes[$arrayIndex]->id;
212
213 3
        $this->schemaManager->deleteIndex($indexId);
214
    }
215
216
    /**
217
     * @param  string|null  $algorithm
218
     * @return mixed|string
219
     */
220 9
    protected function mapIndexAlgorithm($algorithm): mixed
221
    {
222 9
        $algorithmConversion = [
223 9
            'HASH' => 'hash',
224 9
            'BTREE' => 'persistent',
225 9
            'RTREE' => 'geo',
226 9
            'TTL' => 'ttl',
227 9
        ];
228 9
        $algorithm = strtoupper($algorithm);
0 ignored issues
show
Bug introduced by
It seems like $algorithm can also be of type null; however, parameter $string of strtoupper() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

228
        $algorithm = strtoupper(/** @scrutinizer ignore-type */ $algorithm);
Loading history...
229
230 9
        return (isset($algorithmConversion[$algorithm])) ? $algorithmConversion[$algorithm] : 'persistent';
231
    }
232
233
    /**
234
     * Create a default index name for the table.
235
     *
236
     * @param  string  $type
237
     */
238 11
    public function createIndexName($type, array $columns, array $options = []): string
239
    {
240 11
        $nameParts = [];
241 11
        $nameParts[] = $this->prefix . $this->table;
242 11
        $nameParts = array_merge($nameParts, $columns);
243 11
        $nameParts[] = $type;
244 11
        $nameParts = array_merge($nameParts, array_keys($options));
245 11
        array_filter($nameParts);
246
247 11
        $index = strtolower(implode('_', $nameParts));
248 11
        $index = preg_replace("/\[\*+\]+/", '_array', $index);
249
250 11
        return preg_replace('/[^A-Za-z0-9]+/', '_', $index);
251
    }
252
}
253