Passed
Push — master ( 4888c5...34fd2c )
by Mike
02:18
created

CacheKey::getValuesFromBindings()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 7
nc 3
nop 2
dl 0
loc 13
rs 8.8571
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"])) {
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->getOtherClauses($where, $carry);
154
155
                return $value;
156
            });
157
    }
158
159
    protected function getNestedClauses(array $where) : string
160
    {
161
        if (! in_array($where["type"], ["Exists", "Nested", "NotExists"])) {
162
            return "";
163
        }
164
165
        $this->currentBinding++;
166
167
        return "-" . strtolower($where["type"]) . $this->getWhereClauses($where["query"]->wheres);
168
    }
169
170
    protected function getColumnClauses(array $where) : string
171
    {
172
        if ($where["type"] !== "Column") {
173
            return "";
174
        }
175
176
        $this->currentBinding++;
177
178
        return "-{$where["boolean"]}_{$where["first"]}_{$where["operator"]}_{$where["second"]}";
179
    }
180
181
    protected function getRawClauses(array $where) : string
182
    {
183
        if ($where["type"] !== "raw") {
184
            return "";
185
        }
186
187
        $queryParts = explode("?", $where["sql"]);
188
        $clause = "_{$where["boolean"]}";
189
190
        while (count($queryParts) > 1) {
191
            $clause .= "_" . array_shift($queryParts);
192
            $clause .= $this->query->bindings["where"][$this->currentBinding];
193
            $this->currentBinding++;
194
        }
195
196
        $lastPart = array_shift($queryParts);
197
198
        if ($lastPart) {
199
            $clause .= "_" . $lastPart;
200
        }
201
202
        return "-" . str_replace(" ", "_", $clause);
203
    }
204
205
    protected function getOtherClauses(array $where, string $carry = null) : string
0 ignored issues
show
Unused Code introduced by
The parameter $carry is not used and could be removed. ( Ignorable by Annotation )

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

205
    protected function getOtherClauses(array $where, /** @scrutinizer ignore-unused */ string $carry = null) : string

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
206
    {
207
        if (in_array($where["type"], ["Exists", "Nested", "NotExists", "raw", "Column"])) {
208
            return "";
209
        }
210
211
        $value = $this->getTypeClause($where);
212
        $value .= $this->getValuesClause($where);
213
214
        return "-{$where["column"]}_{$value}";
215
    }
216
217
    protected function getWheres(array $wheres) : Collection
218
    {
219
        $wheres = collect($wheres);
220
221
        if ($wheres->isEmpty()) {
222
            $wheres = collect($this->query->wheres);
223
        }
224
225
        return $wheres;
226
    }
227
228
    protected function getWithModels() : string
229
    {
230
        $eagerLoads = collect($this->eagerLoad);
231
232
        if ($eagerLoads->isEmpty()) {
233
            return "";
234
        }
235
236
        return "-" . implode("-", $eagerLoads->keys()->toArray());
237
    }
238
}
239