EloquentEngine::connect()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 1
b 0
f 1
1
<?php
2
namespace Awssat\Visits\DataEngines;
3
4
use Awssat\Visits\Models\Visit as Model;
5
6
class EloquentEngine implements DataEngine
7
{
8
    private $model = null;
9
    private $prefix = null;
10
11
    public function __construct(Model $model)
12
    {
13
        $this->model = $model;
14
    }
15
16
    public function connect(string $connection): DataEngine
17
    {
18
        return $this;
19
    }
20
21
    public function setPrefix(string $prefix): DataEngine
22
    {
23
        $this->prefix = $prefix . ':';
24
        return $this;
25
    }
26
27
    public function increment(string $key, int $value, $member = null): bool
28
    {
29
        if (! empty($member) || is_numeric($member)) {
30
            $row = $this->model->firstOrNew(['primary_key' => $this->prefix.$key, 'secondary_key' => $member]);
31
        } else {
32
            $row = $this->model->firstOrNew(['primary_key' => $this->prefix.$key, 'secondary_key' => null]);
33
        }
34
   
35
        if($row->expired_at !== null && \Carbon\Carbon::now()->gt($row->expired_at)) {
36
            $row->score = $value;
37
            $row->expired_at = null;
38
        } else {
39
            $row->score += $value;
40
        }
41
42
        return $row->save();
43
    }
44
45
    public function decrement(string $key, int $value, $member = null): bool
46
    {
47
        return $this->increment($key, -$value, $member);
48
    }
49
50
    public function delete($key, $member = null): bool
51
    {
52
        if(is_array($key)) {
53
            array_walk($key, function($item) {
54
                $this->delete($item);
55
            });
56
            return true;
57
        }
58
59
        if(! empty($member) || is_numeric($member)) {
60
            return $this->model->where(['primary_key' => $this->prefix.$key, 'secondary_key' => $member])->delete();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->model->whe... => $member))->delete() could return the type integer which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
61
        } else {
62
            return $this->model->where(['primary_key' => $this->prefix.$key])->delete();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->model->whe...efix . $key))->delete() could return the type integer which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
63
        }
64
    }
65
66
    public function get(string $key, $member = null)
67
    {
68
        if(! empty($member) || is_numeric($member)) {
69
             return $this->model->where(['primary_key' => $this->prefix.$key, 'secondary_key' => $member])
70
            ->where(function($q) {
71
                return $q->where('expired_at', '>', \Carbon\Carbon::now())->orWhereNull('expired_at');
72
            })
73
            ->value('score');
74
        } else {
75
            return $this->model->where(['primary_key' => $this->prefix.$key, 'secondary_key' => null])
76
            ->where(function($q) {
77
                return $q->where('expired_at', '>', \Carbon\Carbon::now())->orWhereNull('expired_at');
78
            })
79
            ->value('score');
80
        }
81
    }
82
83
    public function set(string $key, $value, $member = null): bool
84
    {
85
        if(! empty($member) || is_numeric($member)) {
86
            return $this->model->updateOrCreate([
87
                'primary_key' => $this->prefix.$key, 
88
                'secondary_key' => $member,
89
                'score' => $value,
90
                'expired_at' => null,
91
                ]) instanceof Model;
92
        } else {
93
            return $this->model->updateOrCreate([
94
                'primary_key' => $this->prefix.$key, 
95
                'score' => $value,
96
                'expired_at' => null,
97
                ]) instanceof Model;
98
        }
99
    }
100
101
    public function search(string $word, bool $noPrefix = true): array
102
    {
103
        $results = [];
104
105
        if($word == '*') {
106
            $results = $this->model
107
                        ->where(function($q) {
108
                            return $q->where('expired_at', '>', \Carbon\Carbon::now())->orWhereNull('expired_at');
109
                        })
110
                        ->pluck('primary_key');
111
        } else {
112
            $results = $this->model->where('primary_key', 'like', $this->prefix.str_replace('*', '%', $word))
113
                                ->where(function($q) {
114
                                    return $q->where('expired_at', '>', \Carbon\Carbon::now())->orWhereNull('expired_at');
115
                                })
116
                                ->pluck('primary_key');
117
        }
118
    
119
        return array_map(
120
            function($item) use($noPrefix) {
121
                if ($noPrefix && substr($item, 0, strlen($this->prefix)) == $this->prefix) {
122
                    return substr($item, strlen($this->prefix));
123
                } 
124
125
                return $item;
126
            },
127
            $results->toArray() ?? []
128
        );
129
    }
130
131
    public function flatList(string $key, int $limit = -1): array
132
    {
133
        return array_slice(
134
            $this->model->where(['primary_key' => $this->prefix.$key, 'secondary_key' => null])
0 ignored issues
show
Bug introduced by
It seems like $this->model->where(arra...alue('list') ?? array() can also be of type Awssat\Visits\Models\Visit; however, parameter $array of array_slice() 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

134
            /** @scrutinizer ignore-type */ $this->model->where(['primary_key' => $this->prefix.$key, 'secondary_key' => null])
Loading history...
135
                        ->where(function($q) {
136
                            return $q->where('expired_at', '>', \Carbon\Carbon::now())->orWhereNull('expired_at');
137
                        })
138
                        ->value('list') ?? [], 0, $limit
139
        );
140
    }
141
142
    public function addToFlatList(string $key, $value): bool
143
    {
144
        $row = $this->model->firstOrNew(['primary_key' => $this->prefix.$key, 'secondary_key' => null]);
145
146
        if($row->expired_at !== null && \Carbon\Carbon::now()->gt($row->expired_at)) {
0 ignored issues
show
Bug introduced by
The property expired_at does not seem to exist on Awssat\Visits\Models\Visit. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
147
            $row->list = (array) $value;
0 ignored issues
show
Bug introduced by
The property list does not seem to exist on Awssat\Visits\Models\Visit. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
148
            $row->expired_at = null;
149
        } else {
150
            $row->list = array_merge($row->list ?? [], (array) $value);
151
        }
152
153
        $row->score =  $row->score ?? 0;
0 ignored issues
show
Bug introduced by
The property score does not seem to exist on Awssat\Visits\Models\Visit. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
154
        return (bool) $row->save();
155
    }
156
157
    public function valueList(string $key, int $limit = -1, bool $orderByAsc = false, bool $withValues = false): array
158
    {
159
        $rows = $this->model->where('primary_key', $this->prefix.$key)
160
                            ->where(function($q) {
161
                                return $q->where('expired_at', '>', \Carbon\Carbon::now())->orWhereNull('expired_at');
162
                            })
163
                            ->whereNotNull('secondary_key')
164
                            ->orderBy('score', $orderByAsc ? 'asc' : 'desc')
165
                            ->when($limit > -1, function($q) use($limit) {
166
                                return $q->limit($limit+1);
167
                            })->pluck('score', 'secondary_key') ?? \Illuminate\Support\Collection::make();
168
169
        return $withValues ? $rows->toArray() : array_keys($rows->toArray());
170
    }
171
172
    public function exists(string $key): bool
173
    {
174
        return $this->model->where(['primary_key' => $this->prefix.$key, 'secondary_key' => null])
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->model->whe... /* ... */ })->exists() could return the type Illuminate\Database\Eloquent\Builder which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
175
                            ->where(function($q) {
176
                                return $q->where('expired_at', '>', \Carbon\Carbon::now())->orWhereNull('expired_at');
177
                            })
178
                            ->exists();
179
    }
180
181
    public function timeLeft(string $key): int
182
    {
183
        $expired_at = $this->model->where(['primary_key' => $this->prefix.$key])->value('expired_at');
184
185
        if($expired_at === null) {
186
            return -2;
187
        }
188
189
        $ttl =  $expired_at->timestamp - \Carbon\Carbon::now()->timestamp;
0 ignored issues
show
Bug introduced by
The property timestamp does not exist on Awssat\Visits\Models\Visit. Did you mean timestamps?
Loading history...
190
        return $ttl <= 0 ? -1 : $ttl;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $ttl <= 0 ? -1 : $ttl could return the type double which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
191
    }
192
193
    public function setExpiration(string $key, int $time): bool
194
    {
195
         return $this->model->where(['primary_key' => $this->prefix.$key])
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->model->whe...()->addSeconds($time))) returns the type integer which is incompatible with the type-hinted return boolean.
Loading history...
196
                                ->where(function($q) {
197
                                    return $q->where('expired_at', '>', \Carbon\Carbon::now())->orWhereNull('expired_at');
198
                                })
199
                            ->update([
200
                                'expired_at' => \Carbon\Carbon::now()->addSeconds($time)
201
                            ]);
202
    }
203
}