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('Файл "до" обязателен'); $section = sectionById($sectionId); if (!$section) 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 = 'Фото добавлено'; } } catch (Throwable $e) { $errors[] = $e->getMessage(); } } $sections = sectionsAll(); $activeSectionId = (int)($_GET['section_id'] ?? ($sections[0]['id'] ?? 0)); $photos = $activeSectionId > 0 ? photosBySection($activeSectionId) : []; 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, этап 1)

← в галерею

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

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

Фото до:

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

Разделы

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

Фото раздела

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