Passed
Push — dependabot/github_actions/depe... ( d1016c )
by
unknown
11:16
created

Indexes::persistentIndex()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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

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

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

102
        return $this->geoIndex(/** @scrutinizer ignore-type */ $columns, $name);
Loading history...
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

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

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