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.
296 lines
13 KiB
PHP
296 lines
13 KiB
PHP
<?php
|
|
|
|
require_once __DIR__ . '/Cast.php';
|
|
require_once __DIR__ . '/../services/ApiLogger.php';
|
|
|
|
class AdultCast extends Cast {
|
|
|
|
public function getWithAdultSpecifics($id) {
|
|
$cast = $this->getWithFilmography($id);
|
|
if (!$cast) {
|
|
return null;
|
|
}
|
|
|
|
$cast['adult_specifics'] = $this->getAdultSpecifics($id);
|
|
|
|
return $cast;
|
|
}
|
|
|
|
public function getAdultSpecifics($castId) {
|
|
$stmt = $this->pdo->prepare("SELECT * FROM adult_cast_specifics WHERE cast_id = ?");
|
|
$stmt->execute([$castId]);
|
|
return $stmt->fetch();
|
|
}
|
|
|
|
public function createWithAdultSpecifics($data) {
|
|
ApiLogger::getInstance()->logDebug("AdultCast createWithAdultSpecifics called with data: " . json_encode($data));
|
|
|
|
$name = $data['name'] ?? null;
|
|
if (!$name) {
|
|
throw new Exception('Name is required');
|
|
}
|
|
|
|
// cleanname generieren
|
|
$cleanname = generateCleanName($name);
|
|
|
|
// Process photo field (base64 to file path)
|
|
$data = $this->processPhotoField($data);
|
|
|
|
// Zuerst Basis-Cast erstellen
|
|
$castData = [
|
|
'name' => $name,
|
|
'cleanname' => $cleanname,
|
|
'photo' => $data['photo'] ?? null,
|
|
'bio' => $data['bio'] ?? null,
|
|
'birthDate' => $data['birthDate'] ?? null,
|
|
'birthPlace' => $data['birthPlace'] ?? null
|
|
];
|
|
|
|
$castId = $this->create($castData);
|
|
ApiLogger::getInstance()->logDebug("AdultCast createWithAdultSpecifics: Base cast created with id: $castId");
|
|
|
|
// Occupations speichern
|
|
if (isset($data['occupations']) && is_array($data['occupations'])) {
|
|
ApiLogger::getInstance()->logDebug("AdultCast createWithAdultSpecifics: Saving occupations: " . json_encode($data['occupations']));
|
|
$this->saveRelatedItems('occupations', $castId, $data['occupations'], 'cast_id');
|
|
}
|
|
|
|
// Adult-spezifische Daten speichern
|
|
if (isset($data['adult_specifics']) && is_array($data['adult_specifics'])) {
|
|
ApiLogger::getInstance()->logDebug("AdultCast createWithAdultSpecifics: Saving adult_specifics");
|
|
$this->saveAdultSpecifics($castId, $data['adult_specifics']);
|
|
} else {
|
|
ApiLogger::getInstance()->logDebug("AdultCast createWithAdultSpecifics: No adult_specifics found in data");
|
|
}
|
|
|
|
return $castId;
|
|
}
|
|
|
|
public function updateWithAdultSpecifics($id, $data) {
|
|
ApiLogger::getInstance()->logDebug("AdultCast updateWithAdultSpecifics called with id: $id, data: " . json_encode($data));
|
|
|
|
// Set update flag for image replacement
|
|
$this->isUpdate = true;
|
|
$this->castId = $id;
|
|
|
|
// Process photo field (base64 to file path)
|
|
$data = $this->processPhotoField($data);
|
|
|
|
// Basis-Cast aktualisieren
|
|
$castData = [];
|
|
foreach (['name', 'photo', 'bio', 'birthDate', 'birthPlace'] as $field) {
|
|
if (array_key_exists($field, $data)) {
|
|
$castData[$field] = $data[$field];
|
|
}
|
|
}
|
|
|
|
if (!empty($castData)) {
|
|
ApiLogger::getInstance()->logDebug("AdultCast updateWithAdultSpecifics: Updating base cast data: " . json_encode($castData));
|
|
$this->update($id, $castData);
|
|
}
|
|
|
|
// Occupations aktualisieren
|
|
if (isset($data['occupations']) && is_array($data['occupations'])) {
|
|
ApiLogger::getInstance()->logDebug("AdultCast updateWithAdultSpecifics: Updating occupations: " . json_encode($data['occupations']));
|
|
$this->pdo->prepare("DELETE FROM occupations WHERE cast_id = ?")->execute([$id]);
|
|
$this->saveRelatedItems('occupations', $id, $data['occupations'], 'cast_id');
|
|
}
|
|
|
|
// Adult-spezifische Daten aktualisieren
|
|
if (isset($data['adult_specifics']) && is_array($data['adult_specifics'])) {
|
|
ApiLogger::getInstance()->logDebug("AdultCast updateWithAdultSpecifics: Saving adult_specifics");
|
|
ApiLogger::getInstance()->logDebug("AdultCast updateWithAdultSpecifics: adult_specifics data: " . json_encode($data['adult_specifics']));
|
|
$this->saveAdultSpecifics($id, $data['adult_specifics']);
|
|
} else {
|
|
ApiLogger::getInstance()->logDebug("AdultCast updateWithAdultSpecifics: No adult_specifics found in data");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
protected function saveAdultSpecifics($castId, $specifics) {
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics called for cast_id: $castId");
|
|
ApiLogger::getInstance()->logDebug("Specifics data: " . json_encode($specifics));
|
|
|
|
// Prüfen ob bereits Eintrag existiert
|
|
$stmt = $this->pdo->prepare("SELECT * FROM adult_cast_specifics WHERE cast_id = ?");
|
|
$stmt->execute([$castId]);
|
|
$existing = $stmt->fetch();
|
|
|
|
ApiLogger::getInstance()->logDebug("Existing entry: " . ($existing ? 'yes' : 'no'));
|
|
|
|
$fields = ['bust_size', 'cup_size', 'waist_size', 'hip_size', 'height', 'weight',
|
|
'hair_color', 'eye_color', 'ethnicity', 'tattoos', 'piercings', 'measurements', 'shoe_size'];
|
|
|
|
if ($existing) {
|
|
// Update
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics: Existing entry found, doing UPDATE");
|
|
$updateFields = [];
|
|
$params = [];
|
|
foreach ($fields as $field) {
|
|
if (array_key_exists($field, $specifics)) {
|
|
$updateFields[] = "$field = ?";
|
|
$params[] = $specifics[$field];
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics: Found field $field with value: " . json_encode($specifics[$field] ?? 'null'));
|
|
}
|
|
}
|
|
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics: Update fields: " . implode(', ', $updateFields));
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics: Total update fields count: " . count($updateFields));
|
|
|
|
if (!empty($updateFields)) {
|
|
$params[] = $castId;
|
|
$query = "UPDATE adult_cast_specifics SET " . implode(', ', $updateFields) . " WHERE cast_id = ?";
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics: Executing query: $query");
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics: With params: " . json_encode($params));
|
|
$stmt = $this->pdo->prepare($query);
|
|
try {
|
|
$stmt->execute($params);
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics: UPDATE successful");
|
|
} catch (Exception $e) {
|
|
// Fehler loggen
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics Error: " . $e->getMessage());
|
|
ApiLogger::getInstance()->logDebug("Query: $query");
|
|
ApiLogger::getInstance()->logDebug("Params: " . json_encode($params));
|
|
}
|
|
} else {
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics: No fields to update");
|
|
}
|
|
} else {
|
|
// Insert
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics: No existing entry, doing INSERT");
|
|
$insertFields = [];
|
|
$values = [];
|
|
$params = [];
|
|
|
|
$insertFields[] = 'cast_id';
|
|
$values[] = '?';
|
|
$params[] = $castId;
|
|
|
|
foreach ($fields as $field) {
|
|
if (array_key_exists($field, $specifics)) {
|
|
$insertFields[] = $field;
|
|
$values[] = '?';
|
|
$params[] = $specifics[$field];
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics: Found field $field with value: " . json_encode($specifics[$field] ?? 'null'));
|
|
}
|
|
}
|
|
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics: Insert fields: " . implode(', ', $insertFields));
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics: Total fields count: " . count($insertFields));
|
|
|
|
if (count($insertFields) > 1) {
|
|
$query = "INSERT INTO adult_cast_specifics (" . implode(', ', $insertFields) . ") VALUES (" . implode(', ', $values) . ")";
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics: Executing query: $query");
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics: With params: " . json_encode($params));
|
|
$stmt = $this->pdo->prepare($query);
|
|
try {
|
|
$stmt->execute($params);
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics: INSERT successful");
|
|
} catch (Exception $e) {
|
|
// Fehler loggen
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics Error: " . $e->getMessage());
|
|
ApiLogger::getInstance()->logDebug("Query: " . $query);
|
|
ApiLogger::getInstance()->logDebug("Params: " . json_encode($params));
|
|
}
|
|
} else {
|
|
// Keine Felder zum Speichern
|
|
ApiLogger::getInstance()->logDebug("AdultCast saveAdultSpecifics: Keine Felder zum Speichern für cast_id $castId");
|
|
}
|
|
}
|
|
}
|
|
|
|
public function deleteAdultSpecifics($castId) {
|
|
$stmt = $this->pdo->prepare("DELETE FROM adult_cast_specifics WHERE cast_id = ?");
|
|
$stmt->execute([$castId]);
|
|
return $stmt->rowCount() > 0;
|
|
}
|
|
|
|
public function searchAdultActors($filters = [], $page = 1, $limit = 2000000000) {
|
|
// Adult Actors mit Specifics suchen
|
|
$query = "
|
|
SELECT cs.*,
|
|
acs.bust_size, acs.cup_size, acs.waist_size, acs.hip_size,
|
|
acs.height, acs.weight, acs.hair_color, acs.eye_color, acs.ethnicity
|
|
FROM cast_staff cs
|
|
LEFT JOIN adult_cast_specifics acs ON cs.id = acs.cast_id
|
|
WHERE acs.cast_id IS NOT NULL
|
|
";
|
|
$params = [];
|
|
|
|
if (isset($filters['search'])) {
|
|
$query .= " AND cs.name LIKE ?";
|
|
$params[] = "%" . $filters['search'] . "%";
|
|
}
|
|
|
|
if (isset($filters['ethnicity'])) {
|
|
$query .= " AND acs.ethnicity = ?";
|
|
$params[] = $filters['ethnicity'];
|
|
}
|
|
|
|
if (isset($filters['hair_color'])) {
|
|
$query .= " AND acs.hair_color = ?";
|
|
$params[] = $filters['hair_color'];
|
|
}
|
|
|
|
$query .= " ORDER BY cs.createdAt DESC";
|
|
|
|
$offset = ($page - 1) * $limit;
|
|
$query .= " LIMIT " . (int)2000000000000 . " OFFSET " . (int)$offset;
|
|
|
|
$stmt = $this->pdo->prepare($query);
|
|
$stmt->execute($params);
|
|
$items = $stmt->fetchAll();
|
|
ApiLogger::getInstance()->logDebug("AdultCast searchAdultActors: Found " . count($items) . " cast members");
|
|
foreach ($items as $item) {
|
|
ApiLogger::getInstance()->logDebug("AdultCast searchAdultActors: Cast ID {$item['id']} - {$item['name']}");
|
|
}
|
|
|
|
// Occupations und Filmography für jeden laden
|
|
foreach ($items as &$item) {
|
|
$item['occupations'] = $this->getRelatedItems('occupations', $item['id'], 'cast_id');
|
|
// Add filmography information
|
|
$item['filmography'] = $this->getMediaForCast($item['id']);
|
|
// Extract unique media types
|
|
$mediaTypes = array_unique(array_column($item['filmography'], 'category'));
|
|
$item['media_types'] = array_values($mediaTypes);
|
|
ApiLogger::getInstance()->logDebug("AdultCast searchAdultActors: Cast ID {$item['id']} has " . count($item['filmography']) . " filmography items");
|
|
}
|
|
|
|
// Total count
|
|
$countQuery = "
|
|
SELECT COUNT(*)
|
|
FROM cast_staff cs
|
|
INNER JOIN adult_cast_specifics acs ON cs.id = acs.cast_id
|
|
WHERE 1=1
|
|
";
|
|
$countParams = [];
|
|
|
|
if (isset($filters['search'])) {
|
|
$countQuery .= " AND cs.name LIKE ?";
|
|
$countParams[] = "%" . $filters['search'] . "%";
|
|
}
|
|
|
|
if (isset($filters['ethnicity'])) {
|
|
$countQuery .= " AND acs.ethnicity = ?";
|
|
$countParams[] = $filters['ethnicity'];
|
|
}
|
|
|
|
if (isset($filters['hair_color'])) {
|
|
$countQuery .= " AND acs.hair_color = ?";
|
|
$countParams[] = $filters['hair_color'];
|
|
}
|
|
|
|
$countStmt = $this->pdo->prepare($countQuery);
|
|
$countStmt->execute($countParams);
|
|
$total = $countStmt->fetchColumn();
|
|
|
|
return [
|
|
'items' => $items,
|
|
'total' => $total,
|
|
'page' => $page,
|
|
'limit' => $limit
|
|
];
|
|
}
|
|
}
|