Initial project scaffold for a PHP Media API including routing, controllers, models and services under api/ (Router, Media/Cast/Image/Settings controllers, models, database/bootstrap files and automatic docs service). Adds Docker support (Dockerfile, docker-compose.yml, DOCKER_README.md, php-custom.ini), .htaccess for pretty URLs, API documentation and example payloads (API_EXAMPLES.md, api/README.md, api_examples/*.json), image handling service and logging, plus a comprehensive .gitignore. This commit provides a runnable development environment and example requests to get the API up and tested quickly.
69 lines
2.2 KiB
PHP
69 lines
2.2 KiB
PHP
<?php
|
|
|
|
class ImageController {
|
|
private $imageDir;
|
|
|
|
public function __construct() {
|
|
$this->imageDir = __DIR__ . '/../public/images/';
|
|
}
|
|
|
|
public function handleRequest($method, $pathSegments) {
|
|
// Remove 'images' from path segments
|
|
array_shift($pathSegments);
|
|
|
|
// Build file path
|
|
$imagePath = implode('/', $pathSegments);
|
|
$fullPath = $this->imageDir . $imagePath;
|
|
|
|
// Security check: ensure the path is within the images directory
|
|
$realPath = realpath($fullPath);
|
|
$realImageDir = realpath($this->imageDir);
|
|
|
|
if ($realPath === false || strpos($realPath, $realImageDir) !== 0) {
|
|
http_response_code(403);
|
|
return ['success' => false, 'error' => 'Access denied'];
|
|
}
|
|
|
|
// Check if file exists
|
|
if (!file_exists($realPath)) {
|
|
http_response_code(404);
|
|
return ['success' => false, 'error' => 'Image not found'];
|
|
}
|
|
|
|
// Check if it's actually a file
|
|
if (!is_file($realPath)) {
|
|
http_response_code(404);
|
|
return ['success' => false, 'error' => 'Not a file'];
|
|
}
|
|
|
|
// Get file info
|
|
$fileInfo = finfo_open(FILEINFO_MIME_TYPE);
|
|
$mimeType = finfo_file($fileInfo, $realPath);
|
|
finfo_close($fileInfo);
|
|
|
|
if ($mimeType === false) {
|
|
// Fallback to common image types
|
|
$extension = strtolower(pathinfo($realPath, PATHINFO_EXTENSION));
|
|
$mimeTypes = [
|
|
'jpg' => 'image/jpeg',
|
|
'jpeg' => 'image/jpeg',
|
|
'png' => 'image/png',
|
|
'gif' => 'image/gif',
|
|
'webp' => 'image/webp',
|
|
'svg' => 'image/svg+xml'
|
|
];
|
|
$mimeType = $mimeTypes[$extension] ?? 'application/octet-stream';
|
|
}
|
|
|
|
// Set headers for image serving
|
|
header('Content-Type: ' . $mimeType);
|
|
header('Content-Length: ' . filesize($realPath));
|
|
header('Cache-Control: public, max-age=31536000'); // Cache for 1 year
|
|
header('Pragma: public');
|
|
|
|
// Output the image
|
|
readfile($realPath);
|
|
exit;
|
|
}
|
|
}
|