chore: tmdb client cleanup
This commit is contained in:
@@ -4,12 +4,14 @@ namespace App\Tmdb;
|
||||
|
||||
use Aimeos\Map;
|
||||
use App\Base\Enum\MediaType;
|
||||
use App\Base\Util\ImdbMatcher;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\ObjectMapper\ObjectMapper;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
use Tmdb\Api\Find;
|
||||
use Tmdb\Client;
|
||||
use Tmdb\Event\BeforeRequestEvent;
|
||||
use Tmdb\Event\HydrationEvent;
|
||||
@@ -22,22 +24,22 @@ use Tmdb\Event\RequestEvent;
|
||||
use Tmdb\Model\Movie;
|
||||
use Tmdb\Model\Tv;
|
||||
use Tmdb\Repository\MovieRepository;
|
||||
use Tmdb\Repository\SearchRepository;
|
||||
use Tmdb\Repository\TvRepository;
|
||||
use Tmdb\Repository\TvSeasonRepository;
|
||||
use Tmdb\Token\Api\ApiToken;
|
||||
use Tmdb\Token\Api\BearerToken;
|
||||
|
||||
class TmdbClient
|
||||
{
|
||||
protected Client $client;
|
||||
|
||||
protected MovieRepository $movieRepository;
|
||||
|
||||
protected TvRepository $tvRepository;
|
||||
|
||||
protected ObjectMapper $objectMapper;
|
||||
|
||||
const POSTER_IMG_PATH = "https://image.tmdb.org/t/p/w500";
|
||||
|
||||
protected Client $client;
|
||||
protected MovieRepository $movieRepository;
|
||||
protected TvRepository $tvRepository;
|
||||
protected TvSeasonRepository $tvSeasonRepository;
|
||||
protected SearchRepository $searchRepository;
|
||||
|
||||
public function __construct(
|
||||
private readonly SerializerInterface $serializer,
|
||||
private readonly CacheItemPoolInterface $cache,
|
||||
@@ -62,12 +64,8 @@ class TmdbClient
|
||||
'uri_factory' => null,
|
||||
],
|
||||
'hydration' => [
|
||||
'event_listener_handles_hydration' => true,
|
||||
'only_for_specified_models' => [
|
||||
Movie::class,
|
||||
Tv::class,
|
||||
Tv\Episode::class,
|
||||
]
|
||||
'event_listener_handles_hydration' => false,
|
||||
'only_for_specified_models' => []
|
||||
]
|
||||
]
|
||||
);
|
||||
@@ -96,54 +94,102 @@ class TmdbClient
|
||||
$userAgentListener = new UserAgentRequestListener();
|
||||
$this->eventDispatcher->addListener(BeforeRequestEvent::class, $userAgentListener);
|
||||
|
||||
// $hydrationListener = new HydrationListener($this->eventDispatcher);
|
||||
// $this->eventDispatcher->addListener(HydrationEvent::class, $hydrationListener);
|
||||
|
||||
$this->movieRepository = new MovieRepository($this->client);
|
||||
$this->tvRepository = new TvRepository($this->client);
|
||||
$this->tvSeasonRepository = new TvSeasonRepository($this->client);
|
||||
$this->searchRepository = new SearchRepository($this->client);
|
||||
}
|
||||
|
||||
public function search() {}
|
||||
public function search(string $term): TmdbResult|Map
|
||||
{
|
||||
if (ImdbMatcher::isMatch($term)) {
|
||||
$handlers = [
|
||||
'movie' => 'movieDetails',
|
||||
'tvshow' => 'tvshowDetails',
|
||||
];
|
||||
$data = $this->findByImdbId($term);
|
||||
$handler = $handlers[$data['media_type']];
|
||||
return $this->$handler($term);
|
||||
}
|
||||
return $this->parseListOfResults(
|
||||
$this->searchRepository->getApi()->searchMulti($term),
|
||||
"movies"
|
||||
);
|
||||
}
|
||||
|
||||
public function find() {}
|
||||
public function movieDetails(string $imdbId): ?TmdbResult
|
||||
{
|
||||
$tmdbId = $this->findByImdbId($imdbId)['id'];
|
||||
return $this->parseResult(
|
||||
$this->movieRepository->getApi()->getMovie($tmdbId, ['append_to_response' => 'external_ids']),
|
||||
MediaType::Movie->value,
|
||||
$imdbId
|
||||
);
|
||||
}
|
||||
|
||||
public function movieDetails() {}
|
||||
public function tvshowDetails(string $imdbId): ?TmdbResult
|
||||
{
|
||||
$tmdbId = $this->findByImdbId($imdbId)['id'];
|
||||
$media = $this->tvRepository->getApi()->getTvShow($tmdbId, ['append_to_response' => 'external_ids']);
|
||||
$media['seasons'] = Map::from($media['seasons'])->filter(function ($data) {
|
||||
return $data['season_number'] !== 0 &&
|
||||
strtolower($data['name']) !== 'specials';
|
||||
})->map(function ($data) use ($media) {
|
||||
return $this->tvSeasonDetails($media['id'], $data['season_number'])['episodes'];
|
||||
})->toArray();
|
||||
|
||||
public function tvshowDetails() {}
|
||||
return $this->parseResult(
|
||||
$media,
|
||||
MediaType::TvShow->value,
|
||||
$imdbId
|
||||
);
|
||||
}
|
||||
|
||||
public function tvEpisodeDetails() {}
|
||||
public function tvSeasonDetails(string $tmdbId, int $season): array
|
||||
{
|
||||
$result = $this->tvSeasonRepository->getApi()->getSeason($tmdbId, $season);
|
||||
$result['episodes'] = Map::from($result['episodes'])->map(function ($data) {
|
||||
$data['still_path'] = self::POSTER_IMG_PATH . $data['still_path'];
|
||||
$data['poster'] = $data['still_path'];
|
||||
return $data;
|
||||
})->toArray();
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function relatedMedia() {}
|
||||
public function relatedMedia(string $tmdbId, string $mediaType, int $resultCount = 6): Map
|
||||
{
|
||||
$repos = [
|
||||
'movies' => $this->movieRepository,
|
||||
'tvshows' => $this->tvRepository,
|
||||
];
|
||||
$results = $repos[$mediaType]->getApi()->getRecommendations($tmdbId);
|
||||
|
||||
return $this->parseListOfResults(
|
||||
$results,
|
||||
$mediaType,
|
||||
$resultCount
|
||||
);
|
||||
}
|
||||
|
||||
public function popularMovies(int $resultCount = 6): Map
|
||||
{
|
||||
$results = $this->movieRepository->getApi()->getPopular();
|
||||
return Map::from($results['results'])->map(function ($result) {
|
||||
$result['external_ids'] = $this->getExternalIds($result['id'], MediaType::Movie->value);
|
||||
return $result;
|
||||
})->filter(function ($result) {
|
||||
return array_key_exists('imdb_id', $result['external_ids']);
|
||||
})->map(function ($result) {
|
||||
$result = $this->serializer->denormalize($result, TmdbResult::class, context: ['media_type' => MediaType::Movie->value]);
|
||||
return $result;
|
||||
})->slice(0, $resultCount);
|
||||
return $this->parseListOfResults(
|
||||
$this->movieRepository->getApi()->getPopular(),
|
||||
"movies",
|
||||
$resultCount
|
||||
);
|
||||
}
|
||||
|
||||
public function popularTvShows(int $resultCount = 6): Map
|
||||
{
|
||||
$results = $this->tvRepository->getApi()->getPopular();
|
||||
return Map::from($results['results'])->map(function ($result) {
|
||||
$result['external_ids'] = $this->getExternalIds($result['id'], MediaType::Movie->value);
|
||||
return $result;
|
||||
})->filter(function ($result) {
|
||||
return array_key_exists('imdb_id', $result['external_ids']) && $result['external_ids']['imdb_id'] !== null && $result['external_ids']['imdb_id'] !== "";
|
||||
})->map(function ($result) {
|
||||
$result = $this->serializer->denormalize($result, TmdbResult::class, context: ['media_type' => MediaType::TvShow->value]);
|
||||
return $result;
|
||||
})->slice(0, $resultCount);
|
||||
return $this->parseListOfResults(
|
||||
$this->tvRepository->getApi()->getPopular(),
|
||||
"tvshows",
|
||||
$resultCount
|
||||
);
|
||||
}
|
||||
|
||||
public function getExternalIds(string $tmdbId, $mediaType)
|
||||
private function getExternalIds(string $tmdbId, $mediaType): ?array
|
||||
{
|
||||
try {
|
||||
switch (MediaType::tryFrom($mediaType)->value) {
|
||||
@@ -163,4 +209,51 @@ class TmdbClient
|
||||
|
||||
return $externalIds;
|
||||
}
|
||||
|
||||
private function findByImdbId(string $imdbId): array
|
||||
{
|
||||
$finder = new Find($this->client);
|
||||
$result = $finder->findBy($imdbId, ['external_source' => 'imdb_id']);
|
||||
|
||||
if (count($result['movie_results']) > 0) {
|
||||
return $result['movie_results'][0];
|
||||
} elseif (count($result['tv_results']) > 0) {
|
||||
return $result['tv_results'][0];
|
||||
} elseif (count($result['tv_episode_results']) > 0) {
|
||||
return $result['tv_episode_results'][0];
|
||||
}
|
||||
|
||||
throw new \Exception("No results found for $imdbId");
|
||||
}
|
||||
|
||||
private function parseResult(array $data, string $mediaType, string $imdbId): TmdbResult
|
||||
{
|
||||
if (!array_key_exists('external_ids', $data)) {
|
||||
$data['external_ids'] = ['imdb_id' => $imdbId];
|
||||
}
|
||||
return $this->serializer->denormalize($data, TmdbResult::class, context: ['media_type' => $mediaType]);
|
||||
}
|
||||
|
||||
private function parseListOfResults(array $data, string $mediaType, ?int $resultCount = null): Map
|
||||
{
|
||||
$results = Map::from($data['results'])->filter(
|
||||
fn ($result) => array_key_exists('id', $result)
|
||||
)->map(function ($result) {
|
||||
$result['external_ids'] = $this->getExternalIds($result['id'], MediaType::Movie->value);
|
||||
return $result;
|
||||
})->filter(function ($result) {
|
||||
return array_key_exists('id', $result) &&
|
||||
array_key_exists('imdb_id', $result['external_ids']) &&
|
||||
$result['external_ids']['imdb_id'] !== null &&
|
||||
$result['external_ids']['imdb_id'] !== "";
|
||||
})->map(function ($result) use ($mediaType) {
|
||||
return $this->serializer->denormalize($result, TmdbResult::class, context: ['media_type' => $mediaType]);
|
||||
});
|
||||
|
||||
if (null !== $resultCount) {
|
||||
$results = $results->slice(0, $resultCount);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user