Failed Conditions
Push — refactor/improve-static-analys... ( bdf823...46faab )
by Bas
10:08
created

HandlesAqlGrammar::wrap()   A

Complexity

Conditions 6
Paths 5

Size

Total Lines 21
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 9
c 0
b 0
f 0
dl 0
loc 21
rs 9.2222
cc 6
nc 5
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace LaravelFreelancerNL\Aranguent\Query\Concerns;
6
7
use Illuminate\Support\Arr;
8
use Illuminate\Database\Query\Expression;
9
10
trait HandlesAqlGrammar
11
{
12
    /**
13
     * Available predicate operators.
14
     *
15
     * @var array<string, int>
16
     */
17
    protected array $comparisonOperators = [
18
        '=='      => 1,
19
        '!='      => 1,
20
        '<'       => 1,
21
        '>'       => 1,
22
        '<='      => 1,
23
        '>='      => 1,
24
        'IN'      => 1,
25
        'NOT IN'  => 1,
26
        'LIKE'    => 1,
27
        '~'       => 1,
28
        '!~'      => 1,
29
        'ALL =='  => 1,
30
        'ALL !='  => 1,
31
        'ALL <'   => 1,
32
        'ALL >'   => 1,
33
        'ALL <='  => 1,
34
        'ALL >='  => 1,
35
        'ALL IN'  => 1,
36
        'ANY =='  => 1,
37
        'ANY !='  => 1,
38
        'ANY <'   => 1,
39
        'ANY >'   => 1,
40
        'ANY <='  => 1,
41
        'ANY >='  => 1,
42
        'ANY IN'  => 1,
43
        'NONE ==' => 1,
44
        'NONE !=' => 1,
45
        'NONE <'  => 1,
46
        'NONE >'  => 1,
47
        'NONE <=' => 1,
48
        'NONE >=' => 1,
49
        'NONE IN' => 1,
50
    ];
51
52
    /**
53
     * @var array|int[]
54
     */
55
    protected array $arithmeticOperators = [
56
        '+' => 1,
57
        '-' => 1,
58
        '*' => 1,
59
        '/' => 1,
60
        '%' => 1,
61
    ];
62
63
    /**
64
     * @var array|int[]
65
     */
66
    protected array $logicalOperators = [
67
        'AND' => 1,
68
        '&&'  => 1,
69
        'OR'  => 1,
70
        '||'  => 1,
71
        'NOT' => 1,
72
        '!'   => 1,
73
    ];
74
75
    protected string $rangeOperator = '..';
76
77
    /**
78
     * Get the format for database stored dates.
79
     *
80
     * @return string
81
     */
82
    public function getDateFormat(): string
83
    {
84
        return 'Y-m-d\TH:i:s.vp';
85
    }
86
87
    public function isBind($value, string $type): bool
88
    {
89
        if (is_string($value) && preg_match('/^@?[0-9]{4}_' . $value . '_[0-9_]+$/', $value)) {
90
            return true;
91
        }
92
93
        return false;
94
    }
95
96
    /**
97
     * Get the appropriate query parameter place-holder for a value.
98
     *
99
     * @param  mixed  $value
100
     */
101
    public function parameter($value): string
102
    {
103
        return $this->isExpression($value) ? $this->getValue($value) : (string) $value;
0 ignored issues
show
Bug introduced by
It seems like isExpression() 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

103
        return $this->/** @scrutinizer ignore-call */ isExpression($value) ? $this->getValue($value) : (string) $value;
Loading history...
Bug introduced by
It seems like getValue() 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

103
        return $this->isExpression($value) ? $this->/** @scrutinizer ignore-call */ getValue($value) : (string) $value;
Loading history...
104
    }
105
106
107
    /**
108
     * Quote the given string literal.
109
     *
110
     * @param  string|array  $value
111
     * @return string
112
     */
113
    public function quoteString($value)
114
    {
115
        if (is_array($value)) {
116
            return implode(', ', array_map([$this, __FUNCTION__], $value));
117
        }
118
119
        return "`$value`";
120
    }
121
122
123
    /**
124
     * Wrap a value in keyword identifiers.
125
     *
126
     * @param  \Illuminate\Contracts\Database\Query\Expression|string  $value
127
     * @param  bool  $prefixAlias
128
     * @return string|array
129
     */
130
    public function wrap($value, $prefixAlias = false)
131
    {
132
        if ($this->isExpression($value)) {
133
            return $this->getValue($value);
134
        }
135
136
        if (is_array($value)) {
0 ignored issues
show
introduced by
The condition is_array($value) is always false.
Loading history...
137
            foreach($value as $key => $subvalue) {
138
                $value[$key] = $this->wrap($subvalue, $prefixAlias);
139
            }
140
            return $value;
141
        }
142
143
        // If the value being wrapped has a column alias we will need to separate out
144
        // the pieces so we can wrap each of the segments of the expression on its
145
        // own, and then join these both back together using the "as" connector.
146
        if (is_string($value) && stripos($value, ' as ') !== false) {
147
            return $this->wrapAliasedValue($value, $prefixAlias);
0 ignored issues
show
Bug introduced by
It seems like wrapAliasedValue() 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

147
            return $this->/** @scrutinizer ignore-call */ wrapAliasedValue($value, $prefixAlias);
Loading history...
148
        }
149
150
        return $this->wrapSegments(explode('.', $value));
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type Illuminate\Contracts\Database\Query\Expression; however, parameter $string of explode() 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

150
        return $this->wrapSegments(explode('.', /** @scrutinizer ignore-type */ $value));
Loading history...
Bug introduced by
It seems like wrapSegments() 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

150
        return $this->/** @scrutinizer ignore-call */ wrapSegments(explode('.', $value));
Loading history...
151
    }
152
153
154
    /**
155
     * Wrap a table in keyword identifiers.
156
     *
157
     * @param  \Illuminate\Database\Query\Expression|string  $table
158
     * @return string
159
     */
160
    public function wrapTable($table)
161
    {
162
        if (!$this->isExpression($table)) {
163
            return $this->wrap($this->tablePrefix . $table, true);
0 ignored issues
show
Bug introduced by
Are you sure $table of type Illuminate\Database\Query\Expression|string can be used in concatenation? ( Ignorable by Annotation )

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

163
            return $this->wrap($this->tablePrefix . /** @scrutinizer ignore-type */ $table, true);
Loading history...
Bug Best Practice introduced by
The expression return $this->wrap($this...ePrefix . $table, true) also could return the type array which is incompatible with the documented return type string.
Loading history...
164
        }
165
166
        return $this->getValue($table);
167
    }
168
169
    /**
170
     * Wrap a single string in keyword identifiers.
171
     *
172
     * @param  string  $value
173
     * @return string
174
     */
175
    protected function wrapValue($value)
176
    {
177
        if ($value === '*') {
178
            return $value;
179
        }
180
181
        return '`' . str_replace('`', '``', $value) . '`';
182
    }
183
184
    public function generateAqlObject(array $data): string
185
    {
186
        $data = Arr::undot($data);
187
188
        return $this->generateAqlObjectString($data);
189
    }
190
191
    protected function generateAqlObjectString(array $data): string
192
    {
193
        foreach($data as $key => $value) {
194
            $prefix = $key . ': ';
195
            if (array_is_list($data)) {
196
                $prefix = '';
197
            }
198
199
            if (is_array($value)) {
200
                $data[$key] = $prefix . $this->generateAqlObjectString($value);
201
                continue;
202
            }
203
204
            if ($value instanceof Expression) {
205
                $data[$key] = $prefix . $value->getValue($this);
0 ignored issues
show
Bug introduced by
$this of type LaravelFreelancerNL\Aran...cerns\HandlesAqlGrammar is incompatible with the type Illuminate\Database\Grammar expected by parameter $grammar of Illuminate\Database\Query\Expression::getValue(). ( Ignorable by Annotation )

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

205
                $data[$key] = $prefix . $value->getValue(/** @scrutinizer ignore-type */ $this);
Loading history...
206
                continue;
207
            }
208
209
            //TODO: check if value needs additional assurances for regular strings vs binds and references
210
            $data[$key] = $prefix . $value;
211
        }
212
213
        $returnString = implode(', ', $data);
214
        if (array_is_list($data)) {
215
            return '[' . $returnString . ']';
216
        }
217
        return '{' . $returnString . '}';
218
    }
219
}
220