Failed Conditions
Push — refactor/improve-static-analys... ( 8065ea...92b34c )
by Bas
05:43
created

CompilesDataManipulations::compileUpdate()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 25
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 13
c 1
b 0
f 0
nc 4
nop 2
dl 0
loc 25
rs 9.8333
1
<?php
2
3
namespace LaravelFreelancerNL\Aranguent\Query\Concerns;
4
5
use Illuminate\Database\Query\Builder as IlluminateQueryBuilder;
6
use Illuminate\Support\Arr;
7
use LaravelFreelancerNL\Aranguent\Query\Builder;
8
use LaravelFreelancerNL\FluentAQL\Exceptions\BindException as BindException;
9
10
trait CompilesDataManipulations
11
{
12
    /**
13
     * Compile an insert statement into AQL.
14
     *
15
     * @param IlluminateQueryBuilder $query
16
     * @param array   $values
17
     *
18
     * @throws BindException
19
     *
20
     * @return string
21
     */
22
    public function compileInsert(Builder|IlluminateQueryBuilder $query, array $values, string $bindVar = null)
23
    {
24
        $table = $this->prefixTable($query->from);
0 ignored issues
show
Bug introduced by
It seems like prefixTable() 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

24
        /** @scrutinizer ignore-call */ 
25
        $table = $this->prefixTable($query->from);
Loading history...
25
26
        if (empty($values)) {
27
            $aql = /** @lang AQL */ 'INSERT {} INTO ' . $table . ' RETURN NEW._key';
28
29
            return $aql;
30
        }
31
32
        return /** @lang AQL */ 'LET values = ' . $bindVar
33
            . ' FOR value IN values'
34
            . ' INSERT value INTO ' . $table
35
            . ' RETURN NEW._key';
36
    }
37
38
    /**
39
     * Compile an insert and get ID statement into SQL.
40
     *
41
     * @param array<mixed> $values
42
     */
43
    public function compileInsertGetId(IlluminateQueryBuilder $query, $values, $sequence = '_key', string $bindVar = null)
44
    {
45
        $table = $this->prefixTable($query->from);
46
47
        $sequence = $this->convertIdToKey($sequence);
0 ignored issues
show
Bug introduced by
It seems like convertIdToKey() 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

47
        /** @scrutinizer ignore-call */ 
48
        $sequence = $this->convertIdToKey($sequence);
Loading history...
48
49
        if (empty($values)) {
50
            $aql = /** @lang AQL */ 'INSERT {} INTO ' . $table . ' RETURN NEW.' . $sequence;
51
52
            return $aql;
53
        }
54
55
        $aql = /** @lang AQL */ 'LET values = ' . $bindVar
56
            . ' FOR value IN values'
57
            . ' INSERT value INTO ' . $table
58
            . ' RETURN NEW.' . $sequence;
59
60
        return $aql;
61
    }
62
63
    /**
64
     * Compile an insert statement into AQL.
65
     *
66
     * @param IlluminateQueryBuilder $query
67
     * @param array<mixed> $values
68
     * @return string
69
     */
70
    public function compileInsertOrIgnore(IlluminateQueryBuilder $query, array $values, string $bindVar = null)
71
    {
72
        $table = $this->prefixTable($query->from);
73
74
        if (empty($values)) {
75
            $aql = /** @lang AQL */ "INSERT {} INTO $table RETURN NEW._key";
76
77
            return $aql;
78
        }
79
80
        $aql = /** @lang AQL */ "LET values = $bindVar "
81
            . "FOR value IN values "
82
            . "INSERT value INTO $table "
83
            . "OPTIONS { ignoreErrors: true } "
84
            . "RETURN NEW._key";
85
86
        return $aql;
87
    }
88
89
    /**
90
     * Compile an insert statement using a subquery into SQL.
91
     *
92
     * @param  IlluminateQueryBuilder  $query
93
     * @param  array  $columns
94
     * @param  string  $sql
95
     * @return string
96
     */
97
    public function compileInsertUsing(IlluminateQueryBuilder $query, array $columns, string $sql)
98
    {
99
        $table = $this->wrapTable($query->from);
0 ignored issues
show
Bug introduced by
It seems like wrapTable() 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

99
        /** @scrutinizer ignore-call */ 
100
        $table = $this->wrapTable($query->from);
Loading history...
100
101
        $insertDoc = '';
102
        if (empty($columns) || $columns === ['*']) {
103
            $insertDoc = 'docDoc';
104
        }
105
106
107
        if ($insertDoc === '') {
108
            $insertValues = [];
109
            foreach($columns as $column) {
110
                $insertValues[$column] = $this->normalizeColumnReferences($query, $column, 'docs');
0 ignored issues
show
Bug introduced by
It seems like normalizeColumnReferences() 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

110
                /** @scrutinizer ignore-call */ 
111
                $insertValues[$column] = $this->normalizeColumnReferences($query, $column, 'docs');
Loading history...
111
            }
112
            $insertDoc = $this->generateAqlObject($insertValues);
0 ignored issues
show
Bug introduced by
It seems like generateAqlObject() 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

112
            /** @scrutinizer ignore-call */ 
113
            $insertDoc = $this->generateAqlObject($insertValues);
Loading history...
113
        }
114
115
116
        //        if ($insertDoc !== '') {
117
        //            $insertValues;
118
        //        }
119
120
        $aql = /** @lang AQL */ 'LET docs = ' . $sql
121
            . ' FOR docDoc IN docs'
122
            . ' INSERT ' . $insertDoc . ' INTO ' . $table
123
            . ' RETURN NEW._key';
124
125
126
        return $aql;
127
    }
128
129
    protected function createUpdateObject($values)
130
    {
131
        $valueStrings = [];
132
        foreach($values as $key => $value) {
133
            if (is_array($value)) {
134
                $valueStrings[] = $key . ': ' . $this->createUpdateObject($value);
135
            } else {
136
                $valueStrings[] = $key . ': ' . $value;
137
            }
138
        }
139
140
        return '{ ' . implode(', ', $valueStrings) . ' }';
141
    }
142
143
    /**
144
     * Compile an update statement into AQL.
145
     *
146
     * @param  \Illuminate\Database\Query\Builder  $query
147
     * @param  array  $values
148
     * @return string
149
     */
150
    public function compileUpdate(IlluminateQueryBuilder $query, array|string $values)
151
    {
152
        assert($query instanceof Builder);
153
154
        $table = $query->from;
155
        $alias = $query->getTableAlias($query->from);
156
157
        if (!is_array($values)) {
0 ignored issues
show
introduced by
The condition is_array($values) is always true.
Loading history...
158
            $values = Arr::wrap($values);
159
        }
160
161
        $updateValues = $this->generateAqlObject($values);
162
163
        $aqlElements = [];
164
        $aqlElements[] = $this->compileFrom($query, $query->from);
0 ignored issues
show
Bug introduced by
It seems like compileFrom() 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

164
        /** @scrutinizer ignore-call */ 
165
        $aqlElements[] = $this->compileFrom($query, $query->from);
Loading history...
165
166
        if (!empty($query->joins)) {
167
            $aqlElements[] = $this->compileJoins($query, $query->joins);
0 ignored issues
show
Bug introduced by
The method compileJoins() does not exist on LaravelFreelancerNL\Aran...mpilesDataManipulations. Did you maybe mean compileInsert()? ( Ignorable by Annotation )

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

167
            /** @scrutinizer ignore-call */ 
168
            $aqlElements[] = $this->compileJoins($query, $query->joins);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
168
        }
169
170
        $aqlElements[] = $this->compileWheres($query);
0 ignored issues
show
Bug introduced by
The method compileWheres() does not exist on LaravelFreelancerNL\Aran...mpilesDataManipulations. Did you maybe mean compileInsert()? ( Ignorable by Annotation )

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

170
        /** @scrutinizer ignore-call */ 
171
        $aqlElements[] = $this->compileWheres($query);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
171
172
        $aqlElements[] = 'UPDATE ' . $alias . ' WITH ' . $updateValues . ' IN ' . $table;
173
174
        return implode(' ', $aqlElements);
175
    }
176
177
    /**
178
     * Compile an "upsert" statement into AQL.
179
     *
180
     * @param  \Illuminate\Database\Query\Builder  $query
181
     * @param  array  $values
182
     * @param  array  $uniqueBy
183
     * @param  array  $update
184
     * @return string
185
     */
186
    public function compileUpsert(IlluminateQueryBuilder $query, array $values, array $uniqueBy, array $update)
187
    {
188
        $searchFields = [];
189
        foreach($uniqueBy as $key => $field) {
190
            $searchFields[$field] = 'doc.' . $field;
191
        }
192
        $searchObject = $this->generateAqlObject($searchFields);
193
194
        $updateFields = [];
195
        foreach($update as $key => $field) {
196
            $updateFields[$field] = 'doc.' . $field;
197
        }
198
        $updateObject = $this->generateAqlObject($updateFields);
199
200
        $valueObjects = [];
201
        foreach($values as $data) {
202
            $valueObjects[] = $this->generateAqlObject($data);
203
        }
204
205
        return 'LET docs = [' . implode(', ', $valueObjects) . ']'
206
            . ' FOR doc IN docs'
207
            . ' UPSERT ' . $searchObject
208
            . ' INSERT doc'
209
            . ' UPDATE ' . $updateObject
210
            . ' IN ' . $query->from;
211
    }
212
213
    /**
214
     * Compile a delete statement into SQL.
215
     *
216
     * @param  \Illuminate\Database\Query\Builder  $query
217
     * @return string
218
     */
219
    public function compileDelete(IlluminateQueryBuilder $query)
220
    {
221
        $table = $query->from;
222
223
        $where = $this->compileWheres($query);
224
225
        return trim(
226
            !empty($query->joins)
227
                ? $this->compileDeleteWithJoins($query, $table, $where)
0 ignored issues
show
Bug introduced by
The method compileDeleteWithJoins() does not exist on LaravelFreelancerNL\Aran...mpilesDataManipulations. Did you maybe mean compileDelete()? ( Ignorable by Annotation )

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

227
                ? $this->/** @scrutinizer ignore-call */ compileDeleteWithJoins($query, $table, $where)

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
228
                : $this->compileDeleteWithoutJoins($query, $table, $where)
229
        );
230
    }
231
232
    /**
233
     * Compile a delete statement without joins into SQL.
234
     *
235
     * @param  \Illuminate\Database\Query\Builder  $query
236
     * @param  string  $table
237
     * @param  string  $where
238
     * @return string
239
     */
240
    protected function compileDeleteWithoutJoins(IlluminateQueryBuilder $query, $table, $where)
241
    {
242
        assert($query instanceof Builder);
243
244
        $alias = $this->normalizeColumn($query, $query->registerTableAlias($table));
0 ignored issues
show
Bug introduced by
It seems like normalizeColumn() 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

244
        /** @scrutinizer ignore-call */ 
245
        $alias = $this->normalizeColumn($query, $query->registerTableAlias($table));
Loading history...
245
246
        $table = $this->wrapTable($this->prefixTable($table));
247
248
        return "FOR {$alias} IN {$table} {$where} REMOVE {$alias} IN {$table}";
249
    }
250
251
    /**
252
     * Compile a truncate table statement into SQL.
253
     *
254
     * @param  IlluminateQueryBuilder  $query
255
     * @return array
256
     */
257
    public function compileTruncate(IlluminateQueryBuilder $query)
258
    {
259
        return [$this->compileDelete($query) => []];
260
    }
261
262
}
263