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:
388
api/database.php
Normal file
388
api/database.php
Normal file
@@ -0,0 +1,388 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
class Database {
|
||||
private $pdo;
|
||||
|
||||
public function __construct() {
|
||||
try {
|
||||
$dsn = 'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8mb4';
|
||||
$this->pdo = new PDO($dsn, DB_USER, DB_PASS);
|
||||
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||
$this->initializeTables();
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'error' => 'Database connection failed: ' . $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
private function initializeTables() {
|
||||
// Media-Tabelle
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS media (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
title TEXT NOT NULL,
|
||||
cleanname TEXT,
|
||||
year TEXT,
|
||||
poster TEXT,
|
||||
banner TEXT,
|
||||
description TEXT,
|
||||
rating FLOAT,
|
||||
category TEXT,
|
||||
type TEXT,
|
||||
status TEXT,
|
||||
aspectRatio TEXT,
|
||||
runtime INT,
|
||||
director TEXT,
|
||||
writer TEXT,
|
||||
releaseDate TEXT,
|
||||
createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
)
|
||||
");
|
||||
|
||||
// cleanname Feld zu bestehender Tabelle hinzufügen, falls nicht vorhanden
|
||||
try {
|
||||
$this->pdo->exec("ALTER TABLE media ADD COLUMN cleanname TEXT");
|
||||
} catch (Exception $e) {
|
||||
// Feld existiert bereits
|
||||
}
|
||||
|
||||
// Index für cleanname erstellen
|
||||
try {
|
||||
$this->pdo->exec("CREATE INDEX idx_media_cleanname ON media(cleanname)");
|
||||
} catch (Exception $e) {
|
||||
// Index existiert bereits
|
||||
}
|
||||
|
||||
// Genres-Tabelle
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS genres (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
media_id INT,
|
||||
genre TEXT,
|
||||
FOREIGN KEY (media_id) REFERENCES media(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// Tags-Tabelle
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS tags (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
media_id INT,
|
||||
tag TEXT,
|
||||
FOREIGN KEY (media_id) REFERENCES media(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// Studios-Tabelle
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS studios (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
media_id INT,
|
||||
studio TEXT,
|
||||
FOREIGN KEY (media_id) REFERENCES media(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// Cast/Staff-Tabelle (Stammdaten - ohne media_id)
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS cast_staff (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
cleanname TEXT,
|
||||
photo TEXT,
|
||||
bio TEXT,
|
||||
birthDate TEXT,
|
||||
birthPlace TEXT,
|
||||
createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
)
|
||||
");
|
||||
|
||||
// cleanname Feld zu bestehender Tabelle hinzufügen, falls nicht vorhanden
|
||||
try {
|
||||
$this->pdo->exec("ALTER TABLE cast_staff ADD COLUMN cleanname TEXT");
|
||||
} catch (Exception $e) {
|
||||
// Feld existiert bereits
|
||||
}
|
||||
|
||||
// Index für cleanname erstellen
|
||||
try {
|
||||
$this->pdo->exec("CREATE INDEX idx_cast_staff_cleanname ON cast_staff(cleanname)");
|
||||
} catch (Exception $e) {
|
||||
// Index existiert bereits
|
||||
}
|
||||
|
||||
// n:m Beziehung zwischen Media und Cast
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS media_cast (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
media_id INT,
|
||||
cast_id INT,
|
||||
role TEXT,
|
||||
characterName TEXT,
|
||||
characterImage TEXT,
|
||||
FOREIGN KEY (media_id) REFERENCES media(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (cast_id) REFERENCES cast_staff(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// Occupations-Tabelle
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS occupations (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
cast_id INT,
|
||||
occupation TEXT,
|
||||
FOREIGN KEY (cast_id) REFERENCES cast_staff(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// Episodes-Tabelle (für Series)
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS episodes (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
media_id INT,
|
||||
season INT,
|
||||
episode_number INT,
|
||||
title TEXT,
|
||||
description TEXT,
|
||||
air_date TEXT,
|
||||
duration INT,
|
||||
thumbnail TEXT,
|
||||
FOREIGN KEY (media_id) REFERENCES media(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// Tracks-Tabelle (für Music/Albums)
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS tracks (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
media_id INT,
|
||||
track_number INT,
|
||||
title TEXT,
|
||||
duration INT,
|
||||
artist TEXT,
|
||||
FOREIGN KEY (media_id) REFERENCES media(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// Adult-spezifische Cast-Infos
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS adult_cast_specifics (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
cast_id INT UNIQUE,
|
||||
bust_size TEXT,
|
||||
cup_size TEXT,
|
||||
waist_size TEXT,
|
||||
hip_size TEXT,
|
||||
height INT,
|
||||
weight INT,
|
||||
hair_color TEXT,
|
||||
eye_color TEXT,
|
||||
ethnicity TEXT,
|
||||
tattoos TEXT,
|
||||
piercings TEXT,
|
||||
measurements TEXT,
|
||||
shoe_size TEXT,
|
||||
FOREIGN KEY (cast_id) REFERENCES cast_staff(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// Media-Games Tabelle (1:1 Relation zu media für spiel-spezifische Daten)
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS media_games (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
media_id INT UNIQUE,
|
||||
sortingName TEXT,
|
||||
notes TEXT,
|
||||
completionStatus TEXT,
|
||||
source TEXT,
|
||||
gameId TEXT,
|
||||
pluginId TEXT,
|
||||
isInstalled BOOLEAN DEFAULT 0,
|
||||
installDirectory TEXT,
|
||||
installSize BIGINT DEFAULT 0,
|
||||
hidden BOOLEAN DEFAULT 0,
|
||||
favorite BOOLEAN DEFAULT 0,
|
||||
playCount INT DEFAULT 0,
|
||||
lastActivity TIMESTAMP NULL,
|
||||
added TIMESTAMP NULL,
|
||||
modified TIMESTAMP NULL,
|
||||
communityScore INT DEFAULT 0,
|
||||
criticScore INT DEFAULT 0,
|
||||
userScore INT DEFAULT 0,
|
||||
hasIcon BOOLEAN DEFAULT 0,
|
||||
hasCover BOOLEAN DEFAULT 0,
|
||||
hasBackground BOOLEAN DEFAULT 0,
|
||||
version TEXT,
|
||||
playtime INT DEFAULT 0,
|
||||
FOREIGN KEY (media_id) REFERENCES media(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// Achievements-Tabelle (für Games - referenziert media_games)
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS achievements (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
media_game_id INT,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
icon TEXT,
|
||||
unlocked BOOLEAN DEFAULT 0,
|
||||
unlocked_date TIMESTAMP NULL,
|
||||
FOREIGN KEY (media_game_id) REFERENCES media_games(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// Game Categories-Tabelle
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS game_categories (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
media_game_id INT,
|
||||
category TEXT,
|
||||
FOREIGN KEY (media_game_id) REFERENCES media_games(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// Game Features-Tabelle
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS game_features (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
media_game_id INT,
|
||||
feature TEXT,
|
||||
FOREIGN KEY (media_game_id) REFERENCES media_games(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// Game Platforms-Tabelle
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS game_platforms (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
media_game_id INT,
|
||||
platform TEXT,
|
||||
FOREIGN KEY (media_game_id) REFERENCES media_games(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// Game Developers-Tabelle
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS game_developers (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
media_game_id INT,
|
||||
developer TEXT,
|
||||
FOREIGN KEY (media_game_id) REFERENCES media_games(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// Game Publishers-Tabelle
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS game_publishers (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
media_game_id INT,
|
||||
publisher TEXT,
|
||||
FOREIGN KEY (media_game_id) REFERENCES media_games(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// Game Series-Tabelle
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS game_series (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
media_game_id INT,
|
||||
series TEXT,
|
||||
FOREIGN KEY (media_game_id) REFERENCES media_games(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// Game Age Ratings-Tabelle
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS game_age_ratings (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
media_game_id INT,
|
||||
age_rating TEXT,
|
||||
FOREIGN KEY (media_game_id) REFERENCES media_games(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// Game Regions-Tabelle
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS game_regions (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
media_game_id INT,
|
||||
region TEXT,
|
||||
FOREIGN KEY (media_game_id) REFERENCES media_games(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// Game Links-Tabelle (mit name und url)
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS game_links (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
media_game_id INT,
|
||||
name TEXT,
|
||||
url TEXT,
|
||||
FOREIGN KEY (media_game_id) REFERENCES media_games(id) ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
|
||||
// API Logs-Tabelle
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS api_logs (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
type TEXT NOT NULL,
|
||||
method TEXT,
|
||||
path TEXT,
|
||||
params JSON,
|
||||
body JSON,
|
||||
status_code INT,
|
||||
response JSON,
|
||||
error TEXT,
|
||||
INDEX idx_timestamp (timestamp),
|
||||
INDEX idx_type (type)
|
||||
)
|
||||
");
|
||||
|
||||
// Settings-Tabelle
|
||||
$this->pdo->exec("
|
||||
CREATE TABLE IF NOT EXISTS settings (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
enabled_categories JSON,
|
||||
items_per_page INT DEFAULT 20,
|
||||
default_view TEXT DEFAULT 'grid',
|
||||
show_adult_content BOOLEAN DEFAULT 0,
|
||||
auto_play_trailers BOOLEAN DEFAULT 0,
|
||||
language TEXT DEFAULT 'en',
|
||||
theme TEXT DEFAULT 'system',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
)
|
||||
");
|
||||
|
||||
// Bestehende Einträge mit cleanname aktualisieren
|
||||
$this->updateExistingCleanNames();
|
||||
}
|
||||
|
||||
private function updateExistingCleanNames() {
|
||||
// Media cleanname aktualisieren
|
||||
$this->pdo->exec("
|
||||
UPDATE media
|
||||
SET cleanname = LOWER(REPLACE(REPLACE(REPLACE(REPLACE(title, ' ', '-'), '.', '-'), ',', '-'), '--', '-'))
|
||||
WHERE cleanname IS NULL OR cleanname = ''
|
||||
");
|
||||
|
||||
// Cast cleanname aktualisieren
|
||||
$this->pdo->exec("
|
||||
UPDATE cast_staff
|
||||
SET cleanname = LOWER(REPLACE(REPLACE(REPLACE(REPLACE(name, ' ', '-'), '.', '-'), ',', '-'), '--', '-'))
|
||||
WHERE cleanname IS NULL OR cleanname = ''
|
||||
");
|
||||
}
|
||||
|
||||
public function getConnection() {
|
||||
return $this->pdo;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user