IndexCommands   A
last analyzed

Complexity

Total Complexity 31

Size/Duplication

Total Lines 276
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 70
dl 0
loc 276
rs 9.92
c 0
b 0
f 0
wmc 31

20 Methods

Rating   Name   Duplication   Size   Complexity  
A multiDimensionalIndex() 0 7 1
A dropMultiDimensionalIndex() 0 3 1
A dropSpatialIndex() 0 3 1
A spatialIndex() 0 3 1
A mapIndexAlgorithm() 0 12 2
A dropPersistentIndex() 0 3 1
A primary() 0 5 1
A dropUnique() 0 3 1
A geoIndex() 0 3 1
A dropIndex() 0 9 1
A unique() 0 8 1
A invertedIndex() 0 3 1
A executeDropIndexCommand() 0 12 2
A dropPrimary() 0 3 1
A ttlIndex() 0 4 1
A index() 0 5 1
A persistentIndex() 0 3 1
A dropInvertedIndex() 0 3 1
A indexCommand() 0 19 4
B executeIndexCommand() 0 29 7
1
<?php
2
3
namespace LaravelFreelancerNL\Aranguent\Schema\Concerns;
4
5
use ArangoClient\Exceptions\ArangoException;
6
use Illuminate\Support\Fluent;
7
8
trait IndexCommands
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
    protected function indexCommand(
18
        string $type,
19
        array|null|string $columns = null,
20
        string $name = null,
21
        array $indexOptions = [],
22
    ): Fluent {
23
        if ($columns === null) {
24
            $columns = end($this->columns);
25
        }
26
27
        if (is_string($columns)) {
28
            $columns = [$columns];
29
        }
30
31
        $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
        $indexOptions['name'] = $name ?: $this->createIndexName($type, $columns, $indexOptions);
34
35
        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
    public function index($columns = null, $name = null, $algorithm = null, $indexOptions = [])
48
    {
49
        $type = $this->mapIndexAlgorithm($algorithm);
50
51
        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
    public function spatialIndex($columns, $name = null, $indexOptions = [])
63
    {
64
        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
    public function geoIndex($columns, $name = null, $indexOptions = [])
76
    {
77
        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
    public function invertedIndex($columns = null, $name = null, $indexOptions = [])
89
    {
90
        return $this->indexCommand('inverted', $columns, $name, $indexOptions);
91
    }
92
93
94
    public function multiDimensionalIndex(array $columns = null, string $name = null, array $indexOptions = [], string $type = 'mdi'): Fluent
95
    {
96
        return $this->indexCommand(
97
            $type,
98
            $columns,
99
            $name,
100
            $indexOptions,
101
        );
102
    }
103
104
    public function persistentIndex(array $columns = null, string $name = null, array $indexOptions = []): Fluent
105
    {
106
        return $this->indexCommand('persistent', $columns, $name, $indexOptions);
107
    }
108
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
    }
121
122
    /**
123
     * 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
        $indexOptions['expireAfter'] = $expireAfter;
134
        return $this->indexCommand('ttl', $columns, $name, $indexOptions);
135
    }
136
137
    /**
138
     * Specify a unique index for the table.
139
     *
140
     * @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
        $type = $this->mapIndexAlgorithm($algorithm);
147
148
        $indexOptions = [];
149
        $indexOptions['unique'] = true;
150
151
        return $this->indexCommand($type, $columns, $name, $indexOptions);
152
    }
153
154
    /**
155
     * @throws ArangoException
156
     */
157
    public function executeIndexCommand(Fluent $command)
158
    {
159
        if ($this->connection->pretending()) {
160
            $this->connection->logQuery('/* ' . $command->explanation . " */\n", []);
161
162
            return;
163
        }
164
165
        // Skip persistent indexes set solely on id - ArangoDB already sets a unique index on _key.
166
        if (
167
            $command->type === 'persistent'
0 ignored issues
show
introduced by
The condition $command->type === 'persistent' is always false.
Loading history...
168
            && count($command->columns) === 1
169
            && $command->columns[0] === '_key'
170
        ) {
171
            return;
172
        }
173
174
        $options = [
175
            'type' => $command->type,
176
            'fields' => $command->columns,
177
            'unique' => $command->unique,
178
            'options' => $command->indexOptions,
179
        ];
180
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
            $options = array_merge($options, $command->indexOptions);
183
        }
184
185
        $this->schemaManager->createIndex($this->table, $options);
186
    }
187
188
    /**
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
    /**
203
     * Indicate that the given index should be dropped.
204
     */
205
    public function dropPersistentIndex(string $name): Fluent
206
    {
207
        return $this->dropIndex($name);
208
    }
209
210
    /**
211
     * Indicate that the given index should be dropped.
212
     */
213
    public function dropPrimary(string $name): Fluent
214
    {
215
        return $this->dropIndex($name);
216
    }
217
218
    /**
219
     * Indicate that the given index should be dropped.
220
     */
221
    public function dropUnique(string $name): Fluent
222
    {
223
        return $this->dropIndex($name);
224
    }
225
226
    /**
227
     * Indicate that the given index should be dropped.
228
     */
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
    public function dropInvertedIndex(string $name): Fluent
238
    {
239
        return $this->dropIndex($name);
240
    }
241
242
    /**
243
     * Indicate that the given index should be dropped.
244
     */
245
    public function dropMultiDimensionalIndex(string $name): Fluent
246
    {
247
        return $this->dropIndex($name);
248
    }
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
    {
256
        if ($this->connection->pretending()) {
257
            $this->connection->logQuery('/* ' . $command->explanation . " */\n", []); // @phpstan-ignore-line
258
259
            return;
260
        }
261
        $indexes = $this->schemaManager->getIndexes($this->table);
262
        $arrayIndex = array_search($command->index, array_column($indexes, 'name'), true);
263
        $indexId = $indexes[$arrayIndex]->id;
264
265
        $this->schemaManager->deleteIndex($indexId);
266
    }
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