WIP: Blogposts
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
php_flag display_errors Off
|
php_flag display_errors On
|
||||||
# php_value error_reporting -1
|
# php_value error_reporting -1
|
||||||
RedirectMatch 403 ^/\.well-known
|
RedirectMatch 403 ^/\.well-known
|
||||||
Options -Indexes
|
Options -Indexes
|
||||||
|
|||||||
144
admin_blogs.php
Normal file
144
admin_blogs.php
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
<?php include_once('header02.php');
|
||||||
|
checkAdmin();
|
||||||
|
checkUserSession();
|
||||||
|
|
||||||
|
$result = $conn->prepare("
|
||||||
|
SELECT
|
||||||
|
b.blog_id,
|
||||||
|
b.title,
|
||||||
|
b.description,
|
||||||
|
b.status,
|
||||||
|
b.date,
|
||||||
|
b.image,
|
||||||
|
CONCAT(u.first_name, ' ', u.last_name) AS author_name,
|
||||||
|
u.email AS author_email,
|
||||||
|
u.profile_pic
|
||||||
|
FROM blogs b
|
||||||
|
JOIN users u ON b.author = u.user_id
|
||||||
|
WHERE b.status != 'deleted'
|
||||||
|
ORDER BY b.date DESC
|
||||||
|
");
|
||||||
|
|
||||||
|
$result->execute();
|
||||||
|
$posts = $result->get_result();
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.image {
|
||||||
|
width: 400px;
|
||||||
|
/* Set your desired width */
|
||||||
|
height: 350px;
|
||||||
|
/* Set your desired height */
|
||||||
|
overflow: hidden;
|
||||||
|
/* Hide any overflow */
|
||||||
|
display: block;
|
||||||
|
/* Ensure proper block behavior */
|
||||||
|
}
|
||||||
|
|
||||||
|
.image img {
|
||||||
|
width: 100%;
|
||||||
|
/* Image scales to fill the container */
|
||||||
|
height: 100%;
|
||||||
|
/* Image scales to fill the container */
|
||||||
|
object-fit: cover;
|
||||||
|
/* Fills the container while maintaining aspect ratio */
|
||||||
|
object-position: top;
|
||||||
|
/* Aligns the top of the image with the top of the container */
|
||||||
|
display: block;
|
||||||
|
/* Prevents inline whitespace issues */
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$bannerFolder = 'assets/images/banners/';
|
||||||
|
$bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE);
|
||||||
|
|
||||||
|
$randomBanner = 'assets/images/base4/camping.jpg'; // default fallback
|
||||||
|
if (!empty($bannerImages)) {
|
||||||
|
$randomBanner = $bannerImages[array_rand($bannerImages)];
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<section class="page-banner-area pt-50 pb-35 rel z-1 bgs-cover" style="background-image: url('<?php echo $randomBanner; ?>');">
|
||||||
|
<!-- Overlay PNG -->
|
||||||
|
<div class="banner-overlay"></div>
|
||||||
|
<div class="container">
|
||||||
|
<div class="banner-inner text-white">
|
||||||
|
<h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">Admin Blogs</h2>
|
||||||
|
<nav aria-label="breadcrumb">
|
||||||
|
<ol class="breadcrumb justify-content-center mb-20" data-aos="fade-right" data-aos-delay="200" data-aos-duration="1500" data-aos-offset="50">
|
||||||
|
<li class="breadcrumb-item"><a href="index.php">Home</a></li>
|
||||||
|
<li class="breadcrumb-item active">Admin Blogs</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- Page Banner End -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Blog List Area start -->
|
||||||
|
<section class="blog-list-page py-100 rel z-1">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
|
||||||
|
<h2>My Posts</h2>
|
||||||
|
<?php if (isset($_SESSION['message'])): ?>
|
||||||
|
<div class="alert alert-warning message-box">
|
||||||
|
<?php echo $_SESSION['message']; ?>
|
||||||
|
<span class="close-btn" onclick="this.parentElement.style.display='none'">×</span>
|
||||||
|
</div>
|
||||||
|
<?php unset($_SESSION['message']); ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
<a href="blog_create.php">+ New Post</a>
|
||||||
|
|
||||||
|
<?php while ($post = $posts->fetch_assoc()):
|
||||||
|
// Output the HTML structure with dynamic data
|
||||||
|
echo '
|
||||||
|
<div class="destination-item style-three bgc-lighter booking" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||||
|
<div class="image" style="width:200px;height:200px;">
|
||||||
|
<img src="' . $post["image"] . '" alt="' . $post["title"] . '">
|
||||||
|
</div>
|
||||||
|
<div class="content" style="width:100%;">
|
||||||
|
<div class="destination-header d-flex align-items-start gap-3">
|
||||||
|
<img src="' . $post["profile_pic"] . '" alt="Author" class="rounded-circle border" width="80" height="80">
|
||||||
|
<div>
|
||||||
|
<span class="badge bg-dark mb-1">' . strtoupper($post["status"]) . '</span>
|
||||||
|
<h5 class="mb-0">' . $post["title"] . '</h5>
|
||||||
|
<small class="text-muted">' . $post["author_name"] . '</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>' . $post["description"] . '</p>
|
||||||
|
<div class="destination-footer">
|
||||||
|
<div class="btn-group" style="display:flex; justify-content:flex-end; gap:10px; margin-top:10px;">
|
||||||
|
<a href="blog_edit.php?token='.encryptData($post["blog_id"], $salt).'" class="btn btn-sm" data-bs-toggle="tooltip" data-bs-placement="top" title="Edit"><i class="bi bi-pencil"></i></a>
|
||||||
|
<a href="blog_read.php?token='.encryptData($post["blog_id"], $salt).'" class="btn btn-sm" data-bs-toggle="tooltip" data-bs-placement="top" title="Preview"><i class="bi bi-eye"></i></a>
|
||||||
|
<a href="blog_delete.php?token='.encryptData($post["blog_id"], $salt).'" class="btn btn-sm" data-bs-toggle="tooltip" data-bs-placement="top" title="Delete"><i class="bi bi-trash"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
';
|
||||||
|
endwhile; ?>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- Blog List Area end -->
|
||||||
|
<script>
|
||||||
|
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
|
||||||
|
tooltipTriggerList.forEach(el => new bootstrap.Tooltip(el));
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<?php include_once("insta_footer.php"); ?>
|
||||||
101
autosave.php
Normal file
101
autosave.php
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
<?php
|
||||||
|
require_once("env.php");
|
||||||
|
require_once("session.php");
|
||||||
|
require_once("connection.php");
|
||||||
|
require_once("functions.php");
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
http_response_code(401);
|
||||||
|
echo "Not authorized";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$article_id = (int)($_POST['id'] ?? 0);
|
||||||
|
$title = $_POST['title'] ?? '';
|
||||||
|
$content = $_POST['content'] ?? '';
|
||||||
|
$description = $_POST['subtitle'] ?? '';
|
||||||
|
$category = $_POST['category'] ?? '';
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
|
||||||
|
// Default to current user
|
||||||
|
$author_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
// Allow override if admin
|
||||||
|
$role = getUserRole();
|
||||||
|
if (($role === 'admin' || $role === 'superadmin') && isset($_POST['author'])) {
|
||||||
|
$author_id = (int)$_POST['author'];
|
||||||
|
}
|
||||||
|
echo $author_id;
|
||||||
|
|
||||||
|
$cover_image_path = null;
|
||||||
|
|
||||||
|
// Only attempt upload if a file was submitted
|
||||||
|
if (!empty($_FILES['cover_image']['name'])) {
|
||||||
|
$uploadDir = __DIR__ . "/uploads/blogs/".$article_id."/images/";
|
||||||
|
if (!is_dir($uploadDir)) {
|
||||||
|
mkdir($uploadDir, 0777, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanitize and rename file
|
||||||
|
$originalName = basename($_FILES['cover_image']['name']);
|
||||||
|
$originalName = preg_replace("/[^a-zA-Z0-9\._-]/", "_", $originalName); // remove unsafe characters
|
||||||
|
|
||||||
|
$targetPath = $uploadDir . $originalName;
|
||||||
|
$publicPath = "/uploads/blogs/".$article_id."/images/" . $originalName;
|
||||||
|
|
||||||
|
// Error detection before upload
|
||||||
|
$fileError = $_FILES['cover_image']['error'];
|
||||||
|
if ($fileError !== UPLOAD_ERR_OK) {
|
||||||
|
$errorMessages = [
|
||||||
|
UPLOAD_ERR_INI_SIZE => 'The uploaded file exceeds the upload_max_filesize directive in php.ini.',
|
||||||
|
UPLOAD_ERR_FORM_SIZE => 'The uploaded file exceeds the MAX_FILE_SIZE directive in the HTML form.',
|
||||||
|
UPLOAD_ERR_PARTIAL => 'The uploaded file was only partially uploaded.',
|
||||||
|
UPLOAD_ERR_NO_FILE => 'No file was uploaded.',
|
||||||
|
UPLOAD_ERR_NO_TMP_DIR => 'Missing a temporary folder.',
|
||||||
|
UPLOAD_ERR_CANT_WRITE => 'Failed to write file to disk.',
|
||||||
|
UPLOAD_ERR_EXTENSION => 'A PHP extension stopped the upload.',
|
||||||
|
];
|
||||||
|
$errorMessage = $errorMessages[$fileError] ?? 'Unknown upload error.';
|
||||||
|
http_response_code(500);
|
||||||
|
echo "Upload error: $errorMessage";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip upload if identical file already exists
|
||||||
|
if (file_exists($targetPath)) {
|
||||||
|
$cover_image_path = $publicPath;
|
||||||
|
} else {
|
||||||
|
if (move_uploaded_file($_FILES['cover_image']['tmp_name'], $targetPath)) {
|
||||||
|
$cover_image_path = $publicPath;
|
||||||
|
} else {
|
||||||
|
http_response_code(500);
|
||||||
|
echo "Failed to move uploaded file.";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare SQL with/without image update
|
||||||
|
if ($cover_image_path) {
|
||||||
|
$stmt = $conn->prepare("
|
||||||
|
UPDATE blogs
|
||||||
|
SET title = ?, content = ?, description = ?, category = ?, image = ?, author = ?
|
||||||
|
WHERE blog_id = ?
|
||||||
|
");
|
||||||
|
$stmt->bind_param("ssssssi", $title, $content, $description, $category, $cover_image_path, $author_id, $article_id);
|
||||||
|
} else {
|
||||||
|
$stmt = $conn->prepare("
|
||||||
|
UPDATE blogs
|
||||||
|
SET title = ?, content = ?, description = ?, category = ?, author = ?
|
||||||
|
WHERE blog_id = ?
|
||||||
|
");
|
||||||
|
$stmt->bind_param("ssssii", $title, $content, $description, $category, $author_id, $article_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($stmt->execute()) {
|
||||||
|
echo "Saved";
|
||||||
|
} else {
|
||||||
|
http_response_code(500);
|
||||||
|
echo "Database update failed: " . $stmt->error;
|
||||||
|
}
|
||||||
8
blog.php
8
blog.php
@@ -64,7 +64,7 @@ if (!empty($bannerImages)) {
|
|||||||
<div class="col-lg-8">
|
<div class="col-lg-8">
|
||||||
<?php
|
<?php
|
||||||
// Query to retrieve data from the trips table
|
// Query to retrieve data from the trips table
|
||||||
$sql = "SELECT blog_id, title, date, category, image, description, author, members_only, link FROM blogs ORDER BY date DESC";
|
$sql = "SELECT blog_id, title, date, category, image, description, author, members_only, link FROM blogs WHERE status = 'published' ORDER BY date DESC";
|
||||||
$result = $conn->query($sql);
|
$result = $conn->query($sql);
|
||||||
|
|
||||||
if ($result->num_rows > 0) {
|
if ($result->num_rows > 0) {
|
||||||
@@ -86,7 +86,7 @@ if (!empty($bannerImages)) {
|
|||||||
$icon = "fa-lock";
|
$icon = "fa-lock";
|
||||||
} else {
|
} else {
|
||||||
if (getUserMemberStatus($_SESSION['user_id'])) {
|
if (getUserMemberStatus($_SESSION['user_id'])) {
|
||||||
$blog_link = $row['link'];
|
$blog_link = "blog_read.php?token=".encryptData($blog_id, $salt);
|
||||||
$button_hover = "Read More";
|
$button_hover = "Read More";
|
||||||
$icon = "fa-arrow-right";
|
$icon = "fa-arrow-right";
|
||||||
} else {
|
} else {
|
||||||
@@ -96,7 +96,7 @@ if (!empty($bannerImages)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$blog_link = $row['link'];
|
$blog_link = "blog_read.php?token=".encryptData($blog_id, $salt);
|
||||||
$button_hover = "Read More";
|
$button_hover = "Read More";
|
||||||
$icon = "fa-arrow-right";
|
$icon = "fa-arrow-right";
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ if (!empty($bannerImages)) {
|
|||||||
echo '
|
echo '
|
||||||
<div class="blog-item style-three" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
<div class="blog-item style-three" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||||
<div class="image">
|
<div class="image">
|
||||||
<img style="border-radius:20px;" src="assets/images/blog/' . $blog_id . '/' . $image . '" alt="Blog List">
|
<img style="border-radius:20px;" src="' . $image . '" alt="Blog List">
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<a href="blog.php" class="category">' . $category . '</a>
|
<a href="blog.php" class="category">' . $category . '</a>
|
||||||
|
|||||||
33
blog_create.php
Normal file
33
blog_create.php
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
// session_start();
|
||||||
|
require_once("env.php");
|
||||||
|
require_once("session.php");
|
||||||
|
require_once("connection.php");
|
||||||
|
require_once("functions.php");
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
die("Not logged in");
|
||||||
|
}
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
$role = getUserRole();
|
||||||
|
|
||||||
|
if(!getUserMemberStatus($user_id)){
|
||||||
|
if ($role === 'user'){
|
||||||
|
$_SESSION['message'] = "Blogs only available to active members. Please contact info@4wdcsa.co.za for more information.";
|
||||||
|
header("Location: user_blogs.php");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$date = date('Y-m-d');
|
||||||
|
$status = 'draft';
|
||||||
|
|
||||||
|
$stmt = $conn->prepare("INSERT INTO blogs (author, title, category, description, content, date, status)
|
||||||
|
VALUES (?, '', '', '', '', ?, ?)");
|
||||||
|
$stmt->bind_param("iss", $user_id, $date, $status);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$blog_id = $stmt->insert_id;
|
||||||
|
header("Location: blog_edit.php?token=" . encryptData($blog_id, $salt));
|
||||||
|
exit;
|
||||||
36
blog_delete.php
Normal file
36
blog_delete.php
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
require_once("env.php");
|
||||||
|
require_once("session.php");
|
||||||
|
require_once("connection.php");
|
||||||
|
require_once("functions.php");
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
$_SESSION['message'] = "Not authorized.";
|
||||||
|
header("Location: user_blogs.php");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$token = $_GET['token'];
|
||||||
|
// Sanitize the trip_id to prevent SQL injection
|
||||||
|
$article_id = intval(decryptData($token, $salt)); // Ensures $trip_id is treated as an integer
|
||||||
|
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
if ($article_id <= 0) {
|
||||||
|
$_SESSION['message'] = "Invalid blog ID.";
|
||||||
|
header("Location: user_blogs.php");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $conn->prepare("UPDATE blogs SET status = 'deleted' WHERE blog_id = ? AND author = ?");
|
||||||
|
$stmt->bind_param("ii", $article_id, $user_id);
|
||||||
|
|
||||||
|
if ($stmt->execute()) {
|
||||||
|
$_SESSION['message'] = "Blog deleted!";
|
||||||
|
} else {
|
||||||
|
$_SESSION['message'] = "Failed to delete blog: " . $stmt->error;
|
||||||
|
}
|
||||||
|
|
||||||
|
header("Location: user_blogs.php");
|
||||||
|
exit;
|
||||||
|
?>
|
||||||
265
blog_edit.php
Normal file
265
blog_edit.php
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
<?php
|
||||||
|
include_once('header02.php');
|
||||||
|
|
||||||
|
// Ensure the user is logged in
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
die("User not logged in.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$token = $_GET['token'];
|
||||||
|
// Sanitize the trip_id to prevent SQL injection
|
||||||
|
$blog_id = intval(decryptData($token, $salt)); // Ensures $trip_id is treated as an integer
|
||||||
|
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
$role = getUserRole();
|
||||||
|
|
||||||
|
// Fetch article info
|
||||||
|
$stmt = $conn->prepare("SELECT * FROM blogs WHERE blog_id = ?");
|
||||||
|
$stmt->bind_param("i", $blog_id);
|
||||||
|
$stmt->execute();
|
||||||
|
$result = $stmt->get_result();
|
||||||
|
if ($result->num_rows === 0) {
|
||||||
|
die("Blog post not found.");
|
||||||
|
}
|
||||||
|
$article = $result->fetch_assoc();
|
||||||
|
$stmt->close();
|
||||||
|
?>
|
||||||
|
|
||||||
|
<script src="https://cdn.tiny.cloud/1/o6xuedbd9z22xk0p5zszinevn4bdbljxnfwn0tjjvv6r37pb/tinymce/6/tinymce.min.js" referrerpolicy="origin"></script>
|
||||||
|
<script>
|
||||||
|
tinymce.init({
|
||||||
|
selector: '#content',
|
||||||
|
plugins: 'image code link',
|
||||||
|
toolbar: 'undo redo | blocks | bold italic | alignleft aligncenter alignright | code | image | link',
|
||||||
|
images_upload_url: 'upload.php?blog_id=<?= $blog_id ?>',
|
||||||
|
image_class_list: [
|
||||||
|
{ title: 'None', value: '' },
|
||||||
|
{ title: 'Left Align', value: 'img-left' },
|
||||||
|
{ title: 'Right Align', value: 'img-right' },
|
||||||
|
{ title: 'Rounded', value: 'img-rounded' }
|
||||||
|
],
|
||||||
|
automatic_uploads: true,
|
||||||
|
images_upload_credentials: true, // include cookies if needed
|
||||||
|
content_style: "body { font-family:Helvetica,Arial,sans-serif; font-size:14px }",
|
||||||
|
|
||||||
|
setup: function (editor) {
|
||||||
|
editor.on('init', function () {
|
||||||
|
setTimeout(() => {
|
||||||
|
editor.setContent(`<?= str_replace("`", "\`", addslashes($article['content'])) ?>`);
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section class="account-settings-area py-70 rel z-1">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row align-items-center">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="comment-form bgc-lighter z-1 rel mb-55">
|
||||||
|
<form action="submit_blog.php" method="POST" enctype="multipart/form-data">
|
||||||
|
<input type="hidden" name="article_id" value="<?= htmlspecialchars($blog_id) ?>">
|
||||||
|
<div class="section-title py-20">
|
||||||
|
<h2>Edit Blog</h2>
|
||||||
|
<div id="autosave-status" style="font-style: italic; font-size: 0.9em;"></div>
|
||||||
|
</div>
|
||||||
|
<div class="row mt-35">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="title">Blog Title</label>
|
||||||
|
<input type="text" id="title" class="form-control" name="title" placeholder="Title" required value="<?= htmlspecialchars($article['title']) ?>">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="subtitle">Description</label>
|
||||||
|
<input type="text" id="subtitle" class="form-control" name="subtitle" placeholder="Description" required value="<?= htmlspecialchars($article['description']) ?>">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="cover_image">Cover Image</label>
|
||||||
|
<input type="file" class="form-control" name="cover_image" id="cover_image" accept="image/*">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12 mb-10">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="category">Blog Category</label>
|
||||||
|
<select name="category" class="form-control" id="category" required>
|
||||||
|
<option value="Trip Report" <?= $article['category'] == 'Trip Report' ? 'selected' : '' ?>>Trip Report</option>
|
||||||
|
<option value="Gear Review" <?= $article['category'] == 'Gear Review' ? 'selected' : '' ?>>Gear Review</option>
|
||||||
|
<option value="Talking Dirty" <?= $article['category'] == 'Talking Dirty' ? 'selected' : '' ?>>Talking Dirty</option>
|
||||||
|
<option value="Report" <?= $article['category'] == 'Report' ? 'selected' : '' ?>>Report</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12 mb-10">
|
||||||
|
<div class="form-group">
|
||||||
|
<?php if ($role === 'admin' || $role === 'superadmin'): ?>
|
||||||
|
<label for="author">Author:</label>
|
||||||
|
<select class="form-control" name="author" id="author">
|
||||||
|
<?php
|
||||||
|
$user_query = $conn->query("SELECT user_id, CONCAT(first_name, ' ', last_name) AS name FROM users ORDER BY first_name ASC");
|
||||||
|
while ($user = $user_query->fetch_assoc()):
|
||||||
|
?>
|
||||||
|
<option value="<?= $user['user_id'] ?>" <?= $user['user_id'] == $article['author'] ? 'selected' : '' ?>>
|
||||||
|
<?= htmlspecialchars($user['name']) ?>
|
||||||
|
</option>
|
||||||
|
<?php endwhile; ?>
|
||||||
|
</select>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="form-group">
|
||||||
|
<textarea id="content" name="content"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="button" class="theme-btn style-three" style="width:100%;" id="manualSaveBtn">Save Draft</button>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<a href="blog_read.php?token=<?php echo encryptData($blog_id, $salt); ?>" class="theme-btn style-three" style="width:100%;">Preview</a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12">
|
||||||
|
<?php
|
||||||
|
if ($article['status'] == 'draft'){
|
||||||
|
echo '<div class="form-group">
|
||||||
|
<button type="button" class="theme-btn style-two" style="width:100%;" id="manualPostBtn">Publish</button>
|
||||||
|
|
||||||
|
</div> ';
|
||||||
|
} else {
|
||||||
|
echo '<div class="form-group">
|
||||||
|
<button type="button" class="theme-btn style-two" style="width:100%;" id="manualDraftBtn">Un-Publish</button>
|
||||||
|
|
||||||
|
</div> ';
|
||||||
|
}?>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
||||||
|
<script>
|
||||||
|
function autosavePost() {
|
||||||
|
const title = document.querySelector('[name="title"]').value;
|
||||||
|
const content = tinymce.get("content").getContent();
|
||||||
|
const subtitle = document.querySelector('[name="subtitle"]').value;
|
||||||
|
const category = document.querySelector('[name="category"]').value;
|
||||||
|
const author = document.querySelector('[name="author"]').value;
|
||||||
|
const articleId = document.querySelector('[name="article_id"]').value;
|
||||||
|
const coverImageInput = document.querySelector('[name="cover_image"]');
|
||||||
|
|
||||||
|
console.log("Saving: ", { title, subtitle, content, category, articleId, author });
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("id", articleId);
|
||||||
|
formData.append("title", title);
|
||||||
|
formData.append("content", content);
|
||||||
|
formData.append("subtitle", subtitle);
|
||||||
|
formData.append("category", category);
|
||||||
|
formData.append("author", author);
|
||||||
|
|
||||||
|
// Only append image if a new file is selected
|
||||||
|
if (coverImageInput.files.length > 0) {
|
||||||
|
formData.append("cover_image", coverImageInput.files[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetch("autosave.php", {
|
||||||
|
method: "POST",
|
||||||
|
body: formData
|
||||||
|
}).then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
document.getElementById("autosave-status").innerText = "Draft autosaved at " + new Date().toLocaleTimeString();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
document.getElementById("autosave-status").innerText = "Autosave failed";
|
||||||
|
console.error("Autosave failed", response.statusText);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
console.error("Autosave error:", err);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger autosave every 15s
|
||||||
|
setInterval(autosavePost, 15000);
|
||||||
|
|
||||||
|
// Manual autosave button
|
||||||
|
document.getElementById("manualSaveBtn").addEventListener("click", autosavePost);
|
||||||
|
|
||||||
|
// Manual publish button
|
||||||
|
document.getElementById("manualPostBtn").addEventListener("click", function () {
|
||||||
|
autosavePost().then(success => {
|
||||||
|
if (!success) return;
|
||||||
|
|
||||||
|
const articleId = document.querySelector('[name="article_id"]').value;
|
||||||
|
const publishData = new FormData();
|
||||||
|
publishData.append("id", articleId);
|
||||||
|
|
||||||
|
fetch("publish_blog.php", {
|
||||||
|
method: "POST",
|
||||||
|
body: publishData
|
||||||
|
}).then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
alert("Post published successfully!");
|
||||||
|
// Optional: redirect to the live post
|
||||||
|
window.location.href = "blog_read.php?token=<?php echo encryptData($blog_id, $salt);?>";
|
||||||
|
} else {
|
||||||
|
alert("Publish failed.");
|
||||||
|
console.error("Publish error:", response.statusText);
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
console.error("Publish error:", err);
|
||||||
|
alert("Publish failed due to network error.");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Manual unpublish button
|
||||||
|
document.getElementById("manualDraftBtn").addEventListener("click", function () {
|
||||||
|
autosavePost().then(success => {
|
||||||
|
if (!success) return;
|
||||||
|
|
||||||
|
const articleId = document.querySelector('[name="article_id"]').value;
|
||||||
|
const publishData = new FormData();
|
||||||
|
publishData.append("id", articleId);
|
||||||
|
|
||||||
|
fetch("blog_unpublish.php", {
|
||||||
|
method: "POST",
|
||||||
|
body: publishData
|
||||||
|
}).then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
alert("Post unpublished successfully!");
|
||||||
|
// Optional: redirect to the live post
|
||||||
|
window.location.href = "blog_read.php?token=<?php echo encryptData($blog_id, $salt);?>";
|
||||||
|
} else {
|
||||||
|
alert("unPublish failed.");
|
||||||
|
console.error("Publish error:", response.statusText);
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
console.error("Publish error:", err);
|
||||||
|
alert("Publish failed due to network error.");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<?php include_once("insta_footer.php"); ?>
|
||||||
176
blog_read.php
Normal file
176
blog_read.php
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
<?php include_once('header02.php');
|
||||||
|
|
||||||
|
$token = $_GET['token'];
|
||||||
|
// Sanitize the trip_id to prevent SQL injection
|
||||||
|
$blog_id = intval(decryptData($token, $salt)); // Ensures $trip_id is treated as an integer
|
||||||
|
|
||||||
|
|
||||||
|
$page_id = 'blog_'.$blog_id;
|
||||||
|
echo getCommentCount($page_id);
|
||||||
|
|
||||||
|
|
||||||
|
$stmt = $conn->prepare("
|
||||||
|
SELECT a.title, a.category, a.description, a.content, a.date,
|
||||||
|
u.first_name, u.last_name
|
||||||
|
FROM blogs a
|
||||||
|
JOIN users u ON a.author = u.user_id
|
||||||
|
WHERE a.blog_id = ?
|
||||||
|
");
|
||||||
|
$stmt->bind_param("i", $blog_id);
|
||||||
|
$stmt->execute();
|
||||||
|
$result = $stmt->get_result();
|
||||||
|
|
||||||
|
if ($result->num_rows === 0) {
|
||||||
|
die("Article not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$row = $result->fetch_assoc();
|
||||||
|
$author = htmlspecialchars($row['first_name'] . ' ' . $row['last_name']);
|
||||||
|
?>
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.image {
|
||||||
|
width: 400px;
|
||||||
|
/* Set your desired width */
|
||||||
|
height: 350px;
|
||||||
|
/* Set your desired height */
|
||||||
|
overflow: hidden;
|
||||||
|
/* Hide any overflow */
|
||||||
|
display: block;
|
||||||
|
/* Ensure proper block behavior */
|
||||||
|
}
|
||||||
|
|
||||||
|
.image img {
|
||||||
|
width: 100%;
|
||||||
|
/* Image scales to fill the container */
|
||||||
|
height: 100%;
|
||||||
|
/* Image scales to fill the container */
|
||||||
|
object-fit: cover;
|
||||||
|
/* Fills the container while maintaining aspect ratio */
|
||||||
|
object-position: top;
|
||||||
|
/* Aligns the top of the image with the top of the container */
|
||||||
|
display: block;
|
||||||
|
/* Prevents inline whitespace issues */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
/* font-family: Arial, sans-serif; */
|
||||||
|
line-height: 1.6;
|
||||||
|
/* max-width: 800px; */
|
||||||
|
margin: auto;
|
||||||
|
/* padding: 20px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
color: #2c3e50;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin-top: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
margin-bottom: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-left,
|
||||||
|
.img-right {
|
||||||
|
max-width: 30%;
|
||||||
|
margin: 20px;
|
||||||
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-left {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-right {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clearfix {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$bannerFolder = 'assets/images/banners/';
|
||||||
|
$bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE);
|
||||||
|
|
||||||
|
$randomBanner = 'assets/images/base4/camping.jpg'; // default fallback
|
||||||
|
if (!empty($bannerImages)) {
|
||||||
|
$randomBanner = $bannerImages[array_rand($bannerImages)];
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<section class="page-banner-area pt-50 pb-35 rel z-1 bgs-cover" style="background-image: url('<?php echo $randomBanner; ?>');">
|
||||||
|
<div class="banner-overlay"></div>
|
||||||
|
<div class="container">
|
||||||
|
<div class="banner-inner text-white">
|
||||||
|
<h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50"><?= htmlspecialchars($row['title']) ?></h2>
|
||||||
|
<nav aria-label="breadcrumb">
|
||||||
|
<ol class="breadcrumb justify-content-center mb-20" data-aos="fade-right" data-aos-delay="200" data-aos-duration="1500" data-aos-offset="50">
|
||||||
|
<li class="breadcrumb-item"><a href="index.php">Home</a></li>
|
||||||
|
<li class="breadcrumb-item active"><?= htmlspecialchars($row['title']) ?></li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- Page Banner End -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Blog Detaisl Area start -->
|
||||||
|
<section class="blog-detaisl-page py-100 rel z-1">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<div class="blog-details-content" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||||
|
<a href="blog.html" class="category"><?= htmlspecialchars($row['category']) ?></a>
|
||||||
|
<ul class="blog-meta mb-30">
|
||||||
|
<li><img src="assets/images/pp/default.png" alt="Admin"> <a href="#"><?= $author?></a></li>
|
||||||
|
<li><i class="far fa-calendar-alt"></i> <a href="#"><?= htmlspecialchars($row['date']) ?></a></li>
|
||||||
|
<li><i class="far fa-comments"></i> <a href="#">Comments (<?= getCommentCount($page_id);?>)</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<?= $row['content'] ?>
|
||||||
|
</div>
|
||||||
|
<hr class="mb-45">
|
||||||
|
<div class="tag-share mb-50">
|
||||||
|
<div class="item" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">
|
||||||
|
<h6>Tags </h6>
|
||||||
|
<div class="tag-coulds">
|
||||||
|
<a href="blog.php"><?= htmlspecialchars($row['category']) ?></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php include_once('comment_box.php'); ?>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4 col-md-8 col-sm-10 rmt-75">
|
||||||
|
<div class="blog-sidebar">
|
||||||
|
<div class="widget widget-gallery" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||||
|
<h5 class="widget-title">Gallery</h5>
|
||||||
|
<div class="gallery">
|
||||||
|
<?php
|
||||||
|
$folder = 'uploads/blogs/'.$blog_id.'/images/';
|
||||||
|
$files = glob($folder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE);
|
||||||
|
shuffle($files); // Randomize the order
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
echo '<a href="' . $file . '" style="width: 110px; height: 110px; overflow: hidden; display: inline-block; margin: 2px;">';
|
||||||
|
echo '<img src="' . $file . '" alt="Gallery" style="width: 100%; height: 100%; object-fit: cover; display: block;">';
|
||||||
|
echo '</a>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<?php include_once("insta_footer.php"); ?>
|
||||||
31
blog_unpublish.php
Normal file
31
blog_unpublish.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
require_once("env.php");
|
||||||
|
require_once("session.php");
|
||||||
|
require_once("connection.php");
|
||||||
|
require_once("functions.php");
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
http_response_code(401);
|
||||||
|
echo "Not authorized";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$article_id = (int)($_POST['id'] ?? 0);
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
if ($article_id <= 0) {
|
||||||
|
http_response_code(400);
|
||||||
|
echo "Invalid blog ID";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $conn->prepare("UPDATE blogs SET status = 'draft' WHERE blog_id = ? AND author = ?");
|
||||||
|
$stmt->bind_param("ii", $article_id, $user_id);
|
||||||
|
|
||||||
|
if ($stmt->execute()) {
|
||||||
|
echo "Published";
|
||||||
|
} else {
|
||||||
|
http_response_code(500);
|
||||||
|
echo "Failed to publish: " . $stmt->error;
|
||||||
|
}
|
||||||
|
?>
|
||||||
@@ -1784,8 +1784,8 @@ function getCommentCount($page_id) {
|
|||||||
$conn = openDatabaseConnection();
|
$conn = openDatabaseConnection();
|
||||||
|
|
||||||
// Prepare statement to avoid SQL injection
|
// Prepare statement to avoid SQL injection
|
||||||
$stmt = $conn->prepare("SELECT COUNT(*) FROM comments WHERE page_id = ?");
|
$stmt = $conn->prepare("SELECT COUNT(*) FROM comments WHERE `page_id` = ?");
|
||||||
$stmt->bind_param("i", $page_id);
|
$stmt->bind_param("s", $page_id);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
|
|
||||||
// Get result
|
// Get result
|
||||||
|
|||||||
@@ -211,6 +211,7 @@ logVisitor();
|
|||||||
<!-- <li><a href="admin_payments.php">Payfast Payments</a></li> -->
|
<!-- <li><a href="admin_payments.php">Payfast Payments</a></li> -->
|
||||||
<li><a href="admin_efts.php">EFT Payments</a></li>
|
<li><a href="admin_efts.php">EFT Payments</a></li>
|
||||||
<li><a href="process_payments.php">Process Payments</a></li>
|
<li><a href="process_payments.php">Process Payments</a></li>
|
||||||
|
<li><a href="admin_blogs.php">Manage Blogs</a></li>
|
||||||
<!-- <li><a href="bar_tabs.php">Bar</a></li> -->
|
<!-- <li><a href="bar_tabs.php">Bar</a></li> -->
|
||||||
<?php if ($role === 'superadmin') { ?>
|
<?php if ($role === 'superadmin') { ?>
|
||||||
<li><a href="admin_visitors.php">Visitor Log</a></li>
|
<li><a href="admin_visitors.php">Visitor Log</a></li>
|
||||||
@@ -232,6 +233,7 @@ logVisitor();
|
|||||||
<li><a href="account_settings.php">Account Settings</a></li>
|
<li><a href="account_settings.php">Account Settings</a></li>
|
||||||
<li><a href="membership_details.php">Membership</a></li>
|
<li><a href="membership_details.php">Membership</a></li>
|
||||||
<li><a href="bookings.php">My Bookings</a></li>
|
<li><a href="bookings.php">My Bookings</a></li>
|
||||||
|
<li><a href="user_blogs.php">My Blogs</a></li>
|
||||||
<li><a href="submit_pop.php">Submit P.O.P</a></li>
|
<li><a href="submit_pop.php">Submit P.O.P</a></li>
|
||||||
<li><a href="logout.php">Log Out</a></li>
|
<li><a href="logout.php">Log Out</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ logVisitor();
|
|||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
|
||||||
|
|
||||||
<!-- Flaticon -->
|
<!-- Flaticon -->
|
||||||
<link rel="stylesheet" href="assets/css/flaticon.min.css">
|
<link rel="stylesheet" href="assets/css/flaticon.min.css">
|
||||||
<!-- Font Awesome -->
|
<!-- Font Awesome -->
|
||||||
@@ -224,6 +226,7 @@ logVisitor();
|
|||||||
<!-- <li><a href="admin_payments.php">Payfast Payments</a></li> -->
|
<!-- <li><a href="admin_payments.php">Payfast Payments</a></li> -->
|
||||||
<li><a href="admin_efts.php">EFT Payments</a></li>
|
<li><a href="admin_efts.php">EFT Payments</a></li>
|
||||||
<li><a href="process_payments.php">Process Payments</a></li>
|
<li><a href="process_payments.php">Process Payments</a></li>
|
||||||
|
<li><a href="admin_blogs.php">Manage Blogs</a></li>
|
||||||
<?php if ($role === 'superadmin') { ?>
|
<?php if ($role === 'superadmin') { ?>
|
||||||
<li><a href="admin_visitors.php">Visitor Log</a></li>
|
<li><a href="admin_visitors.php">Visitor Log</a></li>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
@@ -238,6 +241,7 @@ logVisitor();
|
|||||||
<li><a href="account_settings.php">Account Settings</a></li>
|
<li><a href="account_settings.php">Account Settings</a></li>
|
||||||
<li><a href="membership_details.php">Membership</a></li>
|
<li><a href="membership_details.php">Membership</a></li>
|
||||||
<li><a href="bookings.php">My Bookings</a></li>
|
<li><a href="bookings.php">My Bookings</a></li>
|
||||||
|
<li><a href="user_blogs.php">My Blogs</a></li>
|
||||||
<li><a href="submit_pop.php">Submit P.O.P</a></li>
|
<li><a href="submit_pop.php">Submit P.O.P</a></li>
|
||||||
<li><a href="logout.php">Log Out</a></li>
|
<li><a href="logout.php">Log Out</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
12
index.php
12
index.php
@@ -51,7 +51,7 @@ if (!empty($bannerImages)) {
|
|||||||
<div style="padding-top: 50px; padding-bottom: 50px;">
|
<div style="padding-top: 50px; padding-bottom: 50px;">
|
||||||
<img style="width: 250px; margin-bottom: 20px;" src="assets/images/logos/weblogo2.png" alt="Logo">
|
<img style="width: 250px; margin-bottom: 20px;" src="assets/images/logos/weblogo2.png" alt="Logo">
|
||||||
<h1 class="hero-title" data-aos="flip-up" data-aos-delay="50" data-aos-duration="1500" data-aos-offset="50">
|
<h1 class="hero-title" data-aos="flip-up" data-aos-delay="50" data-aos-duration="1500" data-aos-offset="50">
|
||||||
Welcome to<br>the Four Wheel Drive Club<br>of Southern Africa
|
Welcome to<br>the 4 Wheel Drive Club<br>of Southern Africa
|
||||||
</h1>
|
</h1>
|
||||||
<a href="membership.php" class="theme-btn style-two bgc-secondary" style="margin-top: 20px; background-color: #e90000; padding: 10px 20px; color: white; text-decoration: none; border-radius: 25px;">
|
<a href="membership.php" class="theme-btn style-two bgc-secondary" style="margin-top: 20px; background-color: #e90000; padding: 10px 20px; color: white; text-decoration: none; border-radius: 25px;">
|
||||||
<span data-hover="Become a Member">Become a Member</span>
|
<span data-hover="Become a Member">Become a Member</span>
|
||||||
@@ -112,7 +112,7 @@ if (countUpcomingTrips() > 0) { ?>
|
|||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<span class="location"><i class="fal fa-map-marker-alt"></i> ' . $location . '</span>
|
<span class="location"><i class="fal fa-map-marker-alt"></i> ' . $location . '</span>
|
||||||
<h5><a href="trip-details.php?trip_id=' . $trip_id . '">' . $trip_name . '</a></h5>
|
<h5><a href="trip-details.php?token=' . encryptData($trip_id, $salt) . '">' . $trip_name . '</a></h5>
|
||||||
<span class="time">' . convertDate($start_date) . ' - ' . convertDate($end_date) . '</span><br>
|
<span class="time">' . convertDate($start_date) . ' - ' . convertDate($end_date) . '</span><br>
|
||||||
<span class="time">' . calculateDaysAndNights($start_date, $end_date) . '</span>
|
<span class="time">' . calculateDaysAndNights($start_date, $end_date) . '</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -541,7 +541,7 @@ if (countUpcomingTrips() > 0) { ?>
|
|||||||
</div>
|
</div>
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<?php
|
<?php
|
||||||
$sql = "SELECT blog_id, title, date, category, image, description, author, link, members_only FROM blogs ORDER BY date DESC LIMIT 3";
|
$sql = "SELECT blog_id, title, date, category, image, description, author, link, members_only FROM blogs WHERE status = 'published' ORDER BY date DESC LIMIT 3 ";
|
||||||
$result = $conn->query($sql);
|
$result = $conn->query($sql);
|
||||||
|
|
||||||
if ($result->num_rows > 0) {
|
if ($result->num_rows > 0) {
|
||||||
@@ -562,7 +562,7 @@ if (countUpcomingTrips() > 0) { ?>
|
|||||||
$icon = "fa-lock";
|
$icon = "fa-lock";
|
||||||
}else{
|
}else{
|
||||||
if (getUserMemberStatus($_SESSION['user_id'])) {
|
if (getUserMemberStatus($_SESSION['user_id'])) {
|
||||||
$blog_link = $row['link'];
|
$blog_link = "blog_read.php?token=".encryptData($blog_id, $salt);
|
||||||
$button_hover = "Read More";
|
$button_hover = "Read More";
|
||||||
$icon = "fa-arrow-right";
|
$icon = "fa-arrow-right";
|
||||||
}else{
|
}else{
|
||||||
@@ -572,7 +572,7 @@ if (countUpcomingTrips() > 0) { ?>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
$blog_link = $row['link'];
|
$blog_link = "blog_read.php?token=".encryptData($blog_id, $salt);
|
||||||
$button_hover = "Read More";
|
$button_hover = "Read More";
|
||||||
$icon = "fa-arrow-right";
|
$icon = "fa-arrow-right";
|
||||||
}
|
}
|
||||||
@@ -591,7 +591,7 @@ if (countUpcomingTrips() > 0) { ?>
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="image">
|
<div class="image">
|
||||||
<img style="border-radius:20px;" src="assets/images/blog/' . $blog_id . '/' . $blog_image . '" alt="Blog List">
|
<img style="border-radius:20px;" src="' . $blog_image . '" alt="Blog List">
|
||||||
</div>
|
</div>
|
||||||
<a style="width:100%;" href="' . $blog_link . '" class="theme-btn">
|
<a style="width:100%;" href="' . $blog_link . '" class="theme-btn">
|
||||||
<span style="width:100%;" data-hover="'.$button_hover.'">Read More</span>
|
<span style="width:100%;" data-hover="'.$button_hover.'">Read More</span>
|
||||||
|
|||||||
3
phpinfo.php
Normal file
3
phpinfo.php
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
echo phpinfo();
|
||||||
31
publish_blog.php
Normal file
31
publish_blog.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
require_once("env.php");
|
||||||
|
require_once("session.php");
|
||||||
|
require_once("connection.php");
|
||||||
|
require_once("functions.php");
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
http_response_code(401);
|
||||||
|
echo "Not authorized";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$article_id = (int)($_POST['id'] ?? 0);
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
if ($article_id <= 0) {
|
||||||
|
http_response_code(400);
|
||||||
|
echo "Invalid blog ID";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $conn->prepare("UPDATE blogs SET status = 'published' WHERE blog_id = ? AND author = ?");
|
||||||
|
$stmt->bind_param("ii", $article_id, $user_id);
|
||||||
|
|
||||||
|
if ($stmt->execute()) {
|
||||||
|
echo "Published";
|
||||||
|
} else {
|
||||||
|
http_response_code(500);
|
||||||
|
echo "Failed to publish: " . $stmt->error;
|
||||||
|
}
|
||||||
|
?>
|
||||||
24
submit_blog.php
Normal file
24
submit_blog.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once("env.php");
|
||||||
|
require_once("session.php");
|
||||||
|
require_once("connection.php");
|
||||||
|
require_once("functions.php");
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
die("Login required");
|
||||||
|
}
|
||||||
|
|
||||||
|
$title = $_POST['title'];
|
||||||
|
$category = $_POST['category'];
|
||||||
|
$description = $_POST['description'];
|
||||||
|
$content = $_POST['content'];
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
$date = date('Y-m-d');
|
||||||
|
|
||||||
|
|
||||||
|
$stmt = $conn->prepare("INSERT INTO blogs (author, title, content, description, category, date) VALUES (?, ?, ?, ?, ?, ?)");
|
||||||
|
$stmt->bind_param("isssss", $user_id, $title, $content, $description, $category, $date);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
header("Location: blog.php");
|
||||||
27
upload.php
Normal file
27
upload.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
$blog_id = $_GET['blog_id'] ?? null;
|
||||||
|
|
||||||
|
|
||||||
|
if (!isset($_FILES['file'])) {
|
||||||
|
echo json_encode(['error' => 'No file uploaded']);
|
||||||
|
http_response_code(400);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$targetDir = "uploads/blogs/".$blog_id."/images/";
|
||||||
|
if (!file_exists($targetDir)) {
|
||||||
|
mkdir($targetDir, 0777, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tmp = $_FILES['file']['tmp_name'];
|
||||||
|
$name = basename($_FILES['file']['name']);
|
||||||
|
$targetFile = $targetDir . uniqid() . "-" . $name;
|
||||||
|
|
||||||
|
if (move_uploaded_file($tmp, $targetFile)) {
|
||||||
|
echo json_encode(['location' => $targetFile]);
|
||||||
|
} else {
|
||||||
|
echo json_encode(['error' => 'Failed to move uploaded file']);
|
||||||
|
http_response_code(500);
|
||||||
|
}
|
||||||
24
upload_blog_image.php
Normal file
24
upload_blog_image.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
if (!isset($_FILES['file'])) {
|
||||||
|
echo json_encode(['error' => 'No file uploaded']);
|
||||||
|
http_response_code(400);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$targetDir = "uploads/blogs/images/";
|
||||||
|
if (!file_exists($targetDir)) {
|
||||||
|
mkdir($targetDir, 0777, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tmp = $_FILES['file']['tmp_name'];
|
||||||
|
$name = basename($_FILES['file']['name']);
|
||||||
|
$targetFile = $targetDir . uniqid() . "-" . $name;
|
||||||
|
|
||||||
|
if (move_uploaded_file($tmp, $targetFile)) {
|
||||||
|
echo json_encode(['location' => $targetFile]);
|
||||||
|
} else {
|
||||||
|
echo json_encode(['error' => 'Failed to move uploaded file']);
|
||||||
|
http_response_code(500);
|
||||||
|
}
|
||||||
0
upload_debug.log
Normal file
0
upload_debug.log
Normal file
124
user_blogs.php
Normal file
124
user_blogs.php
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
<?php include_once('header02.php');
|
||||||
|
|
||||||
|
checkUserSession();
|
||||||
|
|
||||||
|
$result = $conn->prepare("SELECT blog_id, title, description, status, date, image FROM blogs WHERE author = ? AND status != 'deleted' ORDER BY date DESC");
|
||||||
|
|
||||||
|
$result->bind_param("i", $user_id);
|
||||||
|
$result->execute();
|
||||||
|
$posts = $result->get_result();
|
||||||
|
?>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.image {
|
||||||
|
width: 400px;
|
||||||
|
/* Set your desired width */
|
||||||
|
height: 350px;
|
||||||
|
/* Set your desired height */
|
||||||
|
overflow: hidden;
|
||||||
|
/* Hide any overflow */
|
||||||
|
display: block;
|
||||||
|
/* Ensure proper block behavior */
|
||||||
|
}
|
||||||
|
|
||||||
|
.image img {
|
||||||
|
width: 100%;
|
||||||
|
/* Image scales to fill the container */
|
||||||
|
height: 100%;
|
||||||
|
/* Image scales to fill the container */
|
||||||
|
object-fit: cover;
|
||||||
|
/* Fills the container while maintaining aspect ratio */
|
||||||
|
object-position: top;
|
||||||
|
/* Aligns the top of the image with the top of the container */
|
||||||
|
display: block;
|
||||||
|
/* Prevents inline whitespace issues */
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$bannerFolder = 'assets/images/banners/';
|
||||||
|
$bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE);
|
||||||
|
|
||||||
|
$randomBanner = 'assets/images/base4/camping.jpg'; // default fallback
|
||||||
|
if (!empty($bannerImages)) {
|
||||||
|
$randomBanner = $bannerImages[array_rand($bannerImages)];
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<section class="page-banner-area pt-50 pb-35 rel z-1 bgs-cover" style="background-image: url('<?php echo $randomBanner; ?>');">
|
||||||
|
<!-- Overlay PNG -->
|
||||||
|
<div class="banner-overlay"></div>
|
||||||
|
<div class="container">
|
||||||
|
<div class="banner-inner text-white">
|
||||||
|
<h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">My Blogs</h2>
|
||||||
|
<nav aria-label="breadcrumb">
|
||||||
|
<ol class="breadcrumb justify-content-center mb-20" data-aos="fade-right" data-aos-delay="200" data-aos-duration="1500" data-aos-offset="50">
|
||||||
|
<li class="breadcrumb-item"><a href="index.php">Home</a></li>
|
||||||
|
<li class="breadcrumb-item active">My Blogs</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- Page Banner End -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Blog List Area start -->
|
||||||
|
<section class="blog-list-page py-100 rel z-1">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
|
||||||
|
<h2>My Posts</h2>
|
||||||
|
<?php if (isset($_SESSION['message'])): ?>
|
||||||
|
<div class="alert alert-warning message-box">
|
||||||
|
<?php echo $_SESSION['message']; ?>
|
||||||
|
<span class="close-btn" onclick="this.parentElement.style.display='none'">×</span>
|
||||||
|
</div>
|
||||||
|
<?php unset($_SESSION['message']); ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
<a href="blog_create.php">+ New Post</a>
|
||||||
|
|
||||||
|
<?php while ($post = $posts->fetch_assoc()):
|
||||||
|
// Output the HTML structure with dynamic data
|
||||||
|
echo '
|
||||||
|
<div class="destination-item style-three bgc-lighter booking" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
|
||||||
|
<div class="image" style="width:200px;height:200px;"><img src="' . $post["image"] . '" alt="' . $post["title"] . '"></div>
|
||||||
|
<div class="content" style="width:100%;">
|
||||||
|
|
||||||
|
<div class="destination-header">
|
||||||
|
<span class="badge bg-dark"> ' . strtoupper($post["status"]) . '</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h5>' . $post["title"] . '</a></h5>
|
||||||
|
<p>' . $post["description"] . '</p>
|
||||||
|
<div class="destination-footer">
|
||||||
|
<div class="btn-group" style="display:flex; justify-content:flex-end; gap:10px; margin-top:10px;">
|
||||||
|
<a href="blog_edit.php?token='.encryptData($post["blog_id"], $salt).'" class="btn btn-sm" data-bs-toggle="tooltip" data-bs-placement="top" title="Edit"><i class="bi bi-pencil"></i></a>
|
||||||
|
<a href="blog_read.php?token='.encryptData($post["blog_id"], $salt).'" class="btn btn-sm" data-bs-toggle="tooltip" data-bs-placement="top" title="Preview"><i class="bi bi-eye"></i></a>
|
||||||
|
<a href="blog_delete.php?token='.encryptData($post["blog_id"], $salt).'" class="btn btn-sm" data-bs-toggle="tooltip" data-bs-placement="top" title="Delete"><i class="bi bi-trash"></i></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>';
|
||||||
|
endwhile; ?>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- Blog List Area end -->
|
||||||
|
<script>
|
||||||
|
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
|
||||||
|
tooltipTriggerList.forEach(el => new bootstrap.Tooltip(el));
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<?php include_once("insta_footer.php"); ?>
|
||||||
Reference in New Issue
Block a user