fix(filament): fixed belongs to entry (#909)

This commit is contained in:
Kyrch
2025-08-03 05:02:41 -03:00
committed by GitHub
parent 3a79dc85c8
commit 0484fd73cb
19 changed files with 113 additions and 89 deletions
@@ -33,7 +33,7 @@ class MembershipCreated extends WikiCreatedEvent implements UpdateRelatedIndices
*/
protected function getDiscordMessageDescription(): string
{
return "Membership '**{$this->getModel()->member->getName()}**' of Group '**{$this->getModel()->artist->getName()}**' has been created.";
return "Membership '**{$this->getModel()->member->getName()}**' of Group '**{$this->getModel()->group->getName()}**' has been created.";
}
/**
@@ -41,9 +41,9 @@ class MembershipCreated extends WikiCreatedEvent implements UpdateRelatedIndices
*/
public function updateRelatedIndices(): void
{
$membership = $this->getModel()->load([Membership::RELATION_ARTIST, Membership::RELATION_MEMBER]);
$membership = $this->getModel()->load([Membership::RELATION_GROUP, Membership::RELATION_MEMBER]);
$membership->artist->searchable();
$membership->group->searchable();
$membership->member->searchable();
}
}
@@ -34,7 +34,7 @@ class MembershipDeleted extends WikiDeletedEvent implements UpdateRelatedIndices
*/
protected function getDiscordMessageDescription(): string
{
return "Membership '**{$this->getModel()->member->getName()}**' of Group '**{$this->getModel()->artist->getName()}**' has been deleted.";
return "Membership '**{$this->getModel()->member->getName()}**' of Group '**{$this->getModel()->group->getName()}**' has been deleted.";
}
/**
@@ -60,9 +60,9 @@ class MembershipDeleted extends WikiDeletedEvent implements UpdateRelatedIndices
*/
public function updateRelatedIndices(): void
{
$membership = $this->getModel()->load([Membership::RELATION_ARTIST, Membership::RELATION_MEMBER]);
$membership = $this->getModel()->load([Membership::RELATION_GROUP, Membership::RELATION_MEMBER]);
$membership->artist->searchable();
$membership->group->searchable();
$membership->member->searchable();
}
}
@@ -33,10 +33,10 @@ class MembershipDeleting extends BaseEvent implements UpdateRelatedIndicesEvent
*/
public function updateRelatedIndices(): void
{
$membership = $this->getModel()->load([Membership::RELATION_ARTIST, Membership::RELATION_MEMBER]);
$membership = $this->getModel()->load([Membership::RELATION_GROUP, Membership::RELATION_MEMBER]);
if ($membership->isForceDeleting()) {
$membership->artist->searchable();
$membership->group->searchable();
$membership->member->searchable();
}
}
@@ -41,9 +41,9 @@ class MembershipRestored extends WikiRestoredEvent implements UpdateRelatedIndic
*/
public function updateRelatedIndices(): void
{
$membership = $this->getModel()->load([Membership::RELATION_ARTIST, Membership::RELATION_MEMBER]);
$membership = $this->getModel()->load([Membership::RELATION_GROUP, Membership::RELATION_MEMBER]);
$membership->artist->searchable();
$membership->group->searchable();
$membership->member->searchable();
}
}
@@ -42,9 +42,9 @@ class MembershipUpdated extends WikiUpdatedEvent implements UpdateRelatedIndices
*/
public function updateRelatedIndices(): void
{
$membership = $this->getModel()->load([Membership::RELATION_ARTIST, Membership::RELATION_MEMBER]);
$membership = $this->getModel()->load([Membership::RELATION_GROUP, Membership::RELATION_MEMBER]);
$membership->artist->searchable();
$membership->group->searchable();
$membership->member->searchable();
}
}
@@ -43,7 +43,7 @@ class PerformanceCreated extends WikiCreatedEvent implements SyncArtistSongEvent
$artist = $performance->artist;
if ($this->getModel()->isMembership()) {
return "Song '**{$song->getName()}**' has been attached to Artist '**{$artist->member->getName()}**' as member of '**{$artist->artist->getName()}**'.";
return "Song '**{$song->getName()}**' has been attached to Artist '**{$artist->member->getName()}**' as member of '**{$artist->group->getName()}**'.";
}
return "Song '**{$song->getName()}**' has been attached to Artist '**{$artist->getName()}**'.";
@@ -57,7 +57,7 @@ class PerformanceCreated extends WikiCreatedEvent implements SyncArtistSongEvent
$performance = $this->getModel()->load([Performance::RELATION_ARTIST]);
if ($performance->isMembership()) {
$performance->artist->artist->searchable();
$performance->artist->group->searchable();
$performance->artist->member->searchable();
return;
@@ -78,7 +78,7 @@ class PerformanceCreated extends WikiCreatedEvent implements SyncArtistSongEvent
$artist = match ($performance->artist_type) {
Artist::class => $performance->artist,
Membership::class => $performance->artist->artist,
Membership::class => $performance->artist->group,
default => throw new Exception('Invalid artist type.'),
};
@@ -46,7 +46,7 @@ class PerformanceDeleted extends WikiDeletedEvent implements SyncArtistSongEvent
$artist = $performance->artist;
if ($performance->isMembership()) {
return "Song '**{$song->getName()}**' has been detached from Artist '**{$artist->member->getName()}**' via Group '**{$artist->artist->getName()}**'.";
return "Song '**{$song->getName()}**' has been detached from Artist '**{$artist->member->getName()}**' via Group '**{$artist->group->getName()}**'.";
}
return "Song '**{$song->getName()}**' has been detached from Artist '**{$artist->getName()}**'.";
@@ -79,13 +79,13 @@ class PerformanceDeleted extends WikiDeletedEvent implements SyncArtistSongEvent
Performance::RELATION_ARTIST => function (MorphTo $morphTo) {
$morphTo->morphWith([
Artist::class => [],
Membership::class => [Membership::RELATION_ARTIST, Membership::RELATION_MEMBER],
Membership::class => [Membership::RELATION_GROUP, Membership::RELATION_MEMBER],
]);
},
]);
if ($performance->isMembership()) {
$performance->artist->artist->searchable();
$performance->artist->group->searchable();
$performance->artist->member->searchable();
return;
@@ -108,7 +108,7 @@ class PerformanceDeleted extends WikiDeletedEvent implements SyncArtistSongEvent
&& Performance::query()
->whereBelongsTo($song)
->where(Performance::ATTRIBUTE_ARTIST_TYPE, Membership::class)
->whereHas(Performance::RELATION_ARTIST, fn (Builder $query) => $query->where(Artist::ATTRIBUTE_ID, $performance->artist->artist->getKey()))
->whereHas(Performance::RELATION_ARTIST, fn (Builder $query) => $query->where(Artist::ATTRIBUTE_ID, $performance->artist->group->getKey()))
->exists()
) {
return;
@@ -116,7 +116,7 @@ class PerformanceDeleted extends WikiDeletedEvent implements SyncArtistSongEvent
$artist = match ($performance->artist_type) {
Artist::class => $performance->artist,
Membership::class => $performance->artist->artist,
Membership::class => $performance->artist->group,
default => throw new Exception('Invalid artist type.'),
};
@@ -40,14 +40,14 @@ class PerformanceDeleting extends BaseEvent implements UpdateRelatedIndicesEvent
Performance::RELATION_ARTIST => function (MorphTo $morphTo) {
$morphTo->morphWith([
Artist::class => [],
Membership::class => [Membership::RELATION_ARTIST, Membership::RELATION_MEMBER],
Membership::class => [Membership::RELATION_GROUP, Membership::RELATION_MEMBER],
]);
},
]);
if ($performance->isForceDeleting()) {
if ($performance->isMembership()) {
$performance->artist->artist->searchable();
$performance->artist->group->searchable();
$performance->artist->member->searchable();
return;
@@ -51,13 +51,13 @@ class PerformanceRestored extends WikiRestoredEvent implements SyncArtistSongEve
Performance::RELATION_ARTIST => function (MorphTo $morphTo) {
$morphTo->morphWith([
Artist::class => [],
Membership::class => [Membership::RELATION_ARTIST, Membership::RELATION_MEMBER],
Membership::class => [Membership::RELATION_GROUP, Membership::RELATION_MEMBER],
]);
},
]);
if ($performance->isMembership()) {
$performance->artist->artist->searchable();
$performance->artist->group->searchable();
$performance->artist->member->searchable();
return;
@@ -77,7 +77,7 @@ class PerformanceRestored extends WikiRestoredEvent implements SyncArtistSongEve
$artist = match ($performance->artist_type) {
Artist::class => $performance->artist,
Membership::class => $performance->artist->artist,
Membership::class => $performance->artist->group,
default => throw new Exception('Invalid artist type.'),
};
@@ -52,13 +52,13 @@ class PerformanceUpdated extends WikiUpdatedEvent implements SyncArtistSongEvent
Performance::RELATION_ARTIST => function (MorphTo $morphTo) {
$morphTo->morphWith([
Artist::class => [],
Membership::class => [Membership::RELATION_ARTIST, Membership::RELATION_MEMBER],
Membership::class => [Membership::RELATION_GROUP, Membership::RELATION_MEMBER],
]);
},
]);
if ($performance->isMembership()) {
$performance->artist->artist->searchable();
$performance->artist->group->searchable();
$performance->artist->member->searchable();
return;
@@ -78,7 +78,7 @@ class PerformanceUpdated extends WikiUpdatedEvent implements SyncArtistSongEvent
$artist = match ($performance->artist_type) {
Artist::class => $performance->artist,
Membership::class => $performance->artist->artist,
Membership::class => $performance->artist->group,
default => throw new Exception('Invalid artist type.'),
};
@@ -51,32 +51,29 @@ class BelongsToColumn extends TextColumn
->weight(FontWeight::SemiBold)
->color('related-link')
->url(function (Model $record) {
$relation = $this->getName();
/** @var (Model&Nameable)|null $related */
$related = $record->$relation;
$related = $this->getRelated($record);
if ($related === null) {
return null;
}
$this->formatStateUsing(function () use ($related) {
$name = $this->shouldUseModelName
? $related->getName()
: $this->resource->getRecordTitle($related);
$nameLimited = Str::limit($name, $this->getCharacterLimit() ?? 50);
return $nameLimited;
});
return $this->resource::getUrl('view', ['record' => $related]);
})
->tooltip(function (Model $record) {
$relation = $this->getName();
->formatStateUsing(function (Model $record) {
$related = $this->getRelated($record);
/** @var (Model&Nameable)|null $related */
$related = $record->$relation;
if ($related === null) {
return null;
}
$name = $this->shouldUseModelName
? $related->getName()
: $this->resource->getRecordTitle($related);
return Str::limit($name, $this->getCharacterLimit() ?? 50);
})
->tooltip(function (Model $record) {
$related = $this->getRelated($record);
if ($related === null) {
return null;
@@ -87,4 +84,20 @@ class BelongsToColumn extends TextColumn
: $this->resource->getRecordTitle($related);
});
}
/**
* Get the related model of the owner record.
*
* @return (Model&Nameable)|null
*/
private function getRelated(?Model $record): ?Model
{
$relation = $this->getName();
foreach (explode('.', $relation) as $relationPart) {
$record = $record->getRelation($relationPart);
}
return $record;
}
}
@@ -50,33 +50,29 @@ class BelongsToEntry extends TextEntry
->color('related-link')
->placeholder('-')
->url(function (BaseModel|Model $record) {
$relation = $this->getName();
/** @var (Model&Nameable)|null $related */
$related = $record;
foreach (explode('.', $relation) as $relationPart) {
$related = $related->$relationPart;
}
$related = $this->getRelated($record);
if ($related === null) {
return null;
}
$this->formatStateUsing(function () use ($related) {
$name = $this->shouldUseModelName
? $related->getName()
: $this->resource->getRecordTitle($related);
return $name;
});
return $this->resource::getUrl('view', ['record' => $related]);
})
->tooltip(function (Model $record) {
$relation = $this->getName();
->formatStateUsing(function (Model $record) {
$related = $this->getRelated($record);
/** @var (Model&Nameable)|null $related */
$related = $record->$relation;
if ($related === null) {
return null;
}
$name = $this->shouldUseModelName
? $related->getName()
: $this->resource->getRecordTitle($related);
return $name;
})
->tooltip(function (Model $record) {
$related = $this->getRelated($record);
if ($related === null) {
return null;
@@ -87,4 +83,20 @@ class BelongsToEntry extends TextEntry
: $this->resource->getRecordTitle($related);
});
}
/**
* Get the related model of the owner record.
*
* @return (Model&Nameable)|null
*/
private function getRelated(?Model $record): ?Model
{
$relation = $this->getName();
foreach (explode('.', $relation) as $relationPart) {
$record = $record->getRelation($relationPart);
}
return $record;
}
}
+1 -1
View File
@@ -149,7 +149,7 @@ class Theme extends BaseResource
AnimeTheme::RELATION_PERFORMANCES_ARTISTS => function (MorphTo $morphTo) {
$morphTo->morphWith([
Artist::class => [],
Membership::class => [Membership::RELATION_ARTIST, Membership::RELATION_MEMBER],
Membership::class => [Membership::RELATION_GROUP, Membership::RELATION_MEMBER],
]);
},
]);
@@ -101,7 +101,7 @@ class Membership extends BaseResource
// Necessary to prevent lazy loading when loading related resources
return $query->with([
MembershipModel::RELATION_ARTIST,
MembershipModel::RELATION_GROUP,
MembershipModel::RELATION_MEMBER,
]);
}
@@ -145,7 +145,7 @@ class Membership extends BaseResource
TextColumn::make(MembershipModel::ATTRIBUTE_ID)
->label(__('filament.fields.base.id')),
BelongsToColumn::make(MembershipModel::RELATION_ARTIST, ArtistResource::class),
BelongsToColumn::make(MembershipModel::RELATION_GROUP, ArtistResource::class),
BelongsToColumn::make(MembershipModel::RELATION_MEMBER, ArtistResource::class)
->label(__('filament.fields.membership.member')),
@@ -173,7 +173,7 @@ class Membership extends BaseResource
TextEntry::make(MembershipModel::ATTRIBUTE_ID)
->label(__('filament.fields.base.id')),
BelongsToEntry::make(MembershipModel::RELATION_ARTIST, ArtistResource::class),
BelongsToEntry::make(MembershipModel::RELATION_GROUP, ArtistResource::class),
BelongsToEntry::make(MembershipModel::RELATION_MEMBER, ArtistResource::class)
->label(__('filament.fields.membership.member')),
@@ -113,7 +113,7 @@ class Performance extends BaseResource
PerformanceModel::RELATION_ARTIST => function (MorphTo $morphTo) {
$morphTo->morphWith([
Artist::class => [],
Membership::class => [Membership::RELATION_ARTIST, Membership::RELATION_MEMBER],
Membership::class => [Membership::RELATION_GROUP, Membership::RELATION_MEMBER],
]);
},
PerformanceModel::RELATION_SONG,
@@ -163,7 +163,7 @@ class Performance extends BaseResource
->hiddenOn([PerformanceArtistRelationManager::class])
->state(function ($record) {
if ($record->artist instanceof Membership) {
return $record->artist->artist->name;
return $record->artist->group->name;
}
return $record->artist->name;
@@ -210,7 +210,7 @@ class Performance extends BaseResource
BelongsToEntry::make(PerformanceModel::RELATION_ARTIST, ArtistResource::class)
->hidden(fn (PerformanceModel $record) => $record->artist instanceof Membership),
BelongsToEntry::make(PerformanceModel::RELATION_ARTIST.'.'.Membership::RELATION_ARTIST, ArtistResource::class)
BelongsToEntry::make(PerformanceModel::RELATION_ARTIST.'.'.Membership::RELATION_GROUP, ArtistResource::class)
->label(__('filament.fields.performance.artist'))
->hidden(fn ($state) => is_null($state)),
@@ -37,8 +37,7 @@ class MembershipType extends EloquentType implements ReportableType
public function relations(): array
{
return [
new BelongsToRelation(new ArtistType(), Membership::RELATION_ARTIST)
->renameTo('group')
new BelongsToRelation(new ArtistType(), Membership::RELATION_GROUP)
->notNullable(),
new BelongsToRelation(new ArtistType(), Membership::RELATION_MEMBER)
->notNullable(),
@@ -35,7 +35,7 @@ class MembershipSchema extends EloquentSchema implements SearchableSchema
public function allowedIncludes(): array
{
return $this->withIntermediatePaths([
new AllowedInclude(new ArtistSchema(), Membership::RELATION_ARTIST),
new AllowedInclude(new ArtistSchema(), Membership::RELATION_GROUP),
new AllowedInclude(new ArtistSchema(), Membership::RELATION_MEMBER),
]);
}
+7 -7
View File
@@ -27,7 +27,7 @@ use Illuminate\Support\Collection;
* @property string|null $alias
* @property string|null $as
* @property int $artist_id
* @property Artist $artist
* @property Artist $group
* @property int $member_id
* @property Artist $member
* @property Collection<int, Performance> $performances
@@ -48,7 +48,7 @@ class Membership extends BaseModel implements SoftDeletable
final public const ATTRIBUTE_AS = 'as';
final public const ATTRIBUTE_MEMBER = 'member_id';
final public const RELATION_ARTIST = 'artist';
final public const RELATION_GROUP = 'group';
final public const RELATION_MEMBER = 'member';
final public const RELATION_PERFORMANCES = 'performances';
@@ -107,11 +107,11 @@ class Membership extends BaseModel implements SoftDeletable
public function getSubtitle(): string
{
$this->loadMissing([
Membership::RELATION_ARTIST,
Membership::RELATION_GROUP,
Membership::RELATION_MEMBER,
]);
return "Member {$this->member->getName()} of Group {$this->artist->getName()}";
return "Member {$this->member->getName()} of Group {$this->group->getName()}";
}
/**
@@ -122,17 +122,17 @@ class Membership extends BaseModel implements SoftDeletable
public static function getEagerLoadsForSubtitle(): array
{
return [
Membership::RELATION_ARTIST,
Membership::RELATION_GROUP,
Membership::RELATION_MEMBER,
];
}
/**
* Get the artist that owns the membership.
* Get the group that owns the membership.
*
* @return BelongsTo<Artist, $this>
*/
public function artist(): BelongsTo
public function group(): BelongsTo
{
return $this->belongsTo(Artist::class, Membership::ATTRIBUTE_ARTIST);
}
@@ -31,7 +31,7 @@ test('render index page', function () {
$records = MembershipModel::factory()
->count(10)
->for(Artist::factory(), MembershipModel::RELATION_ARTIST)
->for(Artist::factory(), MembershipModel::RELATION_GROUP)
->for(Artist::factory(), MembershipModel::RELATION_MEMBER)
->create();
@@ -53,7 +53,7 @@ test('render view page', function () {
actingAs($user);
$record = MembershipModel::factory()
->for(Artist::factory(), MembershipModel::RELATION_ARTIST)
->for(Artist::factory(), MembershipModel::RELATION_GROUP)
->for(Artist::factory(), MembershipModel::RELATION_MEMBER)
->createOne();
@@ -87,7 +87,7 @@ test('mount edit action', function () {
actingAs($user);
$record = MembershipModel::factory()
->for(Artist::factory(), MembershipModel::RELATION_ARTIST)
->for(Artist::factory(), MembershipModel::RELATION_GROUP)
->for(Artist::factory(), MembershipModel::RELATION_MEMBER)
->createOne();
@@ -104,7 +104,7 @@ test('user cannot create record', function () {
test('user cannot edit record', function () {
$record = MembershipModel::factory()
->for(Artist::factory(), MembershipModel::RELATION_ARTIST)
->for(Artist::factory(), MembershipModel::RELATION_GROUP)
->for(Artist::factory(), MembershipModel::RELATION_MEMBER)
->createOne();
@@ -114,7 +114,7 @@ test('user cannot edit record', function () {
test('user cannot delete record', function () {
$record = MembershipModel::factory()
->for(Artist::factory(), MembershipModel::RELATION_ARTIST)
->for(Artist::factory(), MembershipModel::RELATION_GROUP)
->for(Artist::factory(), MembershipModel::RELATION_MEMBER)
->createOne();
@@ -124,7 +124,7 @@ test('user cannot delete record', function () {
test('user cannot restore record', function () {
$record = MembershipModel::factory()
->for(Artist::factory(), MembershipModel::RELATION_ARTIST)
->for(Artist::factory(), MembershipModel::RELATION_GROUP)
->for(Artist::factory(), MembershipModel::RELATION_MEMBER)
->createOne();
@@ -137,7 +137,7 @@ test('user cannot restore record', function () {
test('user cannot force delete record', function () {
$record = MembershipModel::factory()
->for(Artist::factory(), MembershipModel::RELATION_ARTIST)
->for(Artist::factory(), MembershipModel::RELATION_GROUP)
->for(Artist::factory(), MembershipModel::RELATION_MEMBER)
->createOne();