From 36a633aabb591aae600a0e94f7720cda52b2c18f Mon Sep 17 00:00:00 2001 From: Refringe Date: Wed, 15 May 2024 00:31:24 -0400 Subject: [PATCH] First Pass on Mod Structures --- app/Http/Controllers/ModController.php | 52 +++++++++++++ app/Http/Requests/ModRequest.php | 25 +++++++ app/Http/Resources/LicenseResource.php | 21 ++++++ app/Http/Resources/ModResource.php | 28 +++++++ app/Http/Resources/ModVersionResource.php | 29 ++++++++ app/Http/Resources/SptVersionResource.php | 21 ++++++ app/Models/License.php | 23 ++++++ app/Models/Mod.php | 48 ++++++++++++ app/Models/ModVersion.php | 32 ++++++++ app/Models/SptVersion.php | 23 ++++++ app/Models/User.php | 26 ++----- app/Nova/License.php | 56 ++++++++++++++ app/Nova/Mod.php | 74 +++++++++++++++++++ app/Nova/ModVersion.php | 72 ++++++++++++++++++ app/Nova/SptVersion.php | 58 +++++++++++++++ app/Nova/User.php | 11 +-- database/factories/LicenseFactory.php | 22 ++++++ database/factories/ModFactory.php | 41 ++++++++++ database/factories/ModVersionFactory.php | 28 +++++++ database/factories/SptVersionFactory.php | 22 ++++++ ...024_05_15_022315_create_licenses_table.php | 24 ++++++ .../2024_05_15_022710_create_mods_table.php | 31 ++++++++ ...05_15_023430_create_spt_versions_table.php | 24 ++++++ ...05_15_023705_create_mod_versions_table.php | 30 ++++++++ database/seeders/DatabaseSeeder.php | 23 ++++-- 25 files changed, 810 insertions(+), 34 deletions(-) create mode 100644 app/Http/Controllers/ModController.php create mode 100644 app/Http/Requests/ModRequest.php create mode 100644 app/Http/Resources/LicenseResource.php create mode 100644 app/Http/Resources/ModResource.php create mode 100644 app/Http/Resources/ModVersionResource.php create mode 100644 app/Http/Resources/SptVersionResource.php create mode 100644 app/Models/License.php create mode 100644 app/Models/Mod.php create mode 100644 app/Models/ModVersion.php create mode 100644 app/Models/SptVersion.php create mode 100644 app/Nova/License.php create mode 100644 app/Nova/Mod.php create mode 100644 app/Nova/ModVersion.php create mode 100644 app/Nova/SptVersion.php create mode 100644 database/factories/LicenseFactory.php create mode 100644 database/factories/ModFactory.php create mode 100644 database/factories/ModVersionFactory.php create mode 100644 database/factories/SptVersionFactory.php create mode 100644 database/migrations/2024_05_15_022315_create_licenses_table.php create mode 100644 database/migrations/2024_05_15_022710_create_mods_table.php create mode 100644 database/migrations/2024_05_15_023430_create_spt_versions_table.php create mode 100644 database/migrations/2024_05_15_023705_create_mod_versions_table.php diff --git a/app/Http/Controllers/ModController.php b/app/Http/Controllers/ModController.php new file mode 100644 index 0000000..0311e1f --- /dev/null +++ b/app/Http/Controllers/ModController.php @@ -0,0 +1,52 @@ +authorize('viewAny', Mod::class); + + return ModResource::collection(Mod::all()); + } + + public function store(ModRequest $request) + { + $this->authorize('create', Mod::class); + + return new ModResource(Mod::create($request->validated())); + } + + public function show(Mod $mod) + { + $this->authorize('view', $mod); + + return new ModResource($mod); + } + + public function update(ModRequest $request, Mod $mod) + { + $this->authorize('update', $mod); + + $mod->update($request->validated()); + + return new ModResource($mod); + } + + public function destroy(Mod $mod) + { + $this->authorize('delete', $mod); + + $mod->delete(); + + return response()->json(); + } +} diff --git a/app/Http/Requests/ModRequest.php b/app/Http/Requests/ModRequest.php new file mode 100644 index 0000000..9f483ad --- /dev/null +++ b/app/Http/Requests/ModRequest.php @@ -0,0 +1,25 @@ + ['required', 'exists:users'], + 'name' => ['required'], + 'slug' => ['required'], + 'description' => ['required'], + 'license_id' => ['required', 'exists:licenses'], + 'source_code_link' => ['required'], + ]; + } + + public function authorize(): bool + { + return true; + } +} diff --git a/app/Http/Resources/LicenseResource.php b/app/Http/Resources/LicenseResource.php new file mode 100644 index 0000000..ccc580b --- /dev/null +++ b/app/Http/Resources/LicenseResource.php @@ -0,0 +1,21 @@ + $this->created_at, + 'updated_at' => $this->updated_at, + 'id' => $this->id, + 'name' => $this->name, + 'link' => $this->link, + ]; + } +} diff --git a/app/Http/Resources/ModResource.php b/app/Http/Resources/ModResource.php new file mode 100644 index 0000000..ce0d0bb --- /dev/null +++ b/app/Http/Resources/ModResource.php @@ -0,0 +1,28 @@ + $this->created_at, + 'updated_at' => $this->updated_at, + 'id' => $this->id, + 'name' => $this->name, + 'slug' => $this->slug, + 'description' => $this->description, + 'source_code_link' => $this->source_code_link, + + 'user_id' => $this->user_id, + 'license_id' => $this->license_id, + + 'license' => new LicenseResource($this->whenLoaded('license')), + ]; + } +} diff --git a/app/Http/Resources/ModVersionResource.php b/app/Http/Resources/ModVersionResource.php new file mode 100644 index 0000000..7b09558 --- /dev/null +++ b/app/Http/Resources/ModVersionResource.php @@ -0,0 +1,29 @@ + $this->created_at, + 'updated_at' => $this->updated_at, + 'id' => $this->id, + 'version' => $this->version, + 'description' => $this->description, + 'virus_total_link' => $this->virus_total_link, + 'downloads' => $this->downloads, + + 'mod_id' => $this->mod_id, + 'spt_version_id' => $this->spt_version_id, + + 'mod' => new ModResource($this->whenLoaded('mod')), + 'sptVersion' => new SptVersionResource($this->whenLoaded('sptVersion')), + ]; + } +} diff --git a/app/Http/Resources/SptVersionResource.php b/app/Http/Resources/SptVersionResource.php new file mode 100644 index 0000000..49ecf3a --- /dev/null +++ b/app/Http/Resources/SptVersionResource.php @@ -0,0 +1,21 @@ + $this->created_at, + 'updated_at' => $this->updated_at, + 'id' => $this->id, + 'version' => $this->version, + 'color_class' => $this->color_class, + ]; + } +} diff --git a/app/Models/License.php b/app/Models/License.php new file mode 100644 index 0000000..2c8363d --- /dev/null +++ b/app/Models/License.php @@ -0,0 +1,23 @@ +hasMany(Mod::class); + } +} diff --git a/app/Models/Mod.php b/app/Models/Mod.php new file mode 100644 index 0000000..437d22e --- /dev/null +++ b/app/Models/Mod.php @@ -0,0 +1,48 @@ +belongsTo(User::class); + } + + public function license(): BelongsTo + { + return $this->belongsTo(License::class); + } + + public function versions(): HasMany + { + return $this->hasMany(ModVersion::class); + } + + protected function slug(): Attribute + { + return Attribute::make( + get: fn (string $value) => strtolower($value), + set: fn (string $value) => Str::slug($value), + ); + } +} diff --git a/app/Models/ModVersion.php b/app/Models/ModVersion.php new file mode 100644 index 0000000..58bfa50 --- /dev/null +++ b/app/Models/ModVersion.php @@ -0,0 +1,32 @@ +belongsTo(Mod::class); + } + + public function spt_version(): BelongsTo + { + return $this->belongsTo(SptVersion::class, 'spt_version_id'); + } +} diff --git a/app/Models/SptVersion.php b/app/Models/SptVersion.php new file mode 100644 index 0000000..1393fd3 --- /dev/null +++ b/app/Models/SptVersion.php @@ -0,0 +1,23 @@ +hasMany(ModVersion::class); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index 3b4dde5..dbb3446 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -4,6 +4,7 @@ namespace App\Models; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Fortify\TwoFactorAuthenticatable; @@ -18,22 +19,12 @@ class User extends Authenticatable implements MustVerifyEmail use Notifiable; use TwoFactorAuthenticatable; - /** - * The attributes that are mass assignable. - * - * @var array - */ protected $fillable = [ 'name', 'email', 'password', ]; - /** - * The attributes that should be hidden for serialization. - * - * @var array - */ protected $hidden = [ 'password', 'remember_token', @@ -41,20 +32,10 @@ class User extends Authenticatable implements MustVerifyEmail 'two_factor_secret', ]; - /** - * The accessors to append to the model's array form. - * - * @var array - */ protected $appends = [ 'profile_photo_url', ]; - /** - * Get the attributes that should be cast. - * - * @return array - */ protected function casts(): array { return [ @@ -62,4 +43,9 @@ class User extends Authenticatable implements MustVerifyEmail 'password' => 'hashed', ]; } + + public function mods(): HasMany + { + return $this->hasMany(Mod::class); + } } diff --git a/app/Nova/License.php b/app/Nova/License.php new file mode 100644 index 0000000..87f8719 --- /dev/null +++ b/app/Nova/License.php @@ -0,0 +1,56 @@ +sortable(), + + Text::make('Name') + ->sortable() + ->rules('required'), + + Text::make('Link') + ->sortable() + ->rules('required'), + + HasMany::make('Mods'), + ]; + } + + public function cards(Request $request): array + { + return []; + } + + public function filters(Request $request): array + { + return []; + } + + public function lenses(Request $request): array + { + return []; + } + + public function actions(Request $request): array + { + return []; + } +} diff --git a/app/Nova/Mod.php b/app/Nova/Mod.php new file mode 100644 index 0000000..125d81d --- /dev/null +++ b/app/Nova/Mod.php @@ -0,0 +1,74 @@ +sortable(), + + Text::make('Name') + ->sortable() + ->rules('required'), + + Text::make('Slug') + ->sortable() + ->rules('required'), + + Text::make('Description') + ->sortable() + ->rules('required'), + + Text::make('Source Code Link') + ->sortable() + ->rules('required'), + + Boolean::make('Contains AI Content') + ->sortable() + ->rules('required'), + + BelongsTo::make('User', 'user', User::class), + + BelongsTo::make('License', 'license', License::class), + + HasMany::make('Versions', 'versions', ModVersion::class), + ]; + } + + public function cards(Request $request): array + { + return []; + } + + public function filters(Request $request): array + { + return []; + } + + public function lenses(Request $request): array + { + return []; + } + + public function actions(Request $request): array + { + return []; + } +} diff --git a/app/Nova/ModVersion.php b/app/Nova/ModVersion.php new file mode 100644 index 0000000..6cff9d3 --- /dev/null +++ b/app/Nova/ModVersion.php @@ -0,0 +1,72 @@ +sortable(), + + Text::make('Version') + ->sortable() + ->rules('required'), + + Text::make('Description') + ->sortable() + ->rules('required'), + + Text::make('Virus Total Link') + ->sortable() + ->rules('required'), + + Number::make('Downloads') + ->sortable() + ->rules('required', 'integer'), + + BelongsTo::make('Mod', 'mod', Mod::class), + + BelongsTo::make('SptVersion', 'spt_version', SptVersion::class), + ]; + } + + public function cards(Request $request): array + { + return []; + } + + public function filters(Request $request): array + { + return []; + } + + public function lenses(Request $request): array + { + return []; + } + + public function actions(Request $request): array + { + return []; + } +} diff --git a/app/Nova/SptVersion.php b/app/Nova/SptVersion.php new file mode 100644 index 0000000..73a138f --- /dev/null +++ b/app/Nova/SptVersion.php @@ -0,0 +1,58 @@ +sortable(), + + Text::make('Version') + ->sortable() + ->rules('required'), + + Text::make('Color Class') + ->sortable() + ->rules('required'), + ]; + } + + public function cards(Request $request): array + { + return []; + } + + public function filters(Request $request): array + { + return []; + } + + public function lenses(Request $request): array + { + return []; + } + + public function actions(Request $request): array + { + return []; + } +} diff --git a/app/Nova/User.php b/app/Nova/User.php index a4b8c55..7659462 100644 --- a/app/Nova/User.php +++ b/app/Nova/User.php @@ -2,9 +2,9 @@ namespace App\Nova; -use Illuminate\Http\Request; use Illuminate\Validation\Rules; use Laravel\Nova\Fields\Gravatar; +use Laravel\Nova\Fields\HasMany; use Laravel\Nova\Fields\ID; use Laravel\Nova\Fields\Password; use Laravel\Nova\Fields\Text; @@ -14,8 +14,6 @@ class User extends Resource { /** * The model the resource corresponds to. - * - * @var class-string<\App\Models\User> */ public static $model = \App\Models\User::class; @@ -38,7 +36,6 @@ class User extends Resource /** * Get the fields displayed by the resource. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request * @return array */ public function fields(NovaRequest $request) @@ -62,13 +59,14 @@ class User extends Resource ->onlyOnForms() ->creationRules('required', Rules\Password::defaults()) ->updateRules('nullable', Rules\Password::defaults()), + + HasMany::make('Mods', 'mods', Mod::class), ]; } /** * Get the cards available for the request. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request * @return array */ public function cards(NovaRequest $request) @@ -79,7 +77,6 @@ class User extends Resource /** * Get the filters available for the resource. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request * @return array */ public function filters(NovaRequest $request) @@ -90,7 +87,6 @@ class User extends Resource /** * Get the lenses available for the resource. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request * @return array */ public function lenses(NovaRequest $request) @@ -101,7 +97,6 @@ class User extends Resource /** * Get the actions available for the resource. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request * @return array */ public function actions(NovaRequest $request) diff --git a/database/factories/LicenseFactory.php b/database/factories/LicenseFactory.php new file mode 100644 index 0000000..3ab33d8 --- /dev/null +++ b/database/factories/LicenseFactory.php @@ -0,0 +1,22 @@ + $this->faker->name(), + 'link' => $this->faker->url, + 'created_at' => Carbon::now(), + 'updated_at' => Carbon::now(), + ]; + } +} diff --git a/database/factories/ModFactory.php b/database/factories/ModFactory.php new file mode 100644 index 0000000..61a6e3d --- /dev/null +++ b/database/factories/ModFactory.php @@ -0,0 +1,41 @@ +faker->words(3, true); + + return [ + 'user_id' => User::factory(), + 'name' => $name, + 'slug' => Str::slug($name), + 'description' => $this->faker->paragraph, + 'license_id' => License::factory(), + 'source_code_link' => $this->faker->url(), + 'contains_ai_content' => $this->faker->boolean, + 'created_at' => now(), + 'updated_at' => now(), + ]; + } + + /** + * Indicate that the mod should be soft-deleted. + */ + public function deleted(): static + { + return $this->state(fn (array $attributes) => [ + 'deleted_at' => now(), + ]); + } +} diff --git a/database/factories/ModVersionFactory.php b/database/factories/ModVersionFactory.php new file mode 100644 index 0000000..d092fcf --- /dev/null +++ b/database/factories/ModVersionFactory.php @@ -0,0 +1,28 @@ + Mod::factory(), + 'version' => $this->faker->numerify('1.#.#'), + 'description' => $this->faker->text(), + 'spt_version_id' => SptVersion::factory(), + 'virus_total_link' => $this->faker->url(), + 'downloads' => $this->faker->randomNumber(), + 'created_at' => Carbon::now(), + 'updated_at' => Carbon::now(), + ]; + } +} diff --git a/database/factories/SptVersionFactory.php b/database/factories/SptVersionFactory.php new file mode 100644 index 0000000..18095a6 --- /dev/null +++ b/database/factories/SptVersionFactory.php @@ -0,0 +1,22 @@ + $this->faker->numerify('1.#.#'), + 'color_class' => $this->faker->word(), + 'created_at' => Carbon::now(), + 'updated_at' => Carbon::now(), + ]; + } +} diff --git a/database/migrations/2024_05_15_022315_create_licenses_table.php b/database/migrations/2024_05_15_022315_create_licenses_table.php new file mode 100644 index 0000000..4e7ff7d --- /dev/null +++ b/database/migrations/2024_05_15_022315_create_licenses_table.php @@ -0,0 +1,24 @@ +id(); + $table->string('name'); + $table->string('link'); + $table->softDeletes(); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('licenses'); + } +}; diff --git a/database/migrations/2024_05_15_022710_create_mods_table.php b/database/migrations/2024_05_15_022710_create_mods_table.php new file mode 100644 index 0000000..002574d --- /dev/null +++ b/database/migrations/2024_05_15_022710_create_mods_table.php @@ -0,0 +1,31 @@ +id(); + $table->foreignIdFor(User::class)->constrained('users'); + $table->string('name'); + $table->string('slug'); + $table->longText('description'); + $table->foreignIdFor(License::class)->constrained('licenses'); + $table->string('source_code_link'); + $table->boolean('contains_ai_content')->default(false); + $table->softDeletes(); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('mods'); + } +}; diff --git a/database/migrations/2024_05_15_023430_create_spt_versions_table.php b/database/migrations/2024_05_15_023430_create_spt_versions_table.php new file mode 100644 index 0000000..a47d369 --- /dev/null +++ b/database/migrations/2024_05_15_023430_create_spt_versions_table.php @@ -0,0 +1,24 @@ +id(); + $table->string('version'); + $table->string('color_class'); + $table->softDeletes(); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('spt_versions'); + } +}; diff --git a/database/migrations/2024_05_15_023705_create_mod_versions_table.php b/database/migrations/2024_05_15_023705_create_mod_versions_table.php new file mode 100644 index 0000000..a5de806 --- /dev/null +++ b/database/migrations/2024_05_15_023705_create_mod_versions_table.php @@ -0,0 +1,30 @@ +id(); + $table->foreignIdFor(Mod::class)->constrained('mods'); + $table->string('version'); + $table->longText('description'); + $table->foreignIdFor(SptVersion::class)->constrained('spt_versions'); + $table->string('virus_total_link'); + $table->unsignedBigInteger('downloads'); + $table->softDeletes(); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('mod_versions'); + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index d01a0ef..c81ce99 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -2,8 +2,11 @@ namespace Database\Seeders; +use App\Models\License; +use App\Models\Mod; +use App\Models\ModVersion; +use App\Models\SptVersion; use App\Models\User; -// use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder @@ -13,11 +16,19 @@ class DatabaseSeeder extends Seeder */ public function run(): void { - // User::factory(10)->create(); + // Create a few SPT versions. + $spt_versions = SptVersion::factory(10)->create(); - User::factory()->create([ - 'name' => 'Test User', - 'email' => 'test@example.com', - ]); + // Create some code licenses. + $licenses = License::factory(10)->create(); + + // Add 100 users. + $users = User::factory(100)->create(); + + // Add 200 mods, assigning them to the users we just created. + $mods = Mod::factory(200)->recycle([$users, $licenses])->create(); + + // Add 1000 mod versions, assigning them to the mods we just created. + ModVersion::factory(1000)->recycle([$mods, $spt_versions])->create(); } }