Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
analyticsevent.php
1<?php
2
3declare(strict_types=1);
4
6
12
13final class AnalyticsEvent
14{
15 public const STATUS_SUCCESS = 'success';
16 public const STATUS_ERROR = 'error';
17 public const STATUS_ATTEMPT = 'attempt';
18 public const STATUS_CANCEL = 'cancel';
19
20 private ?string $section;
21 private ?string $subSection;
22 private ?string $element;
23 private ?string $type;
24 private ?string $p1;
25 private ?string $p2;
26 private ?string $p3;
27 private ?string $p4;
28 private ?string $p5;
30 private string $status = self::STATUS_SUCCESS;
31 private ?int $userId;
32 private string $userAgent;
33
34 private bool $isInvalid = false;
35
36 public function __construct(
37 private string $event,
38 private string $tool,
39 private string $category,
40 )
41 {
42 $userAgent = Context::getCurrent()?->getRequest()->getUserAgent();
43 if ($userAgent && \is_string($userAgent))
44 {
45 $this->userAgent = $userAgent;
46 }
47 }
48
49 public function setUserId(int $userId): self
50 {
51 $this->userId = $userId;
52
53 return $this;
54 }
55
56 public function setSection(string $section): self
57 {
58 $this->section = $section;
59
60 return $this;
61 }
62
63 public function setSubSection(string $subSection): self
64 {
65 $this->subSection = $subSection;
66
67 return $this;
68 }
69
70 public function setElement(string $element): self
71 {
72 $this->element = $element;
73
74 return $this;
75 }
76
77 public function setType(string $type): self
78 {
79 $this->type = $type;
80
81 return $this;
82 }
83
87 public function setP1(string $p1): self
88 {
89 $this->validatePField($p1);
90 $this->p1 = $p1;
91
92 return $this;
93 }
94
98 public function setP2(string $p2): self
99 {
100 $this->validatePField($p2);
101 $this->p2 = $p2;
102
103 return $this;
104 }
105
109 public function setP3(string $p3): self
110 {
111 $this->validatePField($p3);
112 $this->p3 = $p3;
113
114 return $this;
115 }
116
120 public function setP4(string $p4): self
121 {
122 $this->validatePField($p4);
123 $this->p4 = $p4;
124
125 return $this;
126 }
127
131 public function setP5(string $p5): self
132 {
133 $this->validatePField($p5);
134 $this->p5 = $p5;
135
136 return $this;
137 }
138
139 public function setStatus(string $status): self
140 {
141 $this->status = $status;
142
143 return $this;
144 }
145
146 public function setUserAgent(string $userAgent): self
147 {
148 $this->userAgent = $userAgent;
149
150 return $this;
151 }
152
153 public function markAsSuccess(): self
154 {
155 return $this->setStatus(self::STATUS_SUCCESS);
156 }
157
158 public function markAsCanceled(): self
159 {
160 return $this->setStatus(self::STATUS_CANCEL);
161 }
162
163 public function markAsError(): self
164 {
165 return $this->setStatus(self::STATUS_ERROR);
166 }
167
168 public function markAsAttempt(): self
169 {
170 return $this->setStatus(self::STATUS_ATTEMPT);
171 }
172
176 private function validatePField(string $value): void
177 {
178 $invalidValue = substr_count($value, '_') > 1;
179 if ($invalidValue)
180 {
181 $this->isInvalid = true;
182 }
183
184 if ($invalidValue && $this->isDevMode())
185 {
186 throw new ArgumentException('Value for p{1-5} field must contain a single underscore.');
187 }
188 }
189
193 private function validateRequiredFields(): void
194 {
195 if (empty($this->event) || empty($this->tool) || empty($this->category))
196 {
197 $this->isInvalid = true;
198
199 if ($this->isDevMode())
200 {
201 throw new ArgumentException('Event, tool and category fields are required and should be filled.');
202 }
203 }
204 }
205
206 private function isDevMode(): bool
207 {
208 $exceptionHandling = Configuration::getValue('exception_handling');
209
210 return !empty($exceptionHandling['debug']);
211 }
212
213 public function exportToArray(): array
214 {
215 return [
216 'event' => $this->event,
217 'tool' => $this->tool,
218 'category' => $this->category,
219 'section' => $this->section ?? null,
220 'subSection' => $this->subSection ?? null,
221 'element' => $this->element ?? null,
222 'type' => $this->type ?? null,
223 'p1' => $this->p1 ?? null,
224 'p2' => $this->p2 ?? null,
225 'p3' => $this->p3 ?? null,
226 'p4' => $this->p4 ?? null,
227 'p5' => $this->p5 ?? null,
228 'status' => $this->status ?? null,
229 'userAgent' => $this->userAgent ?? null,
230 ];
231 }
232
236 public function send(): void
237 {
238 if (!\defined('ANALYTICS_V2_FILENAME') || !is_writable(ANALYTICS_V2_FILENAME))
239 {
240 return;
241 }
242
243 $this->validateRequiredFields();
244 if ($this->isInvalid)
245 {
246 return;
247 }
248
249 if (!isset($this->userId) && !\defined('BX_CHECK_AGENT_START') && ($GLOBALS['USER'] instanceof \CUser))
250 {
251 $this->userId = (int)$GLOBALS['USER']->getId();
252 }
253
254 $data = $this->buildLogData();
255 $jsonData = Json::encode($data, JSON_UNESCAPED_UNICODE);
256
257 $fp = @fopen(ANALYTICS_V2_FILENAME, "ab");
258 if ($fp && flock($fp, LOCK_EX))
259 {
260 @fwrite($fp, $jsonData . PHP_EOL);
261 @fflush($fp);
262 @flock($fp, LOCK_UN);
263 @fclose($fp);
264 }
265 }
266
267 private function buildLogData(): array
268 {
269 $data = [
270 'date' => date('Y-m-d H:i:s'),
271 'host' => Context::getCurrent()->getServer()->getHttpHost(),
272 'dbname' => \defined('BX24_DB_NAME') ? BX24_DB_NAME : null,
273 'userId' => $this->userId ?? 0,
274 'event' => $this->exportToArray(),
275 ];
276
277 if (Loader::includeModule('bitrix24'))
278 {
279 $data['license'] = \CBitrix24::getLicenseType();
280 }
281
282 return $data;
283 }
284}
__construct(private string $event, private string $tool, private string $category,)
static getCurrent()
Definition context.php:241
static includeModule($moduleName)
Definition loader.php:69
$GLOBALS['____1444769544']
Definition license.php:1