Passed
Push — master ( b9494e...ff42fa )
by Mike
02:52
created

CacheKey::getInClauses()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 1
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
1
<?php namespace GeneaLabs\LaravelModelCaching;
2
3
use GeneaLabs\LaravelModelCaching\Traits\CachePrefixing;
4
use Illuminate\Database\Eloquent\Model;
5
use Illuminate\Database\Query\Builder;
6
use Illuminate\Support\Collection;
7
8
class CacheKey
9
{
10
    use CachePrefixing;
1 ignored issue
show
Bug introduced by
The trait GeneaLabs\LaravelModelCa...g\Traits\CachePrefixing requires the property $connection which is not provided by GeneaLabs\LaravelModelCaching\CacheKey.
Loading history...
11
12
    protected $eagerLoad;
13
    protected $model;
14
    protected $query;
15
    protected $currentBinding = 0;
16
17
    public function __construct(
18
        array $eagerLoad,
19
        Model $model,
20
        Builder $query
21
    ) {
22
        $this->eagerLoad = $eagerLoad;
23
        $this->model = $model;
24
        $this->query = $query;
25
    }
26
27
    public function make(
28
        array $columns = ["*"],
29
        $idColumn = null,
30
        string $keyDifferentiator = ""
31
    ) : string {
32
        $key = $this->getCachePrefix();
33
        $key .= $this->getModelSlug();
34
        $key .= $this->getIdColumn($idColumn ?: "");
35
        $key .= $this->getQueryColumns($columns);
36
        $key .= $this->getWhereClauses();
37
        $key .= $this->getWithModels();
38
        $key .= $this->getOrderByClauses();
39
        $key .= $this->getOffsetClause();
40
        $key .= $this->getLimitClause();
41
        $key .= $keyDifferentiator;
42
43
        return $key;
44
    }
45
46
    protected function getIdColumn(string $idColumn) : string
47
    {
48
        return $idColumn ? "_{$idColumn}" : "";
49
    }
50
51
    protected function getLimitClause() : string
52
    {
53
        if (! $this->query->limit) {
54
            return "";
55
        }
56
57
        return "-limit_{$this->query->limit}";
58
    }
59
60
    protected function getModelSlug() : string
61
    {
62
        return str_slug(get_class($this->model));
63
    }
64
65
    protected function getOffsetClause() : string
66
    {
67
        if (! $this->query->offset) {
68
            return "";
69
        }
70
71
        return "-offset_{$this->query->offset}";
72
    }
73
74
    protected function getOrderByClauses() : string
75
    {
76
        $orders = collect($this->query->orders);
77
78
        return $orders
79
            ->reduce(function ($carry, $order) {
80
                if (($order["type"] ?? "") === "Raw") {
81
                    return $carry . "_orderByRaw_" . str_slug($order["sql"]);
82
                }
83
84
                return $carry . "_orderBy_" . $order["column"] . "_" . $order["direction"];
85
            })
86
            ?: "";
87
    }
88
89
    protected function getQueryColumns(array $columns) : string
90
    {
91
        if ($columns === ["*"] || $columns === []) {
92
            return "";
93
        }
94
95
        return "_" . implode("_", $columns);
96
    }
97
98
    protected function getTypeClause($where) : string
99
    {
100
        $type =in_array($where["type"], ["In", "NotIn", "Null", "NotNull", "between"])
101
            ? strtolower($where["type"])
102
            : strtolower($where["operator"]);
103
104
        return str_replace(" ", "_", $type);
105
    }
106
107
    protected function getValuesClause(array $where = null) : string
108
    {
109
        if (in_array($where["type"], ["NotNull", "Null"])) {
110
            return "";
111
        }
112
113
        $values = $this->getValuesFromWhere($where);
114
        $values = $this->getValuesFromBindings($where, $values);
0 ignored issues
show
Bug introduced by
It seems like $where can also be of type null; however, parameter $where of GeneaLabs\LaravelModelCa...getValuesFromBindings() does only seem to accept array, 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

114
        $values = $this->getValuesFromBindings(/** @scrutinizer ignore-type */ $where, $values);
Loading history...
115
116
117
118
        return "_" . $values;
119
    }
120
121
    protected function getValuesFromWhere(array $where) : string
122
    {
123
        if (is_array(array_get($where, "values"))) {
124
            return implode("_", $where["values"]);
125
        }
126
127
        return array_get($where, "value", "");
128
    }
129
130
    protected function getValuesFromBindings(array $where, string $values) : string
131
    {
132
        if (! $values && ($this->query->bindings["where"] ?? false)) {
133
            $values = $this->query->bindings["where"][$this->currentBinding];
134
            $this->currentBinding++;
135
136
            if ($where["type"] === "between") {
137
                $values .= "_" . $this->query->bindings["where"][$this->currentBinding];
138
                $this->currentBinding++;
139
            }
140
        }
141
142
        return $values ?: "";
143
    }
144
145
    protected function getWhereClauses(array $wheres = []) : string
146
    {
147
        return "" . $this->getWheres($wheres)
148
            ->reduce(function ($carry, $where) {
149
                $value = $carry;
150
                $value .= $this->getNestedClauses($where);
151
                $value .= $this->getColumnClauses($where);
152
                $value .= $this->getRawClauses($where);
153
                $value .= $this->getInClauses($where);
154
                $value .= $this->getOtherClauses($where, $carry);
0 ignored issues
show
Unused Code introduced by
The call to GeneaLabs\LaravelModelCa...eKey::getOtherClauses() has too many arguments starting with $carry. ( Ignorable by Annotation )

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

154
                $value .= $this->/** @scrutinizer ignore-call */ getOtherClauses($where, $carry);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
155
156
                return $value;
157
            });
158
    }
159
160
    protected function getNestedClauses(array $where) : string
161
    {
162
        if (! in_array($where["type"], ["Exists", "Nested", "NotExists"])) {
163
            return "";
164
        }
165
166
        $this->currentBinding++;
167
168
        return "-" . strtolower($where["type"]) . $this->getWhereClauses($where["query"]->wheres);
169
    }
170
171
    protected function getColumnClauses(array $where) : string
172
    {
173
        if ($where["type"] !== "Column") {
174
            return "";
175
        }
176
177
        $this->currentBinding++;
178
179
        return "-{$where["boolean"]}_{$where["first"]}_{$where["operator"]}_{$where["second"]}";
180
    }
181
182
    protected function getInClauses(array $where) : string
183
    {
184
        if ($where["type"] !== "In") {
185
            return "";
186
        }
187
188
        $this->currentBinding++;
189
        $values = $this->recursiveImplode($where["values"], "_");
190
191
        return "-{$where["column"]}_in{$values}";
192
    }
193
194
    protected function recursiveImplode(array $items, string $glue = ",") : string
195
    {
196
        $result = "";
197
198
        foreach ($items as $key => $value) {
199
            if (is_array($value)) {
200
                $result .= $this->recursiveImplode($value, $glue);
201
202
                continue;
203
            }
204
205
            $result .= $glue . $value;
206
        }
207
208
        return $result;
209
    }
210
211
    protected function getRawClauses(array $where) : string
212
    {
213
        if ($where["type"] !== "raw") {
214
            return "";
215
        }
216
217
        $queryParts = explode("?", $where["sql"]);
218
        $clause = "_{$where["boolean"]}";
219
220
        while (count($queryParts) > 1) {
221
            $clause .= "_" . array_shift($queryParts);
222
            $clause .= $this->query->bindings["where"][$this->currentBinding];
223
            $this->currentBinding++;
224
        }
225
226
        $lastPart = array_shift($queryParts);
227
228
        if ($lastPart) {
229
            $clause .= "_" . $lastPart;
230
        }
231
232
        return "-" . str_replace(" ", "_", $clause);
233
    }
234
235
    protected function getOtherClauses(array $where) : string
236
    {
237
        if (in_array($where["type"], ["Exists", "Nested", "NotExists", "Column", "raw", "In"])) {
238
            return "";
239
        }
240
241
        $value = $this->getTypeClause($where);
242
        $value .= $this->getValuesClause($where);
243
244
        return "-{$where["column"]}_{$value}";
245
    }
246
247
    protected function getWheres(array $wheres) : Collection
248
    {
249
        $wheres = collect($wheres);
250
251
        if ($wheres->isEmpty()) {
252
            $wheres = collect($this->query->wheres);
253
        }
254
255
        return $wheres;
256
    }
257
258
    protected function getWithModels() : string
259
    {
260
        $eagerLoads = collect($this->eagerLoad);
261
262
        if ($eagerLoads->isEmpty()) {
263
            return "";
264
        }
265
266
        return "-" . implode("-", $eagerLoads->keys()->toArray());
267
    }
268
}
269