**/ class Client { const POST = 'post'; const GET = 'get'; const MIRROR_TYPE_XML = 1; const MIRROR_TYPE_BANNER = 2; const MIRROR_TYPE_ZIP = 4; const DEFAULT_LANGUAGE = 'en'; const FORMAT_XML = 'xml'; const FORMAT_ZIP = 'zip'; /** * Base url for TheTVDB * * @var string */ protected $baseUrl = ''; /** * API key for thetvdb.com * * @var string */ protected $apiKey = ''; /** * Array of available mirrors * * @var array */ protected $mirrors = array(); /** * Array of available languages * * @var array */ protected $languages = array(); /** * @param string $baseUrl Domain name of the api without trailing slash * @param string $apiKey Api key provided by http://thetvdb.com */ public function __construct($baseUrl, $apiKey) { $this->baseUrl = $baseUrl; $this->apiKey = $apiKey; } /** * Get a language information * * @param string $abbreviation * @return array * @throws \Exception */ public function getLanguage($abbreviation) { if (empty($this->languages)) { $this->getLanguages(); } if (!isset($this->languages[$abbreviation])) { throw new \Exception('This language is not available'); } return $this->languages[$abbreviation]; } /** * Get the server time for further updates * * @return string */ public function getServerTime() { return (string)$this->fetchXml('Updates.php?type=none')->Time; } /** * Searches for tv serie based on series name * * @param string $seriesName * @param string $language * @internal param string $seriesName the show name to search for * @return array */ public function getSeries($seriesName, $language = self::DEFAULT_LANGUAGE) { $data = $this->fetchXml('GetSeries.php?seriesname=' . urlencode($seriesName) . '&language=' . $language); $series = array(); foreach ($data->Series as $serie) { $series[] = new Serie($serie); } return $series; } /** * Find a tv serie by the id from thetvdb.com * * @var int $serieId * @var string $language * * @return Serie A serie object or false if not found **/ public function getSerie($serieId, $language = self::DEFAULT_LANGUAGE) { $data = $this->fetchXml('series/' . $serieId . '/' . $language . '.xml'); return new Serie($data->Series); } /** * Find a tv serie by a remote id * * @param array $remoteId * @param string $language * * @example
$obj->getSerieByRemoteId(array('imdbid' => ''));
* @example
$obj->getSerieByRemoteId(array('zap2it' => ''));
* * @return Serie */ public function getSerieByRemoteId(array $remoteId, $language = self::DEFAULT_LANGUAGE) { $data = $this->fetchXml('GetSeriesByRemoteID.php?' . http_build_query($remoteId) . '&language=' . $language); return new Serie($data->Series); } /** * Find all banners related to a serie * * @param int $serieId * @return string */ public function getBanners($serieId) { $data = $this->fetchXml('series/' . $serieId . '/banners.xml'); $banners = array(); foreach ($data->Banner as $banner) { $banners[] = new Banner($banner); } return $banners; } /** * Find all actors related to a serie * * @param int $serieId * @return array */ public function getActors($serieId) { $data = $this->fetchXml('series/'. $serieId . '/actors.xml'); $actors = array(); foreach ($data->Actor as $actor) { $actors [] = new Actor($actor); } return $actors; } /** * Get all episodes for a serie * * @param int $serieId * @param string $language * @param string $format * @return array * @throws \ErrorException */ public function getSerieEpisodes($serieId, $language = self::DEFAULT_LANGUAGE, $format = self::FORMAT_XML) { switch ($format) { case self::FORMAT_XML: $data = $this->fetchXml('series/' . $serieId . '/all/' . $language . '.' . $format); break; case self::FORMAT_ZIP: default: throw new \ErrorException('Unsupported format'); break; } $serie = new Serie($data->Series); $episodes = array(); foreach ($data->Episode as $episode) { $episodes[(int)$episode->id] = new Episode($episode); } return array('serie' => $serie, 'episodes' => $episodes); } /** * Get a specific episode by season and episode number * * @var int $serieId required the id of the serie * @var int $season required the season number * @var int $episode required the episode number * @var string $language language abbreviation * * @return Episode **/ public function getEpisode($serieId, $season, $episode, $language = self::DEFAULT_LANGUAGE) { $data = $this->fetchXml('series/' . $serieId . '/default/' . $season . '/' . $episode . '/' . $language . '.xml'); return new Episode($data->Episode); } /** * Get a specific episode by his id * * @var int $episodeId required the id of the episode * @var string $language * @return Episode **/ public function getEpisodeById($episodeId, $language = self::DEFAULT_LANGUAGE) { $data = $this->fetchXml('episodes/' . $episodeId . '/' . $language . '.xml'); return new Episode($data->Episode); } /** * Get updates list based on previous time you got data * * @param int $previousTime * @return array */ public function getUpdates($previousTime) { $data = $this->fetchXml('Updates.php?type=all&time=' . $previousTime); $series = array(); foreach ($data->Series as $serieId) { $series[] = (int)$serieId; } $episodes = array(); foreach ($data->Episode as $episodeId) { $episodes[] = (int)$episodeId; } return array('series' => $series, 'episodes' => $episodes); } /** * Fetches data via curl and returns result * * @access protected * @param string $function The function used to fetch data in xml * @param array $params * @param string $method * @return string The data */ protected function fetchXml($function, $params = array(), $method = self::GET) { if (strpos($function, '.php') > 0) { // no need of api key for php calls $url = $this->getMirror(self::MIRROR_TYPE_XML) . '/api/' . $function; } else { $url = $this->getMirror(self::MIRROR_TYPE_XML) . '/api/' . $this->apiKey . '/' . $function; } $data = $this->fetch($url, $params, $method); $simpleXml = $this->getXml($data); return $simpleXml; } /** * Fetch data with curl * * @param string $url * @param array $params * @param string $method * @throws CurlException * @return bool|string */ protected function fetch($url, array $params = array(), $method = self::GET) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); if ($method == self::POST) { curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $params); } $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $data = substr($response, $headerSize); curl_close($ch); if ($httpCode != 200) { throw new CurlException(sprintf('Cannot fetch %s', $url), $httpCode); } return $data; } /** * Convert xml string to SimpleXMLElement * * @param string $data * @return \SimpleXMLElement * @throws \ErrorException|\Exception */ protected function getXml($data) { if (extension_loaded('libxml')) { libxml_use_internal_errors(true); } $simpleXml = simplexml_load_string($data); if (!$simpleXml) { if (extension_loaded('libxml')) { $xmlErrors = libxml_get_errors(); $errors = array(); foreach ($xmlErrors as $error) { $errors[] = sprintf('Error in file %s on line %d with message : %s', $error->file, $error->line, $error->message); } if (count($errors) > 0) { throw new XmlException(implode("\n", $errors)); } } throw new XmlException('Xml file cound not be loaded'); } return $simpleXml; } /** * Get a list of mirrors available to fetchXml the data from the api * @return void */ protected function getMirrors() { $data = $this->fetch($this->baseUrl . '/api/' . $this->apiKey . '/mirrors.xml'); $mirrors = $this->getXml($data); foreach ($mirrors->Mirror as $mirror) { $typeMask = (int)$mirror->typemask; $mirrorPath = (string)$mirror->mirrorpath; if ($typeMask & self::MIRROR_TYPE_XML) { $this->mirrors[self::MIRROR_TYPE_XML][] = $mirrorPath; } if ($typeMask & self::MIRROR_TYPE_BANNER) { $this->mirrors[self::MIRROR_TYPE_BANNER][] = $mirrorPath; } if ($typeMask & self::MIRROR_TYPE_ZIP) { $this->mirrors[self::MIRROR_TYPE_ZIP][] = $mirrorPath; } } } /** * Get a random mirror from the list of available mirrors * * @param int $typeMask * @return string * @access protected */ public function getMirror($typeMask = self::MIRROR_TYPE_XML) { if (empty($this->mirrors)) { $this->getMirrors(); } return $this->mirrors[$typeMask][array_rand($this->mirrors[$typeMask], 1)]; } /** * Get a list of languages available for the content of the api * @return \SimpleXMLElement */ protected function getLanguages() { $languages = $this->fetchXml('languages.xml'); foreach ($languages->Language as $language) { $this->languages[(string)$language->abbreviation] = array( 'name' => (string)$language->name, 'abbreviation' => (string)$language->abbreviation, 'id' => (int)$language->id, ); } } /** * Removes indexes from an array if they are zero length after trimming * * @param array $array The array to remove empty indexes from * @return array An array with all empty indexes removed **/ public static function removeEmptyIndexes($array) { $length = count($array); for ($i = $length - 1; $i >= 0; $i--) { if (trim($array[$i]) == '') { unset($array[$i]); } } sort($array); return $array; } }