Add PWA reminders and flexible walk scoring
This commit is contained in:
@@ -29,6 +29,14 @@ function redirect(string $path): never
|
||||
exit;
|
||||
}
|
||||
|
||||
function json_response(array $payload, int $status = 200): never
|
||||
{
|
||||
http_response_code($status);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
exit;
|
||||
}
|
||||
|
||||
function request_path(): string
|
||||
{
|
||||
$path = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);
|
||||
@@ -80,6 +88,17 @@ function verify_csrf(?string $token): bool
|
||||
return hash_equals(csrf_token(), $token);
|
||||
}
|
||||
|
||||
function verify_request_csrf(): bool
|
||||
{
|
||||
$headerToken = $_SERVER['HTTP_X_CSRF_TOKEN'] ?? null;
|
||||
|
||||
if (is_string($headerToken) && $headerToken !== '') {
|
||||
return verify_csrf($headerToken);
|
||||
}
|
||||
|
||||
return verify_csrf($_POST['_token'] ?? null);
|
||||
}
|
||||
|
||||
function is_active_path(string $path): bool
|
||||
{
|
||||
return request_path() === $path;
|
||||
@@ -117,6 +136,18 @@ function decode_json_file(string $path, array $fallback = []): array
|
||||
return is_array($decoded) ? $decoded : $fallback;
|
||||
}
|
||||
|
||||
function request_json_body(): array
|
||||
{
|
||||
$raw = file_get_contents('php://input');
|
||||
if (!is_string($raw) || trim($raw) === '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
$decoded = json_decode($raw, true);
|
||||
|
||||
return is_array($decoded) ? $decoded : [];
|
||||
}
|
||||
|
||||
function encode_payload(array $payload): string
|
||||
{
|
||||
return base64_encode((string) json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
@@ -188,6 +219,14 @@ function request_is_secure(): bool
|
||||
);
|
||||
}
|
||||
|
||||
function app_origin(): string
|
||||
{
|
||||
$host = (string) ($_SERVER['HTTP_HOST'] ?? 'localhost');
|
||||
$scheme = request_is_secure() ? 'https' : 'http';
|
||||
|
||||
return $scheme . '://' . $host;
|
||||
}
|
||||
|
||||
function remember_me_lifetime(): int
|
||||
{
|
||||
return 60 * 60 * 24 * 30;
|
||||
@@ -257,6 +296,62 @@ function sport_location_label(?string $value): string
|
||||
return $options[$value] ?? '';
|
||||
}
|
||||
|
||||
function walk_mode_options(): array
|
||||
{
|
||||
return [
|
||||
'time' => 'Spaziergang nach Zeit',
|
||||
'steps' => 'Spaziergang nach Schritten',
|
||||
];
|
||||
}
|
||||
|
||||
function walk_mode_label(string $mode): string
|
||||
{
|
||||
return walk_mode_options()[$mode] ?? walk_mode_options()['time'];
|
||||
}
|
||||
|
||||
function format_walk_value(array $entry): string
|
||||
{
|
||||
$mode = (string) ($entry['walk_mode'] ?? 'time');
|
||||
|
||||
if ($mode === 'steps') {
|
||||
return number_format((int) ($entry['walk_steps'] ?? 0), 0, ',', '.') . ' Schritte';
|
||||
}
|
||||
|
||||
return (string) ((int) ($entry['walk_minutes'] ?? 0)) . ' min';
|
||||
}
|
||||
|
||||
function walk_chart_value(array $entry): int
|
||||
{
|
||||
$mode = (string) ($entry['walk_mode'] ?? 'time');
|
||||
|
||||
if ($mode === 'steps') {
|
||||
return max(0, (int) round(((int) ($entry['walk_steps'] ?? 0)) / 200));
|
||||
}
|
||||
|
||||
return max(0, (int) ($entry['walk_minutes'] ?? 0));
|
||||
}
|
||||
|
||||
function base64url_encode(string $data): string
|
||||
{
|
||||
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
|
||||
}
|
||||
|
||||
function base64url_decode(string $data): string
|
||||
{
|
||||
$padding = strlen($data) % 4;
|
||||
if ($padding > 0) {
|
||||
$data .= str_repeat('=', 4 - $padding);
|
||||
}
|
||||
|
||||
$decoded = base64_decode(strtr($data, '-_', '+/'), true);
|
||||
|
||||
if ($decoded === false) {
|
||||
throw new RuntimeException('Ungültige Base64url-Daten.');
|
||||
}
|
||||
|
||||
return $decoded;
|
||||
}
|
||||
|
||||
function normalize_sport_type_id(string $value): string
|
||||
{
|
||||
$value = trim(strtr($value, [
|
||||
|
||||
Reference in New Issue
Block a user