Files
RomhackPlaza/app/Services/ActivityService.php
2026-06-29 19:24:35 +02:00

259 lines
9.3 KiB
PHP

<?php
namespace App\Services;
use App\Models\Entry;
use App\Models\EntryReview;
use App\Models\News;
use App\View\Components\EntryCard;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
class ActivityService
{
private const CACHE_ENTRIES = 300; // seconds.
private const CACHE_NEWS = 300; // seconds.
private const CACHE_MESSAGES = 300; // seconds.
private const CACHE_THREADS = 300; // seconds.
private const CACHE_CLUBS = 300; // seconds.
private const CACHE_REVIEWS = 300; // seconds.
private const ITEMS_PER_TYPE = 15;
public function getActivities( array $activities = [ 'entries', 'news', 'messages', 'threads', 'clubs', 'reviews' ] ): Collection
{
$c = collect();
if( in_array( 'entries', $activities ) ) {
$c = $c->merge($this->getEntries());
}
if( in_array( 'news', $activities ) ) {
$c = $c->merge($this->getNews());
}
if( in_array( 'messages', $activities ) ) {
$c = $c->merge($this->getMessages());
}
if( in_array( 'threads', $activities ) ) {
$c = $c->merge($this->getThreads());
}
if( in_array( 'clubs', $activities ) ) {
$c = $c->merge($this->getClubs());
}
if( in_array( 'reviews', $activities ) ) {
$c = $c->merge($this->getReviews());
}
return $c->sortByDesc('date')
->values()
->take(30)
->map(function(array $item){
$obj = (object) $item;
$obj->date = Carbon::createFromTimestamp($obj->date);
return $obj;
});
}
private function formatEntry( Entry $entry ): array
{
return [
'type' => 'entry',
'title' => $entry->complete_title ?? $entry->title,
'url' => route('entries.show', ['section' => $entry->type, 'entry' => $entry]),
'image' => $entry->main_image ? \Storage::url($entry->main_image) : null,
'date' => $entry->created_at->timestamp,
'author' => $entry->authors->pluck('name')->implode(', '),
'user_id' => $entry->user_id,
'badge' => EntryCard::ENTRY_TYPES_BADGE[$entry->type],
'badge_class' => $entry->type,
'excerpt' => $entry->description ? \Str::limit(strip_tags($entry->description), 80) : null,
'meta' => $entry->getRealPlatform()?->name
];
}
private function formatNews( News $news ): array
{
return [
'type' => 'news',
'title' => $news->title,
'url' => route('news.show', ['news' => $news]),
'image' => $news->gallery()->first() ? \Storage::url($news->gallery()->first()->image) : null,
'date' => $news->created_at->timestamp,
'author' => null,
'user_id' => $news->user_id,
'badge' => 'News',
'badge_class' => 'news',
'excerpt' => $news->description ? \Str::limit(strip_tags($news->description), 80) : null,
'meta' => $news->category?->name
];
}
private function formatMessage( object $message ): array
{
return [
'type' => 'message',
'title' => $message->title,
'url' => xfRoute('threads/.' ) . $message->thread_id . '/post-' . $message->post_id,
'image' => null,
'date' => $message->post_date,
'author' => null,
'user_id' => $message->user_id,
'badge' => 'Post',
'badge_class' => 'message',
'excerpt' => $message->message ? \Str::limit(strip_tags($message->message), 80) : null,
'meta' => null
];
}
private function formatThread( object $thread ): array
{
return [
'type' => 'thread',
'title' => $thread->title,
'url' => xfRoute('threads/.' ) . $thread->thread_id,
'image' => null,
'date' => $thread->post_date,
'author' => null,
'user_id' => $thread->user_id,
'badge' => 'Thread',
'badge_class' => 'thread',
'excerpt' => $thread->message ? \Str::limit(strip_tags($thread->message), 80) : null,
'meta' => null
];
}
private function formatClub( object $club ): array
{
return [
'type' => 'club',
'title' => $club->title,
'url' => xfRoute('forums/.' ) . $club->node_id,
'image' => null, // TODO: Remplacer par banner_date
'date' => $club->club_creation_date,
'author' => null,
'user_id' => $club->user_id,
'badge' => 'Club',
'badge_class' => 'club',
'excerpt' => $club->description ? \Str::limit(strip_tags($club->description), 80) : null,
'meta' => null
];
}
private function formatReview( EntryReview $review ): array
{
return [
'type' => 'review',
'title' => $review->title,
'url' => $review->entry()->exists() ? route('entries.show', ['section' => $review->entry->type, 'entry' => $review->entry]) : '',
'image' => null,
'date' => $review->created_at->timestamp,
'author' => null,
'user_id' => $review->user_id,
'badge' => 'Review',
'badge_class' => 'review',
'excerpt' => $review->description ? \Str::limit(strip_tags($review->description), 80) : null,
'meta' => $review->entry()->exists() ? ( $review->entry->complete_title ?? $review->entry->title ) : null,
];
}
private function getEntries(): array
{
return Cache::remember('activity_entries', self::CACHE_ENTRIES, function() {
return Entry::published()
->with(['authors', 'game.platform'])
->latest('created_at')
->limit(self::ITEMS_PER_TYPE)
->get()
->map($this->formatEntry(...))
->toArray();
});
}
private function getNews(): array
{
return Cache::remember('activity_news', self::CACHE_NEWS, function() {
return News::published()
->with('gallery')
->latest('created_at')
->limit(self::ITEMS_PER_TYPE)
->get()
->map($this->formatNews(...))
->toArray();
});
}
private function getMessages(): array
{
return Cache::remember('activity_messages', self::CACHE_MESSAGES, function() {
return DB::connection('xenforo')
->table('post')
->join('user', 'post.user_id', '=', 'user.user_id')
->join('thread', 'post.thread_id', '=', 'thread.thread_id')
->where('post.message_state', 'visible')
->where('thread.first_post_id', '!=', 'post.post_id')
->orderByDesc('post.post_date')
->limit(self::ITEMS_PER_TYPE)
->select([
'thread.title', 'thread.thread_id', 'post.post_id', 'post.post_date',
'post.user_id', 'post.message'
])
->get()
->map($this->formatMessage(...))
->toArray();
});
}
private function getThreads(): array
{
return Cache::remember('activity_threads', self::CACHE_THREADS, function() {
return DB::connection('xenforo')
->table('thread')
->join('user', 'thread.user_id', '=', 'user.user_id')
->join('post', 'thread.first_post_id', '=', 'post.post_id')
->where('thread.discussion_state', 'visible')
->where('thread.discussion_type', '!=', 'redirect' )
->where('thread.node_id', '!=', config('xenforo.comments_node_id') )
->orderByDesc('thread.post_date')
->limit(self::ITEMS_PER_TYPE)
->select([
'thread.title', 'thread.thread_id', 'thread.post_date', 'thread.user_id',
'post.message'
])
->get()
->map($this->formatThread(...))
->toArray();
});
}
private function getClubs(): array
{
return Cache::remember('activity_clubs', self::CACHE_CLUBS, function() {
return DB::connection('xenforo')
->table('club')
->where('club_state', 'visible')
->orderByDesc('club_creation_date')
->limit(self::ITEMS_PER_TYPE)
->select([
'club.title', 'club.description', 'club.node_id',
'club.club_creation_date', 'club.user_id'
])
->get()
->map($this->formatClub(...))
->toArray();
});
}
private function getReviews(): array
{
return Cache::remember('activity_reviews', self::CACHE_REVIEWS, function() {
return EntryReview::with(['entry'])
->latest('created_at')
->limit(self::ITEMS_PER_TYPE)
->get()
->map($this->formatReview(...))
->toArray();
});
}
}