1: <?php
2: namespace Duyplus\TMDBApi;
3:
4: use Duyplus\TMDBApi\Classes\Config\APIConfiguration;
5: use Duyplus\TMDBApi\Classes\Config\Configuration;
6: use Duyplus\TMDBApi\Classes\Data\Collection;
7: use Duyplus\TMDBApi\Classes\Data\Company;
8: use Duyplus\TMDBApi\Classes\Data\Episode;
9: use Duyplus\TMDBApi\Classes\Data\Genre;
10: use Duyplus\TMDBApi\Classes\Data\Movie;
11: use Duyplus\TMDBApi\Classes\Data\Person;
12: use Duyplus\TMDBApi\Classes\Data\Season;
13: use Duyplus\TMDBApi\Classes\Data\TVShow;
14:
15: /**
16: * TMDB API v3 PHP class - wrapper to API version 3 of 'themoviedb.org
17: * API Documentation: https://developers.themoviedb.org/3/
18: * Documentation and usage in README file
19: *
20: */
21:
22: class TMDB
23: {
24: /**
25: * @var string url of API TMDB
26: */
27: const API_URL = "https://api.themoviedb.org/3/";
28:
29: /**
30: * @var Configuration
31: */
32: private $config;
33:
34: /**
35: * @var APIConfiguration
36: */
37: private $apiconfig;
38:
39: /**
40: * Construct Class
41: *
42: * @param array|null $config The necessary configuration
43: */
44: public function __construct($config = null)
45: {
46: // Set configuration
47: $this->setConfig($config);
48: // Load the API configuration
49: if (!$this->loadConfig()) {
50: if (function_exists('log_message')) {
51: log_message('error', 'TMDB API: Unable to read configuration, verify that the API key is valid');
52: }
53: throw new \RuntimeException('Unable to read configuration, verify that the API key is valid');
54: }
55: }
56:
57: //------------------------------------------------------------------------------
58: // Configuration Parameters
59: //------------------------------------------------------------------------------
60:
61: /**
62: * Set configuration parameters
63: *
64: * @param array $config
65: */
66: private function setConfig($config)
67: {
68: $this->config = new Configuration($config);
69: }
70:
71: /**
72: * Get the config parameters
73: *
74: * @return Configuration
75: */
76: private function getConfig(): Configuration
77: {
78: return $this->config;
79: }
80:
81: //------------------------------------------------------------------------------
82: // API Key
83: //------------------------------------------------------------------------------
84:
85: /**
86: * Set the API Key
87: *
88: * @param string $apikey
89: * @return void
90: */
91: public function setAPIKey(string $apikey): void
92: {
93: $this->getConfig()->setAPIKey($apikey);
94: }
95:
96: //------------------------------------------------------------------------------
97: // Language
98: //------------------------------------------------------------------------------
99:
100: /**
101: * Set the language
102: * By default english
103: *
104: * @param string $lang
105: * @return void
106: */
107: public function setLang(string $lang = 'en'): void
108: {
109: $this->getConfig()->setLang($lang);
110: }
111:
112: /**
113: * Get the language
114: *
115: * @return string
116: */
117: public function getLang(): string
118: {
119: return $this->getConfig()->getLang();
120: }
121:
122: //------------------------------------------------------------------------------
123: // TimeZone
124: //------------------------------------------------------------------------------
125:
126: /**
127: * Set the timezone
128: * By default 'Europe/London'
129: *
130: * @param string $timezone
131: * @return void
132: */
133: public function setTimeZone(string $timezone = 'Europe/Berlin'): void
134: {
135: $this->getConfig()->setTimeZone($timezone);
136: }
137:
138: /**
139: * Get the timezone
140: *
141: * @return string
142: */
143: public function getTimeZone(): string
144: {
145: return $this->getConfig()->getTimeZone();
146: }
147:
148: //------------------------------------------------------------------------------
149: // Adult Content
150: //------------------------------------------------------------------------------
151:
152: /**
153: * Set adult content flag
154: * By default false
155: *
156: * @param boolean $adult
157: * @return void
158: */
159: public function setAdult(bool $adult = false): void
160: {
161: $this->getConfig()->setAdult($adult);
162: }
163:
164: /**
165: * Get the adult content flag
166: *
167: * @return boolean
168: */
169: public function getAdult(): bool
170: {
171: return $this->getConfig()->getAdult();
172: }
173:
174: //------------------------------------------------------------------------------
175: // Debug Mode
176: //------------------------------------------------------------------------------
177:
178: /**
179: * Set debug mode
180: * By default false
181: *
182: * @param boolean $debug
183: * @return void
184: */
185: public function setDebug(bool $debug = false): void
186: {
187: $this->getConfig()->setDebug($debug);
188: }
189:
190: /**
191: * Get debug status
192: *
193: * @return boolean
194: */
195: public function getDebug(): bool
196: {
197: return $this->getConfig()->getDebug();
198: }
199:
200: //------------------------------------------------------------------------------
201: // Config
202: //------------------------------------------------------------------------------
203:
204: /**
205: * Loads the configuration of the API
206: *
207: * @return boolean
208: */
209: private function loadConfig()
210: {
211: $this->apiconfig = new APIConfiguration($this->call('configuration'));
212: return !empty($this->apiconfig);
213: }
214:
215: /**
216: * Get Configuration of the API
217: *
218: * @return APIConfiguration
219: */
220: public function getAPIConfig(): APIConfiguration
221: {
222: return $this->apiconfig;
223: }
224:
225: //------------------------------------------------------------------------------
226: // Get Variables
227: //------------------------------------------------------------------------------
228:
229: /**
230: * Get the URL images
231: * You can specify the width, by default original
232: *
233: * @param string $size A String like 'w185' where you specify the image width
234: * @return string
235: */
236: public function getImageURL(string $size = 'original'): string
237: {
238: return $this->apiconfig->getImageBaseURL() . $size;
239: }
240:
241: //------------------------------------------------------------------------------
242: // Get Lists of Discover
243: //------------------------------------------------------------------------------
244:
245: /**
246: * Discover Movies
247: *
248: * @return Movie[]
249: */
250: public function getDiscoverMovies(int $page = 1): array
251: {
252: $movies = array();
253: $result = $this->call('discover/movie', '&page=' . $page);
254: foreach ($result['results'] as $data) {
255: $movies[] = new Movie($data);
256: }
257: return $movies;
258: }
259:
260: /**
261: * Discover TVShows
262: * @add by tnsws
263: *
264: * @param int $page
265: * @return TVShow[]
266: */
267: public function getDiscoverTVShows(int $page = 1): array
268: {
269: $tvShows = array();
270: $result = $this->call('discover/tv', '&page=' . $page);
271: foreach ($result['results'] as $data) {
272: $tvShows[] = new TVShow($data);
273: }
274: return $tvShows;
275: }
276:
277: //------------------------------------------------------------------------------
278: // Get Lists of Discover
279: //------------------------------------------------------------------------------
280:
281: /**
282: * Discover Movie
283: *
284: * @param int $page
285: * @return array
286: */
287: public function getDiscoverMovie(int $page = 1): array
288: {
289: $movies = array();
290: $result = $this->call('discover/movie', '&page=' . $page);
291: foreach ($result['results'] as $data) {
292: $movies[] = new Movie($data);
293: }
294: return $movies;
295: }
296:
297: //------------------------------------------------------------------------------
298: // Get Featured Movies
299: //------------------------------------------------------------------------------
300:
301: /**
302: * Get latest Movie
303: *
304: * @return Movie
305: */
306: public function getLatestMovie(): Movie
307: {
308: return new Movie($this->call('movie/latest'));
309: }
310:
311: /**
312: * Get Now Playing Movies
313: *
314: * @param integer $page
315: * @return Movie[]
316: */
317: public function getNowPlayingMovies(int $page = 1): array
318: {
319: $movies = array();
320: $result = $this->call('movie/now_playing', '&page=' . $page);
321: foreach ($result['results'] as $data) {
322: $movies[] = new Movie($data);
323: }
324: return $movies;
325: }
326:
327: /**
328: * Get Popular Movies
329: *
330: * @param integer $page
331: * @return Movie[]
332: */
333: public function getPopularMovies(int $page = 1): array
334: {
335: $movies = array();
336: $result = $this->call('movie/popular', '&page=' . $page);
337: foreach ($result['results'] as $data) {
338: $movies[] = new Movie($data);
339: }
340: return $movies;
341: }
342:
343: /**
344: * Get Top Rated Movies
345: * @add by tnsws
346: *
347: * @param integer $page
348: * @return Movie[]
349: */
350: public function getTopRatedMovies(int $page = 1): array
351: {
352: $movies = array();
353: $result = $this->call('movie/top_rated', '&page=' . $page);
354: foreach ($result['results'] as $data) {
355: $movies[] = new Movie($data);
356: }
357: return $movies;
358: }
359:
360: /**
361: * Get Upcoming Movies
362: * @add by tnsws
363: *
364: * @param integer $page
365: * @return Movie[]
366: */
367: public function getUpcomingMovies(int $page = 1): array
368: {
369: $movies = array();
370: $result = $this->call('movie/upcoming', '&page=' . $page);
371: foreach ($result['results'] as $data) {
372: $movies[] = new Movie($data);
373: }
374: return $movies;
375: }
376:
377: //------------------------------------------------------------------------------
378: // Get Featured TVShows
379: //------------------------------------------------------------------------------
380:
381: /**
382: * Get latest TVShow
383: *
384: * @return TVShow
385: */
386: public function getLatestTVShow(): TVShow
387: {
388: return new TVShow($this->call('tv/latest'));
389: }
390:
391: /**
392: * Get On The Air TVShows
393: *
394: * @param int $page
395: * @return TVShow[]
396: */
397: public function getOnTheAirTVShows(int $page = 1): array
398: {
399: $tvShows = array();
400: $result = $this->call('tv/on_the_air', '&page=' . $page);
401: foreach ($result['results'] as $data) {
402: $tvShows[] = new TVShow($data);
403: }
404: return $tvShows;
405: }
406:
407: /**
408: * Get Airing Today TVShows
409: *
410: * @param int $page
411: * @param string $timezone
412: * @return TVShow[]
413: */
414: public function getAiringTodayTVShows(int $page = 1, ?string $timeZone = null): array
415: {
416: $timeZone = (isset($timeZone)) ? $timeZone : $this->getConfig()->getTimeZone();
417: $tvShows = array();
418: $result = $this->call('tv/airing_today', '&page=' . $page);
419: foreach ($result['results'] as $data) {
420: $tvShows[] = new TVShow($data);
421: }
422: return $tvShows;
423: }
424:
425: /**
426: * Get Top Rated TVShows
427: *
428: * @param int $page
429: * @return TVShow[]
430: */
431: public function getTopRatedTVShows(int $page = 1): array
432: {
433: $tvShows = array();
434: $result = $this->call('tv/top_rated', '&page=' . $page);
435: foreach ($result['results'] as $data) {
436: $tvShows[] = new TVShow($data);
437: }
438: return $tvShows;
439: }
440:
441: /**
442: * Get Popular TVShows
443: *
444: * @param int $page
445: * @return TVShow[]
446: */
447: public function getPopularTVShows(int $page = 1): array
448: {
449: $tvShows = array();
450: $result = $this->call('tv/popular', '&page=' . $page);
451: foreach ($result['results'] as $data) {
452: $tvShows[] = new TVShow($data);
453: }
454: return $tvShows;
455: }
456:
457: //------------------------------------------------------------------------------
458: // Get Featured Persons
459: //------------------------------------------------------------------------------
460:
461: /**
462: * Get latest Person
463: *
464: * @return Person
465: */
466: public function getLatestPerson(): Person
467: {
468: return new Person($this->call('person/latest'));
469: }
470:
471: /**
472: * Get Popular Persons
473: *
474: * @param int $page
475: * @return Person[]
476: */
477: public function getPopularPersons(int $page = 1): array
478: {
479: $persons = array();
480: $result = $this->call('person/popular', '&page=' . $page);
481: foreach ($result['results'] as $data) {
482: $persons[] = new Person($data);
483: }
484: return $persons;
485: }
486:
487: //------------------------------------------------------------------------------
488: // API Call
489: //------------------------------------------------------------------------------
490:
491: /**
492: * Makes the call to the API and retrieves the data as a JSON
493: *
494: * @param string $action API specific function name for the URL
495: * @param string $appendToResponse The extra append of the request
496: * @return array
497: */
498: private function call($action, $appendToResponse = '')
499: {
500: $url = self::API_URL . $action . '?api_key=' . $this->getConfig()->getAPIKey() .
501: '&language=' . $this->getConfig()->getLang() .
502: '&append_to_response=' . implode(',', (array) $appendToResponse) .
503: '&include_adult=' . ($this->getConfig()->getAdult() ? 'true' : 'false');
504:
505: if ($this->getConfig()->getDebug()) {
506: if (function_exists('log_message')) {
507: log_message('debug', 'TMDB API Request: ' . $url);
508: } else {
509: echo '<pre><a href="' . $url . '">check request</a></pre>';
510: }
511: }
512:
513: $ch = curl_init();
514: curl_setopt($ch, CURLOPT_URL, $url);
515: curl_setopt($ch, CURLOPT_HEADER, 0);
516: curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
517: curl_setopt($ch, CURLOPT_FAILONERROR, 1);
518: curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
519:
520: $results = curl_exec($ch);
521:
522: if (curl_errno($ch)) {
523: if (function_exists('log_message')) {
524: log_message('error', 'TMDB API Error: ' . curl_error($ch));
525: }
526: return [];
527: }
528:
529: $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
530: curl_close($ch);
531:
532: if ($httpCode >= 400) {
533: if (function_exists('log_message')) {
534: log_message('error', 'TMDB API HTTP Error: ' . $httpCode);
535: }
536: return [];
537: }
538:
539: $decoded = json_decode($results, true);
540: return is_array($decoded) ? $decoded : [];
541: }
542:
543: //------------------------------------------------------------------------------
544: // Get Data Objects
545: //------------------------------------------------------------------------------
546:
547: /**
548: * Get a Movie
549: *
550: * @param int $idMovie The Movie id
551: * @param array $appendToResponse The extra append of the request
552: * @return Movie
553: */
554: public function getMovie(int $idMovie, $appendToResponse = null): Movie
555: {
556: $appendToResponse = (isset($appendToResponse)) ? $appendToResponse : $this->getConfig()->getAppender('movie');
557: return new Movie($this->call('movie/' . $idMovie, $appendToResponse));
558: }
559:
560: /**
561: * Get a TVShow
562: *
563: * @param int $idTVShow The TVShow id
564: * @param array $appendToResponse The extra append of the request
565: * @return TVShow
566: */
567: public function getTVShow(int $idTVShow, $appendToResponse = null): TVShow
568: {
569: $appendToResponse = (isset($appendToResponse)) ? $appendToResponse : $this->getConfig()->getAppender('tvshow');
570: return new TVShow($this->call('tv/' . $idTVShow, $appendToResponse));
571: }
572:
573: /**
574: * Get a Season
575: *
576: * @param int $idTVShow The TVShow id
577: * @param int $numSeason The Season number
578: * @param array $appendToResponse The extra append of the request
579: * @return Season
580: */
581: public function getSeason(int $idTVShow, int $numSeason, $appendToResponse = null): Season
582: {
583: $appendToResponse = (isset($appendToResponse)) ? $appendToResponse : $this->getConfig()->getAppender('season');
584: return new Season($this->call('tv/' . $idTVShow . '/season/' . $numSeason, $appendToResponse), $idTVShow);
585: }
586:
587: /**
588: * Get a Episode
589: *
590: * @param int $idTVShow The TVShow id
591: * @param int $numSeason The Season number
592: * @param int $numEpisode the Episode number
593: * @param array $appendToResponse The extra append of the request
594: * @return Episode
595: */
596: public function getEpisode(int $idTVShow, int $numSeason, int $numEpisode, $appendToResponse = null): Episode
597: {
598: $appendToResponse = (isset($appendToResponse)) ? $appendToResponse : $this->getConfig()->getAppender('episode');
599: return new Episode($this->call('tv/' . $idTVShow . '/season/' . $numSeason . '/episode/' . $numEpisode, $appendToResponse), $idTVShow);
600: }
601:
602: /**
603: * Get a Person
604: *
605: * @param int $idPerson The Person id
606: * @param array $appendToResponse The extra append of the request
607: * @return Person
608: */
609: public function getPerson(int $idPerson, $appendToResponse = null): Person
610: {
611: $appendToResponse = (isset($appendToResponse)) ? $appendToResponse : $this->getConfig()->getAppender('person');
612: return new Person($this->call('person/' . $idPerson, $appendToResponse));
613: }
614:
615: /**
616: * Get a Collection
617: *
618: * @param int $idCollection The Collection id
619: * @param array $appendToResponse The extra append of the request
620: * @return Collection
621: */
622: public function getCollection(int $idCollection, $appendToResponse = null): Collection
623: {
624: $appendToResponse = (isset($appendToResponse)) ? $appendToResponse : $this->getConfig()->getAppender('collection');
625: return new Collection($this->call('collection/' . $idCollection, $appendToResponse));
626: }
627:
628: /**
629: * Get a Company
630: *
631: * @param int $idCompany The Company id
632: * @param array $appendToResponse The extra append of the request
633: * @return Company
634: */
635: public function getCompany(int $idCompany, $appendToResponse = null): Company
636: {
637: $appendToResponse = (isset($appendToResponse)) ? $appendToResponse : $this->getConfig()->getAppender('company');
638: return new Company($this->call('company/' . $idCompany, $appendToResponse));
639: }
640:
641: //------------------------------------------------------------------------------
642: // Searches
643: //------------------------------------------------------------------------------
644:
645: /**
646: * Search Multi
647: *
648: * @param string $query The query to search for
649: * @param int $page
650: * @return array
651: */
652: public function multiSearch(string $query, int $page = 1): array
653: {
654: $searchResults = array(
655: Movie::MEDIA_TYPE_MOVIE => array(),
656: TVShow::MEDIA_TYPE_TV => array(),
657: Person::MEDIA_TYPE_PERSON => array(),
658: );
659:
660: $result = $this->call('search/multi', '&query=' . urlencode($query) . '&page=' . $page);
661:
662: if (!isset($result['results']) || empty($result['results'])) {
663: return $searchResults;
664: }
665:
666: foreach ($result['results'] as $data) {
667: if ($data['media_type'] === Movie::MEDIA_TYPE_MOVIE) {
668: $searchResults[Movie::MEDIA_TYPE_MOVIE][] = new Movie($data);
669: } elseif ($data['media_type'] === TVShow::MEDIA_TYPE_TV) {
670: $searchResults[TVShow::MEDIA_TYPE_TV][] = new TVShow($data);
671: } elseif ($data['media_type'] === Person::MEDIA_TYPE_PERSON) {
672: $searchResults[Person::MEDIA_TYPE_PERSON][] = new Person($data);
673: }
674: }
675: return $searchResults;
676: }
677:
678: /**
679: * Search Movie
680: *
681: * @param string $movieTitle The title of a Movie
682: * @return Movie[]
683: */
684: public function searchMovie(string $movieTitle): array
685: {
686: $movies = array();
687: $result = $this->call('search/movie', '&query=' . urlencode($movieTitle));
688: foreach ($result['results'] as $data) {
689: $movies[] = new Movie($data);
690: }
691: return $movies;
692: }
693:
694: /**
695: * Search TVShow
696: *
697: * @param string $tvShowTitle The title of a TVShow
698: * @return TVShow[]
699: */
700: public function searchTVShow(string $tvShowTitle): array
701: {
702: $tvShows = array();
703: $result = $this->call('search/tv', '&query=' . urlencode($tvShowTitle));
704: foreach ($result['results'] as $data) {
705: $tvShows[] = new TVShow($data);
706: }
707: return $tvShows;
708: }
709:
710: /**
711: * Search Person
712: *
713: * @param string $personName The name of the Person
714: * @return Person[]
715: */
716: public function searchPerson(string $personName): array
717: {
718: $persons = array();
719: $result = $this->call('search/person', '&query=' . urlencode($personName));
720: foreach ($result['results'] as $data) {
721: $persons[] = new Person($data);
722: }
723: return $persons;
724: }
725:
726: /**
727: * Search Collection
728: *
729: * @param string $collectionName The name of the Collection
730: * @return Collection[]
731: */
732: public function searchCollection(string $collectionName): array
733: {
734: $collections = array();
735: $result = $this->call('search/collection', '&query=' . urlencode($collectionName));
736: foreach ($result['results'] as $data) {
737: $collections[] = new Collection($data);
738: }
739: return $collections;
740: }
741:
742: /**
743: * Search Company
744: *
745: * @param string $companyName The name of the Company
746: * @return Company[]
747: */
748: public function searchCompany(string $companyName): array
749: {
750: $companies = array();
751: $result = $this->call('search/company', '&query=' . urlencode($companyName));
752: foreach ($result['results'] as $data) {
753: $companies[] = new Company($data);
754: }
755: return $companies;
756: }
757:
758: //------------------------------------------------------------------------------
759: // Find
760: //------------------------------------------------------------------------------
761:
762: /**
763: * Find
764: *
765: * @param string $id The ID from external source
766: * @param string $external_source The external source (e.g., 'imdb_id')
767: * @return array
768: */
769: public function find(string $id, string $external_source = 'imdb_id'): array
770: {
771: $found = array();
772: $result = $this->call('find/' . $id, '&external_source=' . urlencode($external_source));
773: foreach ($result['movie_results'] as $data) {
774: $found['movies'][] = new Movie($data);
775: }
776: foreach ($result['person_results'] as $data) {
777: $found['persons'][] = new Person($data);
778: }
779: foreach ($result['tv_results'] as $data) {
780: $found['tvshows'][] = new TVShow($data);
781: }
782: foreach ($result['tv_season_results'] as $data) {
783: $found['seasons'][] = new Season($data);
784: }
785: foreach ($result['tv_episode_results'] as $data) {
786: $found['episodes'][] = new Episode($data);
787: }
788: return $found;
789: }
790:
791: //------------------------------------------------------------------------------
792: // API Extra Info
793: //------------------------------------------------------------------------------
794:
795: /**
796: * Get Timezones
797: *
798: * @return array
799: */
800: public function getTimezones(): array
801: {
802: return $this->call('timezones/list');
803: }
804:
805: /**
806: * Get Jobs
807: *
808: * @return array
809: */
810: public function getJobs(): array
811: {
812: return $this->call('job/list');
813: }
814:
815: /**
816: * Get Movie Genres
817: *
818: * @return Genre[]
819: */
820: public function getMovieGenres(): array
821: {
822: $genres = array();
823: $result = $this->call('genre/movie/list');
824: foreach ($result['genres'] as $data) {
825: $genres[] = new Genre($data);
826: }
827: return $genres;
828: }
829:
830: /**
831: * Get TV Genres
832: *
833: * @return Genre[]
834: */
835: public function getTVGenres(): array
836: {
837: $genres = array();
838: $result = $this->call('genre/tv/list');
839: foreach ($result['genres'] as $data) {
840: $genres[] = new Genre($data);
841: }
842: return $genres;
843: }
844:
845: /**
846: * Get Movies by Genre
847: *
848: * @param int $idGenre
849: * @param int $page
850: * @return Movie[]
851: */
852: public function getMoviesByGenre(int $idGenre, int $page = 1): array
853: {
854: $movies = array();
855: $result = $this->call('genre/' . $idGenre . '/movies', '&page=' . $page);
856: foreach ($result['results'] as $data) {
857: $movies[] = new Movie($data);
858: }
859: return $movies;
860: }
861:
862: /**
863: * Search Movies by Year
864: *
865: * @param int $year
866: * @param int $page
867: * @return array
868: */
869: public function searchMoviesByYear(int $year, int $page = 1): array
870: {
871: $movies = array();
872: $result = $this->call('discover/movie', '&page=' . $page . "&year=" . $year);
873:
874: if (!isset($result['results'])) {
875: return $movies;
876: }
877:
878: foreach ($result['results'] as $data) {
879: $movies[] = new Movie($data);
880: }
881: return $movies;
882: }
883:
884: /**
885: * Get TVShows by Year
886: *
887: * @param int $year
888: * @param int $page
889: * @return array
890: */
891: public function searchTVShowsByYear(int $year, int $page = 1): array
892: {
893: $tvShows = array();
894: $result = $this->call('discover/tv', '&page=' . $page . "&first_air_date_year=" . $year);
895:
896: if (!isset($result['results'])) {
897: return $tvShows;
898: }
899:
900: foreach ($result['results'] as $data) {
901: $tvShows[] = new TVShow($data);
902: }
903: return $tvShows;
904: }
905: }