Add PHP Media API scaffold and Docker configs
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.
This commit is contained in:
204
api/services/DocumentationService.php
Normal file
204
api/services/DocumentationService.php
Normal file
@@ -0,0 +1,204 @@
|
||||
<?php
|
||||
|
||||
class DocumentationService {
|
||||
private $controllersPath;
|
||||
private $modelsPath;
|
||||
|
||||
public function __construct($controllersPath = __DIR__ . '/../controllers/', $modelsPath = __DIR__ . '/../models/') {
|
||||
$this->controllersPath = $controllersPath;
|
||||
$this->modelsPath = $modelsPath;
|
||||
}
|
||||
|
||||
public function generateDocumentation() {
|
||||
$docs = [
|
||||
'title' => 'Media API Documentation',
|
||||
'version' => '1.0.0',
|
||||
'baseUrl' => '/api',
|
||||
'endpoints' => [],
|
||||
'models' => []
|
||||
];
|
||||
|
||||
// Controller scannen
|
||||
$docs['endpoints'] = $this->scanControllers();
|
||||
|
||||
// Modelle scannen
|
||||
$docs['models'] = $this->scanModels();
|
||||
|
||||
return $docs;
|
||||
}
|
||||
|
||||
private function scanControllers() {
|
||||
$endpoints = [];
|
||||
|
||||
$controllerFiles = glob($this->controllersPath . '*Controller.php');
|
||||
|
||||
foreach ($controllerFiles as $file) {
|
||||
$className = basename($file, '.php');
|
||||
require_once $file;
|
||||
|
||||
$reflection = new ReflectionClass($className);
|
||||
$methods = $reflection->getMethods(ReflectionMethod::IS_PUBLIC);
|
||||
|
||||
foreach ($methods as $method) {
|
||||
if ($method->getName() === '__construct') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$docComment = $method->getDocComment();
|
||||
$endpointInfo = $this->parseMethodDoc($docComment, $method->getName(), $className);
|
||||
|
||||
if ($endpointInfo) {
|
||||
$endpoints[] = $endpointInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $endpoints;
|
||||
}
|
||||
|
||||
private function parseMethodDoc($docComment, $methodName, $className) {
|
||||
if (!$docComment) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$info = [
|
||||
'controller' => $className,
|
||||
'method' => $methodName,
|
||||
'description' => '',
|
||||
'parameters' => [],
|
||||
'response' => [],
|
||||
'example' => null
|
||||
];
|
||||
|
||||
// Beschreibung extrahieren
|
||||
if (preg_match('/\*\s*(.+?)\n/', $docComment, $matches)) {
|
||||
$info['description'] = trim($matches[1]);
|
||||
}
|
||||
|
||||
// @param extrahieren
|
||||
if (preg_match_all('/@param\s+(\w+)\s+\$(\w+)\s+(.+)/', $docComment, $matches)) {
|
||||
foreach ($matches[1] as $i => $type) {
|
||||
$info['parameters'][] = [
|
||||
'name' => $matches[2][$i],
|
||||
'type' => $type,
|
||||
'description' => trim($matches[3][$i])
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// @return extrahieren
|
||||
if (preg_match('/@return\s+(\w+)\s+(.+)/', $docComment, $matches)) {
|
||||
$info['response'] = [
|
||||
'type' => $matches[1],
|
||||
'description' => trim($matches[2])
|
||||
];
|
||||
}
|
||||
|
||||
// @example extrahieren
|
||||
if (preg_match('/@example\s+(.+)/', $docComment, $matches)) {
|
||||
$info['example'] = trim($matches[1]);
|
||||
}
|
||||
|
||||
// HTTP-Methoden und Pfade aus Methodennamen ableiten
|
||||
$info['httpMethods'] = $this->inferHttpMethods($methodName);
|
||||
$info['path'] = $this->inferPath($className, $methodName);
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
private function inferHttpMethods($methodName) {
|
||||
$methods = [];
|
||||
|
||||
if (strpos($methodName, 'get') === 0) {
|
||||
$methods[] = 'GET';
|
||||
}
|
||||
if (strpos($methodName, 'create') !== false || strpos($methodName, 'add') !== false || strpos($methodName, 'post') !== false) {
|
||||
$methods[] = 'POST';
|
||||
}
|
||||
if (strpos($methodName, 'update') !== false) {
|
||||
$methods[] = 'PUT';
|
||||
}
|
||||
if (strpos($methodName, 'delete') !== false) {
|
||||
$methods[] = 'DELETE';
|
||||
}
|
||||
|
||||
if (empty($methods)) {
|
||||
$methods[] = 'GET'; // Default
|
||||
}
|
||||
|
||||
return $methods;
|
||||
}
|
||||
|
||||
private function inferPath($className, $methodName) {
|
||||
$resource = strtolower(str_replace('Controller', '', $className));
|
||||
$path = "/{$resource}";
|
||||
|
||||
if (strpos($methodName, 'getOne') !== false || strpos($methodName, 'update') !== false || strpos($methodName, 'delete') !== false) {
|
||||
$path .= '/:id';
|
||||
}
|
||||
|
||||
if (strpos($methodName, 'getMedia') !== false) {
|
||||
$path .= '/:id/media';
|
||||
}
|
||||
|
||||
if (strpos($methodName, 'handleEpisodes') !== false) {
|
||||
$path .= '/:id/episodes';
|
||||
}
|
||||
|
||||
if (strpos($methodName, 'handleTracks') !== false) {
|
||||
$path .= '/:id/tracks';
|
||||
}
|
||||
|
||||
if (strpos($methodName, 'handleAdult') !== false) {
|
||||
$path .= '/adult';
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
private function scanModels() {
|
||||
$models = [];
|
||||
|
||||
$modelFiles = glob($this->modelsPath . '*.php');
|
||||
|
||||
foreach ($modelFiles as $file) {
|
||||
$className = basename($file, '.php');
|
||||
if ($className === 'BaseModel' || $className === 'MediaType') {
|
||||
continue;
|
||||
}
|
||||
|
||||
require_once $file;
|
||||
|
||||
$reflection = new ReflectionClass($className);
|
||||
$docComment = $reflection->getDocComment();
|
||||
|
||||
$modelInfo = [
|
||||
'name' => $className,
|
||||
'description' => '',
|
||||
'fields' => []
|
||||
];
|
||||
|
||||
if ($docComment) {
|
||||
if (preg_match('/\*\s*(.+?)\n/', $docComment, $matches)) {
|
||||
$modelInfo['description'] = trim($matches[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Properties aus Klasse ableiten
|
||||
$properties = $reflection->getProperties();
|
||||
foreach ($properties as $property) {
|
||||
if ($property->isPublic() || $property->isProtected()) {
|
||||
$modelInfo['fields'][] = [
|
||||
'name' => $property->getName(),
|
||||
'type' => 'mixed',
|
||||
'description' => ''
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$models[] = $modelInfo;
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user