2023-09-08 13:22:46 +00:00
< ? php
namespace Misuzu\Forum ;
use InvalidArgumentException ;
use RuntimeException ;
use stdClass ;
use Index\Colour\Colour ;
2024-10-05 02:40:29 +00:00
use Index\Db\ { DbConnection , DbStatementCache , DbTools };
2023-09-08 13:22:46 +00:00
use Misuzu\Pagination ;
use Misuzu\Users\UserInfo ;
class ForumCategories {
private DbStatementCache $cache ;
2024-10-05 02:40:29 +00:00
public function __construct ( DbConnection $dbConn ) {
2023-09-08 13:22:46 +00:00
$this -> cache = new DbStatementCache ( $dbConn );
}
2024-12-02 21:33:15 +00:00
/**
* @ param \Iterator < int , ForumCategoryInfo >| ForumCategoryInfo [] $catInfos
* @ return object { info : ForumCategoryInfo , colour : Colour , children : mixed [], childIds : string []}[]
*/
2023-09-08 13:22:46 +00:00
public static function convertCategoryListToTree (
2024-02-07 00:04:45 +00:00
iterable $catInfos ,
2023-09-08 13:22:46 +00:00
ForumCategoryInfo | string | null $parentInfo = null ,
? Colour $colour = null
) : array {
2024-02-07 00:04:45 +00:00
if ( ! is_array ( $catInfos ))
$catInfos = iterator_to_array ( $catInfos );
2023-09-08 13:22:46 +00:00
$colour ? ? = Colour :: none ();
$tree = [];
$predicate = $parentInfo
? fn ( $catInfo ) => $catInfo -> isDirectChildOf ( $parentInfo )
2024-11-30 04:09:29 +00:00
: fn ( $catInfo ) => ! $catInfo -> hasParent ;
2023-09-08 13:22:46 +00:00
foreach ( $catInfos as $catInfo ) {
if ( ! $predicate ( $catInfo ))
continue ;
2024-11-30 04:09:29 +00:00
$tree [ $catInfo -> id ] = $item = new stdClass ;
2023-09-08 13:22:46 +00:00
$item -> info = $catInfo ;
2024-11-30 04:09:29 +00:00
$item -> colour = $catInfo -> hasColour ? $catInfo -> colour : $colour ;
2023-09-08 13:22:46 +00:00
$item -> children = self :: convertCategoryListToTree ( $catInfos , $catInfo , $item -> colour );
$item -> childIds = [];
foreach ( $item -> children as $child ) {
2024-11-30 04:09:29 +00:00
$item -> childIds [] = $child -> info -> id ;
2023-09-08 13:22:46 +00:00
$item -> childIds += $child -> childIds ;
}
}
return $tree ;
}
public function countCategories (
ForumCategoryInfo | string | null | false $parentInfo = false ,
string | int | null $type = null ,
? bool $hidden = null
) : int {
if ( $parentInfo instanceof ForumCategoryInfo )
2024-11-30 04:09:29 +00:00
$parentInfo = $parentInfo -> id ;
2023-09-08 13:22:46 +00:00
$isRootParent = false ;
$hasParentInfo = $parentInfo !== false ;
$hasType = $type !== null ;
$hasHidden = $hidden !== null ;
$args = 0 ;
$query = 'SELECT COUNT(*) FROM msz_forum_categories' ;
if ( $hasParentInfo ) {
++ $args ;
$isRootParent = $parentInfo === null ;
if ( $isRootParent ) { // make a migration that makes the field DEFAULT NULL and update all 0s to NULL
$query .= 'WHERE (forum_parent IS NULL OR forum_parent = 0)' ;
} else {
$query .= 'WHERE forum_parent = ?' ;
}
}
if ( $hasType ) {
if ( is_string ( $type )) {
if ( ! array_key_exists ( $type , ForumCategoryInfo :: TYPE_ALIASES ))
throw new InvalidArgumentException ( '$type is not a valid alias.' );
$type = ForumCategoryInfo :: TYPE_ALIASES [ $type ];
}
$query .= sprintf ( ' %s forum_type = ?' , ++ $args > 1 ? 'AND' : 'WHERE' );
}
if ( $hasHidden )
$query .= sprintf ( ' %s forum_hidden %s 0' , ++ $args > 1 ? 'AND' : 'WHERE' , $hidden ? '<>' : '=' );
$stmt = $this -> cache -> get ( $query );
if ( $hasParentInfo && ! $isRootParent )
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $parentInfo );
2023-09-08 13:22:46 +00:00
if ( $hasType )
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $type );
2023-09-08 13:22:46 +00:00
$stmt -> execute ();
$result = $stmt -> getResult ();
return $result -> next () ? $result -> getInteger ( 0 ) : 0 ;
}
2024-12-02 21:33:15 +00:00
/** @return \Iterator<int, ForumCategoryInfo>|object{info: ForumCategoryInfo, colour: Colour, children: mixed[], childIds: string[]}[] */
2023-09-08 13:22:46 +00:00
public function getCategories (
ForumCategoryInfo | string | null | false $parentInfo = false ,
string | int | null $type = null ,
? bool $hidden = null ,
bool $asTree = false ,
? Pagination $pagination = null
2024-02-07 00:04:45 +00:00
) : iterable {
2023-09-08 13:22:46 +00:00
$isRootParent = false ;
$hasParentInfo = $parentInfo !== false ;
$hasType = $type !== null ;
$hasHidden = $hidden !== null ;
$hasPagination = $pagination !== null ;
if ( $hasParentInfo && $asTree )
throw new InvalidArgumentException ( '$asTree can only be used with $parentInfo set to false.' );
$args = 0 ;
$query = 'SELECT forum_id, forum_order, forum_parent, forum_name, forum_type, forum_description, forum_icon, forum_colour, forum_link, forum_link_clicks, UNIX_TIMESTAMP(forum_created), forum_archived, forum_hidden, forum_count_topics, forum_count_posts FROM msz_forum_categories' ;
if ( $hasParentInfo ) {
++ $args ;
$isRootParent = $parentInfo === null ;
if ( $isRootParent ) { // make a migration that makes the field DEFAULT NULL and update all 0s to NULL
$query .= ' WHERE (forum_parent IS NULL OR forum_parent = 0)' ;
} else {
$query .= ' WHERE forum_parent = ?' ;
}
}
if ( $hasType ) {
if ( is_string ( $type )) {
if ( ! array_key_exists ( $type , ForumCategoryInfo :: TYPE_ALIASES ))
throw new InvalidArgumentException ( '$type is not a valid alias.' );
$type = ForumCategoryInfo :: TYPE_ALIASES [ $type ];
}
$query .= sprintf ( ' %s forum_type = ?' , ++ $args > 1 ? 'AND' : 'WHERE' );
}
if ( $hasHidden )
$query .= sprintf ( ' %s forum_hidden %s 0' , ++ $args > 1 ? 'AND' : 'WHERE' , $hidden ? '<>' : '=' );
$query .= ' ORDER BY forum_parent, forum_type <> 1, forum_order' ;
if ( $hasPagination )
$query .= ' LIMIT ? OFFSET ?' ;
$stmt = $this -> cache -> get ( $query );
if ( $hasParentInfo && ! $isRootParent ) {
if ( $parentInfo instanceof ForumCategoryInfo )
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $parentInfo -> id );
2023-09-08 13:22:46 +00:00
else
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $parentInfo );
2023-09-08 13:22:46 +00:00
}
if ( $hasType )
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $type );
2024-12-19 02:27:28 +00:00
if ( $hasPagination )
$pagination -> addToStatement ( $stmt );
2023-09-08 13:22:46 +00:00
$stmt -> execute ();
2024-02-07 00:04:45 +00:00
$cats = $stmt -> getResult () -> getIterator ( ForumCategoryInfo :: fromResult ( ... ));
2023-09-08 13:22:46 +00:00
if ( $asTree )
$cats = self :: convertCategoryListToTree ( $cats );
return $cats ;
}
public function getCategory (
? string $categoryId = null ,
ForumTopicInfo | string | null $topicInfo = null ,
ForumPostInfo | string | null $postInfo = null
) : ForumCategoryInfo {
$hasCategoryId = $categoryId !== null ;
$hasTopicInfo = $topicInfo !== null ;
$hasPostInfo = $postInfo !== null ;
if ( ! $hasCategoryId && ! $hasTopicInfo && ! $hasPostInfo )
throw new InvalidArgumentException ( 'You must specify an argument.' );
if (( $hasCategoryId && ( $hasTopicInfo || $hasPostInfo ))
|| ( $hasTopicInfo && ( $hasCategoryId || $hasPostInfo ))
|| ( $hasPostInfo && ( $hasCategoryId || $hasTopicInfo )))
throw new InvalidArgumentException ( 'Only one argument may be specified.' );
$value = null ;
$query = 'SELECT forum_id, forum_order, forum_parent, forum_name, forum_type, forum_description, forum_icon, forum_colour, forum_link, forum_link_clicks, UNIX_TIMESTAMP(forum_created), forum_archived, forum_hidden, forum_count_topics, forum_count_posts FROM msz_forum_categories' ;
if ( $hasCategoryId ) {
$query .= ' WHERE forum_id = ?' ;
$value = $categoryId ;
}
if ( $hasTopicInfo ) {
if ( $topicInfo instanceof ForumTopicInfo ) {
$query .= ' WHERE forum_id = ?' ;
2024-11-30 04:09:29 +00:00
$value = $topicInfo -> categoryId ;
2023-09-08 13:22:46 +00:00
} else {
$query .= ' WHERE forum_id = (SELECT forum_id FROM msz_forum_topics WHERE topic_id = ?)' ;
$value = $topicInfo ;
}
}
if ( $hasPostInfo ) {
if ( $postInfo instanceof ForumPostInfo ) {
$query .= ' WHERE forum_id = ?' ;
2024-11-30 04:09:29 +00:00
$value = $postInfo -> categoryId ;
2023-09-08 13:22:46 +00:00
} else {
$query .= ' WHERE forum_id = (SELECT forum_id FROM msz_forum_posts WHERE post_id = ?)' ;
$value = $postInfo ;
}
}
$stmt = $this -> cache -> get ( $query );
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $value );
2023-09-08 13:22:46 +00:00
$stmt -> execute ();
$result = $stmt -> getResult ();
if ( ! $result -> next ())
throw new RuntimeException ( 'Forum category info not found.' );
2024-02-07 00:04:45 +00:00
return ForumCategoryInfo :: fromResult ( $result );
2023-09-08 13:22:46 +00:00
}
public function updateCategory (
ForumCategoryInfo | string $categoryInfo
) : void {
if ( $categoryInfo instanceof ForumCategoryInfo )
2024-11-30 04:09:29 +00:00
$categoryInfo = $categoryInfo -> id ;
2023-09-08 13:22:46 +00:00
}
public function deleteCategory ( ForumCategoryInfo | string $categoryInfo ) : void {
if ( $categoryInfo instanceof ForumCategoryInfo )
2024-11-30 04:09:29 +00:00
$categoryInfo = $categoryInfo -> id ;
2023-09-08 13:22:46 +00:00
}
public function incrementCategoryClicks ( ForumCategoryInfo | string $categoryInfo ) : void {
if ( $categoryInfo instanceof ForumCategoryInfo )
2024-11-30 04:09:29 +00:00
$categoryInfo = $categoryInfo -> id ;
2023-09-08 13:22:46 +00:00
// previous implementation also WHERE'd for forum_type = link but i don't think there's any other way to get here anyhow
$stmt = $this -> cache -> get ( 'UPDATE msz_forum_categories SET forum_link_clicks = forum_link_clicks + 1 WHERE forum_id = ? AND forum_link_clicks IS NOT NULL' );
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $categoryInfo );
2023-09-08 13:22:46 +00:00
$stmt -> execute ();
}
public function incrementCategoryTopics ( ForumCategoryInfo | string $categoryInfo ) : void {
if ( $categoryInfo instanceof ForumCategoryInfo )
2024-11-30 04:09:29 +00:00
$categoryInfo = $categoryInfo -> id ;
2023-09-08 13:22:46 +00:00
$stmt = $this -> cache -> get ( 'UPDATE msz_forum_categories SET forum_count_topics = forum_count_topics + 1 WHERE forum_id = ?' );
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $categoryInfo );
2023-09-08 13:22:46 +00:00
$stmt -> execute ();
}
public function incrementCategoryPosts ( ForumCategoryInfo | string $categoryInfo ) : void {
if ( $categoryInfo instanceof ForumCategoryInfo )
2024-11-30 04:09:29 +00:00
$categoryInfo = $categoryInfo -> id ;
2023-09-08 13:22:46 +00:00
$stmt = $this -> cache -> get ( 'UPDATE msz_forum_categories SET forum_count_posts = forum_count_posts + 1 WHERE forum_id = ?' );
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $categoryInfo );
2023-09-08 13:22:46 +00:00
$stmt -> execute ();
}
2024-12-02 21:33:15 +00:00
/** @return \Iterator<int, ForumCategoryInfo> */
2023-09-08 13:22:46 +00:00
public function getCategoryAncestry (
ForumCategoryInfo | ForumTopicInfo | ForumPostInfo | string $categoryInfo
2024-02-07 00:04:45 +00:00
) : iterable {
2023-09-08 13:22:46 +00:00
if ( $categoryInfo instanceof ForumCategoryInfo )
2024-11-30 04:09:29 +00:00
$categoryInfo = $categoryInfo -> id ;
2023-09-08 13:22:46 +00:00
elseif ( $categoryInfo instanceof ForumTopicInfo || $categoryInfo instanceof ForumPostInfo )
2024-11-30 04:09:29 +00:00
$categoryInfo = $categoryInfo -> categoryId ;
2023-09-08 13:22:46 +00:00
$query = 'WITH RECURSIVE msz_cte_ancestry AS ('
. 'SELECT forum_id, forum_order, forum_parent, forum_name, forum_type, forum_description, forum_icon, forum_colour, forum_link, forum_link_clicks, UNIX_TIMESTAMP(forum_created), forum_archived, forum_hidden, forum_count_topics, forum_count_posts FROM msz_forum_categories WHERE forum_id = ?'
. ' UNION ALL'
. ' SELECT fc.forum_id, fc.forum_order, fc.forum_parent, fc.forum_name, fc.forum_type, fc.forum_description, fc.forum_icon, fc.forum_colour, fc.forum_link, fc.forum_link_clicks, UNIX_TIMESTAMP(fc.forum_created), fc.forum_archived, fc.forum_hidden, fc.forum_count_topics, fc.forum_count_posts FROM msz_forum_categories AS fc JOIN msz_cte_ancestry AS ca ON fc.forum_id = ca.forum_parent'
. ') SELECT * FROM msz_cte_ancestry' ;
$stmt = $this -> cache -> get ( $query );
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $categoryInfo );
2023-09-08 13:22:46 +00:00
$stmt -> execute ();
2024-02-07 00:04:45 +00:00
return $stmt -> getResult () -> getIterator ( ForumCategoryInfo :: fromResult ( ... ));
2023-09-08 13:22:46 +00:00
}
2024-12-02 21:33:15 +00:00
/** @return \Iterator<int, ForumCategoryInfo>|object{info: ForumCategoryInfo, colour: Colour, children: mixed[], childIds: string[]}[] */
2023-09-08 13:22:46 +00:00
public function getCategoryChildren (
ForumCategoryInfo | string $parentInfo ,
bool $includeSelf = false ,
? bool $hidden = null ,
bool $asTree = false
2024-02-07 00:04:45 +00:00
) : iterable {
2023-09-08 13:22:46 +00:00
if ( $parentInfo instanceof ForumCategoryInfo )
2024-11-30 04:09:29 +00:00
$parentInfo = $parentInfo -> id ;
2023-09-08 13:22:46 +00:00
$hasHidden = $hidden !== null ;
$query = 'WITH RECURSIVE msz_cte_children AS ('
. 'SELECT forum_id, forum_order, forum_parent, forum_name, forum_type, forum_description, forum_icon, forum_colour, forum_link, forum_link_clicks, UNIX_TIMESTAMP(forum_created), forum_archived, forum_hidden, forum_count_topics, forum_count_posts FROM msz_forum_categories WHERE forum_id = ?'
. ' UNION ALL'
. ' SELECT fc.forum_id, fc.forum_order, fc.forum_parent, fc.forum_name, fc.forum_type, fc.forum_description, fc.forum_icon, fc.forum_colour, fc.forum_link, fc.forum_link_clicks, UNIX_TIMESTAMP(fc.forum_created), fc.forum_archived, fc.forum_hidden, fc.forum_count_topics, fc.forum_count_posts FROM msz_forum_categories AS fc JOIN msz_cte_children AS cc ON fc.forum_parent = cc.forum_id'
. ') SELECT * FROM msz_cte_children' ;
$args = 0 ;
if ( ! $includeSelf ) {
++ $args ;
$query .= ' WHERE forum_id <> ?' ;
}
if ( $hasHidden )
$query .= sprintf ( ' %s forum_hidden %s 0' , ++ $args > 1 ? 'AND' : 'WHERE' , $hidden ? '<>' : '=' );
$query .= ' ORDER BY forum_parent, forum_order' ;
$stmt = $this -> cache -> get ( $query );
2024-12-18 03:07:48 +00:00
$stmt -> nextParameter ( $parentInfo );
2023-09-08 13:22:46 +00:00
if ( ! $includeSelf )
2024-12-18 03:07:48 +00:00
$stmt -> nextParameter ( $parentInfo );
2023-09-08 13:22:46 +00:00
$stmt -> execute ();
2024-02-07 00:04:45 +00:00
$cats = $stmt -> getResult () -> getIterator ( ForumCategoryInfo :: fromResult ( ... ));
2023-09-08 13:22:46 +00:00
if ( $asTree )
$cats = self :: convertCategoryListToTree ( $cats , $parentInfo );
return $cats ;
}
2024-12-02 21:33:15 +00:00
/** @param ForumCategoryInfo|string|array<ForumCategoryInfo|string|int> $categoryInfos */
2023-09-08 13:22:46 +00:00
public function checkCategoryUnread (
ForumCategoryInfo | string | array $categoryInfos ,
UserInfo | string | null $userInfo
) : bool {
if ( $userInfo === null )
return false ;
if ( ! is_array ( $categoryInfos ))
$categoryInfos = [ $categoryInfos ];
if ( $userInfo instanceof UserInfo )
2024-11-30 04:20:20 +00:00
$userInfo = $userInfo -> id ;
2023-09-08 13:22:46 +00:00
$stmt = $this -> cache -> get ( sprintf (
'SELECT COUNT(*) FROM msz_forum_topics AS ft LEFT JOIN msz_forum_topics_track AS ftt ON ftt.topic_id = ft.topic_id AND ftt.user_id = ? WHERE ft.forum_id IN (%s) AND ft.topic_deleted IS NULL AND ft.topic_bumped >= NOW() - INTERVAL 1 MONTH AND (ftt.track_last_read IS NULL OR ftt.track_last_read < ft.topic_bumped)' ,
DbTools :: prepareListString ( $categoryInfos )
));
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $userInfo );
2023-09-08 13:22:46 +00:00
foreach ( $categoryInfos as $categoryInfo ) {
if ( $categoryInfo instanceof ForumCategoryInfo )
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $categoryInfo -> id );
2023-09-08 13:22:46 +00:00
elseif ( is_string ( $categoryInfo ) || is_int ( $categoryInfo ))
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $categoryInfo );
2023-09-08 13:22:46 +00:00
else
throw new InvalidArgumentException ( 'Invalid item in $categoryInfos.' );
}
$stmt -> execute ();
$result = $stmt -> getResult ();
return $result -> next () && $result -> getInteger ( 0 ) > 0 ;
}
public function updateUserReadCategory (
UserInfo | string | null $userInfo ,
ForumCategoryInfo | string $categoryInfo
) : void {
if ( $userInfo === null )
return ;
if ( $userInfo instanceof UserInfo )
2024-11-30 04:20:20 +00:00
$userInfo = $userInfo -> id ;
2024-11-30 04:09:29 +00:00
if ( $categoryInfo instanceof ForumCategoryInfo )
$categoryInfo = $categoryInfo -> id ;
2023-09-08 13:22:46 +00:00
$stmt = $this -> cache -> get ( 'REPLACE INTO msz_forum_topics_track (user_id, topic_id, forum_id, track_last_read) SELECT ?, topic_id, forum_id, NOW() FROM msz_forum_topics WHERE forum_id = ? AND topic_bumped >= NOW() - INTERVAL 1 MONTH' );
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $userInfo );
$stmt -> nextParameter ( $categoryInfo );
2023-09-08 13:22:46 +00:00
$stmt -> execute ();
}
public function getCategoryColour (
ForumCategoryInfo | ForumTopicInfo | ForumPostInfo | string $categoryInfo
) : Colour {
if ( $categoryInfo instanceof ForumCategoryInfo )
2024-11-30 04:09:29 +00:00
$categoryInfo = $categoryInfo -> id ;
2023-09-08 13:22:46 +00:00
elseif ( $categoryInfo instanceof ForumTopicInfo || $categoryInfo instanceof ForumPostInfo )
2024-11-30 04:09:29 +00:00
$categoryInfo = $categoryInfo -> categoryId ;
2023-09-08 13:22:46 +00:00
$query = 'WITH RECURSIVE msz_cte_colours AS ('
. 'SELECT forum_id, forum_parent, forum_colour FROM msz_forum_categories WHERE forum_id = ?'
. ' UNION ALL'
. ' SELECT fc.forum_id, fc.forum_parent, fc.forum_colour FROM msz_forum_categories AS fc JOIN msz_cte_colours AS cc ON fc.forum_id = cc.forum_parent'
. ') SELECT forum_colour FROM msz_cte_colours WHERE forum_colour IS NOT NULL' ;
$stmt = $this -> cache -> get ( $query );
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $categoryInfo );
2023-09-08 13:22:46 +00:00
$stmt -> execute ();
$result = $stmt -> getResult ();
return $result -> next () ? Colour :: fromMisuzu ( $result -> getInteger ( 0 )) : Colour :: none ();
}
2024-12-02 21:33:15 +00:00
/**
* @ param array < ForumCategoryInfo | string | int > $exceptCategoryInfos
* @ param array < ForumTopicInfo | string | int > $exceptTopicInfos
*/
2023-09-08 13:22:46 +00:00
public function getMostActiveCategoryInfo (
UserInfo | string $userInfo ,
array $exceptCategoryInfos = [],
array $exceptTopicInfos = [],
? bool $deleted = null
) : object {
if ( $userInfo instanceof UserInfo )
2024-11-30 04:20:20 +00:00
$userInfo = $userInfo -> id ;
2023-09-08 13:22:46 +00:00
$hasExceptCategoryInfos = ! empty ( $exceptCategoryInfos );
$hasExceptTopicInfos = ! empty ( $exceptTopicInfos );
$hasDeleted = $deleted !== null ;
$query = 'SELECT forum_id, COUNT(*) AS post_count FROM msz_forum_posts WHERE user_id = ?' ;
if ( $hasDeleted )
$query .= sprintf ( ' AND post_deleted %s NULL' , $deleted ? 'IS NOT' : 'IS' );
if ( $hasExceptCategoryInfos )
$query .= sprintf ( ' AND forum_id NOT IN (%s)' , DbTools :: prepareListString ( $exceptCategoryInfos ));
if ( $hasExceptTopicInfos )
$query .= sprintf ( ' AND topic_id NOT IN (%s)' , DbTools :: prepareListString ( $exceptTopicInfos ));
$query .= ' GROUP BY forum_id ORDER BY post_count DESC LIMIT 1' ;
$stmt = $this -> cache -> get ( $query );
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $userInfo );
2023-09-08 13:22:46 +00:00
foreach ( $exceptCategoryInfos as $categoryInfo ) {
if ( $categoryInfo instanceof ForumCategoryInfo )
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $categoryInfo -> id );
2023-09-08 13:22:46 +00:00
elseif ( is_string ( $categoryInfo ) || is_int ( $categoryInfo ))
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter (( string ) $categoryInfo );
2023-09-08 13:22:46 +00:00
else
throw new InvalidArgumentException ( '$exceptCategoryInfos may only contain string ids or instances of ForumCategoryInfo.' );
}
foreach ( $exceptTopicInfos as $topicInfo ) {
if ( $topicInfo instanceof ForumTopicInfo )
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $topicInfo -> id );
2023-09-08 13:22:46 +00:00
elseif ( is_string ( $topicInfo ) || is_int ( $topicInfo ))
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter (( string ) $topicInfo );
2023-09-08 13:22:46 +00:00
else
throw new InvalidArgumentException ( '$exceptTopicInfos may only contain string ids or instances of ForumTopicInfo.' );
}
$stmt -> execute ();
$result = $stmt -> getResult ();
$info = new stdClass ;
$info -> success = $result -> next ();
if ( $info -> success ) {
$info -> categoryId = $result -> getString ( 0 );
$info -> postCount = $result -> getInteger ( 1 );
}
return $info ;
}
public function syncForumCounters (
ForumCategoryInfo | string | null $categoryInfo = null ,
bool $updateCounters = true
) : object {
if ( $categoryInfo instanceof ForumCategoryInfo )
2024-11-30 04:09:29 +00:00
$categoryInfo = $categoryInfo -> id ;
2023-09-08 13:22:46 +00:00
elseif ( $categoryInfo === null )
$categoryInfo = '0' ;
$counters = new stdClass ;
$stmt = $this -> cache -> get ( 'SELECT ? AS target_category_id, (SELECT COUNT(*) FROM msz_forum_topics WHERE forum_id = target_category_id AND topic_deleted IS NULL) AS count_topics, (SELECT COUNT(*) FROM msz_forum_posts WHERE forum_id = target_category_id AND post_deleted IS NULL) AS count_posts' );
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $categoryInfo );
2023-09-08 13:22:46 +00:00
$stmt -> execute ();
$result = $stmt -> getResult ();
if ( ! $result -> next ())
throw new RuntimeException ( 'Failed to fetch forum category counters.' );
$counters -> topics = $result -> getInteger ( 1 );
$counters -> posts = $result -> getInteger ( 2 );
$stmt = $this -> cache -> get ( 'SELECT forum_id FROM msz_forum_categories WHERE forum_parent = ?' );
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $categoryInfo );
2023-09-08 13:22:46 +00:00
$stmt -> execute ();
$children = [];
$result = $stmt -> getResult ();
while ( $result -> next ())
$children [] = $result -> getString ( 0 );
foreach ( $children as $childId ) {
$childCounters = $this -> syncForumCounters ( $childId , $updateCounters );
$counters -> topics += $childCounters -> topics ;
$counters -> posts += $childCounters -> posts ;
}
if ( $updateCounters && $categoryInfo !== '0' ) {
$stmt = $this -> cache -> get ( 'UPDATE msz_forum_categories SET forum_count_topics = ?, forum_count_posts = ? WHERE forum_id = ?' );
2024-12-19 02:23:05 +00:00
$stmt -> nextParameter ( $counters -> topics );
$stmt -> nextParameter ( $counters -> posts );
$stmt -> nextParameter ( $categoryInfo );
2023-09-08 13:22:46 +00:00
$stmt -> execute ();
}
return $counters ;
}
}