1 | <?php |
||||
2 | |||||
3 | namespace Sfneal\Tracking\Actions; |
||||
4 | |||||
5 | use Illuminate\Http\RedirectResponse; |
||||
6 | use Illuminate\Http\Request; |
||||
7 | use Illuminate\Http\Response; |
||||
8 | use Illuminate\Support\Facades\Cookie; |
||||
9 | use Jenssegers\Agent\Agent; |
||||
10 | use Sfneal\Actions\Action; |
||||
11 | use Sfneal\Helpers\Arrays\ArrayHelpers; |
||||
12 | use Sfneal\Helpers\Laravel\AppInfo; |
||||
13 | |||||
14 | class ParseTraffic extends Action |
||||
15 | { |
||||
16 | /** |
||||
17 | * Array keys to exclude from the 'request_payload' attribute. |
||||
18 | * |
||||
19 | * @var array |
||||
20 | */ |
||||
21 | private const REQUEST_PAYLOAD_EXCLUSIONS = [ |
||||
22 | '_token', |
||||
23 | '_method', |
||||
24 | 'password', |
||||
25 | ]; |
||||
26 | |||||
27 | /** |
||||
28 | * @var array |
||||
29 | */ |
||||
30 | private $tracking = []; |
||||
31 | |||||
32 | /** |
||||
33 | * @var Request |
||||
34 | */ |
||||
35 | private $request; |
||||
36 | /** |
||||
37 | * @var Response|RedirectResponse |
||||
38 | */ |
||||
39 | private $response; |
||||
40 | |||||
41 | /** |
||||
42 | * @var string |
||||
43 | */ |
||||
44 | private $timestamp; |
||||
45 | |||||
46 | /** |
||||
47 | * Create a new event instance. |
||||
48 | * |
||||
49 | * @param Request $request |
||||
50 | * @param Response|RedirectResponse $response |
||||
51 | * @param string|null $timestamp |
||||
52 | */ |
||||
53 | public function __construct(Request $request, $response, string $timestamp = null) |
||||
54 | { |
||||
55 | $this->request = $request; |
||||
56 | $this->response = $response; |
||||
57 | $this->timestamp = $timestamp ?? microtime(); |
||||
58 | } |
||||
59 | |||||
60 | /** |
||||
61 | * Execute the action. |
||||
62 | * |
||||
63 | * @return array |
||||
64 | */ |
||||
65 | public function execute(): array |
||||
66 | { |
||||
67 | // Initialize event for serialization |
||||
68 | $this->tracking['user_id'] = intval(auth()->id()); |
||||
69 | $this->tracking['session_id'] = Cookie::get(config('session.cookie')); |
||||
70 | $this->tracking['app_version'] = AppInfo::version(); |
||||
71 | $this->tracking['time_stamp'] = self::getTimestamp($this->timestamp); |
||||
72 | |||||
73 | // Request data |
||||
74 | $this->tracking['request'] = $this->parseRequest(); |
||||
75 | |||||
76 | // Response data |
||||
77 | $this->tracking['response'] = $this->parseResponse(); |
||||
78 | |||||
79 | // Request data |
||||
80 | $this->tracking['agent'] = $this->parseAgent(); |
||||
81 | |||||
82 | return $this->tracking; |
||||
83 | } |
||||
84 | |||||
85 | /** |
||||
86 | * Parse a Request object to retrieve relevant data. |
||||
87 | * |
||||
88 | * @return array |
||||
89 | */ |
||||
90 | public function parseRequest(): array |
||||
91 | { |
||||
92 | return [ |
||||
93 | 'host' => $this->request->getHttpHost(), |
||||
94 | 'uri' => $this->request->getRequestUri(), |
||||
95 | 'method' => $this->request->getMethod(), |
||||
96 | 'payload' => $this->getRequestPayload(), |
||||
97 | 'browser' => $_SERVER['HTTP_USER_AGENT'] ?? null, |
||||
98 | 'ip' => $this->request->ip(), |
||||
99 | 'referrer' => $_SERVER['HTTP_REFERER'] ?? null, |
||||
100 | 'token' => $this->request->get('track_traffic_token') ?? uniqid(), |
||||
101 | ]; |
||||
102 | } |
||||
103 | |||||
104 | /** |
||||
105 | * Parse a Response object to retrieve relevant data. |
||||
106 | * |
||||
107 | * @return array |
||||
108 | */ |
||||
109 | public function parseResponse(): array |
||||
110 | { |
||||
111 | // Status code & response time |
||||
112 | $response = [ |
||||
113 | 'code' => $this->response->getStatusCode(), |
||||
114 | 'time' => self::getResponseTime($this->timestamp), |
||||
115 | ]; |
||||
116 | |||||
117 | // Store response content served if enabled |
||||
118 | if (config('tracking.traffic.response_content')) { |
||||
119 | $response['content'] = $this->response->getContent(); |
||||
120 | } |
||||
121 | |||||
122 | return $response; |
||||
123 | } |
||||
124 | |||||
125 | /** |
||||
126 | * Set user agent data on platform, device & browser. |
||||
127 | * |
||||
128 | * @return array |
||||
129 | */ |
||||
130 | public function parseAgent(): array |
||||
131 | { |
||||
132 | $agent = new Agent(); |
||||
133 | |||||
134 | return [ |
||||
135 | 'platform' => $agent->platform(), |
||||
136 | 'device' => $agent->device(), |
||||
137 | 'browser' => $agent->browser(), |
||||
138 | ]; |
||||
139 | } |
||||
140 | |||||
141 | /** |
||||
142 | * Retrieve a request payload with exclusions removed. |
||||
143 | * |
||||
144 | * @return array |
||||
145 | */ |
||||
146 | private function getRequestPayload(): array |
||||
147 | { |
||||
148 | return ArrayHelpers::from($this->request->query()) |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
149 | ->merge($this->request->input()) |
||||
150 | ->removeKeys(self::REQUEST_PAYLOAD_EXCLUSIONS) |
||||
151 | ->get(); |
||||
152 | } |
||||
153 | |||||
154 | /** |
||||
155 | * Determine the amount of time taken to return a response. |
||||
156 | * |
||||
157 | * @param string $timestamp |
||||
158 | * @return float |
||||
159 | */ |
||||
160 | private static function getResponseTime(string $timestamp): float |
||||
161 | { |
||||
162 | return floatval(number_format($timestamp - LARAVEL_START, 2)); |
||||
163 | } |
||||
164 | |||||
165 | /** |
||||
166 | * Retrieve a traffic visit occurred at timestamp. |
||||
167 | * |
||||
168 | * @param string $timestamp |
||||
169 | * @return string |
||||
170 | */ |
||||
171 | private static function getTimestamp(string $timestamp): string |
||||
172 | { |
||||
173 | return date('Y-m-d H:i:s', $timestamp); |
||||
0 ignored issues
–
show
$timestamp of type string is incompatible with the type integer|null expected by parameter $timestamp of date() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
174 | } |
||||
175 | } |
||||
176 |