265 lines
7.9 KiB
PHP
Executable File
265 lines
7.9 KiB
PHP
Executable File
<?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'
|
|
]);
|
|
}
|