Passed
Push — master ( 4f2421...1f8a01 )
by Darko
10:00
created

UserRequest   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 117
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 11
eloc 31
dl 0
loc 117
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A delApiRequests() 0 5 1
A getApiRequests() 0 7 2
A user() 0 3 1
A getHourlyApiRequests() 0 25 4
A addApiRequest() 0 4 1
A clearApiRequests() 0 9 2
1
<?php
2
3
namespace App\Models;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Database\Eloquent\Relations\BelongsTo;
7
use Illuminate\Support\Facades\DB;
8
9
/**
10
 * App\Models\UserRequest.
11
 *
12
 * @property int $id
13
 * @property int $users_id
14
 * @property string $hosthash
15
 * @property string $request
16
 * @property string $timestamp
17
 * @property-read User $user
18
 *
19
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserRequest whereHosthash($value)
20
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserRequest whereId($value)
21
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserRequest whereRequest($value)
22
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserRequest whereTimestamp($value)
23
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserRequest whereUsersId($value)
24
 *
25
 * @mixin \Eloquent
26
 *
27
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserRequest newModelQuery()
28
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserRequest newQuery()
29
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserRequest query()
30
 */
31
class UserRequest extends Model
32
{
33
    /**
34
     * @var string
35
     */
36
37
    /**
38
     * @var bool
39
     */
40
    protected $dateFormat = false;
41
42
    /**
43
     * @var bool
44
     */
45
    public $timestamps = false;
46
47
    /**
48
     * @var array
49
     */
50
    protected $fillable = ['id', 'users_id', 'request', 'hosthash', 'timestamp'];
51
52
    public function user(): BelongsTo
53
    {
54
        return $this->belongsTo(User::class, 'users_id');
55
    }
56
57
    /**
58
     * @throws \Throwable
59
     */
60
    public static function delApiRequests($userID): void
61
    {
62
        DB::transaction(function () use ($userID) {
63
            self::query()->where('users_id', $userID)->delete();
64
        }, 3);
65
    }
66
67
    /**
68
     * Get the quantity of API requests in the last day for the users_id.
69
     *
70
     *
71
     * @throws \Exception
72
     * @throws \Throwable
73
     */
74
    public static function getApiRequests(int $userID): int
75
    {
76
        // Clear old requests.
77
        self::clearApiRequests($userID);
78
        $requests = self::query()->where('users_id', $userID)->count('id');
79
80
        return ! $requests ? 0 : $requests;
0 ignored issues
show
Bug Best Practice introduced by
The expression return ! $requests ? 0 : $requests could return the type Illuminate\Database\Eloquent\Builder which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
81
    }
82
83
    /**
84
     * Get hourly API request counts for the last 24 hours.
85
     *
86
     * @return array Array of hourly counts indexed by hour
87
     *
88
     * @throws \Exception
89
     */
90
    public static function getHourlyApiRequests(int $userID): array
91
    {
92
        $hourlyData = [];
93
        $now = now();
94
95
        // Initialize all 24 hours with 0
96
        for ($i = 23; $i >= 0; $i--) {
97
            $hour = $now->copy()->subHours($i);
98
            $hourlyData[$hour->format('H:00')] = 0;
99
        }
100
101
        // Get API requests from the last 24 hours grouped by hour
102
        $requests = self::query()
103
            ->where('users_id', $userID)
104
            ->where('timestamp', '>', $now->subDay())
105
            ->get();
106
107
        foreach ($requests as $request) {
108
            $hourKey = \Carbon\Carbon::parse($request->timestamp)->format('H:00');
109
            if (isset($hourlyData[$hourKey])) {
110
                $hourlyData[$hourKey]++;
111
            }
112
        }
113
114
        return $hourlyData;
115
    }
116
117
    /**
118
     * If a user accesses the API, log it.
119
     *
120
     * @param  string  $token  API token of the user
121
     * @param  string  $request  The API request.
122
     */
123
    public static function addApiRequest(string $token, string $request): void
124
    {
125
        $userID = User::query()->select(['id'])->where('api_token', $token)->value('id');
126
        self::query()->insert(['users_id' => $userID, 'request' => $request, 'timestamp' => now()]);
127
    }
128
129
    /**
130
     * Delete api requests older than a day.
131
     *
132
     * @param  int|bool  $userID
133
     *                            int The users ID.
134
     *                            bool false do all user ID's..
135
     *
136
     * @throws \Exception
137
     * @throws \Throwable
138
     */
139
    public static function clearApiRequests($userID): void
140
    {
141
        DB::transaction(function () use ($userID) {
142
            if ($userID === false) {
143
                self::query()->where('timestamp', '<', now()->subDay())->delete();
144
            } else {
145
                self::query()->where('users_id', $userID)->where('timestamp', '<', now()->subDay())->delete();
146
            }
147
        }, 3);
148
    }
149
}
150