getMessage()); } if ($_SERVER['REQUEST_METHOD'] === 'POST') { $action = (string)($_POST['action'] ?? ''); try { if ($action === 'create_section') { $name = trim((string)($_POST['name'] ?? '')); $sort = (int)($_POST['sort_order'] ?? 1000); if ($name === '') throw new RuntimeException('Название раздела пустое'); sectionCreate($name, $sort); $message = 'Раздел создан'; } if ($action === 'upload_photo') { $sectionId = (int)($_POST['section_id'] ?? 0); $codeName = trim((string)($_POST['code_name'] ?? '')); $sortOrder = (int)($_POST['sort_order'] ?? 1000); $description = trim((string)($_POST['description'] ?? '')); $description = $description !== '' ? $description : null; if ($sectionId < 1) throw new RuntimeException('Выбери раздел'); if ($codeName === '') throw new RuntimeException('Укажи код фото (например АВФ1)'); if (!isset($_FILES['before'])) throw new RuntimeException('Файл "до" обязателен'); if (!sectionById($sectionId)) throw new RuntimeException('Раздел не найден'); $photoId = photoCreate($sectionId, $codeName, $description, $sortOrder); $before = saveImageUpload($_FILES['before'], $codeName, 'before', $sectionId); photoFileUpsert($photoId, 'before', $before['path'], $before['mime'], $before['size']); if (isset($_FILES['after']) && (int)($_FILES['after']['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_NO_FILE) { $after = saveImageUpload($_FILES['after'], $codeName . 'р', 'after', $sectionId); photoFileUpsert($photoId, 'after', $after['path'], $after['mime'], $after['size']); } $message = 'Фото добавлено'; } if ($action === 'create_commenter') { $displayName = trim((string)($_POST['display_name'] ?? '')); if ($displayName === '') throw new RuntimeException('Укажи имя комментатора'); $u = commenterCreate($displayName); $link = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http') . '://' . ($_SERVER['HTTP_HOST'] ?? 'localhost') . '/index-mysql.php?viewer=' . urlencode($u['token']); $message = 'Комментатор создан: ' . $u['display_name'] . ' | ссылка: ' . $link; } if ($action === 'delete_commenter') { $id = (int)($_POST['id'] ?? 0); if ($id > 0) { commenterDelete($id); $message = 'Комментатор удалён (доступ отозван)'; } } if ($action === 'delete_comment') { $id = (int)($_POST['id'] ?? 0); if ($id > 0) { commentDelete($id); $message = 'Комментарий удалён'; } } } catch (Throwable $e) { $errors[] = $e->getMessage(); } } $sections = sectionsAll(); $activeSectionId = (int)($_GET['section_id'] ?? ($sections[0]['id'] ?? 0)); $photos = $activeSectionId > 0 ? photosBySection($activeSectionId) : []; $commenters = commentersAll(); $latestComments = commentsLatest(80); function h(string $v): string { return htmlspecialchars($v, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); } function assetUrl(string $path): string { $f=__DIR__ . '/' . ltrim($path,'/'); $v=is_file($f)?(string)filemtime($f):(string)time(); return $path . '?v=' . rawurlencode($v); } function saveImageUpload(array $file, string $baseName, string $kind, int $sectionId): array { $allowedMime = ['image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp', 'image/gif' => 'gif']; $err = (int)($file['error'] ?? UPLOAD_ERR_NO_FILE); if ($err !== UPLOAD_ERR_OK) throw new RuntimeException("Ошибка загрузки ({$kind})"); $size = (int)($file['size'] ?? 0); if ($size < 1 || $size > MAX_UPLOAD_BYTES) throw new RuntimeException("Файл {$kind}: превышен лимит 3 МБ"); $tmp = (string)($file['tmp_name'] ?? ''); if (!is_uploaded_file($tmp)) throw new RuntimeException("Файл {$kind}: некорректный источник"); $mime = mime_content_type($tmp) ?: ''; if (!isset($allowedMime[$mime])) throw new RuntimeException("Файл {$kind}: недопустимый mime {$mime}"); $safeBase = preg_replace('/[^\p{L}\p{N}._-]+/u', '_', $baseName) ?? 'photo'; $safeBase = trim($safeBase, '._-'); if ($safeBase === '') $safeBase = 'photo'; $ext = $allowedMime[$mime]; $dir = __DIR__ . '/photos/section_' . $sectionId; if (!is_dir($dir) && !mkdir($dir, 0775, true) && !is_dir($dir)) throw new RuntimeException('Не удалось создать папку раздела'); $final = uniqueName($dir, $safeBase, $ext); $dest = $dir . '/' . $final; if (!move_uploaded_file($tmp, $dest)) throw new RuntimeException('Не удалось сохранить файл'); return [ 'path' => 'photos/section_' . $sectionId . '/' . $final, 'mime' => $mime, 'size' => $size, ]; } function uniqueName(string $dir, string $base, string $ext): string { $i = 0; do { $name = $i === 0 ? "{$base}.{$ext}" : "{$base}_{$i}.{$ext}"; $i++; } while (is_file($dir . '/' . $name)); return $name; } ?> Админка (MySQL)

Админка (MySQL)

Открыть публичную MySQL-галерею

Создать раздел

Добавить фото

Фото до:

Фото после (опционально):

Комментаторы (персональные ссылки)

IDИмяСтатусДействие

После создания ссылки токен показывается один раз в зелёном сообщении.

Разделы

IDНазваниеПорядокФото

Фото раздела

IDКодПревьюОписаниеПорядок

Последние комментарии

IDФотоПользовательКомментарий