Passed
Push — master ( 65709d...74d483 )
by bader
04:24 queued 10s
created

EloquentEngine::set()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 13
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 3
eloc 11
nc 2
nop 3
dl 0
loc 13
rs 9.9
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, ?string $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, ?string $member = null): bool
46
    {
47
        return $this->increment($key, -$value, $member);
48
    }
49
50
    public function delete($key, ?string $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, ?string $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, ?string $member = null): bool
84
    {
85
        if(! empty($member) || is_numeric($member)) {
86
            return $this->model->create([
87
                'primary_key' => $this->prefix.$key, 
88
                'secondary_key' => $member,
89
                'score' => $value,
90
                ]) instanceof Model;
91
        } else {
92
            return $this->model->create([
93
                'primary_key' => $this->prefix.$key, 
94
                'score' => $value,
95
                ]) instanceof Model;
96
        }
97
    }
98
99
    public function search(string $word, bool $noPrefix = true): array
100
    {
101
        $results = [];
102
103
        if($word == '*') {
104
            $results = $this->model
105
                        ->where(function($q) {
106
                            return $q->where('expired_at', '>', \Carbon\Carbon::now())->orWhereNull('expired_at');
107
                        })
108
                        ->pluck('primary_key');
109
        } else {
110
            $results = $this->model->where('primary_key', 'like', $this->prefix.str_replace('*', '%', $word))
111
                                ->where(function($q) {
112
                                    return $q->where('expired_at', '>', \Carbon\Carbon::now())->orWhereNull('expired_at');
113
                                })
114
                                ->pluck('primary_key');
115
        }
116
    
117
        return array_map(
118
            function($item) use($noPrefix) {
119
                if ($noPrefix && substr($item, 0, strlen($this->prefix)) == $this->prefix) {
120
                    return substr($item, strlen($this->prefix));
121
                } 
122
123
                return $item;
124
            },
125
            $results->toArray() ?? []
126
        );
127
    }
128
129
    public function flatList(string $key, int $limit = -1): array
130
    {
131
        return array_slice(
132
            $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

132
            /** @scrutinizer ignore-type */ $this->model->where(['primary_key' => $this->prefix.$key, 'secondary_key' => null])
Loading history...
133
                        ->where(function($q) {
134
                            return $q->where('expired_at', '>', \Carbon\Carbon::now())->orWhereNull('expired_at');
135
                        })
136
                        ->value('list') ?? [], 0, $limit
137
        );
138
    }
139
140
    public function addToFlatList(string $key, $value): bool
141
    {
142
        $row = $this->model->firstOrNew(['primary_key' => $this->prefix.$key, 'secondary_key' => null]);
143
144
        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...
145
            $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...
146
            $row->expired_at = null;
147
        } else {
148
            $row->list = array_merge($row->list ?? [], (array) $value);
149
        }
150
151
        $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...
152
        return (bool) $row->save();
153
    }
154
155
    public function valueList(string $key, int $limit = -1, bool $orderByAsc = false, bool $withValues = false): array
156
    {
157
        $rows = $this->model->where('primary_key', $this->prefix.$key)
158
                            ->where(function($q) {
159
                                return $q->where('expired_at', '>', \Carbon\Carbon::now())->orWhereNull('expired_at');
160
                            })
161
                            // ->where('score', '>', 0)
162
                            ->whereNotNull('secondary_key')
163
                            ->orderBy('score', $orderByAsc ? 'asc' : 'desc')
164
                            ->when($limit > -1, function($q) use($limit) {
165
                                return $q->limit($limit+1);
166
                            })->pluck('score', 'secondary_key') ?? \Illuminate\Support\Collection::make();
167
168
        return $withValues ? $rows->toArray() : array_keys($rows->toArray());
169
    }
170
171
    public function exists(string $key): bool
172
    {
173
        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...
174
                            ->where(function($q) {
175
                                return $q->where('expired_at', '>', \Carbon\Carbon::now())->orWhereNull('expired_at');
176
                            })
177
                            ->exists();
178
    }
179
180
    public function timeLeft(string $key): int
181
    {
182
        $expired_at = $this->model->where(['primary_key' => $this->prefix.$key])->value('expired_at');
183
184
        if($expired_at === null) {
185
            return -2;
186
        }
187
188
        $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...
189
        return $ttl <= 0 ? -1 : $ttl;
190
    }
191
192
    public function setExpiration(string $key, int $time): bool
193
    {
194
        $time = \Carbon\Carbon::now()->addSeconds($time);
195
196
         return $this->model->where(['primary_key' => $this->prefix.$key])
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->model->whe...'expired_at' => $time)) returns the type integer which is incompatible with the type-hinted return boolean.
Loading history...
197
                            ->where(function($q) {
198
                                return $q->where('expired_at', '>', \Carbon\Carbon::now())->orWhereNull('expired_at');
199
                            })
200
                            ->update([
201
                                'expired_at' => $time
202
                            ]);
203
    }
204
}