PIMS/app/Modules/Movies/Services/Omdb/OmdbMovieProvider.php

162 lines
5.5 KiB
PHP
Raw Permalink Normal View History

2025-12-07 03:49:26 +00:00
<?php
namespace App\Modules\Movies\Services\Omdb;
use App\Modules\Movies\Services\Contracts\MovieProvider;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Collection;
class OmdbMovieProvider implements MovieProvider
{
protected string $baseUrl;
protected ?string $apiKey;
protected int $cacheTtl;
public function __construct()
{
$this->baseUrl = rtrim(config('movies.omdb.base_url', 'https://www.omdbapi.com/'), '/');
$this->apiKey = config('movies.omdb.api_key');
$this->cacheTtl = (int) config('movies.omdb.cache_ttl', 3600);
}
public function search(string $query, int $page = 1): array
{
$query = trim($query);
if ($query === '') {
return ['results' => collect(), 'total' => 0, 'page' => 1, 'has_more' => false];
}
$cacheKey = sprintf('omdb.search.%s.p%s', md5($query), $page);
$data = Cache::remember($cacheKey, $this->cacheTtl, function () use ($query, $page) {
$response = Http::acceptJson()
->timeout(6)
->retry(3, 300)
->get($this->baseUrl, [
'apikey' => $this->apiKey,
's' => $query,
'type' => 'movie',
'page' => $page,
]);
if ($response->failed()) {
abort(502, 'Couldnt reach OMDb. Please try again.');
}
return $response->json();
});
$results = collect();
$total = 0;
$hasMore = false;
if (isset($data['Response']) && $data['Response'] === 'True' && isset($data['Search'])) {
$total = (int) ($data['totalResults'] ?? 0);
$hasMore = $page * 10 < $total; // OMDb pages of 10
$results = collect($data['Search'])->map(function ($item) {
return [
'provider' => 'omdb',
'provider_id' => $item['imdbID'] ?? null,
'title' => $item['Title'] ?? null,
'year' => $item['Year'] ?? null,
'poster_url' => ($item['Poster'] ?? 'N/A') !== 'N/A' ? $item['Poster'] : null,
];
});
}
return [
'results' => $results,
'total' => $total,
'page' => $page,
'has_more' => $hasMore,
];
}
public function details(string $id): array
{
$id = trim($id);
$cacheKey = sprintf('omdb.details.%s', $id);
$data = Cache::remember($cacheKey, $this->cacheTtl, function () use ($id) {
$response = Http::acceptJson()
->timeout(6)
->retry(3, 300)
->get($this->baseUrl, [
'apikey' => $this->apiKey,
'i' => $id,
'plot' => 'full',
'type' => 'movie',
]);
if ($response->failed()) {
abort(502, 'Couldnt reach OMDb. Please try again.');
}
return $response->json();
});
if (!isset($data['Response']) || $data['Response'] !== 'True') {
// Map explicit OMDb errors that indicate provider-side issues differently if needed
// Default to not found for details when OMDb says False
abort(404, 'Movie not found in OMDb');
}
// Normalize to internal structure
$genres = $this->splitList($data['Genre'] ?? '');
$actors = $this->splitList($data['Actors'] ?? '');
$directors = $this->splitList($data['Director'] ?? '');
$studios = $this->splitList($data['Production'] ?? '');
$countries = $this->splitList($data['Country'] ?? '');
$languages = $this->splitList($data['Language'] ?? '');
return [
'provider' => 'omdb',
'provider_id' => $data['imdbID'] ?? null,
'external_ids' => [
'imdb' => $data['imdbID'] ?? null,
'omdb' => $data['imdbID'] ?? null,
],
'title' => $data['Title'] ?? null,
'original_title' => $data['Title'] ?? null,
'description' => $data['Plot'] ?? null,
'poster_url' => ($data['Poster'] ?? 'N/A') !== 'N/A' ? $data['Poster'] : null,
'backdrop_url' => null,
'genres' => $genres,
'rating' => $data['Rated'] ?? null,
'release_date' => $this->parseDate($data['Released'] ?? null),
'year' => isset($data['Year']) ? (int) substr($data['Year'], 0, 4) : null,
'runtime' => $this->parseRuntime($data['Runtime'] ?? null),
'actors' => $actors,
'directors' => $directors,
'studios' => $studios,
'countries' => $countries,
'languages' => $languages,
];
}
protected function splitList(?string $value): array
{
if (!$value || $value === 'N/A') return [];
return collect(explode(',', $value))
->map(fn($v) => trim($v))
->filter()
->values()
->all();
}
protected function parseRuntime(?string $runtime): ?int
{
if (!$runtime) return null;
if (preg_match('/(\d+) min/i', $runtime, $m)) {
return (int) $m[1];
}
return null;
}
protected function parseDate(?string $date): ?string
{
if (!$date || $date === 'N/A') return null;
// OMDb uses formats like "01 Jan 2000"
$ts = strtotime($date);
return $ts ? date('Y-m-d', $ts) : null;
}
}