imageHandler = new ImageHandler(); } public function getWithFilmography($id) { $cast = $this->findById($id); if (!$cast) { return null; } $cast['occupations'] = $this->getRelatedItems('occupations', $id, 'cast_id'); $cast['filmography'] = $this->getMediaForCast($id); return $cast; } public function getMediaForCast($castId) { $stmt = $this->pdo->prepare(" SELECT m.id, m.title, m.year, m.poster, m.category, m.type, mc.role, mc.characterName FROM media m INNER JOIN media_cast mc ON m.id = mc.media_id WHERE mc.cast_id = ? ORDER BY m.year DESC "); $stmt->execute([$castId]); return $stmt->fetchAll(); } public function search($filters = [], $page = 1, $limit = 20) { $conditions = []; if (isset($filters['search'])) { $conditions['name'] = ["%" . $filters['search'] . "%"]; } $offset = ($page - 1) * $limit; $items = $this->findAll($conditions, 'createdAt DESC', $limit, $offset); $total = $this->count($conditions); // Load filmography for all cast members in a single query if (!empty($items)) { $castIds = array_column($items, 'id'); $placeholders = str_repeat('?,', count($castIds) - 1) . '?'; $stmt = $this->pdo->prepare(" SELECT mc.cast_id, m.id, m.title, m.year, m.poster, m.category, m.type, mc.role, mc.characterName FROM media m INNER JOIN media_cast mc ON m.id = mc.media_id WHERE mc.cast_id IN ($placeholders) ORDER BY m.year DESC "); $stmt->execute($castIds); $allFilmography = $stmt->fetchAll(); // Group filmography by cast_id $filmographyByCast = []; foreach ($allFilmography as $film) { $castId = $film['cast_id']; unset($film['cast_id']); $filmographyByCast[$castId][] = $film; } // Attach filmography to each cast member foreach ($items as &$item) { $item['filmography'] = $filmographyByCast[$item['id']] ?? []; $mediaTypes = array_unique(array_column($item['filmography'], 'category')); $item['media_types'] = array_values($mediaTypes); } } return [ 'items' => $items, 'total' => $total, 'page' => $page, 'limit' => $limit ]; } protected function processPhotoField($data) { error_log("Cast::processPhotoField - Checking for photo field, isUpdate: " . ($this->isUpdate ? 'yes' : 'no')); if ($this->isUpdate && $this->castId && isset($data['photo']) && !empty($data['photo'])) { $currentCast = $this->findById($this->castId); if ($currentCast && !empty($currentCast['photo'])) { $oldPhoto = $currentCast['photo']; if (strpos($oldPhoto, '/images/') === 0) { error_log("Cast::processPhotoField - Deleting old photo: " . $oldPhoto); $this->imageHandler->deleteImage($oldPhoto); } } } if (isset($data['photo']) && !empty($data['photo'])) { error_log("Cast::processPhotoField - Photo found, length: " . strlen($data['photo'])); if (strpos($data['photo'], '/images/') === 0 || filter_var($data['photo'], FILTER_VALIDATE_URL)) { error_log("Cast::processPhotoField - Photo is already a path or URL, skipping processing"); return $data; } $photoPath = $this->imageHandler->saveBase64Image($data['photo'], 'cast/photo'); error_log("Cast::processPhotoField - ImageHandler returned: " . ($photoPath ?: 'null')); if ($photoPath) { $data['photo'] = $photoPath; error_log("Cast::processPhotoField - Photo path set to: " . $photoPath); } else { error_log("Cast::processPhotoField - Failed to process photo, keeping original data"); } } else { error_log("Cast::processPhotoField - No photo field found or empty"); } return $data; } public function createWithOccupations($data) { $name = $data['name'] ?? null; if (!$name) { throw new Exception('Name is required'); } // cleanname generieren $cleanname = generateCleanName($name); $data = $this->processPhotoField($data); $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); if (isset($data['occupations']) && is_array($data['occupations'])) { $this->saveRelatedItems('occupations', $castId, $data['occupations'], 'cast_id'); } return $castId; } public function updateWithOccupations($id, $data) { $this->isUpdate = true; $this->castId = $id; $data = $this->processPhotoField($data); $castData = []; foreach (['name', 'photo', 'bio', 'birthDate', 'birthPlace'] as $field) { if (array_key_exists($field, $data)) { $castData[$field] = $data[$field]; } } // Wenn name geƤndert wurde, cleanname aktualisieren if (isset($data['name'])) { $castData['cleanname'] = generateCleanName($data['name']); } if (!empty($castData)) { $this->update($id, $castData); } if (isset($data['occupations']) && is_array($data['occupations'])) { $this->pdo->prepare("DELETE FROM occupations WHERE cast_id = ?")->execute([$id]); $this->saveRelatedItems('occupations', $id, $data['occupations'], 'cast_id'); } return true; } public function findByCleanName($cleanname) { $stmt = $this->pdo->prepare("SELECT * FROM {$this->table} WHERE cleanname = ?"); $stmt->execute([$cleanname]); return $stmt->fetch(); } protected function getRelatedItems($table, $id, $fkColumn = 'media_id') { $stmt = $this->pdo->prepare("SELECT * FROM $table WHERE $fkColumn = ?"); $stmt->execute([$id]); $items = $stmt->fetchAll(); $result = []; foreach ($items as $item) { $result[] = $fkColumn === 'cast_id' ? $item['occupation'] : $item['genre']; } return $result; } protected function saveRelatedItems($table, $id, $items, $fkColumn = 'media_id') { $valueColumn = $fkColumn === 'cast_id' ? 'occupation' : 'genre'; $stmt = $this->pdo->prepare("INSERT INTO $table ($fkColumn, $valueColumn) VALUES (?, ?)"); foreach ($items as $item) { $stmt->execute([$id, $item]); } } }