Passed
Push — next ( a87628...835774 )
by Bas
02:38
created

HasAliases::replaceTableForAlias()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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

182
            /** @scrutinizer ignore-call */ 
183
            $column = $this->convertIdToKey($column);
Loading history...
183
        }
184
185 120
        return $column;
186
    }
187
}
188