🔐 ЗАЩИТА:
- ip_check.php + сессия
- CSRF-токен
- htmlspecialchars() везде
- PDO подготовленные запросы
- (int) для category_id
- in_array() валидация типа блока
- trim() очистка данных
📝 ФУНКЦИИ add_code_post.php:
- Форма с блоками (динамическое добавление)
- Выбор категории из БД
- Автодополнение тегов
- Файловый браузер для изображений
- Meta Title/Description для SEO
💾 ФУНКЦИИ save_code_post.php:
- Валидация заголовка
- INSERT в code_posts
- INSERT в code_blocks (блоки контента)
- INSERT в tags + связь code_post_tags
- Редирект с сообщением об успехе/ошибке
🗂️ ТАБЛИЦЫ:
- code_posts — основной пост
- code_blocks — блоки контента
- categories — категории
- tags — теги
- code_post_tags — связь тегов с постами
<?php
include('ip_check.php');
session_start();
if (!isset($_SESSION['user'])) {
header("Location: login.php");
exit;
}
require '../includes/db.php';
include '../includes/header.php';
// CSRF-токен
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
$error = '';
$form_data = [
'title' => '',
'meta_title' => '',
'meta_description' => '',
'preview_text' => '',
'image' => '',
'category_id' => '',
'tags' => ''
];
?>
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Добавить код-пост — Админка</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/adminka.css">
<script src="tag-autocomplete.js"></script>
<style>
.error { background: #f44336; color: white; padding: 10px; border-radius: 5px; margin: 10px 0; }
.form-group { margin-bottom: 15px; }
.form-group label { display: block; font-weight: bold; margin-bottom: 5px; }
.form-group input, .form-group textarea, .form-group select { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; }
.block { background: #f5f5f5; padding: 15px; margin: 10px 0; border-radius: 5px; }
button, input[type="submit"] { background: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; margin: 5px; }
button:hover, input[type="submit"]:hover { background: #0056b3; }
.btn-secondary { background: #6c757d; }
.btn-secondary:hover { background: #5a6268; }
</style>
<script>
function openFileBrowser() {
window.open('file_browser.php', 'FileBrowser', 'width=600,height=400');
}
function insertFilePath(filePath) {
document.getElementsByName('image')[0].value = filePath;
}
let blockCount = 1;
function addBlock() {
const container = document.getElementById('blocks-container');
const div = document.createElement('div');
div.className = 'block';
div.innerHTML = `
<strong>Блок ${blockCount + 1}</strong><br>
<label>Тип блока:
<select name="blocks[${blockCount}][type]">
<option value="heading">Заголовок H2</option>
<option value="text">Обычный текст</option>
<option value="code">Пример кода</option>
<option value="image">Изображение</option>
<option value="quote">Цитата</option>
</select>
</label><br>
<label>Содержание:<br>
<textarea name="blocks[${blockCount}][content]" rows="5" placeholder="Содержание блока"></textarea>
</label><br>
<button type="button" class="btn-secondary" onclick="this.parentElement.remove()">🗑 Удалить блок</button>
`;
container.appendChild(div);
blockCount++;
}
</script>
</head>
<body>
<div class="container">
<?php include '../includes/admin_menu.php'; ?>
<h2>➕ Добавить код-пост</h2>
<?php if ($error): ?>
<div class="error"><?= htmlspecialchars($error) ?></div>
<?php endif; ?>
<form method="post" action="save_code_post.php">
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
<div class="form-group">
<label>🏷️ Теги (через запятую)</label>
<input type="text" id="tag-input" name="tags" value="<?= htmlspecialchars($form_data['tags']) ?>" placeholder="Начните вводить тег...">
</div>
<div class="form-group">
<label>📚 Категория</label>
<select name="category_id">
<option value="">— Без категории —</option>
<?php
$stmt = $pdo->query("SELECT id, name FROM categories ORDER BY name ASC");
while ($cat = $stmt->fetch()): ?>
<option value="<?= $cat['id'] ?>" <?= $form_data['category_id'] == $cat['id'] ? 'selected' : '' ?>>
<?= htmlspecialchars($cat['name']) ?>
</option>
<?php endwhile; ?>
</select>
</div>
<div class="form-group">
<label>📌 Заголовок *</label>
<input type="text" name="title" required value="<?= htmlspecialchars($form_data['title']) ?>">
</div>
<div class="form-group">
<label>📝 Мета-заголовок (SEO)</label>
<input type="text" name="meta_title" value="<?= htmlspecialchars($form_data['meta_title']) ?>">
</div>
<div class="form-group">
<label>📄 Мета-описание (SEO)</label>
<textarea name="meta_description" rows="2"><?= htmlspecialchars($form_data['meta_description']) ?></textarea>
</div>
<div class="form-group">
<label>📖 Краткое описание (предпросмотр)</label>
<textarea name="preview_text" rows="3"><?= htmlspecialchars($form_data['preview_text']) ?></textarea>
</div>
<div class="form-group">
<label>📷 Изображение</label>
<div style="display: flex; gap: 10px;">
<input type="text" name="image" value="<?= htmlspecialchars($form_data['image']) ?>" style="flex:1">
<button type="button" onclick="openFileBrowser()">📁 Выбрать</button>
</div>
</div>
<h3>📦 Блоки контента</h3>
<div id="blocks-container">
<div class="block">
<strong>Блок 1</strong><br>
<label>Тип блока:
<select name="blocks[0][type]">
<option value="heading">Заголовок H2</option>
<option value="text">Обычный текст</option>
<option value="code">Пример кода</option>
<option value="image">Изображение</option>
<option value="quote">Цитата</option>
</select>
</label><br>
<label>Содержание:<br>
<textarea name="blocks[0][content]" rows="5" placeholder="Содержание блока"></textarea>
</label><br>
</div>
</div>
<button type="button" onclick="addBlock()">+ Добавить блок</button>
<button type="submit">💾 Сохранить пост</button>
<a href="index.php"><button type="button" class="btn-secondary">← Назад</button></a>
</form>
</div>
</body>
</html>
<?php
include('ip_check.php');
session_start();
if (!isset($_SESSION['user'])) {
header("Location: login.php");
exit;
}
require '../includes/db.php';
// CSRF-проверка
if (!isset($_POST['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
die("CSRF атака!");
}
// Получаем и очищаем данные
$title = trim($_POST['title'] ?? '');
$meta_title = trim($_POST['meta_title'] ?? '');
$meta_description = trim($_POST['meta_description'] ?? '');
$preview_text = trim($_POST['preview_text'] ?? '');
$image = trim($_POST['image'] ?? '');
$category_id = !empty($_POST['category_id']) ? (int)$_POST['category_id'] : null;
$tags = trim($_POST['tags'] ?? '');
// Валидация
if (empty($title)) {
$_SESSION['error'] = "Заголовок обязателен!";
header("Location: add_code_post.php");
exit;
}
// Сохраняем код-пост
$stmt = $pdo->prepare("INSERT INTO code_posts
(title, meta_title, meta_description, intro, image, category_id, created_at)
VALUES (?, ?, ?, ?, ?, ?, NOW())");
$stmt->execute([$title, $meta_title, $meta_description, $preview_text, $image, $category_id]);
$post_id = $pdo->lastInsertId();
// Сохраняем блоки
if (isset($_POST['blocks']) && is_array($_POST['blocks'])) {
$block_stmt = $pdo->prepare("INSERT INTO code_blocks (post_id, type, content, position) VALUES (?, ?, ?, ?)");
foreach ($_POST['blocks'] as $position => $block) {
$type = in_array($block['type'], ['heading', 'text', 'code', 'image', 'quote']) ? $block['type'] : 'text';
$content = $block['content'] ?? '';
$block_stmt->execute([$post_id, $type, $content, $position]);
}
}
// Сохраняем теги (если есть)
if (!empty($tags)) {
$tag_names = array_map('trim', explode(',', $tags));
foreach ($tag_names as $tag_name) {
if (empty($tag_name)) continue;
$slug = strtolower(trim(preg_replace('/[^a-zA-Z0-9-]/', '-', $tag_name)));
// Вставляем или получаем ID тега
$tag_stmt = $pdo->prepare("INSERT INTO tags (name, slug) VALUES (?, ?) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id)");
$tag_stmt->execute([$tag_name, $slug]);
$tag_id = $pdo->lastInsertId();
// Связываем с постом
$link_stmt = $pdo->prepare("INSERT INTO code_post_tags (code_post_id, tag_id) VALUES (?, ?)");
$link_stmt->execute([$post_id, $tag_id]);
}
}
$_SESSION['success'] = "Код-пост успешно добавлен!";
header("Location: index.php");
exit;
?>
Комментарии
Пока нет комментариев. Будьте первым!