misuzu/src/Home/HomeRoutes.php

284 lines
10 KiB
PHP

<?php
namespace Misuzu\Home;
use Index\DateTime;
use Index\Data\DbTools;
use Index\Data\IDbConnection;
use Index\Routing\IRouter;
use Misuzu\Pagination;
use Misuzu\Template;
use Misuzu\Auth\AuthInfo;
use Misuzu\Changelog\Changelog;
use Misuzu\Comments\Comments;
use Misuzu\Config\IConfig;
use Misuzu\Counters\Counters;
use Misuzu\News\News;
use Misuzu\Users\Users;
class HomeRoutes {
private IConfig $config;
private IDbConnection $dbConn;
private AuthInfo $authInfo;
private Changelog $changelog;
private Comments $comments;
private Counters $counters;
private News $news;
private Users $users;
public function __construct(
IRouter $router,
IConfig $config,
IDbConnection $dbConn,
AuthInfo $authInfo,
Changelog $changelog,
Comments $comments,
Counters $counters,
News $news,
Users $users
) {
$this->config = $config;
$this->dbConn = $dbConn;
$this->authInfo = $authInfo;
$this->changelog = $changelog;
$this->comments = $comments;
$this->counters = $counters;
$this->news = $news;
$this->users = $users;
$router->get('/', [$this, 'getIndex']);
if(MSZ_DEBUG)
$router->get('/dev-landing', [$this, 'getLanding']);
$router->get('/index.php', function($response) {
$response->redirect(url('index'), true);
});
}
private function getStats(): array {
return $this->counters->get([
'users:active',
'users:online:recent',
'users:online:today',
'comments:posts:visible',
'forum:topics:visible',
'forum:posts:visible',
]);
}
private function getOnlineUsers(): array {
return $this->users->getUsers(
lastActiveInMinutes: 5,
deleted: false,
orderBy: 'random',
);
}
private array $userInfos = [];
private array $userColours = [];
private array $newsCategoryInfos = [];
private function getFeaturedNewsPosts(int $amount, bool $decorate): array {
$postInfos = $this->news->getPosts(
onlyFeatured: true,
pagination: new Pagination($amount)
);
if(!$decorate)
return $postInfos;
$posts = [];
foreach($postInfos as $postInfo) {
$userId = $postInfo->getUserId();
$categoryId = $postInfo->getCategoryId();
if(array_key_exists($userId, $this->userInfos)) {
$userInfo = $this->userInfos[$userId];
$userColour = $this->userColours[$userId];
} else {
try {
$userInfo = $this->users->getUser($userId, 'id');
$userColour = $this->users->getUserColour($userInfo);
} catch(RuntimeException $ex) {
$userInfo = null;
$userColour = null;
}
$this->userInfos[$userId] = $userInfo;
$this->userColours[$userId] = $userColour;
}
if(array_key_exists($categoryId, $this->newsCategoryInfos))
$categoryInfo = $this->newsCategoryInfos[$categoryId];
else
$this->newsCategoryInfos[$categoryId] = $categoryInfo = $this->news->getCategory(postInfo: $postInfo);
$commentsCount = $postInfo->hasCommentsCategoryId()
? $this->comments->countPosts(categoryInfo: $postInfo->getCommentsCategoryId(), deleted: false) : 0;
$posts[] = [
'post' => $postInfo,
'category' => $categoryInfo,
'user' => $userInfo,
'user_colour' => $userColour,
'comments_count' => $commentsCount,
];
}
return $posts;
}
public function getPopularForumTopics(array $categoryIds): array {
$args = 0;
$stmt = $this->dbConn->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)'
. ' 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 (' . DbTools::prepareListString($categoryIds) . ') 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'
. ' LIMIT 10'
);
foreach($categoryIds as $categoryId)
$stmt->addParameter(++$args, (string)$categoryId);
$stmt->execute();
$topics = [];
$result = $stmt->getResult();
while($result->next())
$topics[] = [
'topic_id' => $result->getInteger(0),
'forum_id' => $result->getInteger(1),
'topic_title' => $result->getString(2),
'forum_icon' => $result->getString(3),
'topic_count_views' => $result->getInteger(4),
'topic_count_posts' => $result->getInteger(5),
];
return $topics;
}
public function getActiveForumTopics(array $categoryIds): array {
$args = 0;
$stmt = $this->dbConn->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)'
. ', (SELECT MAX(post_id) FROM msz_forum_posts AS p WHERE p.topic_id = t.topic_id AND post_deleted IS NULL)'
. ' 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 (' . DbTools::prepareListString($categoryIds) . ') AND topic_deleted IS NULL AND topic_locked IS NULL'
. ' ORDER BY topic_bumped DESC'
. ' LIMIT 10'
);
foreach($categoryIds as $categoryId)
$stmt->addParameter(++$args, (string)$categoryId);
$stmt->execute();
$topics = [];
$result = $stmt->getResult();
while($result->next())
$topics[] = [
'topic_id' => $result->getInteger(0),
'forum_id' => $result->getInteger(1),
'topic_title' => $result->getString(2),
'forum_icon' => $result->getString(3),
'topic_count_views' => $result->getInteger(4),
'topic_count_posts' => $result->getInteger(5),
'latest_post_id' => $result->getInteger(6),
];
return $topics;
}
public function getIndex(...$args) {
return $this->authInfo->isLoggedIn()
? $this->getHome(...$args)
: $this->getLanding(...$args);
}
public function getHome() {
$stats = $this->getStats();
$onlineUserInfos = $this->getOnlineUsers();
$featuredNews = $this->getFeaturedNewsPosts(5, true);
$changelog = $this->changelog->getChanges(pagination: new Pagination(10));
$stats['users:online:recent'] = count($onlineUserInfos);
$birthdays = [];
$birthdayInfos = $this->users->getUsers(deleted: false, birthdate: DateTime::now(), orderBy: 'random');
foreach($birthdayInfos as $birthdayInfo)
$birthdays[] = [
'info' => $birthdayInfo,
'colour' => $this->users->getUserColour($birthdayInfo),
];
$newestMember = [];
if(empty($birthdays)) {
$newestMemberId = $this->config->getString('users.newest');
if(!empty($newestMemberId))
try {
$newestMemberInfo = $this->users->getUser($newestMemberId, 'id');
$newestMemberColour = $this->users->getUserColour($newestMemberInfo);
$newestMember['info'] = $newestMemberInfo;
$newestMember['colour'] = $newestMemberColour;
} catch(RuntimeException $ex) {
$newestMember = [];
$config->removeValues('users.newest');
}
}
return Template::renderRaw('home.home', [
'statistics' => $stats,
'newest_member' => $newestMember,
'online_users' => $onlineUserInfos,
'birthdays' => $birthdays,
'featured_changelog' => $changelog,
'featured_news' => $featuredNews,
]);
}
public function getLanding() {
$config = $this->config->getValues([
['social.embed_linked:b'],
['landing.forum_categories:a'],
['site.name:s', 'Misuzu'],
'site.url:s',
'site.ext_logo:s',
'social.linked:a'
]);
if($config['social.embed_linked']) {
$linkedData = [
'@context' => 'http://schema.org',
'@type' => 'Organization',
'name' => $config['site.name'],
'url' => $config['site.url'],
'logo' => $config['site.ext_logo'],
'same_as' => $config['social.linked'],
];
} else $linkedData = null;
$stats = $this->getStats();
$onlineUserInfos = $this->getOnlineUsers();
$featuredNews = $this->getFeaturedNewsPosts(3, false);
$popularTopics = $this->getPopularForumTopics($config['landing.forum_categories']);
$activeTopics = $this->getActiveForumTopics($config['landing.forum_categories']);
$stats['users:online:recent'] = count($onlineUserInfos);
return Template::renderRaw('home.landing', [
'statistics' => $stats,
'online_users' => $onlineUserInfos,
'featured_news' => $featuredNews,
'linked_data' => $linkedData,
'forum_popular' => $popularTopics,
'forum_active' => $activeTopics,
]);
}
}