Passed
Push — master ( 8994c2...30162a )
by bader
03:20
created

src/Visits.php (2 issues)

1
<?php
2
3
namespace awssat\Visits;
4
5
use awssat\Visits\Traits\Lists;
6
use awssat\Visits\Traits\Periods;
7
use awssat\Visits\Traits\Record;
8
use awssat\Visits\Traits\Setters;
9
use Carbon\Carbon;
10
use Illuminate\Database\Eloquent\Model;
11
use Illuminate\Support\Facades\Redis;
12
use Jaybizzle\CrawlerDetect\CrawlerDetect;
13
14
class Visits
15
{
16
    use Record, Lists, Periods, Setters;
0 ignored issues
show
The trait awssat\Visits\Traits\Periods requires the property $timestamp which is not provided by awssat\Visits\Visits.
Loading history...
17
18
    /**
19
     * @var mixed
20
     */
21
    protected $ipSeconds;
22
    /**
23
     * @var null
24
     */
25
    protected $subject;
26
    /**
27
     * @var bool|mixed
28
     */
29
    protected $fresh = false;
30
    /**
31
     * @var null
32
     */
33
    protected $country = null;
34
    /**
35
     * @var null
36
     */
37
    protected $referer = null;
38
    /**
39
     * @var mixed
40
     */
41
    protected $periods;
42
    /**
43
     * @var Keys
44
     */
45
    protected $keys;
46
    /**
47
     * @var Redis
48
     */
49
    public $redis;
50
    /**
51
     * @var boolean
52
     */
53
    public $ignoreCrawlers = false;
54
55
    /**
56
     * Visits constructor.
57
     * @param $subject
58
     * @param string $tag|null
59
     */
60
    public function __construct($subject = null, $tag = 'visits')
61
    {
62
        $config = config('visits');
63
        $this->redis = Redis::connection($config['connection']);
64
        $this->periods = $config['periods'];
65
        $this->ipSeconds = $config['remember_ip'];
66
        $this->fresh = $config['always_fresh'];
67
        $this->ignoreCrawlers = $config['ignore_crawlers'];
68
        $this->subject = $subject;
69
        $this->keys = new Keys($subject, $tag);
70
71
        $this->periodsSync();
72
    }
73
74
    /**
75
     * @param $subject
76
     * @return $this
77
     */
78
    public function by($subject)
79
    {
80
        if($subject instanceof Model) {
81
            $this->keys->append($this->keys->modelName($subject), $subject->{$subject->getKeyName()});
82
        } else if (is_array($subject)) {
83
            $this->keys->append(array_keys($subject)[0], array_first($subject));
84
        }
85
86
        return $this;
87
    }
88
89
    /**
90
     * Reset methods
91
     *
92
     * @param $method
93
     * @param string $args
94
     * @return Reset
95
     */
96
    public function reset($method = 'visits', $args = '')
97
    {
98
        return new Reset($this, $method, $args);
99
    }
100
101
    /**
102
     * Check for the ip is has been recorded before
103
     *
104
     * @return bool
105
     * @internal param $subject
106
     */
107
    public function recordedIp()
108
    {
109
        return ! $this->redis->set($this->keys->ip(request()->ip()), true, 'EX', $this->ipSeconds, 'NX');
110
    }
111
112
    /**
113
     * Get visits of model instance.
114
     *
115
     * @return mixed
116
     * @internal param $subject
117
     */
118
    public function count()
119
    {
120
        if ($this->country) {
121
            return $this->redis->zscore($this->keys->visits . "_countries:{$this->keys->id}", $this->country);
122
        } else if ($this->referer) {
123
            return $this->redis->zscore($this->keys->visits . "_referers:{$this->keys->id}", $this->referer);
124
        }
125
126
        return intval(
127
            (!$this->keys->instanceOfModel) ?
128
                $this->redis->get($this->keys->visits . '_total') :
129
                $this->redis->zscore($this->keys->visits, $this->keys->id)
130
        );
131
    }
132
133
    /**
134
     * use diffForHumans to show diff
135
     * @param $period
136
     * @return Carbon
137
     */
138
    public function timeLeft($period = false)
139
    {
140
        return Carbon::now()->addSeconds($this->redis->ttl(
0 ignored issues
show
The method ttl() does not exist on Illuminate\Support\Facades\Redis. ( Ignorable by Annotation )

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

140
        return Carbon::now()->addSeconds($this->redis->/** @scrutinizer ignore-call */ ttl(

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...
141
            $period ? $this->keys->period($period) : $this->keys->ip(request()->ip())
142
        ));
143
    }
144
145
    protected function isCrawler()
146
    {
147
        return $this->ignoreCrawlers && app(CrawlerDetect::class)->isCrawler();
148
    }
149
150
    /**
151
     * Increment a new/old subject to the cache.
152
     *
153
     * @param int $inc
154
     * @param bool $force
155
     * @param bool $periods
156
     * @param bool $country
157
     * @param bool $refer
158
     */
159
    public function increment($inc = 1, $force = false, $periods = true, $country = true, $refer = true)
160
    {
161
        if ($force OR !$this->isCrawler() && !$this->recordedIp()) {
162
            $this->redis->zincrby($this->keys->visits, $inc, $this->keys->id);
163
            $this->redis->incrby($this->keys->visits . '_total', $inc);
164
165
            //NOTE: $method is parameter also .. ($periods,$country,$refer)
166
            foreach (['country', 'refer', 'periods'] as $method) {
167
                $$method && $this->{'record' . studly_case($method)}($inc);
168
            }
169
        }
170
    }
171
172
    /**
173
     * @param int $inc
174
     * @param bool $periods
175
     */
176
    public function forceIncrement($inc = 1, $periods = true)
177
    {
178
        $this->increment($inc, true, $periods);
179
    }
180
181
    /**
182
     * Decrement a new/old subject to the cache cache.
183
     *
184
     * @param int $dec
185
     * @param bool $force
186
     */
187
    public function decrement($dec = 1, $force = false)
188
    {
189
        $this->increment(-$dec, $force);
190
    }
191
192
    /**
193
     * @param int $dec
194
     * @param bool $periods
195
     */
196
    public function forceDecrement($dec = 1, $periods = true)
197
    {
198
        $this->increment(-$dec, true, $periods);
199
    }
200
201
    /**
202
     * @param $period
203
     * @param int $time
204
     * @return bool
205
     */
206
    public function expireAt($period, $time)
207
    {
208
        $periodKey = $this->keys->period($period);
209
        return $this->redis->expire($periodKey, $time);
210
    }
211
}
212