diff --git a/src/Enum/MediaType.php b/src/Enum/MediaType.php new file mode 100644 index 0000000..6503aa0 --- /dev/null +++ b/src/Enum/MediaType.php @@ -0,0 +1,8 @@ +client = new Client( + [ + /** @var ApiToken|BearerToken */ + 'api_token' => new BearerToken($apiKey), + 'secure' => true, + 'base_uri' => Client::TMDB_URI, + 'event_dispatcher' => [ + 'adapter' => $this->eventDispatcher, + ], + // We make use of PSR-17 and PSR-18 auto discovery to automatically guess these, but preferably set these explicitly. + 'http' => [ + 'client' => null, + 'request_factory' => null, + 'response_factory' => null, + 'stream_factory' => null, + 'uri_factory' => null, + ], + 'hydration' => [ + 'event_listener_handles_hydration' => false, + 'only_for_specified_models' => [] + ] + ] + ); + + /** + * Required event listeners and events to be registered with the PSR-14 Event Dispatcher. + */ + $requestListener = new RequestListener($this->client->getHttpClient(), $this->eventDispatcher); + $this->eventDispatcher->addListener(RequestEvent::class, $requestListener); + + $apiTokenListener = new ApiTokenRequestListener($this->client->getToken()); + $this->eventDispatcher->addListener(BeforeRequestEvent::class, $apiTokenListener); + + $acceptJsonListener = new AcceptJsonRequestListener(); + $this->eventDispatcher->addListener(BeforeRequestEvent::class, $acceptJsonListener); + + $jsonContentTypeListener = new ContentTypeJsonRequestListener(); + $this->eventDispatcher->addListener(BeforeRequestEvent::class, $jsonContentTypeListener); + + $userAgentListener = new UserAgentRequestListener(); + $this->eventDispatcher->addListener(BeforeRequestEvent::class, $userAgentListener); + + $this->movieRepository = new MovieRepository($this->client); + $this->tvRepository = new TvRepository($this->client); + } + + public function popularMovies(int $page = 1) + { + $movies = $this->movieRepository->getPopular(['page' => $page]); + + foreach ($movies as $movie) { + $this->parseResult($movie); + } + + return $movies; + } + + public function search(string $term, int $page = 1) + { + $searchRepository = new SearchRepository($this->client); + $searchResults = $searchRepository->searchMulti($term, new KeywordSearchQuery(['page' => $page])); + + $results = []; + foreach ($searchResults as $result) { + if (!$result instanceof Movie && !$result instanceof Tv) { + continue; + } + $results[] = $this->parseResult($result); + } + + return $results; + } + + public function find(string $id) + { + $finder = new Find($this->client); + $result = $finder->findBy($id, ['external_source' => 'imdb_id']); + return $this->parseResult($result); + } + + public function movieDetails(string $id) + { + $client = new MovieRepository($this->client); + $details = $client->getApi()->getMovie($id, ['append_to_response' => 'external_ids']); + return $this->parseResult($details, "movie"); + } + + public function tvDetails(string $id) + { + $client = new TvRepository($this->client); + $details = $client->getApi()->getTvshow($id, ['append_to_response' => 'external_ids,seasons']); + $details = $this->getEpisodesFromSeries($details); + return $this->parseResult($details, "tv"); + } + + public function getEpisodesFromSeries(array $series) + { + $client = new TvSeasonRepository($this->client); + foreach ($series['seasons'] as $season) { + if ($season['episode_count'] <= 0 || $season['name'] === 'Specials') { + continue; + } + + $series['episodes'][$season['season_number']] = $client->getApi()->getSeason($series['id'], $season['season_number'])['episodes']; + } + return $series; + } + + public function mediaDetails(string $id, string $type) + { + if ($type === "movies") { + return $this->movieDetails($id); + } else { + return $this->tvDetails($id); + } + } + + private function parseResult($result, $mediaType = null) + { + if (is_array($result)) { + return $this->parseFromArray($result, $mediaType); + } else { + return $this->parseFromObject($result); + } + } + + private function parseFromArray($data, $mediaType) + { + if (null === $mediaType) { + throw new \Exception("A media type must be set when parsing from an array."); + } + + function parseTvShow(array $data, string $posterBasePath): MediaResult { + return new MediaResult( + imdbId: $data['external_ids']['imdb_id'], + tvdbId: $data['id'], + title: $data['name'], + poster: $posterBasePath . $data['poster_path'], + excerpt: $data['overview'], + year: (new \DateTime($data['first_air_date']))->format('Y'), + mediaType: "tvshows", + episodes: $data['episodes'], + ); + } + + function parseMovie(array $data, string $posterBasePath): MediaResult { + return new MediaResult( + imdbId: $data['external_ids']['imdb_id'], + tvdbId: $data['id'], + title: $data['title'], + poster: $posterBasePath . $data['poster_path'], + excerpt: $data['overview'], + year: (new \DateTime($data['release_date']))->format('Y'), + mediaType: "movies", + ); + } + + $posterBasePath = self::POSTER_IMG_PATH; + $result = ("movie" === $mediaType) ? parseMovie($data, $posterBasePath) : parseTvShow($data, $posterBasePath); + + return $result; + } + + private function parseFromObject($result) + { + $result->mediaType = $result instanceof Movie ? 'movies' : 'tvshows'; + + $externalIds = $this->cache->get("tmdb.externalIds.{$result->getId()}", function (ItemInterface $item) use ($result) { + if ($result instanceof Movie) { + $externalIds = $this->movieRepository->getExternalIds($result->getId()); + } else { + $externalIds = $this->tvRepository->getExternalIds($result->getId()); + } + return $externalIds; + }); + + $images = $this->cache->get("tmdb.images.{$result->getId()}", function (ItemInterface $item) use ($result) { + if ($result instanceof Movie) { + $images = $this->movieRepository->getImages($result->getId()); + } else { + $images = $this->tvRepository->getImages($result->getId()); + } + return $images; + }); + + if (null !== $externalIds) { + $imdbId = $externalIds->getImdbId() !== "" ? $externalIds->getImdbId() : "null"; + + if ("movies" === $result->mediaType) { + $result->setImdbId($imdbId); + } else { + $result->imdbId = $imdbId; + $result->title = $result->getName(); + } + } else { + if ("movies" === $result->mediaType) { + $result->setImdbId("null"); + } else { + $result->imdbId = "null"; + } + } + + if ("movies" === $result->mediaType) { + if ($result->getReleaseDate() instanceof \DateTime) { + $result->year = $result->getReleaseDate()->format("Y"); + } else { + $result->year = (new \DateTime($result->getReleaseDate()))->format('Y'); + } + } else { + if ($result->getFirstAirDate() instanceof \DateTime) { + $result->year = $result->getFirstAirDate()->format("Y"); + } else { + $result->year = (new \DateTime($result->getFirstAirDate()))->format('Y'); + } + } + + /** @var Movie $result */ + $result->setExternalIds($externalIds); + + $result->setImages($images); + $result->getPosterImage()->setFilePath( + self::POSTER_IMG_PATH . $result->getPosterImage()->getFilePath() + ); + + return $result; + } +} diff --git a/src/Tmdb/TmdbResult.php b/src/Tmdb/TmdbResult.php new file mode 100644 index 0000000..7e2974b --- /dev/null +++ b/src/Tmdb/TmdbResult.php @@ -0,0 +1,17 @@ +