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

HandlesAliases   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 165
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 35
eloc 64
c 0
b 0
f 0
dl 0
loc 165
rs 9.6

12 Methods

Rating   Name   Duplication   Size   Complexity  
A getTableAlias() 0 11 3
A getTableAliases() 0 3 1
A registerColumnAlias() 0 13 3
A extractAlias() 0 19 6
A getColumnAlias() 0 7 2
A isTableAlias() 0 3 1
A generateTableAlias() 0 6 2
B registerTableAlias() 0 25 8
A importTableAliases() 0 7 3
A replaceTableForAlias() 0 11 2
A convertColumnId() 0 8 2
A prefixAlias() 0 9 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace LaravelFreelancerNL\Aranguent\Query\Concerns;
6
7
use Exception;
8
use Illuminate\Database\Query\Expression;
9
use Illuminate\Support\Str;
10
use Illuminate\Database\Query\Builder as IlluminateQueryBuilder;
11
12
trait HandlesAliases
13
{
14
    protected $tableAliases = [];
15
16
    protected $columnAliases = [];
17
18
    /**
19
     * @param  array<mixed>|string  $column
20
     * @return array<mixed>|string
21
     */
22
    public function convertColumnId(array|string|Expression $column): array|string|Expression
23
    {
24
25
        if ($column instanceof Expression) {
0 ignored issues
show
introduced by
$column is never a sub-type of Illuminate\Database\Query\Expression.
Loading history...
26
            return $column;
27
        }
28
29
        return $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

29
        return $this->/** @scrutinizer ignore-call */ convertIdToKey($column);
Loading history...
30
    }
31
32
    /**
33
     * Extract table and alias from sql alias notation (entity AS `alias`)
34
     *
35
     * @return array<mixed>
36
     *
37
     * @throws Exception
38
     */
39
    public function extractAlias(string $entity, int|string $key = null): array
40
    {
41
        $results = preg_split("/\sas\s/i", $entity);
42
43
        if ($results === false) {
44
            throw new Exception('Column splitting failed');
45
        }
46
47
        if (isset($results[1])) {
48
            $results[1] = trim($results[1], '`');
49
        }
50
        if (!isset($results[1]) && is_string($key)) {
51
            $results[1] = $key;
52
        }
53
        if (!isset($results[1])) {
54
            $results[1] = $results[0];
55
        }
56
57
        return $results;
58
    }
59
60
    public function generateTableAlias(string|Expression $table, string $postfix = 'Doc'): string
61
    {
62
        if ($table instanceof Expression) {
63
            return 'Expression' . spl_object_id($table);
64
        }
65
        return Str::camel(Str::singular($table)) . $postfix;
66
    }
67
68
    public function getTableAlias(string|Expression $table): string|null
69
    {
70
        if ($table instanceof Expression) {
71
            $table = 'Expression' . spl_object_id($table);
72
        }
73
74
        if (isset($this->tableAliases[$table])) {
75
            return $this->tableAliases[$table];
76
        }
77
78
        return null;
79
    }
80
81
    public function getColumnAlias(string $column): string|null
82
    {
83
        if (isset($this->columnAliases[$column])) {
84
            return $this->columnAliases[$column];
85
        }
86
87
        return null;
88
    }
89
90
    public function getTableAliases(): array
91
    {
92
        return $this->tableAliases;
93
    }
94
95
    public function importTableAliases(array|IlluminateQueryBuilder $aliases): void
96
    {
97
        if ($aliases instanceof IlluminateQueryBuilder) {
0 ignored issues
show
introduced by
$aliases is never a sub-type of Illuminate\Database\Query\Builder.
Loading history...
98
            $aliases = $aliases->getTableAliases();
99
        }
100
        foreach($aliases as $key => $value) {
101
            $this->tableAliases[$key] = $value;
102
        }
103
    }
104
105
    public function isTableAlias(string $alias)
106
    {
107
        return in_array($alias, $this->tableAliases);
108
    }
109
110
    public function prefixAlias(string $target, string $value): string
111
    {
112
        $alias = $this->getTableAlias($target);
113
114
        if (Str::startsWith($value, $alias . '.')) {
115
            return $value;
116
        }
117
118
        return $alias . '.' . $value;
119
    }
120
121
    /**
122
     * @throws Exception
123
     */
124
    public function registerColumnAlias(string $column, string $alias = null): bool
125
    {
126
        if (preg_match("/\sas\s/i", $column)) {
127
            [$column, $alias] = $this->extractAlias($column);
128
        }
129
130
        if (isset($alias)) {
131
            $this->columnAliases[$column] = $alias;
132
133
            return true;
134
        }
135
136
        return false;
137
    }
138
139
    public function registerTableAlias(string|Expression $table, string $alias = null): string
140
    {
141
        if ($table instanceof Expression  && $alias !== null) {
142
            $table = 'Expression' . spl_object_id($table);
143
        }
144
145
        if ($table instanceof Expression && $alias === null) {
146
            $table = 'Expression' . spl_object_id($table);
147
            $alias = $table;
148
        }
149
150
        if ($alias == null && stripos($table, ' as ') !== false) {
0 ignored issues
show
Bug introduced by
It seems like $table can also be of type Illuminate\Database\Query\Expression; however, parameter $haystack of stripos() 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
        if ($alias == null && stripos(/** @scrutinizer ignore-type */ $table, ' as ') !== false) {
Loading history...
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...
151
            $tableParts = [];
152
            preg_match("/(^.*) as (.*?)$/", $table, $tableParts);
0 ignored issues
show
Bug introduced by
It seems like $table can also be of type Illuminate\Database\Query\Expression; however, parameter $subject of preg_match() 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

152
            preg_match("/(^.*) as (.*?)$/", /** @scrutinizer ignore-type */ $table, $tableParts);
Loading history...
153
            $table = $tableParts[1];
154
            $alias = $tableParts[2];
155
        }
156
157
        if ($alias == null) {
158
            $alias = $this->generateTableAlias($table);
159
        }
160
161
        $this->tableAliases[$table] = $alias;
162
163
        return $alias;
164
    }
165
166
    public function replaceTableForAlias($reference): string
167
    {
168
        $referenceParts = explode('.', $reference);
169
        $first = array_shift($referenceParts);
170
        $alias = $this->getTableAlias($first);
171
        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...
172
            $alias = $first;
173
        }
174
        array_unshift($referenceParts, $alias);
175
176
        return implode('.', $referenceParts);
177
    }
178
}
179