/
TorX
/
rasp
Обзор
Документация
Войти
/
TorX
/
rasp
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
includes/helpers.php
248 строк
7 KB
tormovies
Rewrite the app as plain PHP so it runs on shared hosting without Node.
06 авг 2026, 00:17
06 авг 2026, 00:17
b4b9ea6
Код
Авторство
О чём код?
<?php declare(strict_types=1); const RELEASE_TYPES = ['single', 'ep', 'album', 'other']; const FIELD_SEPARATOR = ' - '; function e(?string $value): string { return htmlspecialchars((string) $value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); } function redirect(string $path): never { header('Location: ' . $path); exit; } function today_iso(): string { return date('Y-m-d'); } function format_release_date(string $iso): string { $dt = DateTime::createFromFormat('Y-m-d', $iso); return $dt ? $dt->format('d.m.Y') : $iso; } function parse_release_date(string $display): ?string { $dt = DateTime::createFromFormat('d.m.Y', trim($display)); if (!$dt || $dt->format('d.m.Y') !== trim($display)) { return null; } return $dt->format('Y-m-d'); } function format_month_title(int $year, int $month): string { static $months = [ 1 => 'Январь', 2 => 'Февраль', 3 => 'Март', 4 => 'Апрель', 5 => 'Май', 6 => 'Июнь', 7 => 'Июль', 8 => 'Август', 9 => 'Сентябрь', 10 => 'Октябрь', 11 => 'Ноябрь', 12 => 'Декабрь', ]; return ($months[$month] ?? '') . ' ' . $year; } function release_type_label(string $type): string { return match ($type) { 'single' => 'Single', 'ep' => 'EP', 'album' => 'Album', 'other' => 'Другой', default => $type, }; } function format_pitch_flag(bool $hasPitch): string { return $hasPitch ? 'питчинг' : 'без'; } function parse_pitch_flag(string $value): ?bool { $v = mb_strtolower(trim($value)); if (in_array($v, ['питчинг', 'питч', 'pitch', 'да', 'yes', 'true', '1', 'with'], true)) { return true; } if (in_array($v, ['без', 'без питча', 'без питчинга', 'no', 'false', '0', 'without'], true)) { return false; } return null; } function parse_release_type(string $value): ?string { $v = strtolower(trim($value)); return in_array($v, RELEASE_TYPES, true) ? $v : null; } function format_export_line(array $r): string { return implode(FIELD_SEPARATOR, [ format_release_date($r['release_date']), trim($r['artist_name']), trim($r['title']), trim($r['genre']), trim($r['lyric_author']), trim((string) ($r['label'] ?? '')), $r['type'] ?: 'single', format_pitch_flag((bool) $r['has_pitch']), ]); } function parse_import_line(string $line): array|string { $trimmed = trim($line); if ($trimmed === '') { return 'пустая строка'; } $parts = array_map('trim', explode(FIELD_SEPARATOR, $trimmed)); $count = count($parts); if ($count < 5) { return "ожидалось минимум 5 частей, получено {$count}"; } if ($count > 8) { return "слишком много частей ({$count}), максимум 8"; } $dateRaw = $parts[0]; $artistName = $parts[1]; $title = $parts[2]; $genre = $parts[3]; $authorRaw = $parts[4]; $rest = array_slice($parts, 5); $releaseDate = parse_release_date($dateRaw); if ($releaseDate === null) { return "неверная дата «{$dateRaw}», нужен формат ДД.ММ.ГГГГ"; } if ($artistName === '') { return 'нет артиста'; } if ($title === '') { return 'нет названия'; } if ($genre === '') { return 'нет жанра'; } $lyricAuthor = preg_replace('/^текст\s+/iu', '', $authorRaw) ?? $authorRaw; $lyricAuthor = trim($lyricAuthor); if ($lyricAuthor === '') { return 'нет автора текста'; } $label = ''; $type = null; $hasPitch = null; if (count($rest) === 1) { $only = $rest[0]; $asType = parse_release_type($only); $asPitch = parse_pitch_flag($only); if ($asType !== null) { $type = $asType; } elseif ($asPitch !== null) { $hasPitch = $asPitch; } else { $label = $only; } } elseif (count($rest) === 2) { $label = $rest[0]; $asType = parse_release_type($rest[1]); $asPitch = parse_pitch_flag($rest[1]); if ($asType !== null) { $type = $asType; } elseif ($asPitch !== null) { $hasPitch = $asPitch; } else { return "неизвестный тип/питчинг «{$rest[1]}»"; } } elseif (count($rest) >= 3) { $label = $rest[0]; $asType = parse_release_type($rest[1]); if ($asType === null) { return "неизвестный тип «{$rest[1]}» (single/ep/album/other)"; } $type = $asType; $asPitch = parse_pitch_flag($rest[2]); if ($asPitch === null) { return "неизвестный питчинг «{$rest[2]}» (питчинг/без)"; } $hasPitch = $asPitch; } return [ 'release_date' => $releaseDate, 'artist_name' => $artistName, 'title' => $title, 'genre' => $genre, 'lyric_author' => $lyricAuthor, 'label' => $label, 'type' => $type, 'has_pitch' => $hasPitch, ]; } function label_color(string $label): array { $palette = [ ['bg' => '#0b6e6a', 'fg' => '#ffffff', 'border' => '#085550'], ['bg' => '#1d4ed8', 'fg' => '#ffffff', 'border' => '#1e3a8a'], ['bg' => '#b45309', 'fg' => '#ffffff', 'border' => '#92400e'], ['bg' => '#be123c', 'fg' => '#ffffff', 'border' => '#9f1239'], ['bg' => '#15803d', 'fg' => '#ffffff', 'border' => '#166534'], ['bg' => '#6d28d9', 'fg' => '#ffffff', 'border' => '#5b21b6'], ['bg' => '#0e7490', 'fg' => '#ffffff', 'border' => '#155e75'], ['bg' => '#a16207', 'fg' => '#ffffff', 'border' => '#854d0e'], ['bg' => '#c2410c', 'fg' => '#ffffff', 'border' => '#9a3412'], ['bg' => '#1e3a5f', 'fg' => '#ffffff', 'border' => '#0f2744'], ]; $hash = 0; $key = mb_strtolower(trim($label)); $len = strlen($key); for ($i = 0; $i < $len; $i++) { $hash = ($hash * 31 + ord($key[$i])) % 2147483647; } return $palette[$hash % count($palette)]; } function flash_set(string $type, string $message): void { if (function_exists('start_admin_session')) { start_admin_session(); } elseif (session_status() !== PHP_SESSION_ACTIVE) { session_start(); } $_SESSION['_flash'] = ['type' => $type, 'message' => $message]; } function flash_get(): ?array { if (function_exists('start_admin_session')) { start_admin_session(); } elseif (session_status() !== PHP_SESSION_ACTIVE) { session_start(); } if (empty($_SESSION['_flash'])) { return null; } $flash = $_SESSION['_flash']; unset($_SESSION['_flash']); return $flash; } function request_method(): string { return strtoupper($_SERVER['REQUEST_METHOD'] ?? 'GET'); } function post_string(string $key, string $default = ''): string { return trim((string) ($_POST[$key] ?? $default)); }