2022-09-13 13:14:49 +00:00
< ? php
define ( 'MSZ_FORUM_TYPE_DISCUSSION' , 0 );
define ( 'MSZ_FORUM_TYPE_CATEGORY' , 1 );
define ( 'MSZ_FORUM_TYPE_LINK' , 2 );
define ( 'MSZ_FORUM_TYPES' , [
MSZ_FORUM_TYPE_DISCUSSION ,
MSZ_FORUM_TYPE_CATEGORY ,
MSZ_FORUM_TYPE_LINK ,
]);
define ( 'MSZ_FORUM_MAY_HAVE_CHILDREN' , [
MSZ_FORUM_TYPE_DISCUSSION ,
MSZ_FORUM_TYPE_CATEGORY ,
]);
define ( 'MSZ_FORUM_MAY_HAVE_TOPICS' , [
MSZ_FORUM_TYPE_DISCUSSION ,
]);
define ( 'MSZ_FORUM_ROOT' , 0 );
define ( 'MSZ_FORUM_ROOT_DATA' , [ // should be compatible with the data fetched in forum_get_root_categories
'forum_id' => MSZ_FORUM_ROOT ,
'forum_name' => 'Forums' ,
'forum_children' => 0 ,
'forum_type' => MSZ_FORUM_TYPE_CATEGORY ,
'forum_colour' => null ,
'forum_permissions' => MSZ_FORUM_PERM_SET_READ ,
]);
function forum_is_valid_type ( int $type ) : bool {
return in_array ( $type , MSZ_FORUM_TYPES , true );
}
function forum_may_have_children ( int $forumType ) : bool {
return in_array ( $forumType , MSZ_FORUM_MAY_HAVE_CHILDREN );
}
function forum_may_have_topics ( int $forumType ) : bool {
return in_array ( $forumType , MSZ_FORUM_MAY_HAVE_TOPICS );
}
function forum_get ( int $forumId , bool $showDeleted = false ) : array {
$getForum = \Misuzu\DB :: prepare ( sprintf (
'
SELECT
`forum_id` , `forum_name` , `forum_type` , `forum_link` , `forum_archived` ,
`forum_link_clicks` , `forum_parent` , `forum_colour` , `forum_icon` ,
(
SELECT COUNT ( `topic_id` )
FROM `msz_forum_topics`
WHERE `forum_id` = f . `forum_id`
% 1 $s
) as `forum_topic_count`
FROM `msz_forum_categories` as f
WHERE `forum_id` = : forum_id
' ,
$showDeleted ? '' : 'AND `topic_deleted` IS NULL'
));
$getForum -> bind ( 'forum_id' , $forumId );
return $getForum -> fetch ();
}
function forum_get_root_categories ( int $userId ) : array {
$getCategories = \Misuzu\DB :: prepare ( sprintf (
'
SELECT
f . `forum_id` , f . `forum_name` , f . `forum_type` , f . `forum_colour` , f . `forum_icon` ,
(
SELECT COUNT ( `forum_id` )
FROM `msz_forum_categories` AS sf
WHERE sf . `forum_parent` = f . `forum_id`
) AS `forum_children`
FROM `msz_forum_categories` AS f
WHERE f . `forum_parent` = 0
AND f . `forum_type` = % 1 $d
AND f . `forum_hidden` = 0
GROUP BY f . `forum_id`
ORDER BY f . `forum_order`
' ,
MSZ_FORUM_TYPE_CATEGORY
));
$categories = array_merge ([ MSZ_FORUM_ROOT_DATA ], $getCategories -> fetchAll ());
$getRootForumCount = \Misuzu\DB :: prepare ( sprintf (
"
SELECT COUNT ( `forum_id` )
FROM `msz_forum_categories`
WHERE `forum_parent` = % d
AND `forum_type` != % d
" ,
MSZ_FORUM_ROOT ,
MSZ_FORUM_TYPE_CATEGORY
));
$categories [ 0 ][ 'forum_children' ] = ( int ) $getRootForumCount -> fetchColumn ();
foreach ( $categories as $key => $category ) {
$categories [ $key ][ 'forum_permissions' ] = $perms = forum_perms_get_user ( $category [ 'forum_id' ], $userId )[ MSZ_FORUM_PERMS_GENERAL ];
if ( ! perms_check ( $perms , MSZ_FORUM_PERM_SET_READ )) {
unset ( $categories [ $key ]);
continue ;
}
$categories [ $key ] = array_merge (
$category ,
[ 'forum_unread' => forum_topics_unread ( $category [ 'forum_id' ], $userId )],
forum_latest_post ( $category [ 'forum_id' ], $userId )
);
}
return $categories ;
}
function forum_get_breadcrumbs (
int $forumId ,
string $linkFormat = '/forum/forum.php?f=%d' ,
string $rootFormat = '/forum/#f%d' ,
array $indexLink = [ 'Forums' => '/forum/' ]
) : array {
$breadcrumbs = [];
$getBreadcrumb = \Misuzu\DB :: prepare ( '
SELECT `forum_id` , `forum_name` , `forum_type` , `forum_parent`
FROM `msz_forum_categories`
WHERE `forum_id` = : forum_id
' );
while ( $forumId > 0 ) {
$getBreadcrumb -> bind ( 'forum_id' , $forumId );
$breadcrumb = $getBreadcrumb -> fetch ();
if ( empty ( $breadcrumb )) {
break ;
}
$breadcrumbs [ $breadcrumb [ 'forum_name' ]] = sprintf (
$breadcrumb [ 'forum_parent' ] === MSZ_FORUM_ROOT
&& $breadcrumb [ 'forum_type' ] === MSZ_FORUM_TYPE_CATEGORY
? $rootFormat
: $linkFormat ,
$breadcrumb [ 'forum_id' ]
);
$forumId = $breadcrumb [ 'forum_parent' ];
}
return array_reverse ( $breadcrumbs + $indexLink );
}
function forum_get_colour ( int $forumId ) : int {
$getColours = \Misuzu\DB :: prepare ( '
SELECT `forum_id` , `forum_parent` , `forum_colour`
FROM `msz_forum_categories`
WHERE `forum_id` = : forum_id
' );
while ( $forumId > 0 ) {
$getColours -> bind ( 'forum_id' , $forumId );
$colourInfo = $getColours -> fetch ();
if ( empty ( $colourInfo )) {
break ;
}
if ( ! empty ( $colourInfo [ 'forum_colour' ])) {
return $colourInfo [ 'forum_colour' ];
}
$forumId = $colourInfo [ 'forum_parent' ];
}
return 0x40000000 ;
}
function forum_increment_clicks ( int $forumId ) : void {
$incrementLinkClicks = \Misuzu\DB :: prepare ( sprintf ( '
UPDATE `msz_forum_categories`
SET `forum_link_clicks` = `forum_link_clicks` + 1
WHERE `forum_id` = : forum_id
AND `forum_type` = % d
AND `forum_link_clicks` IS NOT NULL
' , MSZ_FORUM_TYPE_LINK ));
$incrementLinkClicks -> bind ( 'forum_id' , $forumId );
$incrementLinkClicks -> execute ();
}
function forum_get_parent_id ( int $forumId ) : int {
if ( $forumId < 1 ) {
return 0 ;
}
static $memoized = [];
if ( array_key_exists ( $forumId , $memoized )) {
return $memoized [ $forumId ];
}
$getParent = \Misuzu\DB :: prepare ( '
SELECT `forum_parent`
FROM `msz_forum_categories`
WHERE `forum_id` = : forum_id
' );
$getParent -> bind ( 'forum_id' , $forumId );
return ( int ) $getParent -> fetchColumn ();
}
function forum_get_child_ids ( int $forumId ) : array {
if ( $forumId < 1 ) {
return [];
}
static $memoized = [];
if ( array_key_exists ( $forumId , $memoized )) {
return $memoized [ $forumId ];
}
$getChildren = \Misuzu\DB :: prepare ( '
SELECT `forum_id`
FROM `msz_forum_categories`
WHERE `forum_parent` = : forum_id
' );
$getChildren -> bind ( 'forum_id' , $forumId );
$children = $getChildren -> fetchAll ();
return $memoized [ $forumId ] = array_column ( $children , 'forum_id' );
}
function forum_topics_unread ( int $forumId , int $userId ) : int {
if ( $userId < 1 || $forumId < 1 )
return 0 ;
static $memoized = [];
$memoId = " { $forumId } - { $userId } " ;
if ( array_key_exists ( $memoId , $memoized )) {
return $memoized [ $memoId ];
}
$memoized [ $memoId ] = 0 ;
$children = forum_get_child_ids ( $forumId );
foreach ( $children as $child ) {
$memoized [ $memoId ] += forum_topics_unread ( $child , $userId );
}
if ( forum_perms_check_user ( MSZ_FORUM_PERMS_GENERAL , $forumId , $userId , MSZ_FORUM_PERM_SET_READ )) {
$countUnread = \Misuzu\DB :: prepare ( '
SELECT COUNT ( ti . `topic_id` )
FROM `msz_forum_topics` AS ti
LEFT JOIN `msz_forum_topics_track` AS tt
ON tt . `topic_id` = ti . `topic_id` AND tt . `user_id` = : user_id
WHERE ti . `forum_id` = : forum_id
AND ti . `topic_deleted` IS NULL
AND ti . `topic_bumped` >= NOW () - INTERVAL 1 MONTH
AND (
tt . `track_last_read` IS NULL
OR tt . `track_last_read` < ti . `topic_bumped`
)
' );
$countUnread -> bind ( 'forum_id' , $forumId );
$countUnread -> bind ( 'user_id' , $userId );
$memoized [ $memoId ] += ( int ) $countUnread -> fetchColumn ();
}
return $memoized [ $memoId ];
}
function forum_latest_post ( int $forumId , int $userId ) : array {
if ( $forumId < 1 ) {
return [];
}
static $memoized = [];
$memoId = " { $forumId } - { $userId } " ;
if ( array_key_exists ( $memoId , $memoized )) {
return $memoized [ $memoId ];
}
if ( ! forum_perms_check_user ( MSZ_FORUM_PERMS_GENERAL , $forumId , $userId , MSZ_FORUM_PERM_SET_READ )) {
return $memoized [ $memoId ] = [];
}
$getLastPost = \Misuzu\DB :: prepare ( '
SELECT
p . `post_id` AS `recent_post_id` , t . `topic_id` AS `recent_topic_id` ,
t . `topic_title` AS `recent_topic_title` , t . `topic_bumped` AS `recent_topic_bumped` ,
p . `post_created` AS `recent_post_created` ,
u . `user_id` AS `recent_post_user_id` ,
u . `username` AS `recent_post_username` ,
COALESCE ( u . `user_colour` , r . `role_colour` ) AS `recent_post_user_colour` ,
UNIX_TIMESTAMP ( p . `post_created` ) AS `post_created_unix`
FROM `msz_forum_posts` AS p
LEFT JOIN `msz_forum_topics` AS t
ON t . `topic_id` = p . `topic_id`
LEFT JOIN `msz_users` AS u
ON u . `user_id` = p . `user_id`
LEFT JOIN `msz_roles` AS r
ON r . `role_id` = u . `display_role`
WHERE p . `forum_id` = : forum_id
AND p . `post_deleted` IS NULL
ORDER BY p . `post_id` DESC
' );
$getLastPost -> bind ( 'forum_id' , $forumId );
$currentLast = $getLastPost -> fetch ();
$children = forum_get_child_ids ( $forumId );
foreach ( $children as $child ) {
$lastPost = forum_latest_post ( $child , $userId );
if (( $currentLast [ 'post_created_unix' ] ? ? 0 ) < ( $lastPost [ 'post_created_unix' ] ? ? 0 )) {
$currentLast = $lastPost ;
}
}
return $memoized [ $memoId ] = $currentLast ;
}
function forum_get_children ( int $parentId , int $userId ) : array {
$getListing = \Misuzu\DB :: prepare ( sprintf (
'
SELECT
: user_id AS `target_user_id` ,
f . `forum_id` , f . `forum_name` , f . `forum_description` , f . `forum_type` , f . `forum_icon` ,
f . `forum_link` , f . `forum_link_clicks` , f . `forum_archived` , f . `forum_colour` ,
f . `forum_count_topics` , f . `forum_count_posts`
FROM `msz_forum_categories` AS f
WHERE f . `forum_parent` = : parent_id
AND f . `forum_hidden` = 0
AND (
( f . `forum_parent` = % 1 $d AND f . `forum_type` != % 2 $d )
OR f . `forum_parent` != % 1 $d
)
GROUP BY f . `forum_id`
ORDER BY f . `forum_order`
' ,
MSZ_FORUM_ROOT ,
MSZ_FORUM_TYPE_CATEGORY
));
$getListing -> bind ( 'user_id' , $userId );
$getListing -> bind ( 'parent_id' , $parentId );
$listing = $getListing -> fetchAll ();
foreach ( $listing as $key => $forum ) {
$listing [ $key ][ 'forum_permissions' ] = $perms = forum_perms_get_user ( $forum [ 'forum_id' ], $userId )[ MSZ_FORUM_PERMS_GENERAL ];
if ( ! perms_check ( $perms , MSZ_FORUM_PERM_SET_READ )) {
unset ( $listing [ $key ]);
continue ;
}
$listing [ $key ] = array_merge (
$forum ,
[ 'forum_unread' => forum_topics_unread ( $forum [ 'forum_id' ], $userId )],
forum_latest_post ( $forum [ 'forum_id' ], $userId )
);
}
return $listing ;
}
function forum_timeout ( int $forumId , int $userId ) : int {
$checkTimeout = \Misuzu\DB :: prepare ( '
SELECT TIMESTAMPDIFF ( SECOND , COALESCE ( MAX ( `post_created` ), NOW () - INTERVAL 1 YEAR ), NOW ())
FROM `msz_forum_posts`
WHERE `forum_id` = : forum_id
AND `user_id` = : user_id
' );
$checkTimeout -> bind ( 'forum_id' , $forumId );
$checkTimeout -> bind ( 'user_id' , $userId );
return ( int ) $checkTimeout -> fetchColumn ();
}
// $forumId == null marks all forums as read
function forum_mark_read ( ? int $forumId , int $userId ) : void {
2023-01-02 19:50:33 +00:00
// shitty fix for dumb-ass function signature
if ( $forumId === 0 )
$forumId = null ;
2022-09-13 13:14:49 +00:00
if (( $forumId !== null && $forumId < 1 ) || $userId < 1 ) {
return ;
}
$entireForum = $forumId === null ;
if ( ! $entireForum ) {
$children = forum_get_child_ids ( $forumId );
foreach ( $children as $child ) {
forum_mark_read ( $child , $userId );
}
}
$doMark = \Misuzu\DB :: prepare ( sprintf (
'
INSERT INTO `msz_forum_topics_track`
( `user_id` , `topic_id` , `forum_id` , `track_last_read` )
SELECT u . `user_id` , t . `topic_id` , t . `forum_id` , NOW ()
FROM `msz_forum_topics` AS t
LEFT JOIN `msz_users` AS u
ON u . `user_id` = : user
WHERE t . `topic_deleted` IS NULL
AND t . `topic_bumped` >= NOW () - INTERVAL 1 MONTH
% 1 $s
GROUP BY t . `topic_id`
ON DUPLICATE KEY UPDATE
`track_last_read` = NOW ()
' ,
$entireForum ? '' : 'AND t.`forum_id` = :forum'
));
$doMark -> bind ( 'user' , $userId );
if ( ! $entireForum ) {
$doMark -> bind ( 'forum' , $forumId );
}
$doMark -> execute ();
}
function forum_posting_info ( int $userId ) : array {
$getPostingInfo = \Misuzu\DB :: prepare ( '
SELECT
u . `user_country` , u . `user_created` ,
(
SELECT COUNT ( `post_id` )
FROM `msz_forum_posts`
WHERE `user_id` = u . `user_id`
AND `post_deleted` IS NULL
) AS `user_forum_posts` ,
(
SELECT `post_parse`
FROM `msz_forum_posts`
WHERE `user_id` = u . `user_id`
AND `post_deleted` IS NULL
ORDER BY `post_id` DESC
LIMIT 1
) AS `user_post_parse`
FROM `msz_users` as u
WHERE `user_id` = : user_id
' );
$getPostingInfo -> bind ( 'user_id' , $userId );
return $getPostingInfo -> fetch ();
}
function forum_count_increase ( int $forumId , bool $topic = false ) : void {
$increaseCount = \Misuzu\DB :: prepare ( sprintf (
'
UPDATE `msz_forum_categories`
SET `forum_count_posts` = `forum_count_posts` + 1
% s
WHERE `forum_id` = : forum
' ,
$topic ? ',`forum_count_topics` = `forum_count_topics` + 1' : ''
));
$increaseCount -> bind ( 'forum' , $forumId );
$increaseCount -> execute ();
}
function forum_count_synchronise ( int $forumId = MSZ_FORUM_ROOT , bool $save = true ) : array {
static $getChildren = null ;
static $getCounts = null ;
static $setCounts = null ;
if ( is_null ( $getChildren )) {
$getChildren = \Misuzu\DB :: prepare ( '
SELECT `forum_id` , `forum_parent`
FROM `msz_forum_categories`
WHERE `forum_parent` = : parent
' );
}
if ( is_null ( $getCounts )) {
$getCounts = \Misuzu\DB :: prepare ( '
SELECT : forum as `target_forum_id` ,
(
SELECT COUNT ( `topic_id` )
FROM `msz_forum_topics`
WHERE `forum_id` = `target_forum_id`
AND `topic_deleted` IS NULL
) AS `count_topics` ,
(
SELECT COUNT ( `post_id` )
FROM `msz_forum_posts`
WHERE `forum_id` = `target_forum_id`
AND `post_deleted` IS NULL
) AS `count_posts`
' );
}
if ( $save && is_null ( $setCounts )) {
$setCounts = \Misuzu\DB :: prepare ( '
UPDATE `msz_forum_categories`
SET `forum_count_topics` = : topics ,
`forum_count_posts` = : posts
WHERE `forum_id` = : forum_id
' );
}
$getChildren -> bind ( 'parent' , $forumId );
$children = $getChildren -> fetchAll ();
$topics = 0 ;
$posts = 0 ;
foreach ( $children as $child ) {
$childCount = forum_count_synchronise ( $child [ 'forum_id' ], $save );
$topics += $childCount [ 'topics' ];
$posts += $childCount [ 'posts' ];
}
$getCounts -> bind ( 'forum' , $forumId );
$counts = $getCounts -> fetch ();
$topics += $counts [ 'count_topics' ];
$posts += $counts [ 'count_posts' ];
if ( $forumId > 0 && $save ) {
$setCounts -> bind ( 'forum_id' , $forumId );
$setCounts -> bind ( 'topics' , $topics );
$setCounts -> bind ( 'posts' , $posts );
$setCounts -> execute ();
}
return compact ( 'topics' , 'posts' );
}
2023-02-10 09:04:15 +00:00
function forum_get_user_most_active_category_info ( int $userId ) : ? object {
if ( $userId < 1 )
return null ;
global $cfg ;
$getActiveForum = \Misuzu\DB :: prepare ( sprintf (
'SELECT forum_id, COUNT(*) AS post_count FROM msz_forum_posts WHERE user_id = :user AND post_deleted IS NULL AND forum_id NOT IN (%s) GROUP BY forum_id ORDER BY post_count DESC LIMIT 1' ,
2023-07-18 21:48:44 +00:00
implode ( ',' , $cfg -> getArray ( 'forum_leader.unranked.forum' ))
2023-02-10 09:04:15 +00:00
));
$getActiveForum -> bind ( 'user' , $userId );
return $getActiveForum -> fetchObject ();
}