Save workspace changes
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Artwork;
|
||||
use App\Models\Group;
|
||||
use App\Models\GroupActivityItem;
|
||||
use App\Models\GroupAsset;
|
||||
use App\Models\GroupChallenge;
|
||||
use App\Models\GroupEvent;
|
||||
use App\Models\GroupPost;
|
||||
use App\Models\GroupProject;
|
||||
use App\Models\GroupRelease;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class GroupActivityService
|
||||
{
|
||||
public function record(
|
||||
Group $group,
|
||||
?User $actor,
|
||||
string $type,
|
||||
string $subjectType,
|
||||
?int $subjectId,
|
||||
string $headline,
|
||||
?string $summary = null,
|
||||
string $visibility = GroupActivityItem::VISIBILITY_PUBLIC,
|
||||
): GroupActivityItem {
|
||||
return GroupActivityItem::query()->create([
|
||||
'group_id' => (int) $group->id,
|
||||
'type' => $type,
|
||||
'visibility' => $visibility,
|
||||
'actor_user_id' => $actor?->id,
|
||||
'subject_type' => $subjectType,
|
||||
'subject_id' => $subjectId,
|
||||
'headline' => $headline,
|
||||
'summary' => $summary,
|
||||
'is_pinned' => false,
|
||||
'occurred_at' => now(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function pin(GroupActivityItem $item, User $actor, bool $isPinned = true): GroupActivityItem
|
||||
{
|
||||
$item->forceFill([
|
||||
'is_pinned' => $isPinned,
|
||||
])->save();
|
||||
|
||||
app(GroupHistoryService::class)->record(
|
||||
$item->group,
|
||||
$actor,
|
||||
$isPinned ? 'activity_pinned' : 'activity_unpinned',
|
||||
sprintf('%s group activity item.', $isPinned ? 'Pinned' : 'Unpinned'),
|
||||
'group_activity_item',
|
||||
(int) $item->id,
|
||||
['is_pinned' => ! $isPinned],
|
||||
['is_pinned' => $isPinned],
|
||||
);
|
||||
|
||||
return $item->fresh(['actor']);
|
||||
}
|
||||
|
||||
public function publicFeed(Group $group, int $limit = 8): array
|
||||
{
|
||||
return $this->mapItems(
|
||||
GroupActivityItem::query()
|
||||
->with('actor:id,name,username')
|
||||
->where('group_id', $group->id)
|
||||
->where('visibility', GroupActivityItem::VISIBILITY_PUBLIC)
|
||||
->orderByDesc('is_pinned')
|
||||
->orderByDesc('occurred_at')
|
||||
->limit(max(1, min(24, $limit)))
|
||||
->get(),
|
||||
$group
|
||||
);
|
||||
}
|
||||
|
||||
public function studioFeed(Group $group, User $viewer, int $limit = 20): array
|
||||
{
|
||||
if (! $group->canViewStudio($viewer)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->mapItems(
|
||||
GroupActivityItem::query()
|
||||
->with('actor:id,name,username')
|
||||
->where('group_id', $group->id)
|
||||
->orderByDesc('is_pinned')
|
||||
->orderByDesc('occurred_at')
|
||||
->limit(max(1, min(50, $limit)))
|
||||
->get(),
|
||||
$group
|
||||
);
|
||||
}
|
||||
|
||||
private function mapItems(Collection $items, Group $group): array
|
||||
{
|
||||
$subjects = $this->loadSubjects($items);
|
||||
|
||||
return $items->map(function (GroupActivityItem $item) use ($group, $subjects): array {
|
||||
$subject = $subjects[$item->subject_type][$item->subject_id] ?? null;
|
||||
|
||||
return [
|
||||
'id' => (int) $item->id,
|
||||
'type' => (string) $item->type,
|
||||
'visibility' => (string) $item->visibility,
|
||||
'headline' => (string) $item->headline,
|
||||
'summary' => $item->summary,
|
||||
'is_pinned' => (bool) $item->is_pinned,
|
||||
'occurred_at' => $item->occurred_at?->toISOString(),
|
||||
'actor' => $item->actor ? [
|
||||
'id' => (int) $item->actor->id,
|
||||
'name' => $item->actor->name,
|
||||
'username' => $item->actor->username,
|
||||
] : null,
|
||||
'subject' => $subject ? [
|
||||
'type' => (string) $item->subject_type,
|
||||
'id' => (int) $item->subject_id,
|
||||
'title' => $subject->title ?? null,
|
||||
'url' => $this->subjectUrl($group, (string) $item->subject_type, $subject),
|
||||
] : null,
|
||||
];
|
||||
})->values()->all();
|
||||
}
|
||||
|
||||
private function loadSubjects(Collection $items): array
|
||||
{
|
||||
$grouped = $items
|
||||
->filter(fn (GroupActivityItem $item): bool => $item->subject_id !== null)
|
||||
->groupBy('subject_type')
|
||||
->map(fn (Collection $chunk): array => $chunk->pluck('subject_id')->map(fn ($id): int => (int) $id)->unique()->values()->all());
|
||||
|
||||
return [
|
||||
'artwork' => Artwork::query()->whereIn('id', $grouped->get('artwork', []))->get()->keyBy('id')->all(),
|
||||
'group_post' => GroupPost::query()->whereIn('id', $grouped->get('group_post', []))->get()->keyBy('id')->all(),
|
||||
'group_project' => GroupProject::query()->whereIn('id', $grouped->get('group_project', []))->get()->keyBy('id')->all(),
|
||||
'group_release' => GroupRelease::query()->whereIn('id', $grouped->get('group_release', []))->get()->keyBy('id')->all(),
|
||||
'group_challenge' => GroupChallenge::query()->whereIn('id', $grouped->get('group_challenge', []))->get()->keyBy('id')->all(),
|
||||
'group_event' => GroupEvent::query()->whereIn('id', $grouped->get('group_event', []))->get()->keyBy('id')->all(),
|
||||
'group_asset' => GroupAsset::query()->whereIn('id', $grouped->get('group_asset', []))->get()->keyBy('id')->all(),
|
||||
];
|
||||
}
|
||||
|
||||
private function subjectUrl(Group $group, string $subjectType, object $subject): ?string
|
||||
{
|
||||
return match ($subjectType) {
|
||||
'artwork' => route('art.show', ['id' => $subject->id, 'slug' => $subject->slug ?: $subject->id]),
|
||||
'group_post' => route('groups.posts.show', ['group' => $group, 'post' => $subject]),
|
||||
'group_project' => route('groups.projects.show', ['group' => $group, 'project' => $subject]),
|
||||
'group_release' => route('groups.releases.show', ['group' => $group, 'release' => $subject]),
|
||||
'group_challenge' => route('groups.challenges.show', ['group' => $group, 'challenge' => $subject]),
|
||||
'group_event' => route('groups.events.show', ['group' => $group, 'event' => $subject]),
|
||||
'group_asset' => route('groups.assets.download', ['group' => $group, 'asset' => $subject]),
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user