Passed
Push — next ( a87628...835774 )
by Bas
02:38
created

Indexes::executeDropIndexCommand()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2.0625

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
c 1
b 0
f 0
dl 0
loc 12
ccs 6
cts 8
cp 0.75
rs 10
cc 2
nc 2
nop 1
crap 2.0625
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 $type
14
     * @param string|array<string>|null $columns
15
     * @param string|null $name
16
     * @param array $indexOptions
17
     *
18
     * @return Fluent
19
     */
20 139
    protected function indexCommand(
21
        string $type = '',
22
        array|string $columns = null,
23
        string $name = null,
24
        array $indexOptions = []
25
    ): Fluent {
26 139
        if ($type == '') {
27
            $type = $this->mapIndexAlgorithm('persistent');
28
        }
29
30 139
        if ($columns === null) {
31 138
            $columns = end($this->columns);
32
        }
33
34 139
        if (is_string($columns)) {
35 138
            $columns = [$columns];
36
        }
37
38 139
        $indexOptions['name'] = $name ?: $this->createIndexName($type, $columns, $indexOptions);
39
40 139
        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

40
        return $this->/** @scrutinizer ignore-call */ addCommand('index', compact('type', 'columns', 'indexOptions'));
Loading history...
41
    }
42
43
    /**
44
     * Specify an index for the table.
45
     *
46
     * @param string|array $columns
47
     * @param string       $name
48
     * @param string|null  $algorithm
49
     *
50
     * @return Fluent
51
     */
52 138
    public function index($columns = null, $name = null, $algorithm = null)
53
    {
54 138
        $type = $this->mapIndexAlgorithm($algorithm);
55
56 138
        return $this->indexCommand($type, $columns, $name);
57
    }
58
59
    /**
60
     * Create a hash index for fast exact matching.
61
     *
62
     * @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...
63
     * @param array $indexOptions
64
     *
65
     * @return Fluent
66
     */
67
    public function hashIndex($columns = null, $indexOptions = [])
68
    {
69
        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

69
        return $this->indexCommand('hash', $columns, /** @scrutinizer ignore-type */ $indexOptions);
Loading history...
70
    }
71
72
    /**
73
     * @param null|string $column
74
     * @param string $name
75
     * @param array $indexOptions
76
     *
77
     * @return Fluent
78
     */
79
    public function fulltextIndex($column = null, $name = null, $indexOptions = [])
80
    {
81
        return $this->indexCommand('fulltext', $column, $name, $indexOptions);
82
    }
83
84
    /**
85
     *  Specify a spatial index for the table.
86
     *
87
     * @param array<mixed>|null $columns
88
     * @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...
89
     * @param array $indexOptions
90
     *
91
     * @return Fluent
92
     */
93
    public function geoIndex(array $columns = null, $name = null, $indexOptions = [])
94
    {
95
        return $this->indexCommand('geo', $columns, $name, $indexOptions);
96
    }
97
98
    /**
99
     * Specify a spatial index for the table.
100
     *
101
     * @param string|array $columns
102
     * @param string       $name
103
     *
104
     * @return Fluent
105
     */
106
    public function spatialIndex($columns, $name = null)
107
    {
108
        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

108
        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

108
        return $this->geoIndex(/** @scrutinizer ignore-type */ $columns, $name);
Loading history...
109
    }
110
111
    /**
112
     * @param array<mixed>|null$columns
113
     * @param string|null $name
114
     * @param array       $indexOptions
115
     *
116
     * @return Fluent
117
     */
118
    public function skiplistIndex(array $columns = null, $name = null, $indexOptions = [])
119
    {
120
        return $this->indexCommand('skiplist', $columns, $name, $indexOptions);
121
    }
122
123
    public function persistentIndex(array $columns = null, string $name = null, array $indexOptions = []): Fluent
124
    {
125
        return $this->indexCommand('persistent', $columns, $name, $indexOptions);
126
    }
127
128
    /**
129
     * Create a TTL index for the table.
130
     *
131
     * @param array<string>|null $columns
132
     * @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...
133
     * @param array $indexOptions
134
     *
135
     * @return Fluent
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
     * @return Fluent
150
     */
151 139
    public function unique($columns = null, $name = null, $algorithm = null): Fluent
152
    {
153 139
        $type = $this->mapIndexAlgorithm($algorithm);
154
155 139
        $indexOptions = [];
156 139
        $indexOptions['unique'] = true;
157
158 139
        return $this->indexCommand($type, $columns, $name, $indexOptions);
159
    }
160
161
    /**
162
     * @throws ArangoException
163
     */
164 139
    public function executeIndexCommand(Fluent $command)
165
    {
166 139
        if ($this->connection->pretending()) {
167
            $this->connection->logQuery('/* ' . $command->explanation . " */\n", []);
168
169
            return;
170
        }
171
172 139
        $options = [
173 139
            'type'    => $command->type,
174 139
            'fields'  => $command->columns,
175 139
            'unique'  => $command->unique,
176 139
            'options' => $command->indexOptions,
177
        ];
178
179 139
        if (isset($command->indexOptions) && is_array($command->indexOptions)) {
180 139
            $options = array_merge($options, $command->indexOptions);
181
        }
182
183 139
        $this->schemaManager->createIndex($this->table, $options);
184 139
    }
185
186
    /**
187
     * Indicate that the given index should be dropped.
188
     */
189 3
    public function dropIndex(string $name): Fluent
190
    {
191 3
        $parameters = [];
192 3
        $parameters['name'] = 'dropIndex';
193 3
        $parameters['index'] = $name;
194 3
        $parameters['explanation'] = "Drop the '" . $name . "' index on the {$this->table} table.";
195 3
        $parameters['handler'] = 'collection';
196
197 3
        return $this->addCommand('dropIndex', $parameters);
198
    }
199
200
    /**
201
     * Drop the index by first getting all the indexes on the table; then selecting the matching one
202
     * by name.
203
     */
204 3
    public function executeDropIndexCommand(Fluent $command)
205
    {
206 3
        if ($this->connection->pretending()) {
207
            $this->connection->logQuery('/* ' . $command->explanation . " */\n", []); // @phpstan-ignore-line
208
209
            return;
210
        }
211 3
        $indexes = $this->schemaManager->getIndexes($this->table);
212 3
        $arrayIndex = array_search($command->index, array_column($indexes, 'name'), true);
213 3
        $indexId = $indexes[$arrayIndex]->id;
214
215 3
        $this->schemaManager->deleteIndex($indexId);
216 3
    }
217
218
    /**
219
     * @param string|null $algorithm
220
     *
221
     * @return mixed|string
222
     */
223 139
    protected function mapIndexAlgorithm($algorithm): mixed
224
    {
225 139
        $algorithmConversion = [
226
            'HASH'  => 'hash',
227
            'BTREE' => 'persistent',
228
            'RTREE' => 'geo',
229
            'TTL'   => 'ttl',
230
        ];
231 139
        $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

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