misuzu/src/Http/Handlers/HomeHandler.php

186 lines
7.2 KiB
PHP

<?php
namespace Misuzu\Http\Handlers;
use RuntimeException;
use Misuzu\DB;
use Misuzu\Pagination;
use Misuzu\Template;
use Misuzu\Comments\CommentsCategory;
use Misuzu\Users\User;
final class HomeHandler extends Handler {
private const STATS = [
'users:active',
'users:online:recent',
'users:online:today',
'comments:posts:visible',
'forum:topics:visible',
'forum:posts:visible',
];
public function index($response, $request): void {
if(User::hasCurrent())
$this->home($response, $request);
else
$this->landing($response, $request);
}
public function landing($response, $request): void {
$config = $this->context->getConfig();
$counters = $this->context->getCounters();
if($config->getBoolean('social.embed_linked')) {
$ldr = $config->getValues([
['site.name:s', 'Misuzu'],
'site.url:s',
'site.ext_logo:s',
'social.linked:a'
]);
$linkedData = [
'name' => $ldr['site.name'],
'url' => $ldr['site.url'],
'logo' => $ldr['site.ext_logo'],
'same_as' => $ldr['social.linked'],
];
} else $linkedData = null;
$featuredNews = $this->context->getNews()->getAllPosts(
onlyFeatured: true,
pagination: new Pagination(3)
);
$stats = $counters->get(self::STATS);
$onlineUsers = DB::query(
'SELECT u.`user_id`, u.`username`, COALESCE(u.`user_colour`, r.`role_colour`) AS `user_colour`'
. ' FROM `msz_users` AS u'
. ' LEFT JOIN `msz_roles` AS r'
. ' ON r.`role_id` = u.`display_role`'
. ' WHERE u.`user_active` >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)'
. ' ORDER BY u.`user_active` DESC, RAND()'
. ' LIMIT 50'
)->fetchAll();
// TODO: don't hardcode forum ids
$featuredForums = $config->getArray('landing.forum_categories');
$popularTopics = [];
$activeTopics = [];
if(!empty($featuredForums)) {
$getPopularTopics = DB::prepare(
'SELECT t.`topic_id`, c.`forum_id`, t.`topic_title`, c.`forum_icon`, t.`topic_count_views`'
. ', (SELECT COUNT(*) FROM `msz_forum_posts` AS p WHERE p.`topic_id` = t.`topic_id` AND `post_deleted` IS NULL) AS `topic_count_posts`'
. ' FROM `msz_forum_topics` AS t'
. ' LEFT JOIN `msz_forum_categories` AS c ON c.`forum_id` = t.`forum_id`'
. ' WHERE c.`forum_id` IN (' . implode(',', $featuredForums) . ') AND `topic_deleted` IS NULL AND `topic_locked` IS NULL'
. ' ORDER BY (SELECT COUNT(*) FROM `msz_forum_posts` AS p WHERE p.`topic_id` = t.`topic_id` AND `post_deleted` IS NULL AND `post_created` > NOW() - INTERVAL 3 MONTH) DESC'
)->stmt;
$getPopularTopics->execute();
for($i = 0; $i < 10; ++$i) {
$topicInfo = $getPopularTopics->fetchObject();
if(empty($topicInfo))
break;
$popularTopics[] = $topicInfo;
}
$getActiveTopics = DB::prepare(
'SELECT t.`topic_id`, c.`forum_id`, t.`topic_title`, c.`forum_icon`, t.`topic_count_views`'
. ', (SELECT COUNT(*) FROM `msz_forum_posts` AS p WHERE p.`topic_id` = t.`topic_id` AND `post_deleted` IS NULL) AS `topic_count_posts`'
. ', (SELECT MAX(`post_id`) FROM `msz_forum_posts` AS p WHERE p.`topic_id` = t.`topic_id` AND `post_deleted` IS NULL) AS `latest_post_id`'
. ' FROM `msz_forum_topics` AS t'
. ' LEFT JOIN `msz_forum_categories` AS c ON c.`forum_id` = t.`forum_id`'
. ' WHERE c.`forum_id` IN (' . implode(',', $featuredForums) . ') AND `topic_deleted` IS NULL AND `topic_locked` IS NULL'
. ' ORDER BY `topic_bumped` DESC'
)->stmt;
$getActiveTopics->execute();
for($i = 0; $i < 10; ++$i) {
$topicInfo = $getActiveTopics->fetchObject();
if(empty($topicInfo))
break;
$activeTopics[] = $topicInfo;
}
}
$response->setContent(Template::renderRaw('home.landing', [
'statistics' => $stats,
'online_users' => $onlineUsers,
'featured_news' => $featuredNews,
'linked_data' => $linkedData,
'forum_popular' => $popularTopics,
'forum_active' => $activeTopics,
]));
}
public function home($response, $request): void {
$news = $this->context->getNews();
$comments = $this->context->getComments();
$counters = $this->context->getCounters();
$featuredNews = [];
$userInfos = [];
$categoryInfos = [];
$featuredNewsInfos = $news->getAllPosts(
onlyFeatured: true,
pagination: new Pagination(5)
);
foreach($featuredNewsInfos as $postInfo) {
$userId = $postInfo->getUserId();
$categoryId = $postInfo->getCategoryId();
if(array_key_exists($userId, $userInfos)) {
$userInfo = $userInfos[$userId];
} else {
try {
$userInfo = User::byId($userId);
} catch(RuntimeException $ex) {
$userInfo = null;
}
$userInfos[$userId] = $userInfo;
}
if(array_key_exists($categoryId, $categoryInfos))
$categoryInfo = $categoryInfos[$categoryId];
else
$categoryInfos[$categoryId] = $categoryInfo = $news->getCategoryByPost($postInfo);
$commentsCount = $postInfo->hasCommentsCategoryId()
? $comments->countPosts($postInfo->getCommentsCategoryId(), includeReplies: true) : 0;
$featuredNews[] = [
'post' => $postInfo,
'category' => $categoryInfo,
'user' => $userInfo,
'comments_count' => $commentsCount,
];
}
$stats = $counters->get(self::STATS);
$changelog = $this->context->getChangelog()->getAllChanges(pagination: new Pagination(10));
$birthdays = User::byBirthdate();
$latestUser = !empty($birthdays) ? null : User::byLatest();
$onlineUsers = DB::query(
'SELECT u.`user_id`, u.`username`, COALESCE(u.`user_colour`, r.`role_colour`) AS `user_colour`'
. ' FROM `msz_users` AS u'
. ' LEFT JOIN `msz_roles` AS r'
. ' ON r.`role_id` = u.`display_role`'
. ' WHERE u.`user_active` >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)'
. ' ORDER BY u.`user_active` DESC, RAND()'
)->fetchAll();
// today we cheat
$stats['users:online:recent'] = count($onlineUsers);
$response->setContent(Template::renderRaw('home.home', [
'statistics' => $stats,
'latest_user' => $latestUser,
'online_users' => $onlineUsers,
'birthdays' => $birthdays,
'featured_changelog' => $changelog,
'featured_news' => $featuredNews,
]));
}
}