From f8e4a0ffe520eb9a714907047f5d1097eece3ef9 Mon Sep 17 00:00:00 2001 From: kyledoesdev Date: Mon, 8 Jun 2026 23:21:25 -0400 Subject: [PATCH] refactor(enums): Convert Asset and Connection types to string-backed enums Updates `AssetType` and `ConnectionType` enums to use string values instead of integers. This involves renaming `type_id` columns to `type` in the `assets` and `connections` tables, along with a data migration to convert existing integer values to their new string representations. The change enhances readability, improves type safety, and simplifies related logic by leveraging native Laravel string-backed enum casting. --- app/Actions/Api/Spotify/RefreshToken.php | 2 +- app/Actions/Api/Spotify/SearchArtist.php | 2 +- app/Actions/Api/Spotify/SearchTrack.php | 2 +- app/Actions/Api/Twitch/RefreshToken.php | 2 +- app/Actions/Api/Twitch/SearchCategories.php | 2 +- .../Commands/CheckTwitchLiveStatus.php | 2 +- app/Console/Commands/UpdateArtistImages.php | 2 +- app/Enums/AssetType.php | 8 +-- app/Enums/ConnectionType.php | 18 ++---- app/Http/Controllers/ConnectionController.php | 24 +++----- app/Livewire/Forms/PhotoForm.php | 6 +- app/Livewire/Navigation.php | 2 +- app/Livewire/Photos/Gallery.php | 4 +- app/Livewire/Photos/Uploader.php | 2 +- app/Livewire/Resume.php | 4 +- app/Models/Asset.php | 4 +- app/Models/Connection.php | 3 +- database/factories/AssetFactory.php | 6 +- ...112_rename_connections_type_id_to_type.php | 22 +++++++ ...9_031113_rename_assets_type_id_to_type.php | 57 +++++++++++++++++++ resources/views/livewire/connection.blade.php | 4 +- .../livewire/pages/media/games/show.blade.php | 2 +- .../livewire/pages/media/music/edit.blade.php | 4 +- 23 files changed, 124 insertions(+), 60 deletions(-) create mode 100644 database/migrations/2026_06_09_031112_rename_connections_type_id_to_type.php create mode 100644 database/migrations/2026_06_09_031113_rename_assets_type_id_to_type.php diff --git a/app/Actions/Api/Spotify/RefreshToken.php b/app/Actions/Api/Spotify/RefreshToken.php index 26b13a7..9819d97 100644 --- a/app/Actions/Api/Spotify/RefreshToken.php +++ b/app/Actions/Api/Spotify/RefreshToken.php @@ -13,7 +13,7 @@ final class RefreshToken public function handle(User $user): bool { try { - $spotifyConnection = $user->connections->firstWhere('type_id', ConnectionType::SPOTIFY->value); + $spotifyConnection = $user->connections->firstWhere('type', ConnectionType::SPOTIFY->value); $response = Http::asForm()->post('https://accounts.spotify.com/api/token', [ 'grant_type' => 'refresh_token', diff --git a/app/Actions/Api/Spotify/SearchArtist.php b/app/Actions/Api/Spotify/SearchArtist.php index 7e6104b..d922c07 100644 --- a/app/Actions/Api/Spotify/SearchArtist.php +++ b/app/Actions/Api/Spotify/SearchArtist.php @@ -15,7 +15,7 @@ public function handle(User $user, string $phrase) (new RefreshToken)->handle($user); $response = Http::withHeaders([ - 'Authorization' => 'Bearer '.$user->connections->firstWhere('type_id', ConnectionType::SPOTIFY->value)->token, + 'Authorization' => 'Bearer '.$user->connections->firstWhere('type', ConnectionType::SPOTIFY->value)->token, 'Content-Type' => 'application/json', 'Client-Id' => config('services.spotify.client_id'), ])->get('https://api.spotify.com/v1/search', [ diff --git a/app/Actions/Api/Spotify/SearchTrack.php b/app/Actions/Api/Spotify/SearchTrack.php index 8855d1b..d06b739 100644 --- a/app/Actions/Api/Spotify/SearchTrack.php +++ b/app/Actions/Api/Spotify/SearchTrack.php @@ -16,7 +16,7 @@ public function handle(User $user, string $phrase): Collection (new RefreshToken)->handle($user); $response = Http::withHeaders([ - 'Authorization' => 'Bearer '.$user->connections->firstWhere('type_id', ConnectionType::SPOTIFY->value)->token, + 'Authorization' => 'Bearer '.$user->connections->firstWhere('type', ConnectionType::SPOTIFY->value)->token, 'Content-Type' => 'application/json', 'Client-Id' => config('services.spotify.client_id'), ])->get('https://api.spotify.com/v1/search', [ diff --git a/app/Actions/Api/Twitch/RefreshToken.php b/app/Actions/Api/Twitch/RefreshToken.php index ccd05ea..666022e 100644 --- a/app/Actions/Api/Twitch/RefreshToken.php +++ b/app/Actions/Api/Twitch/RefreshToken.php @@ -13,7 +13,7 @@ final class RefreshToken public function handle(User $user): bool { try { - $twitchConnection = $user->connections->firstWhere('type_id', ConnectionType::TWITCH->value); + $twitchConnection = $user->connections->firstWhere('type', ConnectionType::TWITCH->value); $response = Http::asForm()->post('https://id.twitch.tv/oauth2/token', [ 'client_id' => config('services.twitch.client_id'), diff --git a/app/Actions/Api/Twitch/SearchCategories.php b/app/Actions/Api/Twitch/SearchCategories.php index 05d7d2c..2f4e157 100644 --- a/app/Actions/Api/Twitch/SearchCategories.php +++ b/app/Actions/Api/Twitch/SearchCategories.php @@ -15,7 +15,7 @@ public function search(User $user, string $phrase, MediaType $mediaType) (new RefreshToken)->handle($user); $response = Http::withHeaders([ - 'Authorization' => 'Bearer '.$user->connections->firstWhere('type_id', ConnectionType::TWITCH->value)->token, + 'Authorization' => 'Bearer '.$user->connections->firstWhere('type', ConnectionType::TWITCH->value)->token, 'Content-Type' => 'application/json', 'Client-Id' => config('services.twitch.client_id'), ])->get('https://api.twitch.tv/helix/search/categories', [ diff --git a/app/Console/Commands/CheckTwitchLiveStatus.php b/app/Console/Commands/CheckTwitchLiveStatus.php index b449168..bfb0716 100644 --- a/app/Console/Commands/CheckTwitchLiveStatus.php +++ b/app/Console/Commands/CheckTwitchLiveStatus.php @@ -22,7 +22,7 @@ public function handle(): int (new RefreshToken)->handle($user); - $token = $user->connections->firstWhere('type_id', ConnectionType::TWITCH->value)->token ?? null; + $token = $user->connections->firstWhere('type', ConnectionType::TWITCH->value)->token ?? null; if (! $token) { return self::FAILURE; diff --git a/app/Console/Commands/UpdateArtistImages.php b/app/Console/Commands/UpdateArtistImages.php index d9bfaea..18f06a9 100644 --- a/app/Console/Commands/UpdateArtistImages.php +++ b/app/Console/Commands/UpdateArtistImages.php @@ -34,7 +34,7 @@ public function handle() 'GET', "https://api.spotify.com/v1/artists?ids={$ids}", [ 'headers' => [ - 'Authorization' => 'Bearer '.$user->connections->firstWhere('type_id', ConnectionType::SPOTIFY->value)->token, + 'Authorization' => 'Bearer '.$user->connections->firstWhere('type', ConnectionType::SPOTIFY->value)->token, ], ] ); diff --git a/app/Enums/AssetType.php b/app/Enums/AssetType.php index 1e8b524..a8405c0 100644 --- a/app/Enums/AssetType.php +++ b/app/Enums/AssetType.php @@ -2,11 +2,11 @@ namespace App\Enums; -enum AssetType: int +enum AssetType: string { - case PHOTO = 1; - case RESUME = 2; - case THREE_D_PRINTS = 3; + case PHOTO = 'photo'; + case RESUME = 'resume'; + case THREE_D_PRINTS = 'three_d_prints'; public function label(): string { diff --git a/app/Enums/ConnectionType.php b/app/Enums/ConnectionType.php index 2794a32..ea1fc97 100644 --- a/app/Enums/ConnectionType.php +++ b/app/Enums/ConnectionType.php @@ -2,24 +2,16 @@ namespace App\Enums; -enum ConnectionType: int +enum ConnectionType: string { - case SPOTIFY = 1; - case TWITCH = 2; + case SPOTIFY = 'spotify'; + case TWITCH = 'twitch'; - public function label() + public function label(): string { - return match($this) { + return match ($this) { self::SPOTIFY => 'Spotify', self::TWITCH => 'Twitch', }; } - - public function slug() - { - return match($this) { - self::SPOTIFY => 'spotify', - self::TWITCH => 'twitch', - }; - } } diff --git a/app/Http/Controllers/ConnectionController.php b/app/Http/Controllers/ConnectionController.php index b80bef6..e4f2f6d 100644 --- a/app/Http/Controllers/ConnectionController.php +++ b/app/Http/Controllers/ConnectionController.php @@ -10,34 +10,28 @@ class ConnectionController extends Controller { public function connect(Request $request, string $type) { - session()->put('current_connection_type_id', $this->getConnectionTypeId($type)); - session()->put('current_connection_type', $type); + $connectionType = ConnectionType::from($type); - return Socialite::driver($type)->redirect(); + session()->put('current_connection_type', $connectionType->value); + + return Socialite::driver($connectionType->value)->redirect(); } public function processConnection(Request $request) { - $user = Socialite::driver(session()->get('current_connection_type'))->stateless()->user(); + $type = session()->get('current_connection_type'); + + $user = Socialite::driver($type)->stateless()->user(); - auth()->user()->connections()->updateOrCreate(['type_id' => session()->get('current_connection_type_id')], [ - 'type_id' => session()->get('current_connection_type_id'), + auth()->user()->connections()->updateOrCreate(['type' => $type], [ + 'type' => $type, 'external_id' => $user->id, 'token' => $user->token, 'refresh_token' => $user->refreshToken, ]); - session()->forget('current_connection_type_id'); session()->forget('current_connection_type'); return redirect(route('dashboard')); } - - private function getConnectionTypeId(string $type) - { - return match ($type) { - 'twitch' => ConnectionType::TWITCH->slug(), - 'spotify' => ConnectionType::SPOTIFY->slug() - }; - } } diff --git a/app/Livewire/Forms/PhotoForm.php b/app/Livewire/Forms/PhotoForm.php index c31aa38..f4a2d1d 100644 --- a/app/Livewire/Forms/PhotoForm.php +++ b/app/Livewire/Forms/PhotoForm.php @@ -20,7 +20,7 @@ class PhotoForm extends Form public string $description = ''; - public int $type = AssetType::PHOTO->value; + public string $type = AssetType::PHOTO->value; public $photo; @@ -37,7 +37,7 @@ public function store() ); Asset::create([ - 'type_id' => $this->type, + 'type' => $this->type, 'name' => $this->name, 'slug' => Str::uuid(), 'path' => $path, @@ -100,7 +100,7 @@ protected function rules(): array 'description' => 'nullable|string|max:255', 'type' => [ 'required', - 'integer', + 'string', Rule::in([AssetType::PHOTO->value, AssetType::THREE_D_PRINTS->value]), ], 'photo' => 'image:mimes:png,jpg,jpeg,gif,jfif', diff --git a/app/Livewire/Navigation.php b/app/Livewire/Navigation.php index 5f860a8..81233fa 100644 --- a/app/Livewire/Navigation.php +++ b/app/Livewire/Navigation.php @@ -14,7 +14,7 @@ public function render() { return view('navigation', [ 'resume' => Asset::query() - ->where('type_id', AssetType::RESUME->value) + ->where('type', AssetType::RESUME->value) ->latest() ->first()?->slug, ]); diff --git a/app/Livewire/Photos/Gallery.php b/app/Livewire/Photos/Gallery.php index 5f84ae7..215a1f0 100644 --- a/app/Livewire/Photos/Gallery.php +++ b/app/Livewire/Photos/Gallery.php @@ -18,7 +18,7 @@ class Gallery extends Component public string $emptyMessage = 'No Photos'; - public array|int $type = AssetType::PHOTO->value; + public array|string $type = AssetType::PHOTO->value; public PhotoForm $form; @@ -32,7 +32,7 @@ public function render() public function photos() { return Asset::query() - ->whereIn('type_id', is_array($this->type) ? $this->type : [$this->type]) + ->whereIn('type', is_array($this->type) ? $this->type : [$this->type]) ->paginate(9); } diff --git a/app/Livewire/Photos/Uploader.php b/app/Livewire/Photos/Uploader.php index 7ecc584..7864d1d 100644 --- a/app/Livewire/Photos/Uploader.php +++ b/app/Livewire/Photos/Uploader.php @@ -17,7 +17,7 @@ class Uploader extends Component public bool $showGallery = true; - public array|int $galleryType = AssetType::PHOTO->value; + public array|string $galleryType = AssetType::PHOTO->value; public function render() { diff --git a/app/Livewire/Resume.php b/app/Livewire/Resume.php index 18e05e8..2472c41 100644 --- a/app/Livewire/Resume.php +++ b/app/Livewire/Resume.php @@ -34,7 +34,7 @@ public function store() $path = $this->resume->storePubliclyAs('resumes', $name, 's3'); Asset::create([ - 'type_id' => AssetType::RESUME->value, + 'type' => AssetType::RESUME->value, 'slug' => Str::uuid(), 'name' => $name, 'path' => $path, @@ -62,6 +62,6 @@ public function destroy($id) #[Computed] public function resumes() { - return Asset::where('type_id', AssetType::RESUME->value)->get(); + return Asset::where('type', AssetType::RESUME->value)->get(); } } diff --git a/app/Models/Asset.php b/app/Models/Asset.php index 8c9d0e3..30dad83 100644 --- a/app/Models/Asset.php +++ b/app/Models/Asset.php @@ -9,7 +9,7 @@ class Asset extends Model { protected $fillable = [ - 'type_id', + 'type', 'name', 'slug', 'path', @@ -27,7 +27,7 @@ public static function boot() public function casts(): array { return [ - 'type_id' => AssetType::class, + 'type' => AssetType::class, 'data' => 'array', ]; } diff --git a/app/Models/Connection.php b/app/Models/Connection.php index c1b7fa0..2c1fe9d 100644 --- a/app/Models/Connection.php +++ b/app/Models/Connection.php @@ -3,13 +3,12 @@ namespace App\Models; use Illuminate\Database\Eloquent\Relations\BelongsTo; -use Illuminate\Database\Eloquent\Relations\HasOne; class Connection extends Model { protected $fillable = [ 'external_id', - 'type_id', + 'type', 'name', 'token', 'refresh_token', diff --git a/database/factories/AssetFactory.php b/database/factories/AssetFactory.php index 8ad0161..c971f86 100644 --- a/database/factories/AssetFactory.php +++ b/database/factories/AssetFactory.php @@ -22,7 +22,7 @@ public function definition(): array $name = $this->faker->words(3, true); return [ - 'type_id' => $this->faker->randomElement([AssetType::PHOTO->value, AssetType::RESUME->value]), + 'type' => $this->faker->randomElement([AssetType::PHOTO->value, AssetType::RESUME->value]), 'name' => $name, 'slug' => Str::slug($name), 'path' => $this->faker->filePath(), @@ -41,7 +41,7 @@ public function definition(): array public function photo(): static { return $this->state(fn (array $attributes) => [ - 'type_id' => AssetType::PHOTO->value, + 'type' => AssetType::PHOTO->value, 'mime_type' => $this->faker->randomElement([ 'image/jpeg', 'image/png', @@ -59,7 +59,7 @@ public function photo(): static public function resume(): static { return $this->state(fn (array $attributes) => [ - 'type_id' => AssetType::RESUME->value, + 'type' => AssetType::RESUME->value, 'mime_type' => $this->faker->randomElement([ 'application/pdf', ]), diff --git a/database/migrations/2026_06_09_031112_rename_connections_type_id_to_type.php b/database/migrations/2026_06_09_031112_rename_connections_type_id_to_type.php new file mode 100644 index 0000000..90f63e3 --- /dev/null +++ b/database/migrations/2026_06_09_031112_rename_connections_type_id_to_type.php @@ -0,0 +1,22 @@ +renameColumn('type_id', 'type'); + }); + } + + public function down(): void + { + Schema::table('connections', function (Blueprint $table) { + $table->renameColumn('type', 'type_id'); + }); + } +}; diff --git a/database/migrations/2026_06_09_031113_rename_assets_type_id_to_type.php b/database/migrations/2026_06_09_031113_rename_assets_type_id_to_type.php new file mode 100644 index 0000000..0a8e974 --- /dev/null +++ b/database/migrations/2026_06_09_031113_rename_assets_type_id_to_type.php @@ -0,0 +1,57 @@ +renameColumn('type_id', 'type'); + }); + + Schema::table('assets', function (Blueprint $table) { + $table->string('type')->change(); + }); + + $map = [ + 1 => AssetType::PHOTO->value, + 2 => AssetType::RESUME->value, + 3 => AssetType::THREE_D_PRINTS->value, + ]; + + DB::transaction(function () use ($map): void { + foreach ($map as $old => $new) { + Asset::withoutGlobalScopes()->where('type', (string) $old)->update(['type' => $new]); + } + }); + } + + public function down(): void + { + $map = [ + AssetType::PHOTO->value => 1, + AssetType::RESUME->value => 2, + AssetType::THREE_D_PRINTS->value => 3, + ]; + + DB::transaction(function () use ($map): void { + foreach ($map as $old => $new) { + Asset::withoutGlobalScopes()->where('type', $old)->update(['type' => $new]); + } + }); + + Schema::table('assets', function (Blueprint $table) { + $table->integer('type')->change(); + }); + + Schema::table('assets', function (Blueprint $table) { + $table->renameColumn('type', 'type_id'); + }); + } +}; diff --git a/resources/views/livewire/connection.blade.php b/resources/views/livewire/connection.blade.php index e7bf137..324e887 100644 --- a/resources/views/livewire/connection.blade.php +++ b/resources/views/livewire/connection.blade.php @@ -4,13 +4,13 @@ @php $connections = [ 'spotify' => [ - 'connection' => auth()->user()->connections->firstWhere('type_id', App\Enums\ConnectionType::SPOTIFY->value), + 'connection' => auth()->user()->connections->firstWhere('type', App\Enums\ConnectionType::SPOTIFY->value), 'icon' => 'musical-note', 'color' => 'lime', 'name' => 'Spotify' ], 'twitch' => [ - 'connection' => auth()->user()->connections->firstWhere('type_id', App\Enums\ConnectionType::TWITCH->value), + 'connection' => auth()->user()->connections->firstWhere('type', App\Enums\ConnectionType::TWITCH->value), 'icon' => 'tv', 'color' => 'purple', 'name' => 'Twitch' diff --git a/resources/views/livewire/pages/media/games/show.blade.php b/resources/views/livewire/pages/media/games/show.blade.php index 1090211..d9a1def 100644 --- a/resources/views/livewire/pages/media/games/show.blade.php +++ b/resources/views/livewire/pages/media/games/show.blade.php @@ -28,7 +28,7 @@ /> @@ -196,7 +196,7 @@ class="rounded-xl" - +