Completed
Pull Request — master (#3)
by ARCANEDEV
06:34
created

SpamBlocker::resetCache()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
c 0
b 0
f 0
ccs 3
cts 3
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 0
crap 1
1
<?php namespace Arcanedev\SpamBlocker;
2
3
use Arcanedev\SpamBlocker\Contracts\SpamBlocker as SpamBlockerContract;
4
use Arcanedev\SpamBlocker\Entities\Spammers;
5
use Illuminate\Support\Arr;
6
use Illuminate\Support\Facades\Cache;
7
8
/**
9
 * Class     SpamBlocker
10
 *
11
 * @package  Arcanedev\SpamBlocker
12
 * @author   ARCANEDEV <[email protected]>
13
 */
14
class SpamBlocker implements SpamBlockerContract
15
{
16
    /* ------------------------------------------------------------------------------------------------
17
     |  Properties
18
     | ------------------------------------------------------------------------------------------------
19
     */
20
    /**
21
     * The spammers source path.
22
     *
23
     * @var string|null
24
     */
25
    protected $source;
26
27
    /**
28
     * The included spammers.
29
     *
30
     * @var array
31
     */
32
    protected $includes = [];
33
34
    /**
35
     * The excluded spammers.
36
     *
37
     * @var array
38
     */
39
    protected $excludes = [];
40
41
    /**
42
     * The spammers collection.
43
     *
44
     * @var \Arcanedev\SpamBlocker\Entities\Spammers
45
     */
46
    protected $spammers;
47
48
    /**
49
     * Cache key.
50
     *
51
     * @var  string
52
     */
53
    protected $cacheKey;
54
55
    /**
56
     * Cache expiration duration.
57
     *
58
     * @var int
59
     */
60
    protected $cacheExpires;
61
62
    /* ------------------------------------------------------------------------------------------------
63
     |  Constructor
64
     | ------------------------------------------------------------------------------------------------
65
     */
66
    /**
67
     * SpamBlocker constructor.
68
     *
69
     * @param  array  $config
70
     */
71 252
    public function __construct(array $config)
72
    {
73 252
        $this->setSource(Arr::get($config, 'source', null));
74 252
        $this->setIncludes(Arr::get($config, 'include', []));
75 252
        $this->setExcludes(Arr::get($config, 'exclude', []));
76 252
        $this->cacheKey     = Arr::get($config, 'cache.key', 'arcanedev.spammers');
77 252
        $this->cacheExpires = Arr::get($config, 'cache.expires', 24 * 60);
78
79 252
        $this->load();
80 252
    }
81
82
    /* ------------------------------------------------------------------------------------------------
83
     |  Getters & Setters
84
     | ------------------------------------------------------------------------------------------------
85
     */
86
    /**
87
     * Get the loaded spammers.
88
     *
89
     * @return \Arcanedev\SpamBlocker\Entities\Spammers
90
     */
91 162
    public function spammers()
92
    {
93 162
        return $this->spammers;
94
    }
95
96
    /**
97
     * Get the spammer source file.
98
     *
99
     * @return string|null
100
     */
101 18
    public function getSource()
102
    {
103 18
        return $this->source;
104
    }
105
106
    /**
107
     * Set the source path.
108
     *
109
     * @param  string  $source
110
     *
111
     * @return self
112
     */
113 252
    public function setSource($source)
114
    {
115 252
        if ( ! empty($source)) {
116 252
            $this->source = $source;
117 84
        }
118
119 252
        return $this;
120
    }
121
122
    /**
123
     * Get the included spammers.
124
     *
125
     * @return array
126
     */
127 36
    public function getIncludes()
128
    {
129 36
        return $this->includes;
130
    }
131
132
    /**
133
     * Set the included spammers.
134
     *
135
     * @param  array  $includes
136
     *
137
     * @return self
138
     */
139 252
    public function setIncludes(array $includes)
140
    {
141 252
        $this->includes = $includes;
142
143 252
        return $this;
144
    }
145
146
    /**
147
     * Get the excluded spammers.
148
     *
149
     * @return array
150
     */
151 36
    public function getExcludes()
152
    {
153 36
        return $this->excludes;
154
    }
155
156
    /**
157
     * Set the excluded spammers.
158
     *
159
     * @param  array  $excludes
160
     *
161
     * @return self
162
     */
163 252
    public function setExcludes(array $excludes)
164
    {
165 252
        $this->excludes = $excludes;
166
167 252
        return $this;
168
    }
169
170
    /* ------------------------------------------------------------------------------------------------
171
     |  Main Functions
172
     | ------------------------------------------------------------------------------------------------
173
     */
174
    /**
175
     * Load spammers.
176
     *
177
     * @return self
178
     */
179 252
    public function load()
180
    {
181 252
        $this->checkSource();
182
183 252
        $this->spammers = $this->cacheSpammers(function () {
184 252
            return Spammers::load(
185 252
                file($this->source, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)
186 84
            );
187 252
        });
188
189 252
        return $this;
190
    }
191
192
    /**
193
     * Allow a host.
194
     *
195
     * @param  string  $host
196
     *
197
     * @return self
198
     */
199 36
    public function allow($host)
200
    {
201 36
        if ( ! empty($host)) {
202 36
            $this->excludes[] = $host;
203 12
        }
204
205 36
        return $this;
206
    }
207
208
    /**
209
     * Block a host.
210
     *
211
     * @param  string  $host
212
     *
213
     * @return self
214
     */
215 54
    public function block($host)
216
    {
217 54
        if ( ! empty($host)) {
218 54
            $this->includes[] = $host;
219 18
        }
220
221 54
        return $this;
222
    }
223
224
    /**
225
     * Get all spammers (allowed and blocked one).
226
     *
227
     * @return \Arcanedev\SpamBlocker\Entities\Spammers
228
     */
229 72
    public function all()
230
    {
231 72
        return $this->spammers()
232 72
            ->includes($this->includes)
233 72
            ->excludes($this->excludes);
234
    }
235
236
    /**
237
     * Check if the given host is allowed.
238
     *
239
     * @param  string  $host
240
     *
241
     * @return bool
242
     */
243 36
    public function isAllowed($host)
244
    {
245 36
        return ! $this->isBlocked($host);
246
    }
247
248
    /**
249
     * Check if the given host is blocked.
250
     *
251
     * @param  string  $host
252
     *
253
     * @return bool
254
     */
255 72
    public function isBlocked($host)
256
    {
257 72
        $host = parse_url($host, PHP_URL_HOST);
258 72
        $host = utf8_encode(trim($host));
259
260 72
        if (empty($host)) return false;
261
262 72
        $fullDomain = $this->getFullDomain($host);
263 72
        $rootDomain = $this->getRootDomain($fullDomain);
264
265 72
        return $this->spammers()
266 72
            ->whereHostIn([$fullDomain, $rootDomain])
267 72
            ->whereBlocked()
268 72
            ->count() > 0;
269
    }
270
271
    /**
272
     * Get a spammer.
273
     *
274
     * @param  string  $host
275
     *
276
     * @return \Arcanedev\SpamBlocker\Entities\Spammer|null
277
     */
278 36
    public function getSpammer($host)
279
    {
280 36
        return $this->all()->getOne($host);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->all()->getOne($host); of type Arcanedev\SpamBlocker\Entities\Spammer|null adds the type Arcanedev\SpamBlocker\Entities\Spammer to the return on line 280 which is incompatible with the return type declared by the interface Arcanedev\SpamBlocker\Co...SpamBlocker::getSpammer of type array|null.
Loading history...
281
    }
282
283
    /**
284
     * Reset the spammers.
285
     *
286
     * @return self
287
     */
288 18
    public function reset()
289
    {
290 18
        return $this->resetCache()
291 18
             ->setIncludes([])
292 18
             ->setExcludes([])
293 18
             ->load();
294
    }
295
296
    /* ------------------------------------------------------------------------------------------------
297
     |  Other Functions
298
     | ------------------------------------------------------------------------------------------------
299
     */
300
    /**
301
     * Get the full domain.
302
     *
303
     * @param  string  $host
304
     *
305
     * @return string
306
     */
307 72
    protected function getFullDomain($host)
308
    {
309 72
        preg_match('/^(?:[^@\n]+@)?(?:www\.)?([^:\/\n]+)/', $host, $matches);
310
311 72
        return $matches[1];
312
    }
313
314
    /**
315
     * Get the root domain.
316
     *
317
     * @param  string  $domain
318
     *
319
     * @return string
320
     */
321 72
    private function getRootDomain($domain)
322
    {
323 72
        $domainParts = explode('.', $domain);
324 72
        $count       = count($domainParts);
325
326 48
        return $count > 1
327 72
            ? $domainParts[$count - 2].'.'.$domainParts[$count - 1]
328 72
            : $domainParts[0];
329
    }
330
331
    /**
332
     * Reset the cache.
333
     *
334
     * @return self
335
     */
336 18
    protected function resetCache()
337
    {
338 18
        Cache::forget($this->cacheKey);
339
340 18
        return $this;
341
    }
342
343
    /**
344
     * Cache the spammers.
345
     *
346
     * @param  \Closure  $callback
347
     *
348
     * @return \Arcanedev\SpamBlocker\Entities\Spammers
349
     */
350 252
    private function cacheSpammers(\Closure $callback)
351
    {
352 252
        return Cache::remember($this->cacheKey, $this->cacheExpires, $callback);
353
    }
354
355
    /**
356
     * Check the source file.
357
     */
358 252
    private function checkSource()
359
    {
360 252
        if ( ! file_exists($this->source)) {
361 18
            throw new Exceptions\SpammerSourceNotFound(
362 18
                "The spammers source file not found in [{$this->source}]."
363 6
            );
364
        }
365 252
    }
366
}
367