diff --git a/app/Actions/Models/Wiki/Song/ManageSongPerformances.php b/app/Actions/Models/Wiki/Song/ManageSongPerformances.php index 52b5874df..57e0588ac 100644 --- a/app/Actions/Models/Wiki/Song/ManageSongPerformances.php +++ b/app/Actions/Models/Wiki/Song/ManageSongPerformances.php @@ -9,6 +9,7 @@ use App\Models\Wiki\Song; use App\Models\Wiki\Song\Membership; use App\Models\Wiki\Song\Performance; use App\Pivots\Wiki\ArtistMember; +use App\Pivots\Wiki\ArtistSong; use Exception; use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Support\Arr; @@ -137,6 +138,16 @@ class ManageSongPerformances $soloPerformances->each(fn (Performance $performance) => $performance->forceDelete()); + Performance::withoutEvents(function () use ($performancesToCreate) { + foreach ($performancesToCreate as $index => $performanceToSort) { + Performance::query() + ->where(Performance::ATTRIBUTE_SONG, $this->song) + ->where(Performance::ATTRIBUTE_ARTIST_TYPE, Arr::get($performanceToSort, Performance::ATTRIBUTE_ARTIST_TYPE)) + ->where(Performance::ATTRIBUTE_ARTIST_ID, Arr::get($performanceToSort, Performance::ATTRIBUTE_ARTIST_ID)) + ->update([Performance::ATTRIBUTE_RELEVANCE => $index + 1]); + } + }); + // Update artist_member table to match memberships ArtistMember::query()->upsert( $memberships, @@ -144,6 +155,8 @@ class ManageSongPerformances [ArtistMember::ATTRIBUTE_ALIAS, ArtistMember::ATTRIBUTE_AS], ); + $this->syncSongArtist(); + DB::commit(); } catch (Exception $e) { Log::error($e->getMessage()); @@ -155,4 +168,30 @@ class ManageSongPerformances return $this; } + + /** + * Temporary function where the performances feature synchronizes with the artist_song pivot table. + */ + public function syncSongArtist(): void + { + /** @var Song $song */ + $song = Song::query() + ->whereKey($this->song) + ->first(); + + $songArtists = []; + foreach ($this->performances as $performance) { + $groupOrArtist = Arr::get($performance, Performance::RELATION_MEMBERSHIP.'.'.Membership::ATTRIBUTE_ARTIST) + ?? Arr::get($performance, Performance::ATTRIBUTE_ARTIST_ID); + + $songArtists[$groupOrArtist] = [ + ArtistSong::ATTRIBUTE_ALIAS => Arr::get($performance, Performance::ATTRIBUTE_ALIAS), + ArtistSong::ATTRIBUTE_AS => Arr::get($performance, Performance::ATTRIBUTE_AS), + ]; + } + + ArtistSong::withoutEvents(function () use ($song, $songArtists) { + $song->artists()->sync($songArtists); + }); + } } diff --git a/app/Contracts/Events/SyncArtistSongEvent.php b/app/Contracts/Events/SyncArtistSongEvent.php deleted file mode 100644 index 20f8edf86..000000000 --- a/app/Contracts/Events/SyncArtistSongEvent.php +++ /dev/null @@ -1,14 +0,0 @@ - */ -class PerformanceCreated extends WikiCreatedEvent implements SyncArtistSongEvent, UpdateRelatedIndicesEvent +class PerformanceCreated extends WikiCreatedEvent implements UpdateRelatedIndicesEvent { public function __construct(Performance $performance) { @@ -65,28 +59,4 @@ class PerformanceCreated extends WikiCreatedEvent implements SyncArtistSongEvent $performance->artist->searchable(); } - - /** - * Sync the performance with the artist song. - * Temporary function. - */ - public function syncArtistSong(): void - { - $performance = $this->getModel(); - - $song = $performance->song; - - $artist = match (Relation::getMorphedModel($performance->artist_type)) { - Artist::class => $performance->artist, - Membership::class => $performance->artist->group, - default => throw new Exception('Invalid artist type.'), - }; - - ArtistSong::withoutEvents(function () use ($artist, $song, $performance): void { - $artist->songs()->syncWithPivotValues([$song->getKey()], [ - ArtistSong::ATTRIBUTE_ALIAS => $performance->alias, - ArtistSong::ATTRIBUTE_AS => $performance->as, - ], false); - }); - } } diff --git a/app/Events/Wiki/Song/Performance/PerformanceDeleted.php b/app/Events/Wiki/Song/Performance/PerformanceDeleted.php index 20c02cd69..f6f1abe24 100644 --- a/app/Events/Wiki/Song/Performance/PerformanceDeleted.php +++ b/app/Events/Wiki/Song/Performance/PerformanceDeleted.php @@ -4,23 +4,18 @@ declare(strict_types=1); namespace App\Events\Wiki\Song\Performance; -use App\Contracts\Events\SyncArtistSongEvent; use App\Contracts\Events\UpdateRelatedIndicesEvent; use App\Events\Base\Wiki\WikiDeletedEvent; use App\Filament\Resources\Wiki\Song\Performance as PerformanceFilament; use App\Models\Wiki\Artist; use App\Models\Wiki\Song\Membership; use App\Models\Wiki\Song\Performance; -use App\Pivots\Wiki\ArtistSong; -use Exception; -use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Relations\MorphTo; -use Illuminate\Database\Eloquent\Relations\Relation; /** * @extends WikiDeletedEvent */ -class PerformanceDeleted extends WikiDeletedEvent implements SyncArtistSongEvent, UpdateRelatedIndicesEvent +class PerformanceDeleted extends WikiDeletedEvent implements UpdateRelatedIndicesEvent { public function __construct(Performance $performance) { @@ -85,38 +80,4 @@ class PerformanceDeleted extends WikiDeletedEvent implements SyncArtistSongEvent $performance->artist->searchable(); } - - /** - * Sync the performance with the artist song. - * Temporary function. - */ - public function syncArtistSong(): void - { - $performance = $this->getModel(); - $song = $performance->song; - - if ( - $performance->artist_type === Relation::getMorphAlias(Membership::class) - && Performance::query() - ->whereBelongsTo($song) - ->where(Performance::ATTRIBUTE_ARTIST_TYPE, Relation::getMorphAlias(Membership::class)) - ->whereHas(Performance::RELATION_ARTIST, fn (Builder $query) => $query->where(Artist::ATTRIBUTE_ID, $performance->artist->group->getKey())) - ->exists() - ) { - return; - } - - $artist = match (Relation::getMorphedModel($performance->artist_type)) { - Artist::class => $performance->artist, - Membership::class => $performance->artist->group, - default => throw new Exception('Invalid artist type.'), - }; - - ArtistSong::withoutEvents(function () use ($artist, $song): void { - ArtistSong::query()->where([ - ArtistSong::ATTRIBUTE_ARTIST => $artist->getKey(), - ArtistSong::ATTRIBUTE_SONG => $song->getKey(), - ])->delete(); - }); - } } diff --git a/app/Events/Wiki/Song/Performance/PerformanceRestored.php b/app/Events/Wiki/Song/Performance/PerformanceRestored.php index 5f8eb32cd..a2f8496df 100644 --- a/app/Events/Wiki/Song/Performance/PerformanceRestored.php +++ b/app/Events/Wiki/Song/Performance/PerformanceRestored.php @@ -4,21 +4,17 @@ declare(strict_types=1); namespace App\Events\Wiki\Song\Performance; -use App\Contracts\Events\SyncArtistSongEvent; use App\Contracts\Events\UpdateRelatedIndicesEvent; use App\Events\Base\Wiki\WikiRestoredEvent; use App\Models\Wiki\Artist; use App\Models\Wiki\Song\Membership; use App\Models\Wiki\Song\Performance; -use App\Pivots\Wiki\ArtistSong; -use Exception; use Illuminate\Database\Eloquent\Relations\MorphTo; -use Illuminate\Database\Eloquent\Relations\Relation; /** * @extends WikiRestoredEvent */ -class PerformanceRestored extends WikiRestoredEvent implements SyncArtistSongEvent, UpdateRelatedIndicesEvent +class PerformanceRestored extends WikiRestoredEvent implements UpdateRelatedIndicesEvent { public function __construct(Performance $performance) { @@ -55,27 +51,4 @@ class PerformanceRestored extends WikiRestoredEvent implements SyncArtistSongEve $performance->artist->searchable(); } - - /** - * Sync the performance with the artist song. - * Temporary function. - */ - public function syncArtistSong(): void - { - $performance = $this->getModel(); - $song = $performance->song; - - $artist = match (Relation::getMorphedModel($performance->artist_type)) { - Artist::class => $performance->artist, - Membership::class => $performance->artist->group, - default => throw new Exception('Invalid artist type.'), - }; - - ArtistSong::withoutEvents(function () use ($artist, $song, $performance): void { - $artist->songs()->syncWithPivotValues([$song->getKey()], [[ - ArtistSong::ATTRIBUTE_ALIAS => $performance->alias, - ArtistSong::ATTRIBUTE_AS => $performance->as, - ]], false); - }); - } } diff --git a/app/Events/Wiki/Song/Performance/PerformanceUpdated.php b/app/Events/Wiki/Song/Performance/PerformanceUpdated.php index ca3c9f220..1ea0725db 100644 --- a/app/Events/Wiki/Song/Performance/PerformanceUpdated.php +++ b/app/Events/Wiki/Song/Performance/PerformanceUpdated.php @@ -4,21 +4,17 @@ declare(strict_types=1); namespace App\Events\Wiki\Song\Performance; -use App\Contracts\Events\SyncArtistSongEvent; use App\Contracts\Events\UpdateRelatedIndicesEvent; use App\Events\Base\Wiki\WikiUpdatedEvent; use App\Models\Wiki\Artist; use App\Models\Wiki\Song\Membership; use App\Models\Wiki\Song\Performance; -use App\Pivots\Wiki\ArtistSong; -use Exception; use Illuminate\Database\Eloquent\Relations\MorphTo; -use Illuminate\Database\Eloquent\Relations\Relation; /** * @extends WikiUpdatedEvent */ -class PerformanceUpdated extends WikiUpdatedEvent implements SyncArtistSongEvent, UpdateRelatedIndicesEvent +class PerformanceUpdated extends WikiUpdatedEvent implements UpdateRelatedIndicesEvent { public function __construct(Performance $performance) { @@ -56,30 +52,4 @@ class PerformanceUpdated extends WikiUpdatedEvent implements SyncArtistSongEvent $performance->artist->searchable(); } - - /** - * Sync the performance with the artist song. - * Temporary function. - */ - public function syncArtistSong(): void - { - $performance = $this->getModel(); - $song = $performance->song; - - $artist = match (Relation::getMorphedModel($performance->artist_type)) { - Artist::class => $performance->artist, - Membership::class => $performance->artist->group, - default => throw new Exception('Invalid artist type.'), - }; - - ArtistSong::withoutEvents(function () use ($artist, $song, $performance): void { - ArtistSong::query()->where([ - ArtistSong::ATTRIBUTE_ARTIST => $artist->getKey(), - ArtistSong::ATTRIBUTE_SONG => $song->getKey(), - ])->update([ - ArtistSong::ATTRIBUTE_ALIAS => $performance->alias, - ArtistSong::ATTRIBUTE_AS => $performance->as, - ]); - }); - } } diff --git a/app/Filament/Resources/Wiki/Song/Performance/Schemas/PerformanceForm.php b/app/Filament/Resources/Wiki/Song/Performance/Schemas/PerformanceForm.php index 353f86fc0..0426da82b 100644 --- a/app/Filament/Resources/Wiki/Song/Performance/Schemas/PerformanceForm.php +++ b/app/Filament/Resources/Wiki/Song/Performance/Schemas/PerformanceForm.php @@ -62,6 +62,8 @@ class PerformanceForm ->defaultItems(0) ->columns(3) ->columnSpanFull() + ->reorderableWithDragAndDrop(false) + ->reorderableWithButtons() ->formatStateUsing(function ($livewire, Get $get): array { /** @var SongModel|null $song */ $song = $livewire instanceof PerformanceSongRelationManager @@ -93,6 +95,8 @@ class PerformanceForm ->defaultItems(0) ->columns(3) ->columnSpanFull() + ->reorderableWithDragAndDrop(false) + ->reorderableWithButtons() ->schema([ BelongsTo::make(Membership::ATTRIBUTE_MEMBER) ->resource(ArtistResource::class) diff --git a/app/Filament/Resources/Wiki/Song/RelationManagers/PerformanceSongRelationManager.php b/app/Filament/Resources/Wiki/Song/RelationManagers/PerformanceSongRelationManager.php index 240bcab8a..a38a5459c 100644 --- a/app/Filament/Resources/Wiki/Song/RelationManagers/PerformanceSongRelationManager.php +++ b/app/Filament/Resources/Wiki/Song/RelationManagers/PerformanceSongRelationManager.php @@ -14,6 +14,7 @@ use App\Models\Wiki\Song\Performance; use Filament\Actions\Action; use Filament\Tables\Table; use Illuminate\Support\Arr; +use Illuminate\Support\Str; class PerformanceSongRelationManager extends PerformanceRelationManager { @@ -63,7 +64,7 @@ class PerformanceSongRelationManager extends PerformanceRelationManager $artists = []; $memberships = []; foreach ($performances as $performance) { - if ($performance->artist instanceof Membership) { + if ($performance->isMembership()) { $artists[$performance->artist->artist_id] = [ Performance::ATTRIBUTE_ARTIST_TYPE => $performance->artist_type, Performance::ATTRIBUTE_ARTIST_ID => $performance->artist->artist_id, diff --git a/app/Listeners/SyncArtistSong.php b/app/Listeners/SyncArtistSong.php deleted file mode 100644 index f108aefe8..000000000 --- a/app/Listeners/SyncArtistSong.php +++ /dev/null @@ -1,15 +0,0 @@ -syncArtistSong(); - } -} diff --git a/app/Models/Wiki/Song.php b/app/Models/Wiki/Song.php index 1aab0b467..647a7fb66 100644 --- a/app/Models/Wiki/Song.php +++ b/app/Models/Wiki/Song.php @@ -114,7 +114,7 @@ class Song extends BaseModel implements HasResources, SoftDeletable return "{$this->animethemes->first()->anime->getName()} {$this->animethemes->first()->slug}"; } - return $this->title_native ?? $this->getKey(); + return $this->title_native ?? strval($this->getKey()); } /** @@ -142,7 +142,8 @@ class Song extends BaseModel implements HasResources, SoftDeletable */ public function performances(): HasMany { - return $this->hasMany(Performance::class, Performance::ATTRIBUTE_SONG); + return $this->hasMany(Performance::class, Performance::ATTRIBUTE_SONG) + ->orderBy(Performance::ATTRIBUTE_RELEVANCE); } /** diff --git a/app/Models/Wiki/Song/Performance.php b/app/Models/Wiki/Song/Performance.php index 91bda87d9..50d7b4847 100644 --- a/app/Models/Wiki/Song/Performance.php +++ b/app/Models/Wiki/Song/Performance.php @@ -28,6 +28,7 @@ use Illuminate\Database\Eloquent\Relations\Relation; * @property string $artist_type * @property int $artist_id * @property Artist|Membership $artist + * @property int|null $relevance * @property Song $song * * @method static PerformanceFactory factory(...$parameters) @@ -47,6 +48,7 @@ class Performance extends BaseModel implements SoftDeletable final public const string ATTRIBUTE_ARTIST = 'artist'; final public const string ATTRIBUTE_ALIAS = 'alias'; final public const string ATTRIBUTE_AS = 'as'; + final public const string ATTRIBUTE_RELEVANCE = 'relevance'; final public const string RELATION_ARTIST = 'artist'; final public const string RELATION_MEMBERSHIP = self::RELATION_ARTIST; @@ -63,6 +65,7 @@ class Performance extends BaseModel implements SoftDeletable Performance::ATTRIBUTE_ARTIST_ID, Performance::ATTRIBUTE_ALIAS, Performance::ATTRIBUTE_AS, + Performance::ATTRIBUTE_RELEVANCE, ]; /** diff --git a/database/migrations/2025_10_25_033138_add_relevance_to_performances.php b/database/migrations/2025_10_25_033138_add_relevance_to_performances.php new file mode 100644 index 000000000..a321a3f75 --- /dev/null +++ b/database/migrations/2025_10_25_033138_add_relevance_to_performances.php @@ -0,0 +1,23 @@ +integer(Performance::ATTRIBUTE_RELEVANCE)->nullable()->after(Performance::ATTRIBUTE_AS); + }); + } + } +}; diff --git a/tests/Unit/Events/SyncArtistSongTest.php b/tests/Unit/Events/SyncArtistSongTest.php deleted file mode 100644 index 8b08bdfb7..000000000 --- a/tests/Unit/Events/SyncArtistSongTest.php +++ /dev/null @@ -1,11 +0,0 @@ -