*/ private const FRONTEND_TELEMETRY_ALLOWED_EVENTS = ['warn_once', 'ajax_error']; /** @var list|null */ private ?array $cachedAllowedEvents = null; public function __construct(private readonly SettingsMetadataGateway $settingsMetadataGateway) { } public function isFrontendTelemetryEnabled(): bool { $value = strtolower(trim((string) ($this->settingsMetadataGateway->getValue(SettingKeys::FRONTEND_TELEMETRY_ENABLED_KEY) ?? ''))); if ($value === '') { return self::FRONTEND_TELEMETRY_ENABLED_FALLBACK; } return in_array($value, ['1', 'true', 'yes', 'on'], true); } public function setFrontendTelemetryEnabled(bool $enabled, ?string $description = null): bool { $desc = $description ?? 'setting.frontend_telemetry_enabled'; return $this->settingsMetadataGateway->set(SettingKeys::FRONTEND_TELEMETRY_ENABLED_KEY, $enabled ? '1' : '0', $desc); } public function getFrontendTelemetrySampleRate(): float { $raw = trim((string) ($this->settingsMetadataGateway->getValue(SettingKeys::FRONTEND_TELEMETRY_SAMPLE_RATE_KEY) ?? '')); if ($raw === '') { return self::FRONTEND_TELEMETRY_SAMPLE_RATE_FALLBACK; } $value = is_numeric($raw) ? (float) $raw : NAN; if (!is_finite($value) || $value < self::FRONTEND_TELEMETRY_SAMPLE_RATE_MIN || $value > self::FRONTEND_TELEMETRY_SAMPLE_RATE_MAX) { return self::FRONTEND_TELEMETRY_SAMPLE_RATE_FALLBACK; } return $value; } public function setFrontendTelemetrySampleRate(?float $sampleRate, ?string $description = null): bool { $value = $sampleRate ?? self::FRONTEND_TELEMETRY_SAMPLE_RATE_FALLBACK; if (!is_finite($value) || $value < self::FRONTEND_TELEMETRY_SAMPLE_RATE_MIN || $value > self::FRONTEND_TELEMETRY_SAMPLE_RATE_MAX) { return false; } $normalized = $this->normalizeSampleRateString($value); $desc = $description ?? 'setting.frontend_telemetry_sample_rate'; return $this->settingsMetadataGateway->set(SettingKeys::FRONTEND_TELEMETRY_SAMPLE_RATE_KEY, $normalized, $desc); } /** * @return list */ public function getFrontendTelemetryAllowedEvents(): array { if (is_array($this->cachedAllowedEvents)) { return $this->cachedAllowedEvents; } $raw = (string) ($this->settingsMetadataGateway->getValue(SettingKeys::FRONTEND_TELEMETRY_ALLOWED_EVENTS_KEY) ?? ''); $normalized = $this->normalizeAllowedEvents($raw); if ($normalized === []) { $this->cachedAllowedEvents = self::FRONTEND_TELEMETRY_ALLOWED_EVENTS; return $this->cachedAllowedEvents; } $this->cachedAllowedEvents = $normalized; return $this->cachedAllowedEvents; } public function setFrontendTelemetryAllowedEvents(array|string|null $events, ?string $description = null): bool { $normalized = $this->normalizeAllowedEvents($events); if ($normalized === []) { $normalized = self::FRONTEND_TELEMETRY_ALLOWED_EVENTS; } $desc = $description ?? 'setting.frontend_telemetry_allowed_events'; $saved = $this->settingsMetadataGateway->set( SettingKeys::FRONTEND_TELEMETRY_ALLOWED_EVENTS_KEY, implode(',', $normalized), $desc ); $this->cachedAllowedEvents = null; return $saved; } private function normalizeSampleRateString(float $value): string { $formatted = number_format($value, 4, '.', ''); $trimmed = rtrim(rtrim($formatted, '0'), '.'); return $trimmed === '' ? '0' : $trimmed; } /** * @return list */ private function normalizeAllowedEvents(array|string|null $events): array { $raw = []; if (is_array($events)) { $raw = $events; } else { $raw = preg_split('/[\s,]+/', (string) $events) ?: []; } $normalized = []; foreach ($raw as $entry) { $event = strtolower(trim((string) $entry)); if ($event === '') { continue; } if (str_starts_with($event, 'frontend.')) { $event = substr($event, strlen('frontend.')); } if (!in_array($event, self::FRONTEND_TELEMETRY_ALLOWED_EVENTS, true)) { continue; } $normalized[] = $event; } $normalized = array_values(array_unique($normalized)); sort($normalized, SORT_STRING); return $normalized; } }