mirror of
https://github.com/ceratic/MediaCollectorLibary.git
synced 2026-05-13 23:56:46 +02:00
dont know ?
This commit is contained in:
@@ -21,16 +21,22 @@ class ActorController extends Controller
|
||||
{
|
||||
$actorId = $args['id'];
|
||||
|
||||
// Get actor details with counts from all media types
|
||||
// Get actor details with counts from all media types (including episode actors)
|
||||
$stmt = $this->pdo->prepare("
|
||||
SELECT a.*,
|
||||
COUNT(DISTINCT am.movie_id) as movie_count,
|
||||
COUNT(DISTINCT ats.tv_show_id) as tv_show_count,
|
||||
COUNT(DISTINCT CASE WHEN ats.tv_show_id IS NOT NULL THEN ats.tv_show_id
|
||||
WHEN ate.tv_episode_id IS NOT NULL THEN te.tv_show_id END) as tv_show_count,
|
||||
COUNT(DISTINCT aav.adult_video_id) as adult_video_count,
|
||||
(COUNT(DISTINCT am.movie_id) + COUNT(DISTINCT ats.tv_show_id) + COUNT(DISTINCT aav.adult_video_id)) as total_media_count
|
||||
(COUNT(DISTINCT am.movie_id) +
|
||||
COUNT(DISTINCT CASE WHEN ats.tv_show_id IS NOT NULL THEN ats.tv_show_id
|
||||
WHEN ate.tv_episode_id IS NOT NULL THEN te.tv_show_id END) +
|
||||
COUNT(DISTINCT aav.adult_video_id)) as total_media_count
|
||||
FROM actors a
|
||||
LEFT JOIN actor_movie am ON a.id = am.actor_id
|
||||
LEFT JOIN actor_tv_show ats ON a.id = ats.actor_id
|
||||
LEFT JOIN actor_tv_episode ate ON a.id = ate.actor_id
|
||||
LEFT JOIN tv_episodes te ON ate.tv_episode_id = te.id
|
||||
LEFT JOIN actor_adult_video aav ON a.id = aav.actor_id
|
||||
WHERE a.id = :actor_id
|
||||
GROUP BY a.id
|
||||
@@ -66,16 +72,18 @@ class ActorController extends Controller
|
||||
$stmt->execute(['actor_id' => $actorId]);
|
||||
$movies = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Get actor's TV shows
|
||||
// Get actor's TV shows (from main cast and episodes)
|
||||
$stmt = $this->pdo->prepare("
|
||||
SELECT ts.*, s.display_name as source_name
|
||||
SELECT DISTINCT ts.*, s.display_name as source_name
|
||||
FROM tv_shows ts
|
||||
JOIN sources s ON ts.source_id = s.id
|
||||
JOIN actor_tv_show ats ON ts.id = ats.tv_show_id
|
||||
WHERE ats.actor_id = :actor_id
|
||||
LEFT JOIN actor_tv_show ats ON ts.id = ats.tv_show_id AND ats.actor_id = :actor_id
|
||||
LEFT JOIN tv_episodes te ON ts.id = te.tv_show_id
|
||||
LEFT JOIN actor_tv_episode ate ON te.id = ate.tv_episode_id AND ate.actor_id = :actor_id2
|
||||
WHERE ats.actor_id = :actor_id4 OR ate.actor_id = :actor_id3
|
||||
ORDER BY ts.first_air_date DESC, ts.title ASC
|
||||
");
|
||||
$stmt->execute(['actor_id' => $actorId]);
|
||||
$stmt->execute(['actor_id' => $actorId,'actor_id2' => $actorId,'actor_id3' => $actorId, 'actor_id4' => $actorId]);
|
||||
$tvShows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
|
||||
@@ -108,33 +116,314 @@ class ActorController extends Controller
|
||||
'tv_shows' => $tvShows
|
||||
]);
|
||||
}
|
||||
|
||||
public function edit(Request $request, Response $response, $args)
|
||||
{
|
||||
$actorId = $args['id'];
|
||||
|
||||
// Get actor details
|
||||
$stmt = $this->pdo->prepare("SELECT * FROM actors WHERE id = :id");
|
||||
$stmt->execute(['id' => $actorId]);
|
||||
$actor = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$actor) {
|
||||
return $response->withStatus(404)->withHeader('Content-Type', 'text/html');
|
||||
}
|
||||
|
||||
// Decode metadata for form population
|
||||
$metadata = json_decode($actor['metadata'] ?? '{}', true);
|
||||
|
||||
// Handle POST request (form submission)
|
||||
if ($request->getMethod() === 'POST') {
|
||||
$data = $request->getParsedBody();
|
||||
$uploadedFiles = $request->getUploadedFiles();
|
||||
|
||||
// Validate required fields
|
||||
$name = trim($data['name'] ?? '');
|
||||
if (empty($name)) {
|
||||
return $this->view->render($response, 'actor/edit.twig', [
|
||||
'title' => 'Edit Actor',
|
||||
'actor' => $actor,
|
||||
'metadata' => $metadata,
|
||||
'error' => 'Name is required'
|
||||
]);
|
||||
}
|
||||
|
||||
// Handle image upload
|
||||
$thumbnailPath = $actor['thumbnail_path']; // Keep existing by default
|
||||
if (!empty($uploadedFiles['thumbnail']) && $uploadedFiles['thumbnail']->getError() === UPLOAD_ERR_OK) {
|
||||
$uploadedFile = $uploadedFiles['thumbnail'];
|
||||
|
||||
// Validate file type
|
||||
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
|
||||
if (!in_array($uploadedFile->getClientMediaType(), $allowedTypes)) {
|
||||
return $this->view->render($response, 'actor/edit.twig', [
|
||||
'title' => 'Edit Actor',
|
||||
'actor' => $actor,
|
||||
'metadata' => $metadata,
|
||||
'error' => 'Invalid image type. Only JPEG, PNG, GIF, and WebP are allowed.'
|
||||
]);
|
||||
}
|
||||
|
||||
// Generate filename and move file
|
||||
$extension = pathinfo($uploadedFile->getClientFilename(), PATHINFO_EXTENSION);
|
||||
$filename = 'actor_' . $actorId . '_' . time() . '.' . $extension;
|
||||
$uploadPath = __DIR__ . '/../../public/images/actors/' . $filename;
|
||||
|
||||
// Create directory if it doesn't exist
|
||||
$uploadDir = dirname($uploadPath);
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0755, true);
|
||||
}
|
||||
|
||||
$uploadedFile->moveTo($uploadPath);
|
||||
$thumbnailPath = '/images/actors/' . $filename;
|
||||
}
|
||||
|
||||
// Prepare metadata
|
||||
$actorMetadata = [
|
||||
'biography' => trim($data['biography'] ?? ''),
|
||||
'birth_date' => trim($data['birth_date'] ?? ''),
|
||||
'death_date' => trim($data['death_date'] ?? ''),
|
||||
'birth_place' => trim($data['birth_place'] ?? ''),
|
||||
'nationality' => trim($data['nationality'] ?? ''),
|
||||
'gender' => trim($data['gender'] ?? ''),
|
||||
'ethnicity' => trim($data['ethnicity'] ?? ''),
|
||||
'country' => trim($data['nationality'] ?? ''), // Map nationality to country for Stash compatibility
|
||||
'height' => trim($data['height'] ?? ''),
|
||||
'measurements' => trim($data['measurements'] ?? ''),
|
||||
'cup_size' => trim($data['cup_size'] ?? ''),
|
||||
'piercings' => trim($data['piercings'] ?? ''),
|
||||
'tattoos' => trim($data['tattoos'] ?? ''),
|
||||
'hair_color' => trim($data['hair_color'] ?? ''),
|
||||
'eye_color' => trim($data['eye_color'] ?? ''),
|
||||
'weight' => trim($data['weight'] ?? ''),
|
||||
'fake_tits' => trim($data['fake_tits'] ?? ''),
|
||||
'penis_length' => trim($data['penis_length'] ?? ''),
|
||||
'circumcised' => trim($data['circumcised'] ?? ''),
|
||||
'career_length' => trim($data['career_length'] ?? ''),
|
||||
'aliases' => array_filter(array_map('trim', explode(',', $data['aliases'] ?? ''))),
|
||||
'favorite' => isset($data['favorite']) ? true : false,
|
||||
'ignore_auto_tag' => isset($data['ignore_auto_tag']) ? true : false,
|
||||
'scene_count' => (int)($data['scene_count'] ?? 0),
|
||||
'details' => trim($data['details'] ?? ''),
|
||||
'social_media' => [
|
||||
'twitter' => trim($data['twitter'] ?? ''),
|
||||
'instagram' => trim($data['instagram'] ?? ''),
|
||||
'onlyfans' => trim($data['onlyfans'] ?? ''),
|
||||
'website' => trim($data['website'] ?? '')
|
||||
],
|
||||
'adult_specific' => [
|
||||
'debut_year' => trim($data['debut_year'] ?? ''),
|
||||
'retirement_year' => trim($data['retirement_year'] ?? ''),
|
||||
'active' => isset($data['active']) ? true : false,
|
||||
'genres' => array_filter(array_map('trim', explode(',', $data['adult_genres'] ?? ''))),
|
||||
'specialties' => array_filter(array_map('trim', explode(',', $data['specialties'] ?? '')))
|
||||
]
|
||||
];
|
||||
|
||||
// Update actor
|
||||
$stmt = $this->pdo->prepare("
|
||||
UPDATE actors
|
||||
SET name = :name, thumbnail_path = :thumbnail_path, metadata = :metadata, updated_at = NOW()
|
||||
WHERE id = :id
|
||||
");
|
||||
$stmt->execute([
|
||||
'id' => $actorId,
|
||||
'name' => $name,
|
||||
'thumbnail_path' => $thumbnailPath,
|
||||
'metadata' => json_encode($actorMetadata)
|
||||
]);
|
||||
|
||||
// Redirect back to actor show page
|
||||
return $response->withHeader('Location', '/media/actors/' . $actorId)->withStatus(302);
|
||||
}
|
||||
|
||||
// GET request - show edit form
|
||||
return $this->view->render($response, 'actor/edit.twig', [
|
||||
'title' => 'Edit Actor',
|
||||
'actor' => $actor,
|
||||
'metadata' => $metadata
|
||||
]);
|
||||
}
|
||||
public function index(Request $request, Response $response, $args)
|
||||
{
|
||||
// Get all actors with their media counts from all types
|
||||
$stmt = $this->pdo->prepare("
|
||||
SELECT a.*,
|
||||
COUNT(DISTINCT aav.adult_video_id) as adult_video_count,
|
||||
COUNT(DISTINCT am.movie_id) as movie_count,
|
||||
COUNT(DISTINCT ats.tv_show_id) as tv_show_count,
|
||||
(COUNT(DISTINCT aav.adult_video_id) + COUNT(DISTINCT am.movie_id) + COUNT(DISTINCT ats.tv_show_id)) as total_media_count,
|
||||
MAX(COALESCE(av.release_date, m.release_date, ts.first_air_date)) as latest_media_date
|
||||
$queryParams = $request->getQueryParams();
|
||||
|
||||
// Get pagination parameters
|
||||
$page = max(1, (int)($queryParams['page'] ?? 1));
|
||||
$perPage = max(12, min(100, (int)($queryParams['per_page'] ?? 24)));
|
||||
|
||||
// Get search parameters
|
||||
$search = trim($queryParams['search'] ?? '');
|
||||
|
||||
// Get filter parameters
|
||||
$hasMovies = $queryParams['has_movies'] ?? null;
|
||||
$hasTvShows = $queryParams['has_tv_shows'] ?? null;
|
||||
$hasAdultVideos = $queryParams['has_adult_videos'] ?? null;
|
||||
|
||||
// Get sort parameter
|
||||
$sort = $queryParams['sort'] ?? 'total_media_desc'; // total_media_desc, total_media_asc, name_asc, name_desc
|
||||
|
||||
// Build the base query - simplified to ensure all actors are found
|
||||
$sql = "
|
||||
SELECT a.id, a.name, a.thumbnail_path,
|
||||
COALESCE(adult_counts.adult_video_count, 0) as adult_video_count,
|
||||
COALESCE(movie_counts.movie_count, 0) as movie_count,
|
||||
COALESCE(tv_counts.tv_show_count, 0) as tv_show_count,
|
||||
(COALESCE(adult_counts.adult_video_count, 0) + COALESCE(movie_counts.movie_count, 0) + COALESCE(tv_counts.tv_show_count, 0)) as total_media_count,
|
||||
GREATEST(
|
||||
COALESCE(adult_dates.latest_adult, '1900-01-01'),
|
||||
COALESCE(movie_dates.latest_movie, '1900-01-01'),
|
||||
COALESCE(tv_dates.latest_tv, '1900-01-01')
|
||||
) as latest_media_date
|
||||
FROM actors a
|
||||
LEFT JOIN actor_adult_video aav ON a.id = aav.actor_id
|
||||
LEFT JOIN adult_videos av ON aav.adult_video_id = av.id
|
||||
LEFT JOIN actor_movie am ON a.id = am.actor_id
|
||||
LEFT JOIN movies m ON am.movie_id = m.id
|
||||
LEFT JOIN actor_tv_show ats ON a.id = ats.actor_id
|
||||
LEFT JOIN tv_shows ts ON ats.tv_show_id = ts.id
|
||||
GROUP BY a.id
|
||||
ORDER BY total_media_count DESC, a.name ASC
|
||||
LIMIT 50
|
||||
");
|
||||
LEFT JOIN (
|
||||
SELECT actor_id, COUNT(DISTINCT adult_video_id) as adult_video_count
|
||||
FROM actor_adult_video
|
||||
GROUP BY actor_id
|
||||
) adult_counts ON a.id = adult_counts.actor_id
|
||||
LEFT JOIN (
|
||||
SELECT actor_id, COUNT(DISTINCT movie_id) as movie_count
|
||||
FROM actor_movie
|
||||
GROUP BY actor_id
|
||||
) movie_counts ON a.id = movie_counts.actor_id
|
||||
LEFT JOIN (
|
||||
SELECT actor_id, COUNT(DISTINCT tv_show_id) as tv_show_count
|
||||
FROM (
|
||||
SELECT actor_id, tv_show_id FROM actor_tv_show
|
||||
UNION
|
||||
SELECT ate.actor_id, te.tv_show_id
|
||||
FROM actor_tv_episode ate
|
||||
JOIN tv_episodes te ON ate.tv_episode_id = te.id
|
||||
) combined_tv
|
||||
GROUP BY actor_id
|
||||
) tv_counts ON a.id = tv_counts.actor_id
|
||||
LEFT JOIN (
|
||||
SELECT aav.actor_id, MAX(av.release_date) as latest_adult
|
||||
FROM actor_adult_video aav
|
||||
JOIN adult_videos av ON aav.adult_video_id = av.id
|
||||
GROUP BY aav.actor_id
|
||||
) adult_dates ON a.id = adult_dates.actor_id
|
||||
LEFT JOIN (
|
||||
SELECT am.actor_id, MAX(m.release_date) as latest_movie
|
||||
FROM actor_movie am
|
||||
JOIN movies m ON am.movie_id = m.id
|
||||
GROUP BY am.actor_id
|
||||
) movie_dates ON a.id = movie_dates.actor_id
|
||||
LEFT JOIN (
|
||||
SELECT combined_tv.actor_id, MAX(ts.first_air_date) as latest_tv
|
||||
FROM (
|
||||
SELECT actor_id, tv_show_id FROM actor_tv_show
|
||||
UNION
|
||||
SELECT ate.actor_id, te.tv_show_id
|
||||
FROM actor_tv_episode ate
|
||||
JOIN tv_episodes te ON ate.tv_episode_id = te.id
|
||||
) combined_tv
|
||||
JOIN tv_shows ts ON combined_tv.tv_show_id = ts.id
|
||||
GROUP BY combined_tv.actor_id
|
||||
) tv_dates ON a.id = tv_dates.actor_id
|
||||
";
|
||||
|
||||
$params = [];
|
||||
$whereClauses = [];
|
||||
|
||||
// Add search filter
|
||||
if (!empty($search)) {
|
||||
$whereClauses[] = "a.name LIKE :search";
|
||||
$params['search'] = "%{$search}%";
|
||||
}
|
||||
|
||||
if (!empty($whereClauses)) {
|
||||
$sql .= ' WHERE ' . implode(' AND ', $whereClauses);
|
||||
}
|
||||
|
||||
$sql .= " GROUP BY a.id";
|
||||
|
||||
// Add HAVING clause for filters that require aggregation
|
||||
$havingClauses = [];
|
||||
if ($hasMovies === '1') {
|
||||
$havingClauses[] = "movie_count > 0";
|
||||
}
|
||||
if ($hasTvShows === '1') {
|
||||
$havingClauses[] = "tv_show_count > 0";
|
||||
}
|
||||
if ($hasAdultVideos === '1') {
|
||||
$havingClauses[] = "adult_video_count > 0";
|
||||
}
|
||||
|
||||
if (!empty($havingClauses)) {
|
||||
$sql .= ' HAVING ' . implode(' AND ', $havingClauses);
|
||||
}
|
||||
|
||||
// Add sorting
|
||||
$sortMap = [
|
||||
'total_media_desc' => 'total_media_count DESC, a.name ASC',
|
||||
'total_media_asc' => 'total_media_count ASC, a.name ASC',
|
||||
'name_asc' => 'a.name ASC',
|
||||
'name_desc' => 'a.name DESC',
|
||||
'latest_desc' => 'latest_media_date DESC NULLS LAST, a.name ASC',
|
||||
];
|
||||
$orderBy = $sortMap[$sort] ?? 'total_media_count DESC, a.name ASC';
|
||||
$sql .= " ORDER BY {$orderBy}";
|
||||
|
||||
// Get total count for pagination
|
||||
$countSql = str_replace('SELECT a.id, a.name, a.thumbnail_path,', 'SELECT COUNT(*) as count,', $sql);
|
||||
$countSql = preg_replace('/ORDER BY.*$/', '', $countSql);
|
||||
$countStmt = $this->pdo->prepare($countSql);
|
||||
foreach ($params as $key => $value) {
|
||||
$countStmt->bindValue($key, $value);
|
||||
}
|
||||
$countStmt->execute();
|
||||
$countResult = $countStmt->fetch(PDO::FETCH_ASSOC);
|
||||
$totalCount = (int) ($countResult['count'] ?? 0);
|
||||
|
||||
// Add pagination
|
||||
$offset = ($page - 1) * $perPage;
|
||||
$sql .= " LIMIT :limit OFFSET :offset";
|
||||
|
||||
// Execute main query
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
$stmt->bindValue(':limit', $perPage, PDO::PARAM_INT);
|
||||
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
|
||||
foreach ($params as $key => $value) {
|
||||
$stmt->bindValue($key, $value);
|
||||
}
|
||||
$stmt->execute();
|
||||
$actors = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Calculate pagination info
|
||||
$totalPages = ceil($totalCount / $perPage);
|
||||
$hasNextPage = $page < $totalPages;
|
||||
$hasPrevPage = $page > 1;
|
||||
|
||||
return $this->view->render($response, 'actor/index.twig', [
|
||||
'title' => 'Actors & Performers',
|
||||
'actors' => $actors
|
||||
'actors' => $actors,
|
||||
'pagination' => [
|
||||
'current_page' => $page,
|
||||
'per_page' => $perPage,
|
||||
'total_pages' => $totalPages,
|
||||
'total_items' => $totalCount,
|
||||
'has_next' => $hasNextPage,
|
||||
'has_prev' => $hasPrevPage,
|
||||
'next_page' => $page + 1,
|
||||
'prev_page' => $page - 1
|
||||
],
|
||||
'search' => $search,
|
||||
'sort' => $sort,
|
||||
'sort_options' => [
|
||||
'total_media_desc' => 'Most Media',
|
||||
'total_media_asc' => 'Least Media',
|
||||
'name_asc' => 'Name A-Z',
|
||||
'name_desc' => 'Name Z-A',
|
||||
'latest_desc' => 'Recently Active'
|
||||
],
|
||||
'filters' => [
|
||||
'has_movies' => $hasMovies,
|
||||
'has_tv_shows' => $hasTvShows,
|
||||
'has_adult_videos' => $hasAdultVideos
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user