<?php
declare(strict_types=1);
namespace App\Classes;
use App\Models\Article;
use App\Models\Comment;
use App\Models\Down;
use App\Models\Item;
use App\Models\News;
use App\Models\Offer;
use App\Models\Photo;
use App\Models\Poll;
use App\Models\Post;
use App\Models\Topic;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\HtmlString;
class Feed
{
private mixed $user;
public function __construct()
{
$this->user = getUser();
}
/**
* Get feed
*/
public function getFeed(): HtmlString
{
$polls = [];
$collect = new Collection();
if (setting('feed_topics_show')) {
$topics = $this->getTopics();
$collect = $collect->merge($topics);
if ($this->user) {
$ids = $topics->pluck('last_post_id')->all();
$polls[Post::$morphName] = $this->getPolls($ids, Post::$morphName);
}
}
if (setting('feed_news_show')) {
$news = $this->getNews();
$collect = $collect->merge($news);
if ($this->user) {
$ids = $news->pluck('id')->all();
$polls[News::$morphName] = $this->getPolls($ids, News::$morphName);
}
}
if (setting('feed_photos_show')) {
$photos = $this->getPhotos();
$collect = $collect->merge($photos);
if ($this->user) {
$ids = $photos->pluck('id')->all();
$polls[Photo::$morphName] = $this->getPolls($ids, Photo::$morphName);
}
}
if (setting('feed_articles_show')) {
$articles = $this->getArticles();
$collect = $collect->merge($articles);
if ($this->user) {
$ids = $articles->pluck('id')->all();
$polls[Article::$morphName] = $this->getPolls($ids, Article::$morphName);
}
}
if (setting('feed_downs_show')) {
$downs = $this->getDowns();
$collect = $collect->merge($downs);
if ($this->user) {
$ids = $downs->pluck('id')->all();
$polls[Down::$morphName] = $this->getPolls($ids, Down::$morphName);
}
}
if (setting('feed_items_show')) {
$collect = $collect->merge($this->getItems());
}
if (setting('feed_offers_show')) {
$offers = $this->getOffers();
$collect = $collect->merge($offers);
if ($this->user) {
$ids = $offers->pluck('id')->all();
$polls[Offer::$morphName] = $this->getPolls($ids, Offer::$morphName);
}
}
if (setting('feed_comments_show')) {
$comments = $this->getComments();
$collect = $collect->merge($comments);
if ($this->user) {
$ids = $comments->pluck('id')->all();
$polls[Comment::$morphName] = $this->getPolls($ids, Comment::$morphName);
}
}
$posts = $collect
->sortByDesc('created_at')
->sortByDesc('top')
->take(setting('feed_total'));
$user = $this->user;
$posts = simplePaginate($posts, setting('feed_per_page'));
$allowDownload = $user || setting('down_guest_download');
return new HtmlString(view('feeds/_feed', compact('posts', 'polls', 'user', 'allowDownload')));
}
/**
* Get polls
*/
private function getPolls(array $ids, string $morphName): array
{
return Poll::query()
->whereIn('polls.relate_id', $ids)
->where('polls.relate_type', $morphName)
->where('polls.user_id', $this->user->id)
->pluck('vote', 'relate_id')
->all();
}
/**
* Get topics
*
* @return Collection<Topic>
*/
public function getTopics(): Collection
{
return Cache::remember('TopicFeed', 600, static function () {
return Topic::query()
->select('topics.*', 'posts.created_at')
->join('posts', function ($join) {
$join->on('last_post_id', 'posts.id')
->where('posts.rating', '>', setting('feed_topics_rating'));
})
->with('lastPost.user', 'lastPost.files', 'forum.parent')
->orderByDesc('topics.updated_at')
->limit(setting('feed_last_record'))
->get();
});
}
/**
* Get news
*
* @return Collection<News>
*/
public function getNews(): Collection
{
return Cache::remember('NewsFeed', 600, static function () {
return News::query()
->where('rating', '>', setting('feed_news_rating'))
->with('user')
->orderByDesc('created_at')
->limit(setting('feed_last_record'))
->get();
});
}
/**
* Get photos
*
* @return Collection<Photo>
*/
public function getPhotos(): Collection
{
return Cache::remember('PhotoFeed', 600, static function () {
return Photo::query()
->where('rating', '>', setting('feed_photos_rating'))
->with('user', 'files')
->orderByDesc('created_at')
->limit(setting('feed_last_record'))
->get();
});
}
/**
* Get articles
*
* @return Collection<Article>
*/
public function getArticles(): Collection
{
return Cache::remember('ArticleFeed', 600, static function () {
return Article::query()
->where('rating', '>', setting('feed_downs_rating'))
->with('user', 'files', 'category.parent')
->orderByDesc('created_at')
->limit(setting('feed_last_record'))
->get();
});
}
/**
* Get downs
*
* @return Collection<Down>
*/
public function getDowns(): Collection
{
return Cache::remember('DownFeed', 600, static function () {
return Down::query()
->active()
->where('rating', '>', setting('feed_downs_rating'))
->with('user', 'files', 'category.parent')
->orderByDesc('created_at')
->limit(setting('feed_last_record'))
->get();
});
}
/**
* Get items
*
* @return Collection<Item>
*/
public function getItems(): Collection
{
return Cache::remember('ItemFeed', 600, static function () {
return Item::query()
->where('expires_at', '>', SITETIME)
->with('user', 'files', 'category.parent')
->orderByDesc('created_at')
->limit(setting('feed_last_record'))
->get();
});
}
/**
* Get offers
*
* @return Collection<Offer>
*/
public function getOffers(): Collection
{
return Cache::remember('OfferFeed', 600, static function () {
return Offer::query()
->where('rating', '>', setting('feed_offers_rating'))
->with('user')
->orderByDesc('created_at')
->limit(setting('feed_last_record'))
->get();
});
}
/**
* Get comments
*
* @return Collection<Comment>
*/
public function getComments(): Collection
{
return Cache::remember('CommentFeed', 600, static function () {
return Comment::query()
->where('rating', '>', setting('feed_comments_rating'))
->whereIn('id', function ($query) {
$query->selectRaw('MAX(id)')
->from('comments')
->groupBy('relate_id');
})
->with('relate', 'user')
->orderByDesc('created_at')
->limit(setting('feed_last_record'))
->get();
});
}
}