Passed
Push — 127-support-multidimensional-i... ( fe24b7...03f2d3 )
by Bas
05:26
created

Indexes::mapIndexAlgorithm()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 7
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 12
rs 10
ccs 0
cts 0
cp 0
crap 6
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
    use HandlesIndexNaming;
11
12
    /**
13
     * Add a new index command to the blueprint.
14
     *
15
     * @param  string|array<string>|null  $columns
16
     */
17 66
    protected function indexCommand(
18
        string $type,
19
        array|null|string $columns = null,
20
        string $name = null,
21
        array $indexOptions = [],
22
    ): Fluent {
23 66
        if ($columns === null) {
24 50
            $columns = end($this->columns);
25
        }
26
27 66
        if (is_string($columns)) {
28 55
            $columns = [$columns];
29
        }
30
31 66
        $columns = $this->renameIdField($columns);
0 ignored issues
show
Bug introduced by
It seems like renameIdField() 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

31
        /** @scrutinizer ignore-call */ 
32
        $columns = $this->renameIdField($columns);
Loading history...
32
33 66
        $indexOptions['name'] = $name ?: $this->createIndexName($type, $columns, $indexOptions);
34
35 66
        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 array|null|string $columns
42
     * @param null|string $name
43
     * @param null|string $algorithm
44
     * @param array<mixed> $indexOptions
45
     * @return Fluent
46
     */
47 56
    public function index($columns = null, $name = null, $algorithm = null, $indexOptions = [])
48
    {
49 56
        $type = $this->mapIndexAlgorithm($algorithm);
50
51 56
        return $this->indexCommand($type, $columns, $name, $indexOptions);
52
    }
53
54
    /**
55
     * Specify a spatial index for the table.
56
     *
57
     * @param string|array $columns
58
     * @param null|string $name
59
     * @param array<mixed> $indexOptions
60
     * @return Fluent
61
     */
62 2
    public function spatialIndex($columns, $name = null, $indexOptions = [])
63
    {
64 2
        return $this->indexCommand('geo', $columns, $name, $indexOptions);
65
    }
66
67
    /**
68
     *  Specify a spatial index for the table.
69
     *
70
     * @param  array<mixed>|null|string  $columns
71
     * @param  null|string  $name
72
     * @param  array<mixed>  $indexOptions
73
     * @return Fluent
74
     */
75 1
    public function geoIndex($columns, $name = null, $indexOptions = [])
76
    {
77 1
        return $this->spatialIndex($columns, $name, $indexOptions);
78
    }
79
80
    /**
81
     *  Specify a inverted index for the table.
82
     *
83
     * @param  array<mixed>|null|string  $columns
84
     * @param  null|string  $name
85
     * @param  array<mixed>  $indexOptions
86
     * @return Fluent
87
     */
88 49
    public function invertedIndex($columns = null, $name = null, $indexOptions = [])
89
    {
90 49
        return $this->indexCommand('inverted', $columns, $name, $indexOptions);
91
    }
92
93 1
94
    public function multiDimensionalIndex(array $columns = null, string $name = null, array $indexOptions = [], string $type = 'mdi'): Fluent
95 1
    {
96
        return $this->indexCommand(
97
            $type,
98
            $columns,
99
            $name,
100
            $indexOptions,
101
        );
102
    }
103
104 50
    public function persistentIndex(array $columns = null, string $name = null, array $indexOptions = []): Fluent
105
    {
106 50
        return $this->indexCommand('persistent', $columns, $name, $indexOptions);
107
    }
108 50
109
    /**
110
     * @param array<string>|null|string $columns
111
     * @param string|null $name
112
     * @param array<mixed> $indexOptions
113
     * @return Fluent
114
     */
115
    public function primary($columns = null, $name = null, $indexOptions = []): Fluent
116
    {
117
        $indexOptions['unique'] = true;
118
119
        return $this->indexCommand('persistent', $columns, $name, $indexOptions);
120 2
    }
121
122 2
    /**
123 2
     * Create a TTL index for the table.
124
     *
125
     * @param string $columns
126
     * @param int $expireAfter
127
     * @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...
128
     * @param array $indexOptions
129
     * @return Fluent
130
     */
131
    public function ttlIndex($columns, $expireAfter, $name = null, $indexOptions = []): Fluent
132
    {
133 49
        $indexOptions['expireAfter'] = $expireAfter;
134
        return $this->indexCommand('ttl', $columns, $name, $indexOptions);
135 49
    }
136
137 49
    /**
138 49
     * Specify a unique index for the table.
139
     *
140 49
     * @param  string|array  $columns
141
     * @param  string  $name
142
     * @param  string|null  $algorithm
143
     */
144
    public function unique($columns = null, $name = null, $algorithm = null): Fluent
145
    {
146 66
        $type = $this->mapIndexAlgorithm($algorithm);
147
148 66
        $indexOptions = [];
149
        $indexOptions['unique'] = true;
150
151
        return $this->indexCommand($type, $columns, $name, $indexOptions);
152
    }
153
154
    /**
155
     * @throws ArangoException
156 66
     */
157 66
    public function executeIndexCommand(Fluent $command)
158 66
    {
159
        if ($this->connection->pretending()) {
160 49
            $this->connection->logQuery('/* ' . $command->explanation . " */\n", []);
161
162
            return;
163 65
        }
164 65
165 65
        // Skip persistent indexes set solely on id - ArangoDB already sets a unique index on _key.
166 65
        if (
167 65
            $command->type === 'persistent'
0 ignored issues
show
introduced by
The condition $command->type === 'persistent' is always false.
Loading history...
168 65
            && count($command->columns) === 1
169
            && $command->columns[0] === '_key'
170 65
        ) {
171 65
            return;
172
        }
173
174 65
        $options = [
175
            'type' => $command->type,
176
            'fields' => $command->columns,
177
            'unique' => $command->unique,
178
            'options' => $command->indexOptions,
179
        ];
180 10
181
        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...
182 10
            $options = array_merge($options, $command->indexOptions);
183 10
        }
184 10
185 10
        $this->schemaManager->createIndex($this->table, $options);
186 10
    }
187
188 10
    /**
189
     * Indicate that the given index should be dropped.
190
     */
191
    public function dropIndex(string $name): Fluent
192
    {
193
        $parameters = [];
194
        $parameters['name'] = 'dropIndex';
195
        $parameters['index'] = $name;
196
        $parameters['explanation'] = "Drop the '" . $name . "' index on the {$this->table} table.";
197
        $parameters['handler'] = 'collection';
198
199
        return $this->addCommand('dropIndex', $parameters);
200
    }
201
202 1
    /**
203
     * Indicate that the given index should be dropped.
204 1
     */
205
    public function dropPersistentIndex(string $name): Fluent
206
    {
207
        return $this->dropIndex($name);
208
    }
209
210 1
    /**
211
     * Indicate that the given index should be dropped.
212 1
     */
213
    public function dropPrimary(string $name): Fluent
214
    {
215
        return $this->dropIndex($name);
216
    }
217
218 2
    /**
219
     * Indicate that the given index should be dropped.
220 2
     */
221
    public function dropUnique(string $name): Fluent
222
    {
223
        return $this->dropIndex($name);
224
    }
225
226 2
    /**
227
     * Indicate that the given index should be dropped.
228 2
     */
229
    public function dropSpatialIndex(string $name): Fluent
230
    {
231
        return $this->dropIndex($name);
232
    }
233
234
    /**
235
     * Indicate that the given index should be dropped.
236
     */
237 10
    public function dropInvertedIndex(string $name): Fluent
238
    {
239 10
        return $this->dropIndex($name);
240
    }
241
242
    /**
243
     * Indicate that the given index should be dropped.
244 10
     */
245 10
    public function dropMultiDimensionalIndex(string $name): Fluent
246 10
    {
247
        return $this->dropIndex($name);
248 10
    }
249
250
    /**
251
     * Drop the index by first getting all the indexes on the table; then selecting the matching one
252
     * by name.
253
     */
254
    public function executeDropIndexCommand(Fluent $command)
255 57
    {
256
        if ($this->connection->pretending()) {
257 57
            $this->connection->logQuery('/* ' . $command->explanation . " */\n", []); // @phpstan-ignore-line
258
259 57
            return;
260 57
        }
261 57
        $indexes = $this->schemaManager->getIndexes($this->table);
262 57
        $arrayIndex = array_search($command->index, array_column($indexes, 'name'), true);
263 57
        $indexId = $indexes[$arrayIndex]->id;
264 57
265
        $this->schemaManager->deleteIndex($indexId);
266 57
    }
267
268
    /**
269
     * @param  string|null  $algorithm
270
     * @return mixed|string
271
     */
272
    protected function mapIndexAlgorithm($algorithm): mixed
273
    {
274
        $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

274
        $algorithm = strtoupper(/** @scrutinizer ignore-type */ $algorithm);
Loading history...
275
276
        $algorithmConversion = [
277
            'HASH' => 'hash',
278
            'BTREE' => 'persistent',
279
            'RTREE' => 'geo',
280
            'TTL' => 'ttl',
281
        ];
282
283
        return (isset($algorithmConversion[$algorithm])) ? $algorithmConversion[$algorithm] : 'persistent';
284
    }
285
286
}
287