Passed
Pull Request — main (#69)
by
unknown
05:58 queued 02:58
created

VisitorLogsService::trackPostView()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 41
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 3
eloc 27
c 2
b 0
f 0
nc 1
nop 3
dl 0
loc 41
rs 9.488
1
<?php
2
3
namespace CSlant\Blog\Api\Services;
4
5
use Carbon\Carbon;
6
use CSlant\Blog\Api\Models\VisitorLogs;
7
use CSlant\Blog\Core\Models\Post;
8
use Illuminate\Support\Facades\DB;
9
10
class VisitorLogsService
11
{
12
    /**
13
     * Track a view for a post by ID.
14
     *
15
     * @param int $postId The post ID
16
     * @param null|string $ipAddress The viewer's IP address
17
     * @param null|string $userAgent The viewer's user agent
18
     * @return Post The updated post
19
     */
20
    public function trackPostView(int $postId, ?string $ipAddress, ?string $userAgent = null): Post
21
    {
22
        $expirationMinutes = (int) config('blog-core.expiration_view_time', 60);
0 ignored issues
show
Unused Code introduced by
The call to config() has too many arguments starting with 60. ( Ignorable by Annotation )

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

22
        $expirationMinutes = (int) /** @scrutinizer ignore-call */ config('blog-core.expiration_view_time', 60);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
23
        $ipAddress = $ipAddress ?? '';
24
25
        /** @var Post */
26
        return DB::transaction(function () use ($postId, $ipAddress, $userAgent, $expirationMinutes): Post {
27
            $post = Post::findOrFail($postId);
28
            $entityType = get_class($post);
29
            $entityId = $post->getKey();
30
            $now = Carbon::now();
31
32
            /** @var null|VisitorLogs $existingView */
33
            $existingView = VisitorLogs::query()
34
                ->where('viewable_id', '=', $entityId)
35
                ->where('viewable_type', '=', $entityType)
36
                ->where('ip_address', '=', $ipAddress)
37
                ->first();
38
39
            if ($existingView === null) {
40
                VisitorLogs::create([
41
                    'viewable_id' => $entityId,
42
                    'viewable_type' => $entityType,
43
                    'ip_address' => $ipAddress,
44
                    'user_agent' => $userAgent,
45
                    'expired_at' => $now->copy()->addMinutes($expirationMinutes),
46
                ]);
47
48
                $post->increment('views');
49
            } else {
50
                if ($now->isAfter($existingView->expired_at)) {
51
                    $existingView->update([
52
                        'user_agent' => $userAgent,
53
                        'expired_at' => $now->copy()->addMinutes($expirationMinutes),
54
                    ]);
55
56
                    $post->increment('views');
57
                }
58
            }
59
60
            return $post->refresh();
61
        });
62
    }
63
}
64