mirror of
https://github.com/HDInnovations/UNIT3D-Community-Edition.git
synced 2026-04-24 03:59:08 -05:00
refactor: split tmdb recommendations into movies and tv
This commit is contained in:
@@ -22,7 +22,6 @@ use App\Models\TmdbCredit;
|
||||
use App\Models\TmdbGenre;
|
||||
use App\Models\TmdbMovie;
|
||||
use App\Models\TmdbPerson;
|
||||
use App\Models\TmdbRecommendation;
|
||||
use App\Models\Torrent;
|
||||
use App\Services\Tmdb\Client;
|
||||
use Illuminate\Bus\Queueable;
|
||||
@@ -108,7 +107,7 @@ class ProcessMovieJob implements ShouldQueue
|
||||
|
||||
// Recommendations
|
||||
|
||||
TmdbRecommendation::upsert($movieScraper->getRecommendations(), ['recommended_tmdb_movie_id', 'tmdb_movie_id']);
|
||||
$movie->recommendedMovies()->sync(array_unique(array_column($movieScraper->getRecommendations(), 'recommended_tmdb_movie_id')));
|
||||
|
||||
Torrent::query()
|
||||
->where('tmdb_movie_id', '=', $this->id)
|
||||
|
||||
@@ -21,7 +21,6 @@ use App\Models\TmdbCredit;
|
||||
use App\Models\TmdbGenre;
|
||||
use App\Models\TmdbNetwork;
|
||||
use App\Models\TmdbPerson;
|
||||
use App\Models\TmdbRecommendation;
|
||||
use App\Models\Torrent;
|
||||
use App\Models\TmdbTv;
|
||||
use App\Services\Tmdb\Client;
|
||||
@@ -110,7 +109,7 @@ class ProcessTvJob implements ShouldQueue
|
||||
|
||||
// Recommendations
|
||||
|
||||
TmdbRecommendation::upsert($tvScraper->getRecommendations(), ['recommended_tmdb_tv_id', 'tmdb_tv_id']);
|
||||
$tv->recommendedTv()->sync(array_unique(array_column($tvScraper->getRecommendations(), 'recommended_tmdb_tv_id')));
|
||||
|
||||
Torrent::query()
|
||||
->where('tmdb_tv_id', '=', $this->id)
|
||||
|
||||
@@ -116,20 +116,12 @@ class TmdbMovie extends Model
|
||||
return $this->belongsToMany(TmdbCollection::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany<TmdbRecommendation, $this>
|
||||
*/
|
||||
public function recommendations(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
return $this->hasMany(TmdbRecommendation::class, 'tmdb_movie_id', 'id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany<TmdbMovie, $this>
|
||||
*/
|
||||
public function recommendedMovies(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(__CLASS__, TmdbRecommendation::class, 'tmdb_movie_id', 'recommended_tmdb_movie_id', 'id', 'id');
|
||||
return $this->belongsToMany(__CLASS__, 'tmdb_recommended_movies', 'tmdb_movie_id', 'recommended_tmdb_movie_id', 'id', 'id');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* NOTICE OF LICENSE.
|
||||
*
|
||||
* UNIT3D Community Edition is open-sourced software licensed under the GNU Affero General Public License v3.0
|
||||
* The details is bundled with this project in the file LICENSE.txt.
|
||||
*
|
||||
* @project UNIT3D Community Edition
|
||||
*
|
||||
* @author HDVinnie <hdinnovations@protonmail.com>
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
|
||||
*/
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* App\Models\TmdbRecommendation.
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $title
|
||||
* @property string|null $poster
|
||||
* @property string|null $vote_average
|
||||
* @property string|null $release_date
|
||||
* @property string|null $first_air_date
|
||||
* @property int|null $tmdb_movie_id
|
||||
* @property int|null $recommended_tmdb_movie_id
|
||||
* @property int|null $tmdb_tv_id
|
||||
* @property int|null $recommended_tmdb_tv_id
|
||||
*/
|
||||
class TmdbRecommendation extends Model
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\TmdbRecommendationFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo<TmdbMovie, $this>
|
||||
*/
|
||||
public function movie(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
{
|
||||
return $this->belongsTo(TmdbMovie::class, 'tmdb_movie_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo<TmdbTv, $this>
|
||||
*/
|
||||
public function tv(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
{
|
||||
return $this->belongsTo(TmdbTv::class, 'tmdb_tv_id');
|
||||
}
|
||||
}
|
||||
@@ -137,20 +137,12 @@ class TmdbTv extends Model
|
||||
return $this->belongsToMany(TmdbCompany::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany<TmdbRecommendation, $this>
|
||||
*/
|
||||
public function recommendations(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
return $this->hasMany(TmdbRecommendation::class, 'tmdb_tv_id', 'id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany<TmdbTv, $this>
|
||||
*/
|
||||
public function recommendedTv(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(__CLASS__, TmdbRecommendation::class, 'tmdb_tv_id', 'recommended_tmdb_tv_id', 'id', 'id');
|
||||
return $this->belongsToMany(__CLASS__, 'tmdb_recommended_tv', 'tmdb_tv_id', 'recommended_tmdb_tv_id', 'id', 'id');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -390,17 +390,10 @@ class Movie
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<
|
||||
* int<0, max>,
|
||||
* array{
|
||||
* recommended_tmdb_movie_id: ?int,
|
||||
* tmdb_movie_id: ?int,
|
||||
* title: ?string,
|
||||
* vote_average: ?float,
|
||||
* poster: ?string,
|
||||
* release_date: ?string,
|
||||
* }
|
||||
* >
|
||||
* @return list<array{
|
||||
* tmdb_movie_id: ?int,
|
||||
* recommended_tmdb_movie_id: ?int,
|
||||
* }>
|
||||
*/
|
||||
public function getRecommendations(): array
|
||||
{
|
||||
@@ -412,18 +405,14 @@ class Movie
|
||||
$recommendations = [];
|
||||
|
||||
foreach ($this->data['recommendations']['results'] ?? [] as $recommendation) {
|
||||
if ($recommendation === null || $recommendation['id'] === null) {
|
||||
if ($recommendation === null || $recommendation['id'] === null || $this->data['id'] === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($movie_ids->contains($recommendation['id'])) {
|
||||
$recommendations[] = [
|
||||
'tmdb_movie_id' => $this->data['id'],
|
||||
'recommended_tmdb_movie_id' => $recommendation['id'],
|
||||
'tmdb_movie_id' => $this->data['id'] ?? null,
|
||||
'title' => $recommendation['title'] ?? null,
|
||||
'vote_average' => $recommendation['vote_average'] ?? null,
|
||||
'poster' => $this->tmdb->image('poster', $recommendation),
|
||||
'release_date' => $recommendation['release_date'] ?? null,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,17 +452,10 @@ class TV
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<
|
||||
* int<0, max>,
|
||||
* array{
|
||||
* recommended_tmdb_tv_id: ?int,
|
||||
* tmdb_tv_id: ?int,
|
||||
* title: ?string,
|
||||
* vote_average: ?float,
|
||||
* poster: ?string,
|
||||
* first_air_date: ?string,
|
||||
* }
|
||||
* >
|
||||
* @return list<array{
|
||||
* tmdb_tv_id: ?int,
|
||||
* recommended_tmdb_tv_id: ?int,
|
||||
* }>
|
||||
*/
|
||||
public function getRecommendations(): array
|
||||
{
|
||||
@@ -474,18 +467,14 @@ class TV
|
||||
$recommendations = [];
|
||||
|
||||
foreach ($this->data['recommendations']['results'] ?? [] as $recommendation) {
|
||||
if ($recommendation === null || $recommendation['id'] === null) {
|
||||
if ($recommendation === null || $recommendation['id'] === null || $this->data['id'] === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($tv_ids->contains($recommendation['id'])) {
|
||||
$recommendations[] = [
|
||||
'recommended_tmdb_tv_id' => $recommendation['id'],
|
||||
'tmdb_tv_id' => $this->data['id'],
|
||||
'title' => $recommendation['name'],
|
||||
'vote_average' => $recommendation['vote_average'],
|
||||
'poster' => $this->tmdb->image('poster', $recommendation),
|
||||
'first_air_date' => $recommendation['first_air_date'],
|
||||
'recommended_tmdb_tv_id' => $recommendation['id'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* NOTICE OF LICENSE.
|
||||
*
|
||||
* UNIT3D Community Edition is open-sourced software licensed under the GNU Affero General Public License v3.0
|
||||
* The details is bundled with this project in the file LICENSE.txt.
|
||||
*
|
||||
* @project UNIT3D Community Edition
|
||||
*
|
||||
* @author HDVinnie <hdinnovations@protonmail.com>
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
|
||||
*/
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\TmdbMovie;
|
||||
use App\Models\TmdbTv;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use App\Models\TmdbRecommendation;
|
||||
|
||||
/** @extends Factory<TmdbRecommendation> */
|
||||
class TmdbRecommendationFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* The name of the factory's corresponding model.
|
||||
*/
|
||||
protected $model = TmdbRecommendation::class;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'title' => $this->faker->sentence(),
|
||||
'poster' => $this->faker->word(),
|
||||
'vote_average' => $this->faker->word(),
|
||||
'release_date' => $this->faker->date(),
|
||||
'first_air_date' => $this->faker->date(),
|
||||
'tmdb_movie_id' => TmdbMovie::factory(),
|
||||
'recommended_tmdb_movie_id' => $this->faker->unique()->randomDigitNotNull(),
|
||||
'tmdb_tv_id' => TmdbTv::factory(),
|
||||
'recommended_tmdb_tv_id' => $this->faker->unique()->randomDigitNotNull(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* NOTICE OF LICENSE.
|
||||
*
|
||||
* UNIT3D Community Edition is open-sourced software licensed under the GNU Affero General Public License v3.0
|
||||
* The details is bundled with this project in the file LICENSE.txt.
|
||||
*
|
||||
* @project UNIT3D Community Edition
|
||||
*
|
||||
* @author Roardom <roardom@protonmail.com>
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
|
||||
*/
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('tmdb_recommended_movies', function (Blueprint $table): void {
|
||||
$table->unsignedInteger('tmdb_movie_id');
|
||||
$table->unsignedInteger('recommended_tmdb_movie_id');
|
||||
$table->primary(['tmdb_movie_id', 'recommended_tmdb_movie_id']);
|
||||
|
||||
$table->foreign('tmdb_movie_id')->references('id')->on('tmdb_movies')->cascadeOnUpdate()->cascadeOnDelete();
|
||||
$table->foreign('recommended_tmdb_movie_id')->references('id')->on('tmdb_movies')->cascadeOnUpdate()->cascadeOnDelete();
|
||||
});
|
||||
|
||||
Schema::create('tmdb_recommended_tv', function (Blueprint $table): void {
|
||||
$table->unsignedInteger('tmdb_tv_id');
|
||||
$table->unsignedInteger('recommended_tmdb_tv_id');
|
||||
$table->primary(['tmdb_tv_id', 'recommended_tmdb_tv_id']);
|
||||
|
||||
$table->foreign('tmdb_tv_id')->references('id')->on('tmdb_tv')->cascadeOnUpdate()->cascadeOnDelete();
|
||||
$table->foreign('recommended_tmdb_tv_id')->references('id')->on('tmdb_tv')->cascadeOnUpdate()->cascadeOnDelete();
|
||||
});
|
||||
|
||||
DB::table('tmdb_recommended_movies')->insertUsing(
|
||||
['tmdb_movie_id', 'recommended_tmdb_movie_id'],
|
||||
DB::table('tmdb_recommendations')
|
||||
->select([
|
||||
'tmdb_movie_id',
|
||||
'recommended_tmdb_movie_id',
|
||||
])
|
||||
->whereNotNull('tmdb_movie_id')
|
||||
->whereNotNull('recommended_tmdb_movie_id'),
|
||||
);
|
||||
|
||||
DB::table('tmdb_recommended_tv')->insertUsing(
|
||||
['tmdb_tv_id', 'recommended_tmdb_tv_id'],
|
||||
DB::table('tmdb_recommendations')
|
||||
->select([
|
||||
'tmdb_tv_id',
|
||||
'recommended_tmdb_tv_id',
|
||||
])
|
||||
->whereNotNull('tmdb_tv_id')
|
||||
->whereNotNull('recommended_tmdb_tv_id'),
|
||||
);
|
||||
|
||||
Schema::drop('tmdb_recommendations');
|
||||
}
|
||||
};
|
||||
@@ -1902,31 +1902,28 @@ CREATE TABLE `tmdb_people` (
|
||||
KEY `person_name_index` (`name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `tmdb_recommendations`;
|
||||
DROP TABLE IF EXISTS `tmdb_recommended_movies`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `tmdb_recommendations` (
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`poster` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`vote_average` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`release_date` date DEFAULT NULL,
|
||||
`first_air_date` date DEFAULT NULL,
|
||||
`tmdb_movie_id` int unsigned DEFAULT NULL,
|
||||
`recommended_tmdb_movie_id` int unsigned DEFAULT NULL,
|
||||
`tmdb_tv_id` int unsigned DEFAULT NULL,
|
||||
`recommended_tmdb_tv_id` int unsigned DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `recommendations_movie_id_recommendation_movie_id_unique` (`tmdb_movie_id`,`recommended_tmdb_movie_id`),
|
||||
UNIQUE KEY `recommendations_tv_id_recommendation_tv_id_unique` (`tmdb_tv_id`,`recommended_tmdb_tv_id`),
|
||||
KEY `recommendations_movie_id_index` (`tmdb_movie_id`),
|
||||
KEY `recommendations_recommendation_movie_id_index` (`recommended_tmdb_movie_id`),
|
||||
KEY `recommendations_tv_id_index` (`tmdb_tv_id`),
|
||||
KEY `recommendations_recommendation_tv_id_index` (`recommended_tmdb_tv_id`),
|
||||
CONSTRAINT `recommendations_movie_id_foreign` FOREIGN KEY (`tmdb_movie_id`) REFERENCES `tmdb_movies` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT `recommendations_recommendation_movie_id_foreign` FOREIGN KEY (`recommended_tmdb_movie_id`) REFERENCES `tmdb_movies` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT `recommendations_recommendation_tv_id_foreign` FOREIGN KEY (`recommended_tmdb_tv_id`) REFERENCES `tmdb_tv` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT `recommendations_tv_id_foreign` FOREIGN KEY (`tmdb_tv_id`) REFERENCES `tmdb_tv` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
CREATE TABLE `tmdb_recommended_movies` (
|
||||
`tmdb_movie_id` int unsigned NOT NULL,
|
||||
`recommended_tmdb_movie_id` int unsigned NOT NULL,
|
||||
PRIMARY KEY (`tmdb_movie_id`,`recommended_tmdb_movie_id`),
|
||||
KEY `tmdb_recommended_movies_recommended_tmdb_movie_id_foreign` (`recommended_tmdb_movie_id`),
|
||||
CONSTRAINT `tmdb_recommended_movies_recommended_tmdb_movie_id_foreign` FOREIGN KEY (`recommended_tmdb_movie_id`) REFERENCES `tmdb_movies` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT `tmdb_recommended_movies_tmdb_movie_id_foreign` FOREIGN KEY (`tmdb_movie_id`) REFERENCES `tmdb_movies` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `tmdb_recommended_tv`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!50503 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `tmdb_recommended_tv` (
|
||||
`tmdb_tv_id` int unsigned NOT NULL,
|
||||
`recommended_tmdb_tv_id` int unsigned NOT NULL,
|
||||
PRIMARY KEY (`tmdb_tv_id`,`recommended_tmdb_tv_id`),
|
||||
KEY `tmdb_recommended_tv_recommended_tmdb_tv_id_foreign` (`recommended_tmdb_tv_id`),
|
||||
CONSTRAINT `tmdb_recommended_tv_recommended_tmdb_tv_id_foreign` FOREIGN KEY (`recommended_tmdb_tv_id`) REFERENCES `tmdb_tv` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT `tmdb_recommended_tv_tmdb_tv_id_foreign` FOREIGN KEY (`tmdb_tv_id`) REFERENCES `tmdb_tv` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `tmdb_tv`;
|
||||
@@ -2942,3 +2939,4 @@ INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (342,'2025_03_23_20
|
||||
INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (343,'2025_03_25_093436_update_metadata_id_default_to_null',5);
|
||||
INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (344,'2025_03_29_215845_create_playlist_categories',6);
|
||||
INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (345,'2025_04_03_085022_drop_season_and_episodes',7);
|
||||
INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (346,'2025_04_07_152108_split_recommendations_into_movie_and_tv',8);
|
||||
|
||||
Reference in New Issue
Block a user