Passed
Push — refactor/improve-static-analys... ( ed4ce4 )
by Bas
15:29
created

HasAliases::extractAlias()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 6
c 3
b 0
f 0
dl 0
loc 11
ccs 7
cts 7
cp 1
rs 10
cc 3
nc 4
nop 1
crap 3
1
<?php
2
3
namespace LaravelFreelancerNL\Aranguent\Query\Concerns;
4
5
use Illuminate\Support\Str;
6
use LaravelFreelancerNL\Aranguent\Query\Builder;
7
use LaravelFreelancerNL\FluentAQL\Expressions\FunctionExpression;
8
use LaravelFreelancerNL\FluentAQL\QueryBuilder;
9
10
trait HasAliases
11
{
12
13
    protected $tableAliases = [];
14
15
    protected $columnAliases = [];
16
17
    /**
18
     * @param  string  $table
19
     * @param  string|null  $alias
20
     * @return string
21
     */
22 162
    public function registerTableAlias(string $table, string $alias = null): string
23
    {
24 162
        if ($alias == null && stripos($table, ' as ') !== false) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $alias of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
25
            [$table, $alias] = explode(' as ', $table);
26
        }
27 162
        if ($alias == null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $alias of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
28 162
            $alias = $this->generateTableAlias($table);
29
        }
30 162
        $this->tableAliases[$table] = $alias;
31
32 162
        return $alias;
33
    }
34
35 117
    protected function isTableAlias(string $alias)
36
    {
37 117
        return in_array($alias, $this->tableAliases);
38
    }
39
40
    /**
41
     * @param $table
42
     * @return mixed|null
43
     */
44 138
    protected function getTableAlias($table)
45
    {
46 138
        if (isset($this->tableAliases[$table])) {
47 118
            return $this->tableAliases[$table];
48
        }
49
50 117
        return null;
51
    }
52
53
    /**
54
     * Extract table and alias from sql alias notation (entity AS `alias`)
55
     *
56
     * @param  string  $entity
57
     * @return array|false|string[]
58
     */
59 34
    protected function extractAlias(string $entity)
60
    {
61 34
        $results = preg_split("/\sas\s/i", $entity);
62 34
        if (isset($results[1])) {
63 14
            $results[1] = trim($results[1], '`');
64
        }
65 34
        if (! isset($results[1])) {
66 23
            $results[1] = $results[0];
67
        }
68
69 34
        return $results;
70
    }
71
72
    /**
73
     * @param $table
74
     * @param string $postfix
75
     *
76
     * @return mixed
77
     */
78 162
    protected function generateTableAlias($table, $postfix = 'Doc')
79
    {
80 162
        return Str::camel(Str::singular($table)) . $postfix;
81
    }
82
83
    protected function replaceTableForAlias($reference): string
84
    {
85
        $referenceParts = explode('.', $reference);
86
        $first = array_shift($referenceParts);
87
        $alias = $this->getTableAlias($first);
88
        if ($alias == null) {
89
            $alias = $first;
90
        }
91
        array_unshift($referenceParts, $alias);
92
93
        return implode('.', $referenceParts);
94
    }
95
96
    /**
97
     * @param string  $target
98
     * @param string  $value
99
     *
100
     * @return Builder
101
     */
102
    protected function prefixAlias(string $target, string $value): string
103
    {
104
        $alias = $this->getTableAlias($target);
105
106
        if (Str::startsWith($value, $alias . '.')) {
107
            return $value;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $value returns the type string which is incompatible with the documented return type LaravelFreelancerNL\Aranguent\Query\Builder.
Loading history...
108
        }
109
110
        return $alias . '.' . $value;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $alias . '.' . $value returns the type string which is incompatible with the documented return type LaravelFreelancerNL\Aranguent\Query\Builder.
Loading history...
111
    }
112
113
    /**
114
     * @param  string  $column
115
     * @param  string|null  $alias
116
     * @return bool
117
     */
118 1
    public function registerColumnAlias(string $column, string $alias = null): bool
119
    {
120 1
        if (preg_match("/\sas\s/i", $column)) {
121
            [$column, $alias] = $this->extractAlias($column);
122
        }
123
124 1
        if (isset($alias)) {
125 1
            $this->columnAliases[$column] = $alias;
126 1
            return true;
127
        }
128
129
        return false;
130
    }
131
132
    /**
133
     * @param $column
134
     * @return mixed
135
     */
136
    protected function getColumnAlias(string $column)
137
    {
138
        if (isset($this->columnAliases[$column])) {
139
            return $this->columnAliases[$column];
140
        }
141
142
        return null;
143
    }
144
145
    /**
146
     * @param  Builder  $builder
147
     * @param $column
148
     * @param $table
149
     * @return string
150
     */
151 121
    protected function normalizeColumn(Builder $builder, $column, $table = null)
152
    {
153 121
        if ($column instanceof QueryBuilder || $column instanceof FunctionExpression) {
154 3
            return $column;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $column also could return the type LaravelFreelancerNL\Flue...ions\FunctionExpression which is incompatible with the documented return type string.
Loading history...
155
        }
156
157 120
        $column = $this->convertColumnId($column);
158
159 120
        if ((is_string($column) || is_numeric($column)) && key_exists($column, $builder->variables)) {
160 1
            return $column;
161
        }
162
163 120
        if (is_array($builder->groups) && in_array($column, $builder->groups)) {
164 3
            return $column;
165
        }
166
167 117
        if ($table == null) {
168 117
            $table = $builder->from;
169
        }
170
171
        // Replace SQL JSON arrow for AQL dot
172 117
        $column = str_replace('->', '.', $column);
173
174 117
        $references = explode('.', $column);
175
176
        //We check for an existing alias to determine of the first reference is a table.
177
        // In which case we replace it with the alias.
178 117
        $references = $this->normalizeColumnReferences($references, $table);
179
180 117
        return implode('.', $references);
181
    }
182
183
    /**
184
     * @param $references
185
     * @param  null  $table
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $table is correct as it would always require null to be passed?
Loading history...
186
     * @return mixed
187
     */
188 117
    protected function normalizeColumnReferences($references, $table = null)
189
    {
190 117
        $tableAlias = $this->getTableAlias($references[0]);
191 117
        if (isset($tableAlias)) {
192 56
            $references[0] = $tableAlias;
193
        }
194
195 117
        if ($tableAlias === null && $table != null && ! $this->isTableAlias($references[0])) {
0 ignored issues
show
introduced by
The condition $table != null is always false.
Loading history...
196 88
            $tableAlias = $this->generateTableAlias($table);
197 88
            array_unshift($references, $tableAlias);
198
        }
199
200 117
        return $references;
201
    }
202
203
    /**
204
     * @param array<mixed>|string $column
205
     * @return array<mixed>|string
206
     */
207 120
    protected function convertColumnId(array|string $column): array|string
208
    {
209 120
        if (is_string($column) || is_array($column)) {
0 ignored issues
show
introduced by
The condition is_array($column) is always true.
Loading history...
210 120
            $column = $this->convertIdToKey($column);
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

210
            /** @scrutinizer ignore-call */ 
211
            $column = $this->convertIdToKey($column);
Loading history...
211
        }
212
213 120
        return $column;
214
    }
215
}
216