require_once 'includes/config.php';
require_once 'includes/db.php';
require_once 'includes/auth.php';
require_once 'includes/security.php';
require_once 'includes/functions.php';
$db = db();
// Handle comment submission via AJAX is now handled by api/comment.php
// We'll keep the POST handling as fallback for non-JS users
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['submit_comment']) && !isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
$response = ['success' => false, 'message' => ''];
// Check if user is logged in
if (!Auth::isLoggedIn()) {
$_SESSION['comment_error'] = 'You must be logged in to post comments.';
header('Location: ' . $_SERVER['REQUEST_URI']);
exit;
}
// Validate CSRF token
if (!isset($_POST['csrf_token']) || !Security::validateCSRFToken($_POST['csrf_token'])) {
$_SESSION['comment_error'] = 'Invalid security token. Please refresh the page and try again.';
header('Location: ' . $_SERVER['REQUEST_URI']);
exit;
}
$currentUser = Auth::getCurrentUser();
$postId = isset($_POST['post_id']) ? (int)$_POST['post_id'] : 0;
$content = isset($_POST['content']) ? trim($_POST['content']) : '';
$parentId = isset($_POST['parent_id']) && !empty($_POST['parent_id']) ? (int)$_POST['parent_id'] : null;
// Validate
if ($postId <= 0) {
$_SESSION['comment_error'] = 'Invalid post ID.';
header('Location: ' . $_SERVER['REQUEST_URI']);
exit;
}
if (empty($content)) {
$_SESSION['comment_error'] = 'Comment cannot be empty.';
header('Location: ' . $_SERVER['REQUEST_URI']);
exit;
}
if (strlen($content) > 2000) {
$_SESSION['comment_error'] = 'Comment is too long. Maximum 2000 characters.';
header('Location: ' . $_SERVER['REQUEST_URI']);
exit;
}
try {
// Verify that the blog post exists
$stmt = $db->prepare("SELECT id, user_id FROM blog_posts WHERE id = ? AND status = 'published'");
$stmt->execute([$postId]);
$post = $stmt->fetch();
if (!$post) {
$_SESSION['comment_error'] = 'Blog post not found.';
header('Location: ' . $_SERVER['REQUEST_URI']);
exit;
}
// Verify parent comment if provided
if ($parentId) {
$stmt = $db->prepare("SELECT id FROM comments WHERE id = ? AND post_id = ?");
$stmt->execute([$parentId, $postId]);
if (!$stmt->fetch()) {
$_SESSION['comment_error'] = 'Parent comment not found.';
header('Location: ' . $_SERVER['REQUEST_URI']);
exit;
}
}
// Insert comment
$stmt = $db->prepare("
INSERT INTO comments (post_id, user_id, parent_id, content, created_at)
VALUES (?, ?, ?, ?, NOW())
");
$result = $stmt->execute([$postId, $currentUser['id'], $parentId, $content]);
if ($result) {
$commentId = $db->lastInsertId();
// Create notification for post author (if comment is not from the author)
if ($post['user_id'] && $post['user_id'] != $currentUser['id']) {
$notificationMessage = $currentUser['username'] . ' commented on your post: ' . substr($content, 0, 50) . '...';
try {
$stmt = $db->prepare("
INSERT INTO notifications (user_id, type, message, link, created_at)
VALUES (?, 'comment', ?, ?, NOW())
");
$stmt->execute([$post['user_id'], $notificationMessage, 'blog-post.php?id=' . $postId]);
} catch (PDOException $e) {
// Notifications table might not exist, just ignore
error_log("Notification error: " . $e->getMessage());
}
}
$_SESSION['comment_success'] = 'Comment posted successfully!';
} else {
$_SESSION['comment_error'] = 'Failed to post comment. Please try again.';
}
} catch (PDOException $e) {
error_log("Comment error: " . $e->getMessage());
$_SESSION['comment_error'] = 'An error occurred. Please try again.';
}
// Redirect back to the post
header('Location: ' . $_SERVER['REQUEST_URI']);
exit;
}
// Set up page variables and include header
$pageTitle = 'Blog Post';
$pageDescription = 'Read our latest technology insights and tutorials.';
require_once 'includes/header.php';
// Update view count and get post
$db->beginTransaction();
try {
// Increment views
$stmt = $db->prepare("UPDATE blog_posts SET views = views + 1 WHERE slug = ? AND status = 'published'");
$stmt->execute([$slug]);
// Get post details
$stmt = $db->prepare("
SELECT p.*, u.username, u.full_name, u.avatar, u.bio as author_bio, u.role,
GROUP_CONCAT(DISTINCT c.name SEPARATOR ',') as categories,
GROUP_CONCAT(DISTINCT c.slug SEPARATOR ',') as category_slugs
FROM blog_posts p
LEFT JOIN users u ON p.user_id = u.id
LEFT JOIN post_categories pc ON p.id = pc.post_id
LEFT JOIN categories c ON pc.category_id = c.id
WHERE p.slug = ? AND p.status = 'published'
GROUP BY p.id
");
$stmt->execute([$slug]);
$post = $stmt->fetch();
$db->commit();
} catch (Exception $e) {
$db->rollBack();
error_log("Error loading blog post: " . $e->getMessage());
redirect('blog.php');
}
if (!$post) {
redirect('blog.php');
}
// Set page title and description
$pageTitle = htmlspecialchars($post['title'], ENT_QUOTES, 'UTF-8') . ' - BamStarTech Blog';
$pageDescription = htmlspecialchars($post['excerpt'] ?? truncateText(strip_tags($post['content']), 160), ENT_QUOTES, 'UTF-8');
// Get related posts (same categories)
$relatedPosts = [];
if (!empty($post['category_slugs'])) {
$categoryArray = explode(',', $post['category_slugs']);
$placeholders = implode(',', array_fill(0, count($categoryArray), '?'));
$stmt = $db->prepare("
SELECT DISTINCT p.id, p.title, p.slug, p.excerpt, p.created_at, p.featured_image,
u.username, u.full_name
FROM blog_posts p
LEFT JOIN users u ON p.user_id = u.id
LEFT JOIN post_categories pc ON p.id = pc.post_id
WHERE pc.category_id IN (
SELECT id FROM categories WHERE slug IN ($placeholders)
)
AND p.id != ? AND p.status = 'published'
GROUP BY p.id
ORDER BY p.created_at DESC
LIMIT 3
");
$params = array_merge($categoryArray, [$post['id']]);
$stmt->execute($params);
$relatedPosts = $stmt->fetchAll();
}
// Get previous and next posts
$stmt = $db->prepare("
SELECT id, title, slug FROM blog_posts
WHERE created_at < ? AND status = 'published'
ORDER BY created_at DESC LIMIT 1
");
$stmt->execute([$post['created_at']]);
$prevPost = $stmt->fetch();
$stmt = $db->prepare("
SELECT id, title, slug FROM blog_posts
WHERE created_at > ? AND status = 'published'
ORDER BY created_at ASC LIMIT 1
");
$stmt->execute([$post['created_at']]);
$nextPost = $stmt->fetch();
// Get comments for this post
$comments = [];
try {
// Check if comments table exists
$stmt = $db->query("SHOW TABLES LIKE 'comments'");
if ($stmt->rowCount() > 0) {
// Get main comments
$stmt = $db->prepare("
SELECT c.*, u.username, u.full_name, u.avatar, u.email
FROM comments c
LEFT JOIN users u ON c.user_id = u.id
WHERE c.post_id = ? AND c.parent_id IS NULL
ORDER BY c.created_at DESC
");
$stmt->execute([$post['id']]);
$comments = $stmt->fetchAll();
// Get replies for each comment
foreach ($comments as &$comment) {
$stmt = $db->prepare("
SELECT c.*, u.username, u.full_name, u.avatar, u.email
FROM comments c
LEFT JOIN users u ON c.user_id = u.id
WHERE c.parent_id = ?
ORDER BY c.created_at ASC
");
$stmt->execute([$comment['id']]);
$comment['replies'] = $stmt->fetchAll();
}
}
} catch (Exception $e) {
// Comments table might not exist, just continue without comments
error_log("Error loading comments: " . $e->getMessage());
}
// Calculate reading time
$wordCount = str_word_count(strip_tags($post['content'] ?? ''));
$readingTime = max(1, ceil($wordCount / 200));
?>