Passed
Pull Request — main (#69)
by
unknown
03:31
created

PostService::getCustomFilters()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 28
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 15
nc 4
nop 1
dl 0
loc 28
rs 9.7666
c 0
b 0
f 0
1
<?php
2
3
namespace CSlant\Blog\Api\Services;
4
5
use Carbon\Carbon;
6
use CSlant\Blog\Api\Models\PostView;
7
use CSlant\Blog\Core\Http\Responses\Base\BaseHttpResponse;
8
use CSlant\Blog\Core\Models\Post;
9
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
10
use Illuminate\Database\Eloquent\Builder;
11
use Illuminate\Support\Arr;
12
13
/**
14
 * Class PostService
15
 *
16
 * @package CSlant\Blog\Api\Services
17
 *
18
 * @method BaseHttpResponse httpResponse()
19
 */
20
class PostService
21
{
22
    /**
23
     * Get posts by filters.
24
     *
25
     * @param  array<string, mixed>  $filters
26
     *
27
     * @return LengthAwarePaginator<Post>
28
     */
29
    public function getCustomFilters(array $filters): LengthAwarePaginator
30
    {
31
        $data = Post::query();
32
33
        if ($filters['categories'] !== null) {
34
            $categories = array_filter((array) $filters['categories']);
35
36
            $data = $data->whereHas('categories', function (Builder $query) use ($categories): void {
37
                $query->whereIn('categories.id', $categories);
38
            });
39
        }
40
41
        if ($filters['tags'] !== null) {
42
            $tags = array_filter((array) $filters['tags']);
43
44
            $data = $data->whereHas('tags', function (Builder $query) use ($tags): void {
45
                $query->whereIn('tags.id', $tags);
46
            });
47
        }
48
49
        $orderBy = Arr::get($filters, 'order_by', 'updated_at');
50
        $order = Arr::get($filters, 'order', 'desc');
51
52
        $data = $data
53
            ->wherePublished()
54
            ->orderBy($orderBy, $order);
55
56
        return $data->paginate((int) $filters['per_page']);
57
    }
58
59
    /**
60
     * Track a view for a post.
61
     *
62
     * @param int $postId The post ID
63
     * @param string $ipAddress The IP address
64
     * @param string|null $userAgent The user agent
65
     * @return void
66
     */
67
    public function trackView(int $postId, string $ipAddress, ?string $userAgent = null): void
68
    {
69
        /** @var \CSlant\Blog\Api\Models\PostView|null $existingView */
70
        $existingView = PostView::query()
71
            ->where('post_id', '=', $postId)
72
            ->where('ip_address', '=', $ipAddress)
73
            ->first();
74
75
        $timeCheck = now();
76
77
        if (!$existingView) {
78
            /** @var array<string, mixed> $attributes */
79
            $attributes = [
80
                'post_id' => $postId,
81
                'ip_address' => $ipAddress,
82
                'user_agent' => $userAgent,
83
                'time_check' => $timeCheck,
84
            ];
85
86
            PostView::query()->create($attributes);
87
88
            return;
89
        }
90
91
        // Only count as a new view if the last view was more than an hour ago
92
        if ($existingView->time_check->diffInHours(now()) >= 1) {
93
            /** @var array<string, mixed> $attributes */
94
            $attributes = [
95
                'time_check' => $timeCheck,
96
                'user_agent' => $userAgent,
97
            ];
98
99
            $existingView->update($attributes);
100
        }
101
    }
102
}
103