feat: create artist song event (#1151)

This commit is contained in:
Kyrch
2026-04-03 13:32:14 -03:00
committed by GitHub
parent fcaa13891b
commit 4f61a86638
10 changed files with 137 additions and 34 deletions
@@ -4,11 +4,9 @@ declare(strict_types=1);
namespace App\Actions\Models\Wiki\Song;
use App\Models\Wiki\Artist;
use App\Models\Wiki\Song;
use App\Models\Wiki\Song\Performance;
use App\Pivots\Wiki\ArtistMember;
use App\Pivots\Wiki\ArtistSong;
use Exception;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
@@ -90,9 +88,7 @@ class ManageSongPerformances
[ArtistMember::ATTRIBUTE_ALIAS, ArtistMember::ATTRIBUTE_AS],
);
$this->setArtistMemberRelevance();
$this->syncSongArtist();
static::setArtistMemberRelevance();
DB::commit();
} catch (Exception $e) {
@@ -109,7 +105,7 @@ class ManageSongPerformances
/**
* Complex query to set relevance for artist members based on created_at order.
*/
protected function setArtistMemberRelevance(): void
public static function setArtistMemberRelevance(): void
{
DB::statement('
WITH base AS (
@@ -139,16 +135,4 @@ class ManageSongPerformances
SET am.relevance = r.rn + b.max_rel;
');
}
/**
* Temporary function where the performances feature synchronizes with the artist_song pivot table.
*/
protected function syncSongArtist(): void
{
$songArtists = $this->performances->unique(Performance::ATTRIBUTE_ARTIST)->mapWithKeys(fn (array $performance): array => [
$performance[Performance::ATTRIBUTE_ARTIST] => Arr::only($performance, [Performance::ATTRIBUTE_ALIAS, Performance::ATTRIBUTE_AS]),
]);
ArtistSong::withoutEvents(fn () => $this->song->artists()->sync($songArtists));
}
}
@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace App\Contracts\Events;
use Illuminate\Contracts\Events\ShouldHandleEventsAfterCommit;
interface CreateArtistSongEvent extends ShouldHandleEventsAfterCommit
{
public function createArtistSong(): void;
}
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace App\Events\Wiki\Song\Performance;
use App\Contracts\Events\CreateArtistSongEvent;
use App\Contracts\Events\CreateSynonymEvent;
use App\Contracts\Events\UpdateRelatedIndicesEvent;
use App\Enums\Models\Wiki\SynonymType;
@@ -11,11 +12,12 @@ use App\Events\Base\Wiki\WikiCreatedEvent;
use App\Models\Wiki\Artist;
use App\Models\Wiki\Song\Performance;
use App\Models\Wiki\Synonym;
use App\Pivots\Wiki\ArtistSong;
/**
* @extends WikiCreatedEvent<Performance>
*/
class PerformanceCreated extends WikiCreatedEvent implements CreateSynonymEvent, UpdateRelatedIndicesEvent
class PerformanceCreated extends WikiCreatedEvent implements CreateArtistSongEvent, CreateSynonymEvent, UpdateRelatedIndicesEvent
{
protected function getDiscordMessageDescription(): string
{
@@ -63,4 +65,18 @@ class PerformanceCreated extends WikiCreatedEvent implements CreateSynonymEvent,
]);
}
}
public function createArtistSong(): void
{
$performance = $this->getModel();
ArtistSong::withoutEvents(function () use ($performance): void {
$performance->song->artists()->syncWithoutDetaching([
$performance->artist_id => [
ArtistSong::ATTRIBUTE_ALIAS => $performance->alias,
ArtistSong::ATTRIBUTE_AS => $performance->as,
],
]);
});
}
}
@@ -4,16 +4,18 @@ declare(strict_types=1);
namespace App\Events\Wiki\Song\Performance;
use App\Contracts\Events\CreateArtistSongEvent;
use App\Contracts\Events\UpdateRelatedIndicesEvent;
use App\Events\Base\Wiki\WikiDeletedEvent;
use App\Filament\Resources\Wiki\Song\PerformanceResource as PerformanceFilament;
use App\Models\Wiki\Artist;
use App\Models\Wiki\Song\Performance;
use App\Pivots\Wiki\ArtistSong;
/**
* @extends WikiDeletedEvent<Performance>
*/
class PerformanceDeleted extends WikiDeletedEvent implements UpdateRelatedIndicesEvent
class PerformanceDeleted extends WikiDeletedEvent implements CreateArtistSongEvent, UpdateRelatedIndicesEvent
{
protected function getDiscordMessageDescription(): string
{
@@ -58,4 +60,13 @@ class PerformanceDeleted extends WikiDeletedEvent implements UpdateRelatedIndice
$performance->artist->searchable();
$performance->member?->searchable();
}
public function createArtistSong(): void
{
$performance = $this->getModel();
ArtistSong::withoutEvents(function () use ($performance): void {
$performance->song->artists()->detach($performance->artist_id);
});
}
}
@@ -4,20 +4,17 @@ declare(strict_types=1);
namespace App\Events\Wiki\Song\Performance;
use App\Contracts\Events\CreateArtistSongEvent;
use App\Contracts\Events\UpdateRelatedIndicesEvent;
use App\Events\Base\Wiki\WikiRestoredEvent;
use App\Models\Wiki\Song\Performance;
use App\Pivots\Wiki\ArtistSong;
/**
* @extends WikiRestoredEvent<Performance>
*/
class PerformanceRestored extends WikiRestoredEvent implements UpdateRelatedIndicesEvent
class PerformanceRestored extends WikiRestoredEvent implements CreateArtistSongEvent, UpdateRelatedIndicesEvent
{
protected function getDiscordMessageDescription(): string
{
return "Performance '**{$this->getModel()->getName()}**' has been restored.";
}
public function updateRelatedIndices(): void
{
$performance = $this->getModel()->load([
@@ -28,4 +25,18 @@ class PerformanceRestored extends WikiRestoredEvent implements UpdateRelatedIndi
$performance->artist->searchable();
$performance->member?->searchable();
}
public function createArtistSong(): void
{
$performance = $this->getModel();
ArtistSong::withoutEvents(function () use ($performance): void {
$performance->song->artists()->syncWithoutDetaching([
$performance->artist_id => [
ArtistSong::ATTRIBUTE_ALIAS => $performance->alias,
ArtistSong::ATTRIBUTE_AS => $performance->as,
],
]);
});
}
}
@@ -4,14 +4,16 @@ declare(strict_types=1);
namespace App\Events\Wiki\Song\Performance;
use App\Contracts\Events\CreateArtistSongEvent;
use App\Contracts\Events\UpdateRelatedIndicesEvent;
use App\Events\Base\Wiki\WikiUpdatedEvent;
use App\Models\Wiki\Song\Performance;
use App\Pivots\Wiki\ArtistSong;
/**
* @extends WikiUpdatedEvent<Performance>
*/
class PerformanceUpdated extends WikiUpdatedEvent implements UpdateRelatedIndicesEvent
class PerformanceUpdated extends WikiUpdatedEvent implements CreateArtistSongEvent, UpdateRelatedIndicesEvent
{
public function __construct(Performance $performance)
{
@@ -19,11 +21,6 @@ class PerformanceUpdated extends WikiUpdatedEvent implements UpdateRelatedIndice
$this->initializeEmbedFields($performance);
}
protected function getDiscordMessageDescription(): string
{
return "Performance '**{$this->getModel()->getName()}**' has been updated.";
}
public function updateRelatedIndices(): void
{
$performance = $this->getModel()->load([
@@ -34,4 +31,16 @@ class PerformanceUpdated extends WikiUpdatedEvent implements UpdateRelatedIndice
$performance->artist->searchable();
$performance->member?->searchable();
}
public function createArtistSong(): void
{
$performance = $this->getModel();
ArtistSong::withoutEvents(function () use ($performance): void {
$performance->song->artists()->updateExistingPivot($performance->artist_id, [
ArtistSong::ATTRIBUTE_ALIAS => $performance->alias,
ArtistSong::ATTRIBUTE_AS => $performance->as,
]);
});
}
}
@@ -4,12 +4,15 @@ declare(strict_types=1);
namespace App\Filament\Resources\Wiki\Artist\RelationManagers;
use App\Actions\Models\Wiki\Song\ManageSongPerformances;
use App\Filament\Actions\Base\CreateAction;
use App\Filament\Components\Fields\BelongsTo;
use App\Filament\Components\Fields\TextInput;
use App\Filament\RelationManagers\Wiki\Song\PerformanceRelationManager;
use App\Filament\Resources\Wiki\ArtistResource;
use App\Models\Wiki\Artist;
use App\Models\Wiki\Song\Performance;
use Filament\Actions\Action;
use Filament\Schemas\Components\Component;
use Filament\Tables\Table;
@@ -56,4 +59,20 @@ class MemberPerformanceArtistRelationManager extends PerformanceRelationManager
->heading(__('filament.resources.label.member_performances'))
->modelLabel(__('filament.resources.singularLabel.member_performance'));
}
/**
* Get the header actions available for the relation.
*
* @return array<int, Action>
*/
public static function getHeaderActions(): array
{
return [
CreateAction::make('new-performance')
->after(function (Performance $record): void {
$record->moveToEnd();
ManageSongPerformances::setArtistMemberRelevance();
}),
];
}
}
@@ -4,16 +4,23 @@ declare(strict_types=1);
namespace App\Filament\Resources\Wiki\Artist\RelationManagers;
use App\Filament\Actions\Base\CreateAction;
use App\Filament\Components\Fields\BelongsTo;
use App\Filament\Components\Fields\TextInput;
use App\Filament\RelationManagers\Wiki\Song\PerformanceRelationManager;
use App\Filament\Resources\Wiki\ArtistResource;
use App\Models\Wiki\Artist;
use App\Models\Wiki\Song\Performance;
use Filament\Actions\Action;
use Filament\Schemas\Components\Component;
class PerformanceArtistRelationManager extends PerformanceRelationManager
{
/**
* The relationship the relation manager corresponds to.
*/
protected static string $relationship = Artist::RELATION_PERFORMANCES;
/**
* @return Component[]
*/
@@ -44,7 +51,15 @@ class PerformanceArtistRelationManager extends PerformanceRelationManager
}
/**
* The relationship the relation manager corresponds to.
* Get the header actions available for the relation.
*
* @return array<int, Action>
*/
protected static string $relationship = Artist::RELATION_PERFORMANCES;
public static function getHeaderActions(): array
{
return [
CreateAction::make('new-performance')
->after(fn (Performance $record): Performance => $record->moveToEnd()),
];
}
}
+15
View File
@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace App\Listeners;
use App\Contracts\Events\CreateArtistSongEvent;
class CreateArtistSong
{
public function handle(CreateArtistSongEvent $event): void
{
$event->createArtistSong();
}
}
@@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
use App\Contracts\Events\CreateArtistSongEvent;
use App\Listeners\CreateArtistSong;
use Illuminate\Support\Facades\Event;
test('listening', function () {
Event::assertListening(CreateArtistSongEvent::class, CreateArtistSong::class);
});