2023-08-04 20:51:02 +00:00
< ? php
namespace Misuzu\Home ;
2023-08-31 00:38:20 +00:00
use RuntimeException ;
2023-08-04 20:51:02 +00:00
use Index\DateTime ;
use Index\Data\DbTools ;
use Index\Data\IDbConnection ;
2023-09-08 00:13:30 +00:00
use Index\Routing\Route ;
use Index\Routing\RouteHandler ;
2023-08-04 20:51:02 +00:00
use Misuzu\Pagination ;
2023-09-08 20:40:48 +00:00
use Misuzu\SiteInfo ;
2023-08-04 20:51:02 +00:00
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 ;
2023-09-10 00:04:53 +00:00
use Misuzu\URLs\URLInfo ;
2023-09-06 13:50:19 +00:00
use Misuzu\Users\UsersContext ;
2023-08-04 20:51:02 +00:00
2023-09-08 00:13:30 +00:00
class HomeRoutes extends RouteHandler {
2023-08-04 20:51:02 +00:00
public function __construct (
2023-09-06 13:50:19 +00:00
private IConfig $config ,
private IDbConnection $dbConn ,
2023-09-08 20:40:48 +00:00
private SiteInfo $siteInfo ,
2023-09-06 13:50:19 +00:00
private AuthInfo $authInfo ,
private Changelog $changelog ,
private Comments $comments ,
private Counters $counters ,
private News $news ,
private UsersContext $usersCtx
) {}
2023-08-04 20:51:02 +00:00
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 {
2023-09-06 13:50:19 +00:00
return $this -> usersCtx -> getUsers () -> getUsers (
2023-08-04 20:51:02 +00:00
lastActiveInMinutes : 5 ,
deleted : false ,
orderBy : 'random' ,
);
}
private array $newsCategoryInfos = [];
private function getFeaturedNewsPosts ( int $amount , bool $decorate ) : array {
2023-08-05 13:50:15 +00:00
$postInfos = $this -> news -> getPosts (
2023-08-04 20:51:02 +00:00
onlyFeatured : true ,
pagination : new Pagination ( $amount )
);
if ( ! $decorate )
return $postInfos ;
$posts = [];
foreach ( $postInfos as $postInfo ) {
$categoryId = $postInfo -> getCategoryId ();
2023-09-06 13:50:19 +00:00
$userInfo = $postInfo -> hasUserId () ? $this -> usersCtx -> getUserInfo ( $postInfo -> getUserId ()) : null ;
2023-08-04 20:51:02 +00:00
if ( array_key_exists ( $categoryId , $this -> newsCategoryInfos ))
$categoryInfo = $this -> newsCategoryInfos [ $categoryId ];
else
2023-08-05 13:50:15 +00:00
$this -> newsCategoryInfos [ $categoryId ] = $categoryInfo = $this -> news -> getCategory ( postInfo : $postInfo );
2023-08-04 20:51:02 +00:00
$commentsCount = $postInfo -> hasCommentsCategoryId ()
2023-08-05 13:50:15 +00:00
? $this -> comments -> countPosts ( categoryInfo : $postInfo -> getCommentsCategoryId (), deleted : false ) : 0 ;
2023-08-04 20:51:02 +00:00
$posts [] = [
'post' => $postInfo ,
'category' => $categoryInfo ,
'user' => $userInfo ,
2023-09-06 13:50:19 +00:00
'user_colour' => $this -> usersCtx -> getUserColour ( $userInfo ),
2023-08-04 20:51:02 +00:00
'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 ;
}
2023-09-08 00:13:30 +00:00
#[Route('GET', '/')]
2023-09-10 00:04:53 +00:00
#[URLInfo('index', '/')]
2023-08-04 20:51:02 +00:00
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 );
2023-08-05 13:50:15 +00:00
$changelog = $this -> changelog -> getChanges ( pagination : new Pagination ( 10 ));
2023-08-04 20:51:02 +00:00
$stats [ 'users:online:recent' ] = count ( $onlineUserInfos );
$birthdays = [];
2023-09-06 13:50:19 +00:00
$birthdayInfos = $this -> usersCtx -> getUsers () -> getUsers ( deleted : false , birthdate : DateTime :: now (), orderBy : 'random' );
2023-08-04 20:51:02 +00:00
foreach ( $birthdayInfos as $birthdayInfo )
$birthdays [] = [
'info' => $birthdayInfo ,
2023-09-06 13:50:19 +00:00
'colour' => $this -> usersCtx -> getUserColour ( $birthdayInfo ),
2023-08-04 20:51:02 +00:00
];
$newestMember = [];
if ( empty ( $birthdays )) {
$newestMemberId = $this -> config -> getString ( 'users.newest' );
if ( ! empty ( $newestMemberId ))
try {
2023-09-06 13:50:19 +00:00
$newestMember [ 'info' ] = $this -> usersCtx -> getUserInfo ( $newestMemberId );
$newestMember [ 'colour' ] = $this -> usersCtx -> getUserColour ( $newestMemberId );
2023-08-04 20:51:02 +00:00
} catch ( RuntimeException $ex ) {
$newestMember = [];
2023-08-31 00:40:07 +00:00
$this -> config -> removeValues ( 'users.newest' );
2023-08-04 20:51:02 +00:00
}
}
return Template :: renderRaw ( 'home.home' , [
'statistics' => $stats ,
'newest_member' => $newestMember ,
'online_users' => $onlineUserInfos ,
'birthdays' => $birthdays ,
'featured_changelog' => $changelog ,
'featured_news' => $featuredNews ,
]);
}
2023-09-08 00:13:30 +00:00
#[Route('GET', '/_landing')]
public function getLanding ( $response , $request ) {
2023-08-04 20:51:02 +00:00
$config = $this -> config -> getValues ([
[ 'social.embed_linked:b' ],
[ 'landing.forum_categories:a' ],
'social.linked:a'
]);
if ( $config [ 'social.embed_linked' ]) {
$linkedData = [
'@context' => 'http://schema.org' ,
'@type' => 'Organization' ,
2023-09-08 20:40:48 +00:00
'name' => $this -> siteInfo -> getName (),
'url' => $this -> siteInfo -> getURL (),
'logo' => $this -> siteInfo -> getExternalLogo (),
2023-08-04 20:51:02 +00:00
'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 ,
]);
}
}