mrcnpdlk/xmdb-api

View on GitHub
src/Tmdb.php

Summary

Maintainability
F
4 days
Test Coverage
<?php
/**
 * xMDB-API
 *
 * Copyright © 2017 pudelek.org.pl
 *
 * @license MIT License (MIT)
 *
 * For the full copyright and license information, please view source file
 * that is bundled with this package in the file LICENSE
 *
 * @author Marcin Pudełek <marcin@pudelek.org.pl>
 */

/**
 * Created by Marcin.
 * Date: 29.11.2017
 * Time: 21:54
 */

namespace mrcnpdlk\Xmdb;


use Carbon\Carbon;
use mrcnpdlk\Xmdb\Exception\NotFound;
use mrcnpdlk\Xmdb\Model\Tmdb\Company;
use mrcnpdlk\Xmdb\Model\Tmdb\Country;
use mrcnpdlk\Xmdb\Model\Tmdb\Genre;
use mrcnpdlk\Xmdb\Model\Tmdb\Language;
use mrcnpdlk\Xmdb\Model\Tmdb\Movie\Collection;
use mrcnpdlk\Xmdb\Model\Tmdb\Movie\Title as MovieTitle;
use mrcnpdlk\Xmdb\Model\Tmdb\Person;
use mrcnpdlk\Xmdb\Model\Tmdb\Title;
use mrcnpdlk\Xmdb\Model\Tmdb\TvShow\Network;
use mrcnpdlk\Xmdb\Model\Tmdb\TvShow\Season;
use mrcnpdlk\Xmdb\Model\Tmdb\TvShow\Title as TvShowTitle;
use RuntimeException;
use Tmdb\ApiToken;
use Tmdb\Exception\TmdbApiException;

class Tmdb
{
    /**
     * @var \mrcnpdlk\Xmdb\Client
     */
    private $oClient;
    /**
     * @var \Tmdb\Client
     */
    private $oTmdbClient;
    /**
     * @var \Psr\Log\LoggerInterface
     */
    private $oLog;

    /**
     * Tmdb constructor.
     *
     * @param \mrcnpdlk\Xmdb\Client $oClient
     *
     * @throws \mrcnpdlk\Xmdb\Exception
     */
    public function __construct(Client $oClient)
    {
        $this->oClient = $oClient;
        $this->oLog    = $oClient->getLogger();
        try {
            if (null === $this->oTmdbClient) {
                $options = [
                    'cache' => [
                        'enabled' => true,
                    ],
                    'log'   => [
                        'enabled' => true,
                    ],
                ];

                $oToken            = new ApiToken($this->oClient->getTmdbToken());
                $this->oTmdbClient = new \Tmdb\Client($oToken, $options);
            }
        } catch (\Exception $e) {
            throw new Exception(sprintf('Cannot create Tmdb Client'), 1, $e);
        }
    }

    /**
     * @param string|null $imdbId
     *
     * @return Title
     * @throws \mrcnpdlk\Xmdb\Exception\NotFound Title not found
     * @throws \mrcnpdlk\Xmdb\Exception
     */
    public function getByImdbId(string $imdbId = null)
    {
        try {
            $this->oLog->info(sprintf('Searching: %s', $imdbId));
            if ($imdbId === null || $imdbId === '') {
                throw new RuntimeException('ImdbId is require!');
            }

            $oTitle = new Title();
            $find   = $this->oTmdbClient
                ->getFindApi()
                ->findBy($imdbId, [
                    'external_source' => 'imdb_id',
                    'language'        => $this->oClient->getLang(),
                    'include_adult'   => true,
                ])
            ;
            if (!empty($find['movie_results']) && \count($find['movie_results']) === 1) {
                $item = $find['movie_results'][0];

                $oTitle->isAdult      = isset($item['adult']) ? (bool)$item['adult'] : false;
                $oTitle->title        = $item['title'];
                $oTitle->titleOrg     = $item['original_title'];
                $oTitle->titleOrgLang = $item['original_language'];
                $oTitle->id           = $item['id'];
                $oTitle->imdbId       = $imdbId;
                $oTitle->backdrop     = $item['backdrop_path'];
                $oTitle->poster       = $item['poster_path'];
                $oTitle->releaseDate  = $item['release_date'];
                $oTitle->rating       = $item['vote_average'];
                $oTitle->voteCount    = $item['vote_count'];
                $oTitle->popularity   = $item['popularity'];
                $oTitle->isMovie      = true;
                $oTitle->overview     = $item['overview'];
                $oTitle->releaseYear  = $oTitle->releaseDate ? Carbon::parse($oTitle->releaseDate)->format('Y') : null;
            } elseif (!empty($find['tv_results']) && \count($find['tv_results']) === 1) {
                $item = $find['tv_results'][0];

                $oTitle->isAdult      = isset($item['adult']) ? (bool)$item['adult'] : false;
                $oTitle->title        = $item['name'];
                $oTitle->titleOrg     = $item['original_name'];
                $oTitle->titleOrgLang = $item['original_language'];
                $oTitle->id           = $item['id'];
                $oTitle->imdbId       = $imdbId;
                $oTitle->backdrop     = $item['backdrop_path'];
                $oTitle->poster       = $item['poster_path'];
                $oTitle->releaseDate  = $item['first_air_date'];
                $oTitle->rating       = $item['vote_average'];
                $oTitle->voteCount    = $item['vote_count'];
                $oTitle->popularity   = $item['popularity'];
                $oTitle->isMovie      = false;
                $oTitle->overview     = $item['overview'];
                $oTitle->releaseYear  = $oTitle->releaseDate ? Carbon::parse($oTitle->releaseDate)->format('Y') : null;
            } elseif (!empty($find['tv_results']) && !empty($find['movie_results']) && \count($find['movie_results']) === 1  && \count($find['tv_results']) === 1
                ) {
                throw new RuntimeException('Too many items in TMDB database');
            } else {
                throw new NotFound('TMDB response empty');
            }

            return $oTitle;
        } catch (NotFound $e) {
            throw $e;
        } catch (\Exception $e) {
            throw new Exception($e->getMessage());
        }
    }

    /**
     * @param int $id
     *
     * @return \mrcnpdlk\Xmdb\Model\Tmdb\Movie\Title
     * @throws \mrcnpdlk\Xmdb\Exception\NotFound
     * @throws \mrcnpdlk\Xmdb\Exception
     */
    public function getMovie(int $id): Model\Tmdb\Movie\Title
    {
        try {
            $tData                = $this->oTmdbClient->getMoviesApi()->getMovie($id, [
                'language'      => $this->oClient->getLang(),
                'include_adult' => true,
            ])
            ;
            $oTitle               = new MovieTitle();
            $oTitle->id           = $id;
            $oTitle->title        = $tData['title'];
            $oTitle->titleOrg     = $tData['original_title'];
            $oTitle->titleOrgLang = $tData['original_language'];
            $oTitle->isVideo      = $tData['video'];
            $oTitle->isAdult      = $tData['adult'];
            $oTitle->imdbId       = $tData['imdb_id'];
            $oTitle->backdrop     = $tData['backdrop_path'];
            $oTitle->poster       = $tData['poster_path'];
            $oTitle->releaseDate  = $tData['release_date'];
            $oTitle->releaseYear  = null;
            $oTitle->rating       = $tData['vote_average'];
            $oTitle->voteCount    = $tData['vote_count'];
            $oTitle->popularity   = $tData['popularity'];
            $oTitle->overview     = $tData['overview'];
            $oTitle->homepage     = $tData['homepage'];
            $oTitle->budget       = $tData['budget'];
            $oTitle->revenue      = $tData['revenue'];
            $oTitle->runtime      = $tData['runtime'];
            $oTitle->status       = $tData['status'];
            $oTitle->tagline      = $tData['tagline'];

            foreach ($tData['genres'] ?? [] as $g) {
                $oTitle->genres[] = new Genre($g['id'], $g['name']);
            }
            foreach ($tData['production_companies'] ?? [] as $c) {
                $oTitle->productionCompanies[] = new Company($c['id'], $c['name']);
            }
            foreach ($tData['production_countries'] ?? [] as $g) {
                $oTitle->productionCountries[] = new Country($g['iso_3166_1'], $g['name']);
            }
            foreach ($tData['spoken_languages'] ?? [] as $g) {
                $oTitle->spokenLanguages[] = new Language($g['iso_639_1'], $g['name']);
            }
            if (!empty($tData['belongs_to_collection'])) {
                $oTitle->collection = new Collection(
                    $tData['belongs_to_collection']['id'],
                    $tData['belongs_to_collection']['name'],
                    $tData['belongs_to_collection']['poster_path'],
                    $tData['belongs_to_collection']['backdrop_path']);
            }

            return $oTitle;
        } catch (\Exception $e) {
            if ($e instanceof TmdbApiException) {
                if ($e->getCode() === 34) {
                    throw new NotFound($e->getMessage());
                }
                throw new Exception(sprintf('TMDB Response Error: %s', $e->getMessage()));
            }

            throw new Exception($e->getMessage());
        }
    }

    /**
     * @param int $id
     *
     * @return \mrcnpdlk\Xmdb\Model\Tmdb\TvShow\Title
     * @throws \mrcnpdlk\Xmdb\Exception\NotFound
     * @throws \mrcnpdlk\Xmdb\Exception
     */
    public function getTvShow(int $id): TvShowTitle
    {
        try {
            $tData = $this->oTmdbClient
                ->getTvApi()
                ->getTvshow($id, [
                    'language'           => $this->oClient->getLang(),
                    'include_adult'      => true,
                    'append_to_response' => 'external_ids',
                ])
            ;

            $oTitle                  = new TvShowTitle();
            $oTitle->id              = $id;
            $oTitle->title           = $tData['name'];
            $oTitle->titleOrg        = $tData['original_name'];
            $oTitle->titleOrgLang    = $tData['original_language'];
            $oTitle->inProduction    = $tData['in_production'];
            $oTitle->imdbId          = $tData['external_ids']['imdb_id'] ?? null;
            $oTitle->backdrop        = $tData['backdrop_path'];
            $oTitle->poster          = $tData['poster_path'];
            $oTitle->firstAirDate    = $tData['first_air_date'];
            $oTitle->lastAirDate     = $tData['last_air_date'];
            $oTitle->rating          = $tData['vote_average'];
            $oTitle->voteCount       = $tData['vote_count'];
            $oTitle->popularity      = $tData['popularity'];
            $oTitle->overview        = $tData['overview'];
            $oTitle->homepage        = $tData['homepage'];
            $oTitle->episodeRuntimes = $tData['episode_run_time'];
            $oTitle->status          = $tData['status'];
            $oTitle->type            = $tData['type'];
            $oTitle->languages       = $tData['languages'];
            $oTitle->episodesNumber  = $tData['number_of_episodes'];
            $oTitle->seasonsNumber   = $tData['number_of_seasons'];
            $oTitle->originCountries = $tData['origin_country'];

            foreach ($tData['genres'] ?? [] as $item) {
                $oTitle->genres[] = new Genre($item['id'], $item['name']);
            }
            foreach ($tData['networks'] ?? [] as $item) {
                $oTitle->networks[] = new Network($item['id'], $item['name']);
            }
            foreach ($tData['production_companies'] ?? [] as $item) {
                $oTitle->productionCompanies[] = new Company($item['id'], $item['name']);
            }
            foreach ($tData['seasons'] ?? [] as $item) {
                $oTitle->seasons[] = new Season(
                    $item['id'],
                    $item['season_number'],
                    $item['episode_count'],
                    $item['air_date'],
                    $item['poster_path']
                );
            }
            foreach ($tData['created_by'] ?? [] as $item) {
                $oTitle->createdBy[] = new Person(
                    $item['id'],
                    $item['name'],
                    $item['gender'],
                    $item['profile_path']
                );
            }

            return $oTitle;
        } catch (\Exception $e) {
            if ($e instanceof TmdbApiException) {
                if ($e->getCode() === 34) {
                    throw new NotFound($e->getMessage());
                }
                throw new Exception(sprintf('TMDB Response Error: %s', $e->getMessage()));
            }

            throw new Exception($e->getMessage());
        }
    }

    /**
     * @param string $title
     *
     * @return array|\mrcnpdlk\Xmdb\Model\Tmdb\Title[]
     * @throws \mrcnpdlk\Xmdb\Exception
     */
    public function searchByTitle(string $title)
    {
        try {
            /**
             * @var Title[] $answer
             */
            $answer = [];
            $tList  = $this->oTmdbClient
                ->getSearchApi()
                ->searchMulti($title, [
                    'page'          => 1,
                    'language'      => $this->oClient->getLang(),
                    'include_adult' => true,
                ])
            ;
            foreach ($tList['results'] ?? [] as $item) {
                if (\in_array($item['media_type'], ['tv', 'movie'], true)) {
                    $oTitle               = new Title();
                    $oTitle->id           = $item['id'];
                    $oTitle->isMovie      = $item['media_type'] === 'movie';
                    $oTitle->isAdult      = $item['adult'] ?? null;
                    $oTitle->title        = $oTitle->isMovie ? $item['title'] : $item['name'];
                    $oTitle->titleOrg     = $oTitle->isMovie ? $item['original_title'] : $item['original_name'];
                    $oTitle->titleOrgLang = $item['original_language'];
                    $oTitle->backdrop     = $item['backdrop_path'];
                    $oTitle->poster       = $item['poster_path'];
                    $oTitle->releaseDate  = $oTitle->isMovie ? $item['release_date'] : $item['first_air_date'];
                    $oTitle->rating       = $item['vote_average'];
                    $oTitle->voteCount    = $item['vote_count'];
                    $oTitle->popularity   = $item['popularity'];
                    $oTitle->overview     = $item['overview'];
                    $oTitle->releaseYear  = $oTitle->releaseDate ? Carbon::parse($oTitle->releaseDate)->format('Y') : null;

                    $answer[] = $oTitle;
                }
            }

            return $answer;
        } catch (\Exception $e) {
            if ($e instanceof TmdbApiException) {
                throw new Exception(sprintf('TMDB Response Error: %s', $e->getMessage()));
            }
            throw new Exception($e->getMessage());
        }
    }
}