Completed
Push — master ( d0572a...56be9e )
by Pásztor
03:28 queued 01:34
created

RateLimiter   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 142
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 12
lcom 1
cbo 1
dl 0
loc 142
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A tooManyAttempts() 0 16 3
A lockout() 0 6 1
A hit() 0 6 1
A attempts() 0 4 1
A resetAttempts() 0 4 1
A retriesLeft() 0 6 2
A clear() 0 6 1
A availableIn() 0 4 1
1
<?php
2
3
namespace Autumn\Api\Classes;
4
5
use Carbon\Carbon;
6
use Illuminate\Contracts\Cache\Repository as Cache;
7
8
class RateLimiter
9
{
10
    /**
11
     * The cache store implementation.
12
     *
13
     * @var \Illuminate\Contracts\Cache\Repository
14
     */
15
    protected $cache;
16
17
    /**
18
     * Create a new rate limiter instance.
19
     *
20
     * @param  \Illuminate\Contracts\Cache\Repository  $cache
21
     *
22
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
23
     */
24
    public function __construct(Cache $cache)
25
    {
26
        $this->cache = $cache;
27
    }
28
29
    /**
30
     * Determine if the given key has been "accessed" too many times.
31
     *
32
     * @param  string  $key
33
     * @param  int  $maxAttempts
34
     * @param  float|int  $decayMinutes
35
     *
36
     * @return bool
37
     */
38
    public function tooManyAttempts($key, $maxAttempts, $decayMinutes = 1)
39
    {
40
        if ($this->cache->has($key.':lockout')) {
41
            return true;
42
        }
43
44
        if ($this->attempts($key) > $maxAttempts) {
45
            $this->lockout($key, $decayMinutes);
46
47
            $this->resetAttempts($key);
48
49
            return true;
50
        }
51
52
        return false;
53
    }
54
55
    /**
56
     * Add the lockout key to the cache.
57
     *
58
     * @param  string  $key
59
     * @param  int  $decayMinutes
60
     *
61
     * @return void
62
     */
63
    protected function lockout($key, $decayMinutes)
64
    {
65
        $this->cache->add(
66
            $key.':lockout', Carbon::now()->getTimestamp() + ($decayMinutes * 60), $decayMinutes
67
        );
68
    }
69
70
    /**
71
     * Increment the counter for a given key for a given decay time.
72
     *
73
     * @param  string  $key
74
     * @param  float|int  $decayMinutes
75
     *
76
     * @return int
77
     */
78
    public function hit($key, $decayMinutes = 1)
79
    {
80
        $this->cache->add($key, 1, $decayMinutes);
81
82
        return (int) $this->cache->increment($key);
0 ignored issues
show
Bug introduced by
The method increment() does not seem to exist on object<Illuminate\Contracts\Cache\Repository>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
83
    }
84
85
    /**
86
     * Get the number of attempts for the given key.
87
     *
88
     * @param  string  $key
89
     *
90
     * @return mixed
91
     */
92
    public function attempts($key)
93
    {
94
        return $this->cache->get($key, 0);
95
    }
96
97
    /**
98
     * Reset the number of attempts for the given key.
99
     *
100
     * @param  string  $key
101
     *
102
     * @return mixed
103
     */
104
    public function resetAttempts($key)
105
    {
106
        return $this->cache->forget($key);
107
    }
108
109
    /**
110
     * Get the number of retries left for the given key.
111
     *
112
     * @param  string  $key
113
     * @param  int  $maxAttempts
114
     *
115
     * @return int
116
     */
117
    public function retriesLeft($key, $maxAttempts)
118
    {
119
        $attempts = $this->attempts($key);
120
121
        return $attempts === 0 ? $maxAttempts : $maxAttempts - $attempts + 1;
122
    }
123
124
    /**
125
     * Clear the hits and lockout for the given key.
126
     *
127
     * @param  string  $key
128
     *
129
     * @return void
130
     */
131
    public function clear($key)
132
    {
133
        $this->resetAttempts($key);
134
135
        $this->cache->forget($key.':lockout');
136
    }
137
138
    /**
139
     * Get the number of seconds until the "key" is accessible again.
140
     *
141
     * @param  string  $key
142
     *
143
     * @return int
144
     */
145
    public function availableIn($key)
146
    {
147
        return $this->cache->get($key.':lockout') - Carbon::now()->getTimestamp();
148
    }
149
}
150