diff --git a/app/Models/Show.php b/app/Models/Show.php index b64bc56..0d4994e 100644 --- a/app/Models/Show.php +++ b/app/Models/Show.php @@ -35,4 +35,14 @@ class Show extends Model 'vote_average', 'vote_count', ]; + + public function castList() + { + return $this->belongsToMany(Person::class, 'show_cast', 'show_id', 'person_id'); + } + + public function crewList() + { + return $this->belongsToMany(Person::class, 'show_crew', 'show_id', 'person_id'); + } } diff --git a/app/Models/ShowAlternativeTitle.php b/app/Models/ShowAlternativeTitle.php new file mode 100644 index 0000000..00a622b --- /dev/null +++ b/app/Models/ShowAlternativeTitle.php @@ -0,0 +1,15 @@ +showsApi = $showsApi; + $this->personApi = $personApi; } public function process($item, $job) @@ -51,12 +59,51 @@ class ShowProcessingService implements ProcessingInterface $this->processSeasons($show, $tmdbShow['seasons']); } - // @todo remove jobs from db + $this->removeElementFromRemainingJobs($item->tmdb_id, ItemToFetchJobs::JOB_DETAILS); } - private function getAlternativeTitles() + private function getAlternativeTitles($item) { + $tmdbAlternativeTitles = $this->showsApi->getAlternativeTitles($item->tmdb_id); + if (empty($tmdbAlternativeTitles) ||empty($tmdbAlternativeTitles['results'])) { + return; + } + + $show = Show::where('tmdb_id', $item->tmdb_id)->first(); + + foreach ($tmdbAlternativeTitles['results'] as $tmdbAlternativeTitle) { + $alternativeTitle = ShowAlternativeTitle::where('show_id', $show->id) + ->where('iso', $tmdbAlternativeTitle['iso_3166_1']) + ->first(); + + if (!$alternativeTitle) { + ShowAlternativeTitle::create([ + 'iso' => $tmdbAlternativeTitle['iso_3166_1'], + 'title' => $tmdbAlternativeTitle['title'], + 'show_id' => $show->id, + 'type' => $tmdbAlternativeTitle['type'], + ]); + } + } + + $this->removeElementFromRemainingJobs($item->tmdb_id, ItemToFetchJobs::JOB_ALTERNVATIVE_TITLES); + } + + private function getCredits($item) + { + $tmdbCredits = $this->showsApi->getCredits($item->tmdb_id); + + if (empty($tmdbCredits)) { + return; + } + + $show = Show::where('tmdb_id', $item->tmdb_id)->first(); + + $this->processCast($show, $tmdbCredits['cast'] ?? []); + $this->processCrew($show, $tmdbCredits['crew'] ?? []); + + $this->removeElementFromRemainingJobs($item->tmdb_id, ItemToFetchJobs::JOB_CREDITS); } private function processSeasons(Show $show, array $seasons) @@ -99,4 +146,132 @@ class ShowProcessingService implements ProcessingInterface } } } + + private function removeElementFromRemainingJobs(int $tmdbId, string $job) + { + $itemToFetchJobs = ItemToFetchJobs::where('tmdb_id', $tmdbId)->first(); + + $remainingJobs = $itemToFetchJobs->remaining_jobs; + + if (is_string($remainingJobs)) { + $remainingJobs = json_decode($remainingJobs, true); + } + + $remainingJobKey = array_search($job, $remainingJobs); + + unset($remainingJobs[$remainingJobKey]); + + if (empty($remainingJobs)) { + $itemToFetchJobs->delete(); + } + + $itemToFetchJobs->remaining_jobs = $remainingJobs; + $itemToFetchJobs->save(); + } + + private function processCast($show, array $credits) + { + if (empty($credits)) { + return; + } + + foreach ($credits as $castPerson) { + $person = Person::where('tmdb_id', $castPerson['id'])->first(); + + if (!$person) { + $personData = [ + 'adult' => $castPerson['adult'], + 'tmdb_id' => $castPerson['id'], + 'gender' => $castPerson['gender'], + 'name' => $castPerson['name'], + 'slug' => Str::slug($castPerson['name']), + 'popularity' => $castPerson['popularity'], + 'profile_path' => $castPerson['profile_path'], + ]; + + $tmdbPerson = $this->personApi->getPerson($castPerson['id']); + + if (!empty($tmdbPerson)) { + $personData = array_merge($personData, [ + 'biography' => $tmdbPerson['biography'], + 'birtday' => $tmdbPerson['birthday'], + 'deathday' => $tmdbPerson['deathday'], + 'homepage' => $tmdbPerson['homepage'], + 'imdb_id' => $tmdbPerson['imdb_id'], + 'known_for_department' => $tmdbPerson['known_for_department'] ? json_encode($tmdbPerson['known_for_department']) : null, + 'also_known_as' => $tmdbPerson['also_known_as'] ? json_encode($tmdbPerson['also_known_as']) : null, + 'place_of_birth' => $tmdbPerson['place_of_birth'], + ]); + } + + $person = Person::create($personData); + } + + if ($show->whereHas('castList', function ($query) use ($person) { + $query->where('tmdb_id', '=', $person->tmdb_id); + })->exists()) { + return; + } else { + $show->castList()->attach($person, [ + 'known_for_department' => $castPerson['known_for_department'], + 'character' => $castPerson['character'], + 'tmdb_cast_id' => $castPerson['cast_id'], + 'order' => $castPerson['order'], + ]); + } + } + } + + private function processCrew($show, array $credits) + { + if (empty($credits)) { + return; + } + + foreach ($credits as $crewPerson) { + $person = Person::where('tmdb_id', $crewPerson['id'])->first(); + + if (!$person) { + $personData = [ + 'adult' => $crewPerson['adult'], + 'tmdb_id' => $crewPerson['id'], + 'gender' => $crewPerson['gender'], + 'name' => $crewPerson['name'], + 'slug' => Str::slug($crewPerson['name']), + 'popularity' => $crewPerson['popularity'], + 'profile_path' => $crewPerson['profile_path'], + ]; + + $tmdbPerson = $this->personApi->getPerson($crewPerson['id']); + + if (!empty($tmdbPerson)) { + $personData = array_merge($personData, [ + 'biography' => $tmdbPerson['biography'], + 'birtday' => $tmdbPerson['birthday'], + 'deathday' => $tmdbPerson['deathday'], + 'homepage' => $tmdbPerson['homepage'], + 'imdb_id' => $tmdbPerson['imdb_id'], + 'known_for_department' => $tmdbPerson['known_for_department'] ? json_encode($tmdbPerson['known_for_department']) : null, + 'also_known_as' => $tmdbPerson['also_known_as'] ? json_encode($tmdbPerson['also_known_as']) : null, + 'place_of_birth' => $tmdbPerson['place_of_birth'], + ]); + } + + $person = Person::create($personData); + } + + if ($show->whereHas('crewList', function ($query) use ($person) { + $query->where('tmdb_id', '=', $person->tmdb_id); + })->exists()) { + return; + } else { + $show->crewList()->attach($person, [ + 'known_for_department' => json_encode($crewPerson['known_for_department']), + 'job' => $crewPerson['job'], + 'department' => $crewPerson['department'], + 'tmdb_cast_id' => $crewPerson['credit_id'], + ]); + } + } + } } diff --git a/database/migrations/2025_01_04_012337_create_show_alternative_titles_table.php b/database/migrations/2025_01_04_012337_create_show_alternative_titles_table.php new file mode 100644 index 0000000..7a0325a --- /dev/null +++ b/database/migrations/2025_01_04_012337_create_show_alternative_titles_table.php @@ -0,0 +1,31 @@ +id(); + $table->string('iso', 5)->nullable(); + $table->string('title', 500)->nullable(); + $table->integer('show_id')->unsigned()->nullable(); + $table->string('type', 255)->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('show_alternative_titles'); + } +}; diff --git a/database/migrations/2025_01_04_014835_create_show_cast_table.php b/database/migrations/2025_01_04_014835_create_show_cast_table.php new file mode 100644 index 0000000..fb6c391 --- /dev/null +++ b/database/migrations/2025_01_04_014835_create_show_cast_table.php @@ -0,0 +1,33 @@ +id(); + $table->bigInteger('show_id')->nullable(false); + $table->bigInteger('person_id')->nullable(false); + $table->string('known_for_department', 500)->nullable(); + $table->string('character', 500)->nullable(); + $table->string('tmdb_cast_id', 500); + $table->integer('order')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('show_cast'); + } +}; diff --git a/database/migrations/2025_01_04_014840_create_show_crew_table.php b/database/migrations/2025_01_04_014840_create_show_crew_table.php new file mode 100644 index 0000000..fcef405 --- /dev/null +++ b/database/migrations/2025_01_04_014840_create_show_crew_table.php @@ -0,0 +1,33 @@ +id(); + $table->unsignedBigInteger('show_id')->nullable(false); + $table->unsignedBigInteger('person_id')->nullable(false); + $table->string('known_for_department', 500); + $table->string('job', 500); + $table->string('department', 500); + $table->string('tmdb_cast_id', 500); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('show_crew'); + } +};