Passed
Push — master ( 120ad6...d2d121 )
by bader
07:57
created

Visits::isCrawler()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 1
nc 2
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
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;
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 $attribute
76
     * @return $this
77
     */
78
    public function __get($attribute)
79
    {
80
        if($this->keys->instanceOfModel && $relation = $this->subject->$attribute) {
81
            $this->keys->append($attribute, $relation->{$relation->getKeyName()});
82
        }
83
84
        return $this;
85
    }
86
87
    /**
88
     * @param $subject
89
     * @return $this
90
     */
91
    public function by($subject)
92
    {
93
        if($subject instanceof Model) {
94
            $this->keys->append(strtolower(str_singular(class_basename(get_class($subject)))),
95
                $subject->{$subject->getKeyName()});
96
        } else if (is_array($subject)) {
97
            $subject = collect($subject);
98
            $this->keys->append($subject->flip()->first(), $subject->first());
99
        } else {
100
            $this->keys->append('custom', $subject);
101
        }
102
103
        return $this;
104
    }
105
106
    /**
107
     * Reset methods
108
     *
109
     * @param $method
110
     * @param string $args
111
     * @return Reset
112
     */
113
    public function reset($method = 'visits', $args = '')
114
    {
115
        return new Reset($this, $method, $args);
116
    }
117
118
    /**
119
     * Check for the ip is has been recorded before
120
     *
121
     * @return bool
122
     * @internal param $subject
123
     */
124
    public function recordedIp()
125
    {
126
        return ! $this->redis->set($this->keys->ip(request()->ip()), true, 'EX', $this->ipSeconds, 'NX');
127
    }
128
129
    /**
130
     * Get visits of model instance.
131
     *
132
     * @return mixed
133
     * @internal param $subject
134
     */
135
    public function count()
136
    {
137
        if ($this->country) {
138
            return $this->redis->zscore($this->keys->visits . "_countries:{$this->keys->id}", $this->country);
139
        } else if ($this->referer) {
140
            return $this->redis->zscore($this->keys->visits . "_referers:{$this->keys->id}", $this->referer);
141
        }
142
143
        return intval(
144
            (!$this->keys->instanceOfModel) ?
145
                $this->redis->get($this->keys->visits . '_total') :
146
                $this->redis->zscore($this->keys->visits, $this->keys->id)
147
        );
148
    }
149
150
    /**
151
     * use diffForHumans to show diff
152
     * @param $period
153
     * @return Carbon
154
     */
155
    public function timeLeft($period = false)
156
    {
157
        return Carbon::now()->addSeconds($this->redis->ttl(
158
            $period ? $this->keys->period($period) : $this->keys->ip(request()->ip())
159
        ));
160
    }
161
162
    protected function isCrawler()
163
    {
164
        return $this->ignoreCrawlers && app(CrawlerDetect::class)->isCrawler();
165
    }
166
167
    /**
168
     * Increment a new/old subject to the cache.
169
     *
170
     * @param int $inc
171
     * @param bool $force
172
     * @param bool $periods
173
     * @param bool $country
174
     * @param bool $refer
175
     */
176
    public function increment($inc = 1, $force = false, $periods = true, $country = true, $refer = true)
177
    {
178
        if ($force OR !$this->isCrawler() && !$this->recordedIp()) {
179
            $this->redis->zincrby($this->keys->visits, $inc, $this->keys->id);
180
            $this->redis->incrby($this->keys->visits . '_total', $inc);
181
182
            //NOTE: $method is parameter also .. ($periods,$country,$refer)
183
            foreach (['country', 'refer', 'periods'] as $method) {
184
                $$method && $this->{'record' . studly_case($method)}($inc);
185
            }
186
        }
187
    }
188
189
    /**
190
     * @param int $inc
191
     * @param bool $periods
192
     */
193
    public function forceIncrement($inc = 1, $periods = true)
194
    {
195
        $this->increment($inc, true, $periods);
196
    }
197
198
    /**
199
     * Decrement a new/old subject to the cache cache.
200
     *
201
     * @param int $dec
202
     * @param bool $force
203
     */
204
    public function decrement($dec = 1, $force = false)
205
    {
206
        $this->increment(-$dec, $force);
207
    }
208
209
    /**
210
     * @param int $dec
211
     * @param bool $periods
212
     */
213
    public function forceDecrement($dec = 1, $periods = true)
214
    {
215
        $this->increment(-$dec, true, $periods);
216
    }
217
218
    /**
219
     * @param $period
220
     * @param int $time
221
     * @return bool
222
     */
223
    public function expireAt($period, $time)
224
    {
225
        $periodKey = $this->keys->period($period);
226
        return $this->redis->expire($periodKey, $time);
227
    }
228
}
229