Files
MediaCollectorLibary/app/Models/Movie.php
Lars Behrends ca2d3a6960 ...
2025-10-18 22:03:30 +02:00

230 lines
6.2 KiB
PHP

<?php
namespace App\Models;
class Movie extends Model
{
protected string $table = 'movies';
protected array $fillable = [
'title',
'overview',
'director',
'writer',
'genre',
'cast',
'release_date',
'runtime_minutes',
'rating',
'imdb_id',
'tmdb_id',
'poster_url',
'backdrop_url',
'watched',
'watch_count',
'is_favorite',
'metadata',
'source_id',
'last_watched_at'
];
protected array $casts = [
'runtime_minutes' => 'int',
'rating' => 'float',
'watched' => 'bool',
'watch_count' => 'int',
'is_favorite' => 'bool',
'release_date' => 'date',
'last_watched_at' => 'datetime'
];
public function source()
{
$stmt = $this->pdo->prepare("SELECT * FROM sources WHERE id = :source_id");
$stmt->execute(['source_id' => $this->source_id]);
$sourceData = $stmt->fetch(\PDO::FETCH_ASSOC);
return $sourceData ? new Source($this->pdo, $sourceData) : null;
}
public function markAsWatched(): bool
{
$this->watched = true;
$this->watch_count += 1;
$this->last_watched_at = date('Y-m-d H:i:s');
return $this->update($this->id, [
'watched' => $this->watched,
'watch_count' => $this->watch_count,
'last_watched_at' => $this->last_watched_at
]);
}
public function markAsUnwatched(): bool
{
$this->watched = false;
return $this->update($this->id, [
'watched' => $this->watched
]);
}
public function toggleFavorite(): bool
{
return $this->update($this->id, [
'is_favorite' => !$this->is_favorite
]);
}
public function updateRating(float $rating): bool
{
return $this->update($this->id, [
'rating' => min(10.0, max(0.0, $rating))
]);
}
public static function getStats(\PDO $pdo): array
{
$stmt = $pdo->query("
SELECT
COUNT(*) as total_movies,
COUNT(CASE WHEN watched = 1 THEN 1 END) as watched_movies,
SUM(watch_count) as total_watches,
AVG(rating) as avg_rating,
COUNT(CASE WHEN is_favorite = 1 THEN 1 END) as favorite_movies,
SUM(runtime_minutes) as total_runtime
FROM movies
");
return $stmt->fetch(\PDO::FETCH_ASSOC);
}
public static function getRecent(\PDO $pdo, int $limit = 10): array
{
$stmt = $pdo->prepare("
SELECT m.*, s.display_name as source_name
FROM movies m
JOIN sources s ON m.source_id = s.id
WHERE m.last_watched_at IS NOT NULL
ORDER BY m.last_watched_at DESC
LIMIT :limit
");
$stmt->execute(['limit' => $limit]);
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
}
public static function getTotalCount(\PDO $pdo, string $search = ''): int
{
$sql = "SELECT COUNT(*) as count FROM movies m JOIN sources s ON m.source_id = s.id";
$params = [];
if (!empty($search)) {
$sql .= " WHERE m.title LIKE :search";
$params['search'] = "%{$search}%";
}
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
return (int) $stmt->fetch()['count'];
}
public static function getAllWithPagination(\PDO $pdo, int $page, int $perPage, string $search = ''): array
{
$offset = ($page - 1) * $perPage;
$sql = "
SELECT m.*, s.display_name as source_name
FROM movies m
JOIN sources s ON m.source_id = s.id
";
$params = [];
if (!empty($search)) {
$sql .= " WHERE m.title LIKE :search";
$params['search'] = "%{$search}%";
}
$sql .= " ORDER BY m.title ASC LIMIT :limit OFFSET :offset";
$stmt = $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();
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
}
public static function getAll(\PDO $pdo, int $limit = 100): array
{
$stmt = $pdo->prepare("
SELECT m.*, s.display_name as source_name
FROM movies m
JOIN sources s ON m.source_id = s.id
ORDER BY m.title ASC
LIMIT :limit
");
$stmt->execute(['limit' => $limit]);
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
}
/**
* Get all actors associated with this movie
*/
public function actors()
{
$stmt = $this->pdo->prepare("
SELECT a.*
FROM actors a
JOIN actor_movie am ON a.id = am.actor_id
WHERE am.movie_id = :movie_id
ORDER BY a.name ASC
");
$stmt->execute(['movie_id' => $this->id]);
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
}
/**
* Add an actor to this movie
*/
public function addActor(int $actorId): bool
{
$stmt = $this->pdo->prepare("
INSERT IGNORE INTO actor_movie (movie_id, actor_id)
VALUES (:movie_id, :actor_id)
");
return $stmt->execute([
'movie_id' => $this->id,
'actor_id' => $actorId
]);
}
/**
* Remove an actor from this movie
*/
public function removeActor(int $actorId): bool
{
$stmt = $this->pdo->prepare("
DELETE FROM actor_movie
WHERE movie_id = :movie_id AND actor_id = :actor_id
");
return $stmt->execute([
'movie_id' => $this->id,
'actor_id' => $actorId
]);
}
/**
* Update the cast field with actor names
*/
public function updateCastField(): bool
{
$actors = $this->actors();
$actorNames = array_column($actors, 'name');
$castString = implode(', ', $actorNames);
return $this->update($this->id, [
'cast' => $castString
]);
}
}