mirror of
https://github.com/AnimeThemes/animethemes-server.git
synced 2026-07-11 01:24:46 +02:00
Feat/performance relevance (#980)
This commit is contained in:
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Contracts\Events;
|
||||
|
||||
interface SyncArtistSongEvent
|
||||
{
|
||||
/**
|
||||
* Sync the performance with the artist song.
|
||||
* Temporary function.
|
||||
*/
|
||||
public function syncArtistSong(): void;
|
||||
}
|
||||
@@ -4,20 +4,14 @@ 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\WikiCreatedEvent;
|
||||
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\Relation;
|
||||
|
||||
/**
|
||||
* @extends WikiCreatedEvent<Performance>
|
||||
*/
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Performance>
|
||||
*/
|
||||
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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Performance>
|
||||
*/
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Performance>
|
||||
*/
|
||||
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,
|
||||
]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
+2
-1
@@ -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,
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Listeners;
|
||||
|
||||
use App\Contracts\Events\SyncArtistSongEvent;
|
||||
|
||||
class SyncArtistSong
|
||||
{
|
||||
public function handle(SyncArtistSongEvent $event): void
|
||||
{
|
||||
$event->syncArtistSong();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Models\Wiki\Song\Performance;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
if (! Schema::hasColumn(Performance::TABLE, Performance::ATTRIBUTE_RELEVANCE)) {
|
||||
Schema::table(Performance::TABLE, function (Blueprint $table) {
|
||||
$table->integer(Performance::ATTRIBUTE_RELEVANCE)->nullable()->after(Performance::ATTRIBUTE_AS);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Contracts\Events\SyncArtistSongEvent;
|
||||
use App\Listeners\SyncArtistSong;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
||||
test('listening', function () {
|
||||
Event::assertListening(SyncArtistSongEvent::class, SyncArtistSong::class);
|
||||
});
|
||||
Reference in New Issue
Block a user