mirror of
https://github.com/ceratic/MediaCollectorLibary.git
synced 2026-05-13 23:56:46 +02:00
actor merging!
This commit is contained in:
@@ -880,7 +880,14 @@ class AdminController extends AdminBaseController
|
||||
*/
|
||||
public function mergeActors(Request $request, Response $response, $args)
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
$contentType = $request->getHeaderLine('Content-Type');
|
||||
|
||||
if (strstr($contentType, 'application/json')) {
|
||||
$data = json_decode((string)$request->getBody(), true);
|
||||
} else {
|
||||
$data = $request->getParsedBody();
|
||||
}
|
||||
|
||||
$masterActorId = (int)($data['master_actor_id'] ?? 0);
|
||||
$duplicateActorIds = array_map('intval', $data['duplicate_actor_ids'] ?? []);
|
||||
|
||||
@@ -1020,7 +1027,14 @@ class AdminController extends AdminBaseController
|
||||
*/
|
||||
public function autoMergeActors(Request $request, Response $response, $args)
|
||||
{
|
||||
$data = $request->getParsedBody();
|
||||
$contentType = $request->getHeaderLine('Content-Type');
|
||||
|
||||
if (strstr($contentType, 'application/json')) {
|
||||
$data = json_decode((string)$request->getBody(), true);
|
||||
} else {
|
||||
$data = $request->getParsedBody();
|
||||
}
|
||||
|
||||
$actorGroupIds = $data['actor_group_ids'] ?? [];
|
||||
|
||||
if (empty($actorGroupIds)) {
|
||||
|
||||
@@ -180,7 +180,7 @@ class Actor extends Model
|
||||
/**
|
||||
* Get paginated actors with optional search and sorting
|
||||
*/
|
||||
public function getPaginated(PDO $pdo, int $page = 1, int $perPage = 20, string $search = '', string $sort = 'name_asc'): array
|
||||
public function getPaginated(\PDO $pdo, int $page = 1, int $perPage = 20, string $search = '', string $sort = 'name_asc'): array
|
||||
{
|
||||
$offset = ($page - 1) * $perPage;
|
||||
|
||||
@@ -214,15 +214,15 @@ class Actor extends Model
|
||||
LIMIT :limit OFFSET :offset
|
||||
");
|
||||
|
||||
$stmt->bindValue(':limit', $perPage, PDO::PARAM_INT);
|
||||
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
|
||||
$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);
|
||||
$actors = $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
|
||||
// Add relationships data for each actor
|
||||
foreach ($actors as &$actor) {
|
||||
@@ -237,7 +237,7 @@ class Actor extends Model
|
||||
/**
|
||||
* Get total count of actors with optional search
|
||||
*/
|
||||
public function getTotalCount(PDO $pdo, string $search = ''): int
|
||||
public function getTotalCount(\PDO $pdo, string $search = ''): int
|
||||
{
|
||||
$whereClause = '';
|
||||
$params = [];
|
||||
@@ -254,7 +254,7 @@ class Actor extends Model
|
||||
}
|
||||
|
||||
$stmt->execute();
|
||||
return (int)$stmt->fetch(PDO::FETCH_ASSOC)['count'];
|
||||
return (int)$stmt->fetch(\PDO::FETCH_ASSOC)['count'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -270,7 +270,7 @@ class Actor extends Model
|
||||
ORDER BY m.title
|
||||
");
|
||||
$stmt->execute([$actorId]);
|
||||
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -286,7 +286,7 @@ class Actor extends Model
|
||||
ORDER BY ts.title
|
||||
");
|
||||
$stmt->execute([$actorId]);
|
||||
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,6 +302,6 @@ class Actor extends Model
|
||||
ORDER BY av.title
|
||||
");
|
||||
$stmt->execute([$actorId]);
|
||||
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
<p class="text-muted mb-0">View and manage actors, find and merge duplicates</p>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a href="{{ path_for('admin.actors.index') }}" class="btn btn-outline-primary {% if not filters.duplicates %}active{% endif %}">
|
||||
<a href="{{ path_for('admin.actors') }}" class="btn btn-outline-primary {% if not filters.duplicates %}active{% endif %}">
|
||||
<i class="bi bi-people me-2"></i>All Actors
|
||||
</a>
|
||||
<a href="{{ path_for('admin.actors.index', {}, {'duplicates': 1}) }}" class="btn btn-outline-warning {% if filters.duplicates %}active{% endif %}">
|
||||
<a href="{{ path_for('admin.actors', {}, {'duplicates': 1}) }}" class="btn btn-outline-warning {% if filters.duplicates %}active{% endif %}">
|
||||
<i class="bi bi-exclamation-triangle me-2"></i>Duplicates
|
||||
</a>
|
||||
</div>
|
||||
@@ -61,7 +61,7 @@
|
||||
data-group="{{ group.normalized_name }}">
|
||||
</div>
|
||||
{% if actor.thumbnail_path %}
|
||||
<img src="/images/{{ actor.thumbnail_path }}"
|
||||
<img src="{{ actor.thumbnail_path }}"
|
||||
alt="{{ actor.name }}"
|
||||
class="rounded me-3"
|
||||
style="width: 40px; height: 40px; object-fit: cover;">
|
||||
@@ -268,7 +268,7 @@
|
||||
<tr>
|
||||
<td>
|
||||
{% if actor.thumbnail_path %}
|
||||
<img src="/images/{{ actor.thumbnail_path }}" alt="{{ actor.name }}" style="width: 50px; height: 50px; object-fit: cover; border-radius: 50%;">
|
||||
<img src="{{ actor.thumbnail_path }}" alt="{{ actor.name }}" style="width: 50px; height: 50px; object-fit: cover; border-radius: 50%;">
|
||||
{% else %}
|
||||
<div class="bg-light d-flex align-items-center justify-content-center rounded-circle" style="width: 50px; height: 50px;">
|
||||
<i class="bi bi-person text-muted"></i>
|
||||
@@ -442,7 +442,7 @@ function autoMergeGroup(groupName) {
|
||||
return;
|
||||
}
|
||||
|
||||
fetch('{{ path_for("admin.actors.auto_merge") }}', {
|
||||
fetch('{{ path_for("admin.actors.auto-merge") }}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -484,7 +484,7 @@ function autoMergeAll() {
|
||||
return;
|
||||
}
|
||||
|
||||
fetch('{{ path_for("admin.actors.auto_merge") }}', {
|
||||
fetch('{{ path_for("admin.actors.auto-merge") }}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
||||
@@ -359,7 +359,7 @@
|
||||
{% for movie in movies %}
|
||||
<div class="group relative bg-white rounded-xl shadow-lg border border-gray-200 overflow-hidden hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-1">
|
||||
{% if movie.poster_url %}
|
||||
<div class="relative {{ movie.poster_aspect_ratio ? 'aspect-custom' : 'aspect-[2/3]' }} overflow-hidden"{% if movie.poster_aspect_ratio %} style="padding-bottom: {{ (1 / movie.poster_aspect_ratio) * 100 }}%;"{% endif %}>
|
||||
<div class="relative {{ movie.poster_aspect_ratio ? 'aspect-custom' : 'aspect-[2/3]' }} overflow-hidden">
|
||||
<img src="{{ movie.poster_url }}" alt="{{ movie.title }}" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300">
|
||||
<!-- Overlay with movie info -->
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/80 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300">
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
{% block content %}
|
||||
<!-- Hero Section with Backdrop -->
|
||||
<div class="relative">
|
||||
{% if movie.backdrop_url %}
|
||||
<div class="h-96 md:h-[500px] relative overflow-hidden">
|
||||
<img src="/images/{{ movie.backdrop_url }}" alt="{{ movie.title }} backdrop" class="w-full h-full object-cover">
|
||||
<img src="{{ movie.backdrop_url ? movie.backdrop_url : movie.poster_url }}" alt="{{ movie.title }} backdrop" class="w-full h-full object-cover">
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black via-black/50 to-transparent"></div>
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-black/80 via-black/40 to-transparent"></div>
|
||||
|
||||
@@ -114,27 +113,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<!-- Fallback hero without backdrop -->
|
||||
<div class="bg-gradient-to-r from-blue-900 to-purple-900 h-64 relative">
|
||||
<div class="absolute top-4 left-4 z-10">
|
||||
<a href="{{ path_for('adult.index') }}" class="inline-flex items-center text-white hover:text-gray-300 transition-colors">
|
||||
<svg class="mr-2" width="16" height="16" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
|
||||
</svg>
|
||||
Back to Adult Videos
|
||||
</a>
|
||||
</div>
|
||||
<div class="absolute bottom-0 left-0 right-0 p-6">
|
||||
<h1 class="text-4xl font-bold text-white mb-2">{{ movie.title }}</h1>
|
||||
{% if movie.tagline %}
|
||||
<p class="text-xl text-gray-200">{{ movie.tagline }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- Main Content -->
|
||||
<div class="max-w-7xl mx-auto px-4 py-8">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
@@ -143,7 +123,7 @@
|
||||
<div class="sticky top-4">
|
||||
<!-- Poster -->
|
||||
<div class="bg-white rounded-xl shadow-lg overflow-hidden mb-6">
|
||||
<div class="aspect-[2/3]">
|
||||
<div class="{{ movie.poster_aspect_ratio ? 'aspect-custom' : '' }}">
|
||||
{% if movie.poster_url %}
|
||||
<img src="{{ movie.poster_url }}" alt="{{ movie.title }}" class="w-full h-full object-cover">
|
||||
{% else %}
|
||||
@@ -239,11 +219,11 @@
|
||||
{% endif %}
|
||||
|
||||
<!-- Performers with thumbnails -->
|
||||
{% if movie.actors %}
|
||||
{% if actors %}
|
||||
<div class="mt-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">Performers</h3>
|
||||
<div class="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-4">
|
||||
{% for actor in movie.actors %}
|
||||
{% for actor in actors %}
|
||||
<a href="{{ path_for('actors.show', {'id': actor.id}) }}" class="flex flex-col items-center hover:bg-gray-50 rounded-lg p-2 transition-colors">
|
||||
{% if actor.thumbnail_path %}
|
||||
<img src="{{ actor.thumbnail_path }}" alt="{{ actor.name }}" class="w-16 h-16 rounded-full object-cover mb-2">
|
||||
|
||||
@@ -116,7 +116,7 @@ $app->group('', function (RouteCollectorProxy $group) {
|
||||
$adminGroup->group('/actors', function (RouteCollectorProxy $group) {
|
||||
$group->get('', AdminController::class . ':actors')->setName('admin.actors.index');
|
||||
$group->post('/merge', AdminController::class . ':mergeActors')->setName('admin.actors.merge');
|
||||
$group->post('/auto-merge', AdminController::class . ':autoMergeActors')->setName('admin.actors.auto_merge');
|
||||
$group->post('/auto-merge', AdminController::class . ':autoMergeActors')->setName('admin.actors.auto-merge');
|
||||
});
|
||||
|
||||
// Media Sources
|
||||
|
||||
Reference in New Issue
Block a user