Initial commit: MSPE website - full site with admin panel, API, and public pages
This commit is contained in:
Executable
+264
@@ -0,0 +1,264 @@
|
||||
<?php
|
||||
/**
|
||||
* MSPE Portfolio API
|
||||
*/
|
||||
|
||||
require_once 'config.php';
|
||||
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
$id = $_GET['id'] ?? null;
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
if ($id) {
|
||||
getProject($id);
|
||||
} else {
|
||||
getProjects();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
requireAuth();
|
||||
if (!empty($_POST['id'])) {
|
||||
updateProject($_POST['id']);
|
||||
} else {
|
||||
createProject();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
requireAuth();
|
||||
if (!$id) {
|
||||
jsonResponse(['success' => false, 'message' => 'Project ID required'], 400);
|
||||
}
|
||||
updateProject($id);
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
requireAuth();
|
||||
if (!$id) {
|
||||
jsonResponse(['success' => false, 'message' => 'Project ID required'], 400);
|
||||
}
|
||||
deleteProject($id);
|
||||
break;
|
||||
|
||||
default:
|
||||
jsonResponse(['success' => false, 'message' => 'Method not allowed'], 405);
|
||||
}
|
||||
|
||||
function getProjects() {
|
||||
global $db;
|
||||
|
||||
$projects = $db->getAll('portfolio');
|
||||
|
||||
// Apply filters
|
||||
$category = $_GET['category'] ?? null;
|
||||
$featured = $_GET['featured'] ?? null;
|
||||
$limit = (int)($_GET['limit'] ?? 20);
|
||||
$offset = (int)($_GET['offset'] ?? 0);
|
||||
|
||||
if ($category) {
|
||||
$projects = array_filter($projects, function($p) use ($category) {
|
||||
return $p['category'] === $category;
|
||||
});
|
||||
}
|
||||
|
||||
if ($featured !== null) {
|
||||
$projects = array_filter($projects, function($p) use ($featured) {
|
||||
return ($p['featured'] ?? false) == ($featured === 'true' || $featured === '1');
|
||||
});
|
||||
}
|
||||
|
||||
// Public view: only published/active projects
|
||||
if (!checkAuth()) {
|
||||
$projects = array_filter($projects, function($p) {
|
||||
return ($p['status'] ?? 'published') === 'published';
|
||||
});
|
||||
}
|
||||
|
||||
// Sort by order or date
|
||||
usort($projects, function($a, $b) {
|
||||
$orderA = $a['order'] ?? 999;
|
||||
$orderB = $b['order'] ?? 999;
|
||||
if ($orderA !== $orderB) {
|
||||
return $orderA - $orderB;
|
||||
}
|
||||
return strtotime($b['created_at']) - strtotime($a['created_at']);
|
||||
});
|
||||
|
||||
$total = count($projects);
|
||||
$projects = array_slice(array_values($projects), $offset, $limit);
|
||||
|
||||
jsonResponse([
|
||||
'success' => true,
|
||||
'data' => $projects,
|
||||
'total' => $total,
|
||||
'limit' => $limit,
|
||||
'offset' => $offset
|
||||
]);
|
||||
}
|
||||
|
||||
function getProject($id) {
|
||||
global $db;
|
||||
|
||||
$project = $db->get('portfolio', $id);
|
||||
|
||||
if (!$project) {
|
||||
jsonResponse(['success' => false, 'message' => 'Project not found'], 404);
|
||||
}
|
||||
|
||||
jsonResponse([
|
||||
'success' => true,
|
||||
'data' => $project
|
||||
]);
|
||||
}
|
||||
|
||||
function createProject() {
|
||||
global $db;
|
||||
|
||||
// Handle multipart form data or JSON
|
||||
if (!empty($_FILES)) {
|
||||
$data = $_POST;
|
||||
} else {
|
||||
$data = getRequestBody();
|
||||
}
|
||||
|
||||
// Validate required fields
|
||||
if (empty($data['title'])) {
|
||||
jsonResponse(['success' => false, 'message' => 'Title is required'], 400);
|
||||
}
|
||||
|
||||
// Sanitize text fields (allow HTML in description)
|
||||
$data['title'] = sanitize($data['title']);
|
||||
$data['category'] = sanitize($data['category'] ?? '');
|
||||
$data['client'] = sanitize($data['client'] ?? '');
|
||||
$data['technologies'] = sanitize($data['technologies'] ?? '');
|
||||
// Sanitize description: allow only safe formatting tags
|
||||
$data['description'] = sanitizeRichText($data['description'] ?? '');
|
||||
|
||||
// Handle image upload
|
||||
if (!empty($_FILES['image'])) {
|
||||
$upload = handleFileUpload($_FILES['image'], 'portfolio');
|
||||
if ($upload['success']) {
|
||||
$data['image'] = $upload['path'];
|
||||
}
|
||||
}
|
||||
|
||||
// Parse results JSON (JS sends as a serialised string)
|
||||
$data['results'] = json_decode($data['results'] ?? '[]', true) ?? [];
|
||||
|
||||
// Gallery: merge existing-keep list + newly uploaded files
|
||||
$gallery = json_decode($_POST['gallery_keep'] ?? '[]', true) ?? [];
|
||||
if (!empty($_FILES['gallery_images']['tmp_name'])) {
|
||||
foreach ($_FILES['gallery_images']['tmp_name'] as $key => $tmpName) {
|
||||
if ($_FILES['gallery_images']['error'][$key] !== UPLOAD_ERR_OK) continue;
|
||||
$file = [
|
||||
'name' => $_FILES['gallery_images']['name'][$key],
|
||||
'type' => $_FILES['gallery_images']['type'][$key],
|
||||
'tmp_name' => $tmpName,
|
||||
'error' => $_FILES['gallery_images']['error'][$key],
|
||||
'size' => $_FILES['gallery_images']['size'][$key],
|
||||
];
|
||||
$upload = handleFileUpload($file, 'portfolio');
|
||||
if ($upload['success']) {
|
||||
$gallery[] = $upload['path'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$data['gallery'] = $gallery;
|
||||
|
||||
// Set defaults
|
||||
$data['featured'] = $data['featured'] ?? false;
|
||||
$data['order'] = (int)($data['order'] ?? 0);
|
||||
$data['status'] = $data['status'] ?? 'published';
|
||||
|
||||
$project = $db->insert('portfolio', $data);
|
||||
|
||||
jsonResponse([
|
||||
'success' => true,
|
||||
'message' => 'Project created successfully',
|
||||
'data' => $project
|
||||
], 201);
|
||||
}
|
||||
|
||||
function updateProject($id) {
|
||||
global $db;
|
||||
|
||||
$existing = $db->get('portfolio', $id);
|
||||
if (!$existing) {
|
||||
jsonResponse(['success' => false, 'message' => 'Project not found'], 404);
|
||||
}
|
||||
|
||||
// Handle multipart form data or JSON
|
||||
if (!empty($_FILES)) {
|
||||
$data = $_POST;
|
||||
} else {
|
||||
$data = getRequestBody();
|
||||
}
|
||||
|
||||
// Handle image upload
|
||||
if (!empty($_FILES['image'])) {
|
||||
$upload = handleFileUpload($_FILES['image'], 'portfolio');
|
||||
if ($upload['success']) {
|
||||
$data['image'] = $upload['path'];
|
||||
}
|
||||
}
|
||||
|
||||
// Sanitize editable text fields
|
||||
if (isset($data['title'])) $data['title'] = sanitize($data['title']);
|
||||
if (isset($data['category'])) $data['category'] = sanitize($data['category']);
|
||||
if (isset($data['client'])) $data['client'] = sanitize($data['client']);
|
||||
if (isset($data['technologies'])) $data['technologies'] = sanitize($data['technologies']);
|
||||
if (isset($data['description'])) $data['description'] = sanitizeRichText($data['description']);
|
||||
|
||||
// Parse results JSON
|
||||
if (isset($data['results'])) {
|
||||
$data['results'] = json_decode($data['results'], true) ?? $existing['results'] ?? [];
|
||||
}
|
||||
|
||||
// Gallery: merge existing-keep list + newly uploaded files
|
||||
if (array_key_exists('gallery_keep', $_POST)) {
|
||||
$gallery = json_decode($_POST['gallery_keep'], true) ?? [];
|
||||
if (!empty($_FILES['gallery_images']['tmp_name'])) {
|
||||
foreach ($_FILES['gallery_images']['tmp_name'] as $key => $tmpName) {
|
||||
if ($_FILES['gallery_images']['error'][$key] !== UPLOAD_ERR_OK) continue;
|
||||
$file = [
|
||||
'name' => $_FILES['gallery_images']['name'][$key],
|
||||
'type' => $_FILES['gallery_images']['type'][$key],
|
||||
'tmp_name' => $tmpName,
|
||||
'error' => $_FILES['gallery_images']['error'][$key],
|
||||
'size' => $_FILES['gallery_images']['size'][$key],
|
||||
];
|
||||
$upload = handleFileUpload($file, 'portfolio');
|
||||
if ($upload['success']) {
|
||||
$gallery[] = $upload['path'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$data['gallery'] = $gallery;
|
||||
}
|
||||
|
||||
$project = $db->update('portfolio', $id, $data);
|
||||
|
||||
jsonResponse([
|
||||
'success' => true,
|
||||
'message' => 'Project updated successfully',
|
||||
'data' => $project
|
||||
]);
|
||||
}
|
||||
|
||||
function deleteProject($id) {
|
||||
global $db;
|
||||
|
||||
$existing = $db->get('portfolio', $id);
|
||||
if (!$existing) {
|
||||
jsonResponse(['success' => false, 'message' => 'Project not found'], 404);
|
||||
}
|
||||
|
||||
$db->delete('portfolio', $id);
|
||||
|
||||
jsonResponse([
|
||||
'success' => true,
|
||||
'message' => 'Project deleted successfully'
|
||||
]);
|
||||
}
|
||||
Reference in New Issue
Block a user