125 lines
4.0 KiB
PHP
125 lines
4.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\Web;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\ActivityEvent;
|
|
use App\Models\Artwork;
|
|
use App\Models\User;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
/**
|
|
* Community activity feed.
|
|
*
|
|
* GET /community/activity?type=global|following
|
|
*/
|
|
final class CommunityActivityController extends Controller
|
|
{
|
|
private const PER_PAGE = 30;
|
|
|
|
public function index(Request $request)
|
|
{
|
|
$user = $request->user();
|
|
$type = $request->query('type', 'global'); // global | following
|
|
$perPage = self::PER_PAGE;
|
|
|
|
$query = ActivityEvent::query()
|
|
->orderByDesc('created_at')
|
|
->with(['actor:id,name,username']);
|
|
|
|
if ($type === 'following' && $user) {
|
|
// Show only events from followed users
|
|
$followingIds = DB::table('user_followers')
|
|
->where('follower_id', $user->id)
|
|
->pluck('user_id')
|
|
->all();
|
|
|
|
if (empty($followingIds)) {
|
|
$query->whereRaw('0 = 1'); // empty result set
|
|
} else {
|
|
$query->whereIn('actor_id', $followingIds);
|
|
}
|
|
}
|
|
|
|
$events = $query->paginate($perPage)->withQueryString();
|
|
$enriched = $this->enrich($events->getCollection());
|
|
|
|
return view('web.community.activity', [
|
|
'events' => $events,
|
|
'enriched' => $enriched,
|
|
'active_tab' => $type,
|
|
'page_title' => 'Community Activity',
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Attach target object data to each event for display.
|
|
*/
|
|
private function enrich(\Illuminate\Support\Collection $events): \Illuminate\Support\Collection
|
|
{
|
|
// Collect artwork IDs and user IDs to eager-load
|
|
$artworkIds = $events
|
|
->where('target_type', ActivityEvent::TARGET_ARTWORK)
|
|
->pluck('target_id')
|
|
->unique()
|
|
->values()
|
|
->all();
|
|
|
|
$userIds = $events
|
|
->where('target_type', ActivityEvent::TARGET_USER)
|
|
->pluck('target_id')
|
|
->unique()
|
|
->values()
|
|
->all();
|
|
|
|
$artworks = Artwork::whereIn('id', $artworkIds)
|
|
->with('user:id,name,username')
|
|
->get(['id', 'title', 'slug', 'user_id', 'hash', 'thumb_ext'])
|
|
->keyBy('id');
|
|
|
|
$users = User::whereIn('id', $userIds)
|
|
->with('profile:user_id,avatar_hash')
|
|
->get(['id', 'name', 'username'])
|
|
->keyBy('id');
|
|
|
|
return $events->map(function (ActivityEvent $event) use ($artworks, $users): array {
|
|
$target = null;
|
|
|
|
if ($event->target_type === ActivityEvent::TARGET_ARTWORK) {
|
|
$artwork = $artworks->get($event->target_id);
|
|
$target = $artwork ? [
|
|
'id' => $artwork->id,
|
|
'title' => $artwork->title,
|
|
'url' => '/art/' . $artwork->id . '/' . $artwork->slug,
|
|
'thumb' => $artwork->thumbUrl('sm'),
|
|
] : null;
|
|
} elseif ($event->target_type === ActivityEvent::TARGET_USER) {
|
|
$u = $users->get($event->target_id);
|
|
$target = $u ? [
|
|
'id' => $u->id,
|
|
'name' => $u->name,
|
|
'username' => $u->username,
|
|
'url' => '/@' . $u->username,
|
|
] : null;
|
|
}
|
|
|
|
return [
|
|
'id' => $event->id,
|
|
'type' => $event->type,
|
|
'target_type' => $event->target_type,
|
|
'actor' => [
|
|
'id' => $event->actor?->id,
|
|
'name' => $event->actor?->name,
|
|
'username' => $event->actor?->username,
|
|
'url' => '/@' . $event->actor?->username,
|
|
],
|
|
'target' => $target,
|
|
'created_at' => $event->created_at?->toIso8601String(),
|
|
];
|
|
});
|
|
}
|
|
}
|