🤩 File Manager - Mr.X
PHP:
8.3.33
Server:
Apache
OS:
Linux 5.14.0-611.49.1.el9_7.x86_64
User:
websparkit
Navigate
Upload:
Upload
New File
New Folder
Editing:projects.php
<?php /** * ARCHI-TECH Admin Projects CRUD Manager */ require_once __DIR__ . '/../includes/db.php'; require_once __DIR__ . '/../includes/functions.php'; check_admin_auth(); $action = isset($_GET['action']) ? $_GET['action'] : 'list'; $id = isset($_GET['id']) ? intval($_GET['id']) : 0; $success_msg = ''; $error_msg = ''; // Helper function to handle safe file uploads function handle_project_upload($file) { if (!isset($file) || $file['error'] !== UPLOAD_ERR_OK) { return null; } $allowed_types = ['image/jpeg', 'image/png', 'image/webp', 'image/jpg']; if (!in_array($file['type'], $allowed_types)) { return null; } $ext = pathinfo($file['name'], PATHINFO_EXTENSION); $new_name = 'proj_' . bin2hex(random_bytes(8)) . '.' . $ext; $destination = PROJECT_UPLOAD_DIR . $new_name; if (move_uploaded_file($file['tmp_name'], $destination)) { return 'uploads/projects/' . $new_name; } return null; } // Success Notice Handling if (isset($_GET['success'])) { if ($_GET['success'] === 'added') $success_msg = "Project entry and layouts successfully loaded."; if ($_GET['success'] === 'updated') $success_msg = "Project details successfully updated."; if ($_GET['success'] === 'deleted') $success_msg = "Project entry successfully removed."; } // Delete Project if (isset($_GET['delete'])) { $delete_id = intval($_GET['delete']); try { // Fetch files to delete from system $stmt_files = $pdo->prepare("SELECT before_image, after_image FROM projects WHERE id = :id"); $stmt_files->execute(['id' => $delete_id]); $files = $stmt_files->fetch(); if ($files) { if (!empty($files['before_image']) && file_exists(__DIR__ . '/../' . $files['before_image'])) { @unlink(__DIR__ . '/../' . $files['before_image']); } if (!empty($files['after_image']) && file_exists(__DIR__ . '/../' . $files['after_image'])) { @unlink(__DIR__ . '/../' . $files['after_image']); } } // Fetch and delete sub-gallery images $stmt_sub = $pdo->prepare("SELECT image_path FROM project_images WHERE project_id = :project_id"); $stmt_sub->execute(['project_id' => $delete_id]); $sub_images = $stmt_sub->fetchAll(); foreach ($sub_images as $simg) { if (file_exists(__DIR__ . '/../' . $simg['image_path'])) { @unlink(__DIR__ . '/../' . $simg['image_path']); } } // Delete records $stmt = $pdo->prepare("DELETE FROM projects WHERE id = :id"); $stmt->execute(['id' => $delete_id]); header("Location: " . BASE_URL . "admin/projects.php?success=deleted"); exit(); } catch (PDOException $e) { $error_msg = "Failed to delete project: " . $e->getMessage(); } } // Handle Add/Edit Submissions if (isset($_POST['submit_project'])) { $name = trim($_POST['name']); $category = trim($_POST['category']); $location = trim($_POST['location']); $completion_date = trim($_POST['completion_date']); $description = trim($_POST['description']); $is_featured = isset($_POST['is_featured']) ? 1 : 0; // Fallback date to null if empty if (empty($completion_date)) $completion_date = null; if (empty($name) || empty($category) || empty($description)) { $error_msg = "Please fill in all required inputs (Name, Category, Description)."; } else { try { if ($action === 'add') { $before_path = handle_project_upload($_FILES['before_image']); $after_path = handle_project_upload($_FILES['after_image']); $stmt = $pdo->prepare("INSERT INTO projects (name, description, category, location, completion_date, before_image, after_image, is_featured) VALUES (:name, :description, :category, :location, :completion_date, :before_image, :after_image, :is_featured)"); $stmt->execute([ 'name' => $name, 'description' => $description, 'category' => $category, 'location' => $location, 'completion_date' => $completion_date, 'before_image' => $before_path, 'after_image' => $after_path, 'is_featured' => $is_featured ]); $project_id = $pdo->lastInsertId(); // Handle sub-gallery multiple image uploads if (!empty($_FILES['sub_gallery']['name'][0])) { $files_count = count($_FILES['sub_gallery']['name']); for ($i = 0; $i < $files_count; $i++) { $single_file = [ 'name' => $_FILES['sub_gallery']['name'][$i], 'type' => $_FILES['sub_gallery']['type'][$i], 'tmp_name' => $_FILES['sub_gallery']['tmp_name'][$i], 'error' => $_FILES['sub_gallery']['error'][$i], 'size' => $_FILES['sub_gallery']['size'][$i] ]; $path = handle_project_upload($single_file); if ($path) { $stmt_sub = $pdo->prepare("INSERT INTO project_images (project_id, image_path) VALUES (:project_id, :image_path)"); $stmt_sub->execute(['project_id' => $project_id, 'image_path' => $path]); } } } header("Location: " . BASE_URL . "admin/projects.php?success=added"); exit(); } elseif ($action === 'edit') { // Keep original paths unless replaced $stmt_orig = $pdo->prepare("SELECT before_image, after_image FROM projects WHERE id = :id"); $stmt_orig->execute(['id' => $id]); $orig = $stmt_orig->fetch(); $before_path = $orig['before_image']; $after_path = $orig['after_image']; $new_before = handle_project_upload($_FILES['before_image']); $new_after = handle_project_upload($_FILES['after_image']); if ($new_before) { if (!empty($before_path) && file_exists(__DIR__ . '/../' . $before_path)) { @unlink(__DIR__ . '/../' . $before_path); } $before_path = $new_before; } if ($new_after) { if (!empty($after_path) && file_exists(__DIR__ . '/../' . $after_path)) { @unlink(__DIR__ . '/../' . $after_path); } $after_path = $new_after; } $stmt = $pdo->prepare("UPDATE projects SET name = :name, description = :description, category = :category, location = :location, completion_date = :completion_date, before_image = :before_image, after_image = :after_image, is_featured = :is_featured WHERE id = :id"); $stmt->execute([ 'name' => $name, 'description' => $description, 'category' => $category, 'location' => $location, 'completion_date' => $completion_date, 'before_image' => $before_path, 'after_image' => $after_path, 'is_featured' => $is_featured, 'id' => $id ]); // Add more sub-gallery images if uploaded if (!empty($_FILES['sub_gallery']['name'][0])) { $files_count = count($_FILES['sub_gallery']['name']); for ($i = 0; $i < $files_count; $i++) { $single_file = [ 'name' => $_FILES['sub_gallery']['name'][$i], 'type' => $_FILES['sub_gallery']['type'][$i], 'tmp_name' => $_FILES['sub_gallery']['tmp_name'][$i], 'error' => $_FILES['sub_gallery']['error'][$i], 'size' => $_FILES['sub_gallery']['size'][$i] ]; $path = handle_project_upload($single_file); if ($path) { $stmt_sub = $pdo->prepare("INSERT INTO project_images (project_id, image_path) VALUES (:project_id, :image_path)"); $stmt_sub->execute(['project_id' => $id, 'image_path' => $path]); } } } header("Location: " . BASE_URL . "admin/projects.php?success=updated"); exit(); } } catch (PDOException $e) { $error_msg = "Error updating project database: " . $e->getMessage(); } } } // Edit Mode details loader $edit_data = ['name' => '', 'category' => '', 'location' => '', 'completion_date' => '', 'description' => '', 'before_image' => '', 'after_image' => '', 'is_featured' => 0]; $project_sub_images = []; if ($action === 'edit' && $id > 0) { try { $stmt = $pdo->prepare("SELECT * FROM projects WHERE id = :id"); $stmt->execute(['id' => $id]); $edit_data = $stmt->fetch(); if (!$edit_data) { header("Location: " . BASE_URL . "admin/projects.php"); exit(); } $img_stmt = $pdo->prepare("SELECT * FROM project_images WHERE project_id = :project_id ORDER BY id ASC"); $img_stmt->execute(['project_id' => $id]); $project_sub_images = $img_stmt->fetchAll(); } catch (PDOException $e) { $error_msg = "Error loading database entries: " . $e->getMessage(); } } // Remove single sub-gallery image action if (isset($_GET['delete_sub']) && $id > 0) { $sub_id = intval($_GET['delete_sub']); try { $stmt_sub = $pdo->prepare("SELECT image_path FROM project_images WHERE id = :id AND project_id = :project_id"); $stmt_sub->execute(['id' => $sub_id, 'project_id' => $id]); $sub = $stmt_sub->fetch(); if ($sub) { if (file_exists(__DIR__ . '/../' . $sub['image_path'])) { @unlink(__DIR__ . '/../' . $sub['image_path']); } $stmt_del = $pdo->prepare("DELETE FROM project_images WHERE id = :id"); $stmt_del->execute(['id' => $sub_id]); } header("Location: " . BASE_URL . "admin/projects.php?action=edit&id=" . $id); exit(); } catch (PDOException $e) { $error_msg = "Failed to delete sub-gallery image: " . $e->getMessage(); } } // Load all projects $all_projects = []; try { $stmt = $pdo->query("SELECT * FROM projects ORDER BY id DESC"); $all_projects = $stmt->fetchAll(); } catch (PDOException $e) { // offline } require_once __DIR__ . '/header.php'; require_once __DIR__ . '/navbar.php'; ?> <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-4 border-bottom border-secondary"> <h1 class="h2 text-white text-uppercase" style="letter-spacing: -0.01em; font-family: 'Syne', sans-serif;">Manage Projects</h1> <div class="btn-toolbar mb-2 mb-md-0"> <?php if ($action === 'list'): ?> <a href="<?= BASE_URL ?>admin/projects.php?action=add" class="btn btn-gold btn-sm py-2 px-3"><i class="bi bi-plus-circle me-2"></i>Create New Project</a> <?php else: ?> <a href="<?= BASE_URL ?>admin/projects.php" class="btn btn-outline-light btn-sm py-2 px-3"><i class="bi bi-arrow-left me-2"></i>Back to List</a> <?php endif; ?> </div> </div> <!-- Notice Alerts --> <?php if (!empty($success_msg)): ?> <div class="alert alert-success border-0 bg-success text-white mb-4"> <i class="bi bi-check-circle-fill me-2"></i><?= sanitize_input($success_msg) ?> </div> <?php endif; ?> <?php if (!empty($error_msg)): ?> <div class="alert alert-danger border-0 bg-danger text-white mb-4"> <i class="bi bi-exclamation-triangle-fill me-2"></i><?= sanitize_input($error_msg) ?> </div> <?php endif; ?> <?php if ($action === 'list'): ?> <!-- LIST ALL PROJECTS TABLE --> <div class="glass-card p-4"> <div class="table-responsive"> <table class="table table-dark table-striped table-hover align-middle border-secondary table-dark-custom"> <thead> <tr> <th scope="col" style="width: 10%; text-align: center;">Thumbnail</th> <th scope="col" style="width: 25%;">Project Name</th> <th scope="col" style="width: 20%;">Category</th> <th scope="col" style="width: 20%;">Location</th> <th scope="col" style="width: 10%; text-align: center;">Featured</th> <th scope="col" style="width: 15%; text-align: center;">Actions</th> </tr> </thead> <tbody> <?php if (!empty($all_projects)): ?> <?php foreach ($all_projects as $p): ?> <tr> <td align="center"> <img src="<?= BASE_URL . (!empty($p['after_image']) ? sanitize_input($p['after_image']) : 'assets/images/gallery-1.jpg') ?>" class="rounded border border-secondary" style="width: 60px; height: 45px; object-fit: cover;" alt="Project preview"> </td> <td> <strong><?= sanitize_input($p['name']) ?></strong> <small class="d-block text-muted"><?= format_project_date($p['completion_date']) ?></small> </td> <td><span class="badge" style="background-color: var(--light-accent-color); color: var(--accent-color);"><?= sanitize_input($p['category']) ?></span></td> <td><?= sanitize_input($p['location']) ?></td> <td align="center"> <?php if (intval($p['is_featured']) === 1): ?> <span class="text-accent-color fs-5"><i class="bi bi-star-fill" title="Featured Project"></i></span> <?php else: ?> <span class="text-muted"><i class="bi bi-star"></i></span> <?php endif; ?> </td> <td align="center"> <a href="<?= BASE_URL ?>admin/projects.php?action=edit&id=<?= $p['id'] ?>" class="btn btn-outline-light btn-sm me-2" title="Edit"><i class="bi bi-pencil"></i></a> <a href="<?= BASE_URL ?>admin/projects.php?delete=<?= $p['id'] ?>" class="btn btn-outline-danger btn-sm" title="Delete" onclick="return confirm('Are you sure you want to delete this project? All sub-gallery images will be deleted from filesystem.')"><i class="bi bi-trash"></i></a> </td> </tr> <?php endforeach; ?> <?php else: ?> <tr> <td colspan="6" class="text-center text-muted py-4">No projects registered. Admin can upload PDFs or create manual entries.</td> </tr> <?php endif; ?> </tbody> </table> </div> </div> <?php elseif ($action === 'add' || $action === 'edit'): ?> <!-- ADD / EDIT PROJECT FORM --> <div class="row"> <div class="col-lg-8"> <div class="glass-card mb-4"> <h3 class="h5 text-white text-uppercase mb-4" style="letter-spacing: 0.05em;"> <?= ($action === 'add') ? '<i class="bi bi-plus-circle text-accent-color me-2"></i>Create Project' : '<i class="bi bi-pencil-square text-accent-color me-2"></i>Edit Project Properties' ?> </h3> <form action="<?= BASE_URL ?>admin/projects.php?action=<?= $action ?><?= ($action === 'edit') ? '&id=' . $id : '' ?>" method="POST" enctype="multipart/form-data"> <div class="mb-3"> <label for="name" class="form-label text-uppercase small text-muted fw-bold">Project Name <span class="text-accent-color">*</span></label> <input type="text" class="form-control form-dark-control" id="name" name="name" required value="<?= sanitize_input($edit_data['name']) ?>" placeholder="eg: The Grand Horizon Villa"> </div> <div class="row"> <div class="col-md-6 mb-3"> <label for="category" class="form-label text-uppercase small text-muted fw-bold">Project Category <span class="text-accent-color">*</span></label> <select class="form-select form-dark-control" id="category" name="category" required> <option value="">-- Select Category --</option> <option value="Architecture & Planning" <?= ($edit_data['category'] === 'Architecture & Planning') ? 'selected' : '' ?>>Architecture & Planning</option> <option value="Landscape Design" <?= ($edit_data['category'] === 'Landscape Design') ? 'selected' : '' ?>>Landscape Design</option> <option value="Interior Design" <?= ($edit_data['category'] === 'Interior Design') ? 'selected' : '' ?>>Interior Design</option> <option value="Construction Services" <?= ($edit_data['category'] === 'Construction Services') ? 'selected' : '' ?>>Construction Services</option> <option value="CAD & 3D Visualization" <?= ($edit_data['category'] === 'CAD & 3D Visualization') ? 'selected' : '' ?>>CAD & 3D Visualization</option> </select> </div> <div class="col-md-6 mb-3"> <label for="location" class="form-label text-uppercase small text-muted fw-bold">Project Location</label> <input type="text" class="form-control form-dark-control" id="location" name="location" value="<?= sanitize_input($edit_data['location']) ?>" placeholder="eg: Colombo, Sri Lanka"> </div> </div> <div class="row"> <div class="col-md-6 mb-3"> <label for="completion_date" class="form-label text-uppercase small text-muted fw-bold">Completion Date</label> <input type="date" class="form-control form-dark-control" id="completion_date" name="completion_date" value="<?= sanitize_input($edit_data['completion_date']) ?>"> </div> <div class="col-md-6 mb-3 d-flex align-items-center mt-4 pt-2"> <div class="form-check form-switch"> <input class="form-check-input" type="checkbox" id="is_featured" name="is_featured" value="1" <?= (intval($edit_data['is_featured']) === 1) ? 'checked' : '' ?>> <label class="form-check-label text-white small text-uppercase fw-bold ms-2" for="is_featured">Highlight as Featured Project</label> </div> </div> </div> <!-- Images Uploads --> <div class="row mt-4"> <div class="col-md-6 mb-3"> <label for="before_image" class="form-label text-uppercase small text-muted fw-bold">Before Design Image (Optional)</label> <input type="file" class="form-control form-dark-control" id="before_image" name="before_image"> <?php if (!empty($edit_data['before_image'])): ?> <small class="text-accent-color d-block mt-2">Active: <?= basename($edit_data['before_image']) ?></small> <?php endif; ?> </div> <div class="col-md-6 mb-3"> <label for="after_image" class="form-label text-uppercase small text-muted fw-bold">Completed (After) Image <?= ($action === 'add') ? '<span class="text-accent-color">*</span>' : '' ?></label> <input type="file" class="form-control form-dark-control" id="after_image" name="after_image" <?= ($action === 'add') ? 'required' : '' ?>> <?php if (!empty($edit_data['after_image'])): ?> <small class="text-accent-color d-block mt-2">Active: <?= basename($edit_data['after_image']) ?></small> <?php endif; ?> </div> </div> <div class="mb-4"> <label for="sub_gallery" class="form-label text-uppercase small text-muted fw-bold">Upload Sub-Gallery Images (Multiple)</label> <input type="file" class="form-control form-dark-control" id="sub_gallery" name="sub_gallery[]" multiple> <small class="text-muted">Hold CTRL/CMD to select multiple images to populate the project's lightbox sub-gallery.</small> </div> <div class="mb-4"> <label for="description" class="form-label text-uppercase small text-muted fw-bold">Detailed Project Summary</label> <textarea class="form-control form-dark-control" id="description" name="description" rows="8" required placeholder="Outline specifications, material choices, architectural challenges, and solutions..."><?= sanitize_input($edit_data['description']) ?></textarea> </div> <div class="text-end pt-3"> <a href="<?= BASE_URL ?>admin/projects.php" class="btn btn-outline-light me-2">Cancel</a> <button type="submit" name="submit_project" class="btn-gold-filled px-4">Save Project</button> </div> </form> </div> </div> <!-- Right Column: Sub-Gallery list (Only for Edit) --> <div class="col-lg-4"> <?php if ($action === 'edit'): ?> <div class="glass-card"> <h4 class="text-white text-uppercase mb-4" style="font-size: 1.1rem; letter-spacing: 0.05em;"><i class="bi bi-images text-accent-color me-2"></i>Active Sub-Gallery</h4> <?php if (!empty($project_sub_images)): ?> <div class="row g-2"> <?php foreach ($project_sub_images as $simg): ?> <div class="col-6 position-relative mb-2"> <img src="<?= BASE_URL . sanitize_input($simg['image_path']) ?>" class="img-fluid rounded border border-secondary" style="height: 100px; width: 100%; object-fit: cover;" alt="Sub photo"> <a href="<?= BASE_URL ?>admin/projects.php?action=edit&id=<?= $id ?>&delete_sub=<?= $simg['id'] ?>" class="btn btn-danger btn-sm position-absolute top-0 end-0 m-1 p-0 d-flex align-items-center justify-content-center" style="width: 24px; height: 24px; border-radius: 4px;" onclick="return confirm('Delete this image from sub-gallery?')" title="Delete Photo"> <i class="bi bi-x"></i> </a> </div> <?php endforeach; ?> </div> <?php else: ?> <p class="text-muted small">No secondary images loaded for this project. Upload them using the form.</p> <?php endif; ?> </div> <?php else: ?> <div class="glass-card"> <h5 class="text-accent-color text-uppercase mb-3"><i class="bi bi-info-circle me-2"></i>Interactive Sliders</h5> <p class="small text-white-50 mb-0">To enable before/after slider effects in the front pages, please upload both a **Before Design Image** and a **Completed (After) Image**. If the Before image is omitted, only the Completed image will show on detail views.</p> </div> <?php endif; ?> </div> </div> <?php endif; ?> <?php require_once __DIR__ . '/footer.php'; ?>
Save Changes
Cancel
Create New File
Create New Folder