View file blog/index.php

File size: 7.5Kb
<?php
/**
 * CMS: LaiCMS (v1.0 Edition 2026)
 * File: blog/index.php
 * Оптимизация: Ultra-Safe Query Engine & Modern Grid
 */

require_once '../system/db.php';
require_once '../system/functions.php';

// Безопасность заголовков
header("X-Frame-Options: SAMEORIGIN");
header("X-Content-Type-Options: nosniff");

// 1. ПАРАМЕТРЫ И ФИЛЬТРАЦИЯ (Безопасный ввод)
$limit = 6; 
$page = isset($_GET['p']) ? max(1, (int)$_GET['p']) : 1;
$offset = ($page - 1) * $limit;
$cat_id = isset($_GET['cat']) ? (int)$_GET['cat'] : 0;

// 2. ПОДСЧЕТ И ПОЛУЧЕНИЕ ДАННЫХ (Prepared Statements)
$where_sql = $cat_id > 0 ? "WHERE p.category_id = ?" : "WHERE 1=1";

// Считаем общее количество
$stmt_count = $mysqli->prepare("SELECT COUNT(*) FROM posts p $where_sql");
if ($cat_id > 0) $stmt_count->bind_param("i", $cat_id);
$stmt_count->execute();
$total_posts = $stmt_count->get_result()->fetch_row()[0] ?? 0;
$total_pages = ceil($total_posts / $limit);

// Получаем категории для навигации
$categories = $mysqli->query("SELECT * FROM categories ORDER BY name ASC");

// Основной запрос постов
$query = "
    SELECT p.id, p.title, p.slug, p.content, p.created_at, u.username, u.avatar, c.name as cat_name 
    FROM posts p 
    JOIN users u ON p.author_id = u.id 
    LEFT JOIN categories c ON p.category_id = c.id
    $where_sql
    ORDER BY p.created_at DESC 
    LIMIT ? OFFSET ?
";

$stmt = $mysqli->prepare($query);
if ($cat_id > 0) {
    $stmt->bind_param("iii", $cat_id, $limit, $offset);
} else {
    $stmt->bind_param("ii", $limit, $offset);
}
$stmt->execute();
$result = $stmt->get_result();

$page_title = "Блог — LaiCMS 2026";
include '../system/header.php';
?>

<style>
    .b-hero { 
        background: var(--pico-card-background-color); 
        padding: 2rem; 
        border-radius: 24px; 
        margin-bottom: 2rem;
        border: 1px solid var(--pico-muted-border-color);
        box-shadow: var(--pico-card-box-shadow);
    }
    
    /* Улучшенные карточки 2026 */
    .p-card {
        background: var(--pico-card-background-color);
        border-radius: 20px;
        border: 1px solid var(--pico-muted-border-color);
        display: flex;
        flex-direction: column;
        overflow: hidden;
        transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    }
    .p-card:hover {
        border-color: var(--pico-primary);
        transform: translateY(-4px);
        box-shadow: 0 10px 30px rgba(0,0,0,0.1);
    }

    .cat-badge {
        font-size: 0.6rem;
        background: var(--pico-primary-background);
        color: var(--pico-primary);
        padding: 4px 12px;
        border-radius: 8px;
        font-weight: 800;
        text-transform: uppercase;
    }

    /* Плавная навигация категорий */
    .cat-scroller {
        display: flex; gap: 8px; overflow-x: auto; 
        padding-bottom: 15px; margin-bottom: 20px;
        scrollbar-width: none;
    }
    .cat-btn {
        padding: 6px 16px; border-radius: 12px; font-size: 0.85rem;
        border: 1px solid var(--pico-muted-border-color);
        white-space: nowrap; transition: 0.2s;
    }
    .cat-btn.active { background: var(--pico-primary); color: white; border-color: var(--pico-primary); }

    .p-footer {
        padding: 1rem 1.5rem;
        border-top: 1px solid var(--pico-muted-border-color);
        display: flex; justify-content: space-between; align-items: center;
        background: rgba(var(--pico-muted-color-rgb), 0.03);
    }
</style>

<div class="b-hero">
    <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;">
        <hgroup style="margin: 0;">
            <h2 style="margin:0;"><i class="fa-solid fa-layer-group"></i> Журнал событий</h2>
            <p style="font-size: 0.8rem; opacity: 0.7;">Найдено публикаций: <?= $total_posts ?></p>
        </hgroup>
        <?php if(isset($_SESSION['user_id'])): ?>
            <a href="/blog/add_post.php" role="button" class="primary btn-sm" style="border-radius: 12px;">
                <i class="fa-solid fa-pen-nib"></i> Написать
            </a>
        <?php endif; ?>
    </div>
</div>

<nav class="cat-scroller">
    <a href="index.php" class="cat-btn <?= $cat_id == 0 ? 'active' : '' ?>">Все категории</a>
    <?php while($c = $categories->fetch_assoc()): ?>
        <a href="?cat=<?= $c['id'] ?>" class="cat-btn <?= $cat_id == $c['id'] ? 'active' : '' ?>">
            <?= _e($c['name']) ?>
        </a>
    <?php endwhile; ?>
</nav>

<div class="grid" style="grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 20px;">
    <?php if ($result && $result->num_rows > 0): ?>
        <?php while($post = $result->fetch_assoc()): ?>
        <article class="p-card">
            <div style="padding: 1.5rem; flex: 1;">
                <div style="display:flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
                    <span class="cat-badge"><?= _e($post['cat_name'] ?? 'Общее') ?></span>
                    <i class="fa-regular fa-bookmark" style="opacity: 0.3;"></i>
                </div>
                
                <h4 style="margin-bottom: 0.8rem;">
                    <a href="view.php?slug=<?= $post['slug'] ?>" style="color: inherit; text-decoration: none;">
                        <?= _e($post['title']) ?>
                    </a>
                </h4>
                
                <p style="font-size: 0.85rem; opacity: 0.8; line-height: 1.5;">
                    <?= mb_strimwidth(strip_tags($post['content']), 0, 120, "...") ?>
                </p>
            </div>

            <div class="p-footer">
                <div style="display: flex; align-items: center; gap: 8px;">
                    <div style="width: 24px; height: 24px; border-radius: 6px; background: var(--pico-primary); color: white; display: flex; align-items: center; justify-content: center; font-size: 0.6rem; font-weight: bold;">
                        <?= mb_substr($post['username'], 0, 1) ?>
                    </div>
                    <span style="font-size: 0.75rem; font-weight: 700;"><?= _e($post['username']) ?></span>
                </div>
                <time style="font-size: 0.7rem; opacity: 0.5;">
                    <i class="fa-regular fa-calendar"></i> <?= date('d.m.Y', strtotime($post['created_at'])) ?>
                </time>
            </div>
        </article>
        <?php endwhile; ?>
    <?php else: ?>
        <div style="grid-column: 1/-1; text-align: center; padding: 3rem;">
            <p class="secondary">В этой категории пока нет записей.</p>
        </div>
    <?php endif; ?>
</div>

<?php if ($total_pages > 1): ?>
<nav style="margin-top: 3rem; display: flex; justify-content: center;">
    <ul style="display: flex; gap: 10px; list-style: none;">
        <?php if($page > 1): ?>
            <li><a href="?p=<?= $page - 1 ?><?= $cat_id ? '&cat='.$cat_id : '' ?>" role="button" class="outline secondary">←</a></li>
        <?php endif; ?>
        
        <li><span role="button" class="secondary" style="pointer-events: none; opacity: 0.6;"><?= $page ?> / <?= $total_pages ?></span></li>

        <?php if($page < $total_pages): ?>
            <li><a href="?p=<?= $page + 1 ?><?= $cat_id ? '&cat='.$cat_id : '' ?>" role="button" class="outline secondary">→</a></li>
        <?php endif; ?>
    </ul>
</nav>
<?php endif; ?>

<?php include '../system/footer.php'; ?>