2013-08-28 23:08:41 +00:00
< ?
class Subscriptions {
/**
* Parse a post / comment body for quotes and notify all quoted users that have quote notifications enabled .
* @ param string $Body
* @ param int $PostID
* @ param string $Page
* @ param int $PageID
*/
public static function quote_notify ( $Body , $PostID , $Page , $PageID ) {
$QueryID = G :: $DB -> get_query_id ();
/*
* Explanation of the parameters PageID and Page : Page contains where
* this quote comes from and can be forums , artist , collages , requests
* or torrents . The PageID contains the additional value that is
* necessary for the users_notify_quoted table . The PageIDs for the
* different Page are : forums : TopicID artist : ArtistID collages :
* CollageID requests : RequestID torrents : GroupID
*/
$Matches = array ();
preg_match_all ( '/\[quote(?:=(.*)(?:\|.*)?)?]|\[\/quote]/iU' , $Body , $Matches , PREG_SET_ORDER );
if ( count ( $Matches )) {
$Usernames = array ();
$Level = 0 ;
foreach ( $Matches as $M ) {
if ( $M [ 0 ] != '[/quote]' ) {
if ( $Level == 0 && isset ( $M [ 1 ]) && strlen ( $M [ 1 ]) > 0 && preg_match ( USERNAME_REGEX , $M [ 1 ])) {
$Usernames [] = preg_replace ( '/(^[.,]*)|([.,]*$)/' , '' , $M [ 1 ]); // wut?
}
++ $Level ;
} else {
-- $Level ;
}
}
}
// remove any dupes in the array (the fast way)
$Usernames = array_flip ( array_flip ( $Usernames ));
G :: $DB -> query ( "
SELECT m . ID
FROM users_main AS m
LEFT JOIN users_info AS i ON i . UserID = m . ID
WHERE m . Username IN ( '" . implode("' , '", $Usernames) . "' )
AND i . NotifyOnQuote = '1'
AND i . UserID != " . G:: $LoggedUser['ID'] );
$Results = G :: $DB -> to_array ();
foreach ( $Results as $Result ) {
$UserID = db_string ( $Result [ 'ID' ]);
$QuoterID = db_string ( G :: $LoggedUser [ 'ID' ]);
$Page = db_string ( $Page );
$PageID = db_string ( $PageID );
$PostID = db_string ( $PostID );
G :: $DB -> query ( "
INSERT IGNORE INTO users_notify_quoted
( UserID , QuoterID , Page , PageID , PostID , Date )
VALUES
( '$UserID' , '$QuoterID' , '$Page' , '$PageID' , '$PostID' , '" . sqltime() . "' ) " );
G :: $Cache -> delete_value ( 'notify_quoted_' . $UserID );
}
G :: $DB -> set_query_id ( $QueryID );
}
/**
* ( Un ) subscribe from a forum thread .
* If UserID == 0 , G :: $LoggedUser [ ID ] is used
* @ param int $TopicID
* @ param int $UserID
*/
public static function subscribe ( $TopicID , $UserID = 0 ) {
if ( $UserID == 0 ) {
$UserID = G :: $LoggedUser [ 'ID' ];
}
$QueryID = G :: $DB -> get_query_id ();
$UserSubscriptions = self :: get_subscriptions ();
$Key = self :: has_subscribed ( $TopicID );
if ( $Key !== false ) {
G :: $DB -> query ( 'DELETE FROM users_subscriptions WHERE UserID = ' . db_string ( $UserID ) . ' AND TopicID = ' . db_string ( $TopicID ));
unset ( $UserSubscriptions [ $Key ]);
} else {
G :: $DB -> query ( " INSERT IGNORE INTO users_subscriptions (UserID, TopicID) VALUES ( $UserID , " . db_string ( $TopicID ) . " ) " );
array_push ( $UserSubscriptions , $TopicID );
}
G :: $Cache -> replace_value ( 'subscriptions_user_' . $UserID , $UserSubscriptions , 0 );
G :: $Cache -> delete_value ( 'subscriptions_user_new_' . $UserID );
G :: $DB -> set_query_id ( $QueryID );
}
/**
* ( Un ) subscribe from comments .
* If UserID == 0 , G :: $LoggedUser [ ID ] is used
* @ param string $Page 'artist' , 'collages' , 'requests' or 'torrents'
* @ param int $PageID ArtistID , CollageID , RequestID or GroupID
* @ param int $UserID
*/
public static function subscribe_comments ( $Page , $PageID , $UserID = 0 ) {
if ( $UserID == 0 ) {
$UserID = G :: $LoggedUser [ 'ID' ];
}
$QueryID = G :: $DB -> get_query_id ();
$UserCommentSubscriptions = self :: get_comment_subscriptions ();
$Key = self :: has_subscribed_comments ( $Page , $PageID );
if ( $Key !== false ) {
G :: $DB -> query ( " DELETE FROM users_subscriptions_comments WHERE UserID = " . db_string ( $UserID ) . " AND Page = ' " . db_string ( $Page ) . " ' AND PageID = " . db_string ( $PageID ));
unset ( $UserCommentSubscriptions [ $Key ]);
} else {
G :: $DB -> query ( " INSERT IGNORE INTO users_subscriptions_comments (UserID, Page, PageID) VALUES ( $UserID , ' " . db_string ( $Page ) . " ', " . db_string ( $PageID ) . " ) " );
array_push ( $UserCommentSubscriptions , array ( $Page , $PageID ));
}
G :: $Cache -> replace_value ( 'subscriptions_comments_user_' . $UserID , $UserCommentSubscriptions , 0 );
G :: $Cache -> delete_value ( 'subscriptions_comments_user_new_' . $UserID );
G :: $DB -> set_query_id ( $QueryID );
}
/**
* Read $UserID 's subscriptions. If the cache key isn' t set , it gets filled .
* If UserID == 0 , G :: $LoggedUser [ ID ] is used
* @ param int $UserID
* @ return array Array of TopicIDs
*/
public static function get_subscriptions ( $UserID = 0 ) {
if ( $UserID == 0 ) {
$UserID = G :: $LoggedUser [ 'ID' ];
}
$QueryID = G :: $DB -> get_query_id ();
$UserSubscriptions = G :: $Cache -> get_value ( 'subscriptions_user_' . $UserID );
if ( $UserSubscriptions === false ) {
G :: $DB -> query ( 'SELECT TopicID FROM users_subscriptions WHERE UserID = ' . db_string ( $UserID ));
$UserSubscriptions = G :: $DB -> collect ( 0 );
G :: $Cache -> cache_value ( 'subscriptions_user_' . $UserID , $UserSubscriptions , 0 );
}
G :: $DB -> set_query_id ( $QueryID );
return $UserSubscriptions ;
}
/**
* Same as self :: get_subscriptions , but for comment subscriptions
* @ param int $UserID
* @ return array Array of ( $Page , $PageID )
*/
public static function get_comment_subscriptions ( $UserID = 0 ) {
if ( $UserID == 0 ) {
$UserID = G :: $LoggedUser [ 'ID' ];
}
$QueryID = G :: $DB -> get_query_id ();
$UserCommentSubscriptions = G :: $Cache -> get_value ( 'subscriptions_comments_user_' . $UserID );
if ( $UserCommentSubscriptions === false ) {
G :: $DB -> query ( 'SELECT Page, PageID FROM users_subscriptions_comments WHERE UserID = ' . db_string ( $UserID ));
$UserCommentSubscriptions = G :: $DB -> to_array ( false , MYSQLI_NUM );
G :: $Cache -> cache_value ( 'subscriptions_comments_user_' . $UserID , $UserCommentSubscriptions , 0 );
}
G :: $DB -> set_query_id ( $QueryID );
return $UserCommentSubscriptions ;
}
/**
* Returns whether or not the current user has new subscriptions . This handles both forum and comment subscriptions .
* @ return int Number of unread subscribed threads / comments
*/
public static function has_new_subscriptions () {
$QueryID = G :: $DB -> get_query_id ();
$NewSubscriptions = G :: $Cache -> get_value ( 'subscriptions_user_new_' . G :: $LoggedUser [ 'ID' ]);
if ( $NewSubscriptions === false ) {
// forum subscriptions
G :: $DB -> query ( " SELECT COUNT(1)
FROM users_subscriptions AS s
LEFT JOIN forums_last_read_topics AS l ON l . UserID = s . UserID AND l . TopicID = s . TopicID
JOIN forums_topics AS t ON t . ID = s . TopicID
JOIN forums AS f ON f . ID = t . ForumID
WHERE " . Forums::user_forums_sql() . "
AND IF ( t . IsLocked = '1' AND t . IsSticky = '0' " . " , t . LastPostID , IF ( l . PostID IS NULL , 0 , l . PostID )) < t . LastPostID
AND s . UserID = " . G:: $LoggedUser['ID'] );
list ( $NewForumSubscriptions ) = G :: $DB -> next_record ();
// comment subscriptions
G :: $DB -> query ( " SELECT COUNT(1)
FROM users_subscriptions_comments AS s
LEFT JOIN users_comments_last_read AS lr ON lr . UserID = s . UserID AND lr . Page = s . Page AND lr . PageID = s . PageID
LEFT JOIN comments AS c ON c . ID = ( SELECT MAX ( ID ) FROM comments WHERE Page = s . Page AND PageID = s . PageID )
LEFT JOIN collages AS co ON s . Page = 'collages' AND co . ID = s . PageID
WHERE s . UserID = " . G:: $LoggedUser['ID'] . "
AND ( s . Page != 'collages' OR co . Deleted = '0' )
AND IF ( lr . PostID IS NULL , 0 , lr . PostID ) < c . ID " );
list ( $NewCommentSubscriptions ) = G :: $DB -> next_record ();
$NewSubscriptions = $NewForumSubscriptions + $NewCommentSubscriptions ;
G :: $Cache -> cache_value ( 'subscriptions_user_new_' . G :: $LoggedUser [ 'ID' ], $NewSubscriptions , 0 );
}
G :: $DB -> set_query_id ( $QueryID );
return ( int ) $NewSubscriptions ;
}
/**
* Returns whether or not the current user has new quote notifications .
* @ return int Number of unread quote notifications
*/
public static function has_new_quote_notifications () {
$QuoteNotificationsCount = G :: $Cache -> get_value ( 'notify_quoted_' . G :: $LoggedUser [ 'ID' ]);
if ( $QuoteNotificationsCount === false ) {
$sql = "
SELECT COUNT ( 1 )
FROM users_notify_quoted AS q
LEFT JOIN forums_topics AS t ON t . ID = q . PageID
LEFT JOIN forums AS f ON f . ID = t . ForumID
LEFT JOIN collages AS c ON q . Page = 'collages' AND c . ID = q . PageID
WHERE q . UserID = " . G:: $LoggedUser['ID'] . "
AND q . UnRead
AND ( q . Page != 'forums' OR " . Forums::user_forums_sql() . " )
AND ( q . Page != 'collages' OR c . Deleted = '0' ) " ;
$QueryID = G :: $DB -> get_query_id ();
G :: $DB -> query ( $sql );
list ( $QuoteNotificationsCount ) = G :: $DB -> next_record ();
G :: $DB -> set_query_id ( $QueryID );
G :: $Cache -> cache_value ( 'notify_quoted_' . G :: $LoggedUser [ 'ID' ], $QuoteNotificationsCount , 0 );
}
return ( int ) $QuoteNotificationsCount ;
}
/**
* Returns the key which holds this $TopicID in the subscription array .
* Use type - aware comparison operators with this ! ( ie . if ( self :: has_subscribed ( $TopicID ) !== false ) { ... })
* @ param int $TopicID
* @ return bool | int
*/
public static function has_subscribed ( $TopicID ) {
$UserSubscriptions = self :: get_subscriptions ();
return array_search ( $TopicID , $UserSubscriptions );
}
/**
* Same as has_subscribed , but for comment subscriptions .
* @ param string $Page 'artist' , 'collages' , 'requests' or 'torrents'
* @ param int $PageID
* @ return bool | int
*/
public static function has_subscribed_comments ( $Page , $PageID ) {
$UserCommentSubscriptions = self :: get_comment_subscriptions ();
return array_search ( array ( $Page , $PageID ), $UserCommentSubscriptions );
}
/**
* Clear the subscription cache for all subscribers of a forum thread or artist / collage / request / torrent comments .
* @ param type $Page 'forums' , 'artist' , 'collages' , 'requests' or 'torrents'
* @ param type $PageID TopicID , ArtistID , CollageID , RequestID or GroupID , respectively
*/
public static function flush_subscriptions ( $Page , $PageID ) {
$QueryID = G :: $DB -> get_query_id ();
if ( $Page == 'forums' ) {
G :: $DB -> query ( " SELECT UserID FROM users_subscriptions WHERE TopicID = ' $PageID ' " );
} else {
G :: $DB -> query ( " SELECT UserID FROM users_subscriptions_comments WHERE Page = ' $Page ' AND PageID = ' $PageID ' " );
}
$Subscribers = G :: $DB -> collect ( 'UserID' );
foreach ( $Subscribers as $Subscriber ) {
G :: $Cache -> delete_value ( 'subscriptions_user_new_' . $Subscriber );
}
G :: $DB -> set_query_id ( $QueryID );
}
/**
* Move all $Page subscriptions from $OldPageID to $NewPageID ( for example when merging torrent groups ) .
* Passing $NewPageID = null will delete the subscriptions .
* @ param string $Page 'forums' , 'artist' , 'collages' , 'requests' or 'torrents'
* @ param int $OldPageID TopicID , ArtistID , CollageID , RequestID or GroupID , respectively
* @ param int | null $NewPageID As $OldPageID , or null to delete the subscriptions
*/
public static function move_subscriptions ( $Page , $OldPageID , $NewPageID ) {
self :: flush_subscriptions ( $Page , $OldPageID );
$QueryID = G :: $DB -> get_query_id ();
if ( $Page == 'forums' ) {
if ( $NewPageID !== null ) {
G :: $DB -> query ( " UPDATE IGNORE users_subscriptions SET TopicID = ' $NewPageID ' WHERE TopicID = ' $OldPageID ' " );
// explanation see below
G :: $DB -> query ( " UPDATE IGNORE forums_last_read_topics SET TopicID = $NewPageID WHERE TopicID = $OldPageID " );
G :: $DB -> query ( "
SELECT UserID , MIN ( PostID )
FROM forums_last_read_topics
WHERE TopicID IN ( $OldPageID , $NewPageID )
GROUP BY UserID
HAVING COUNT ( 1 ) = 2 " );
$Results = G :: $DB -> to_array ( false , MYSQLI_NUM );
foreach ( $Results as $Result ) {
G :: $DB -> query ( " UPDATE forums_last_read_topics SET PostID = $Result[1] WHERE TopicID = $NewPageID AND UserID = $Result[0] " );
}
}
G :: $DB -> query ( " DELETE FROM users_subscriptions WHERE TopicID = ' $OldPageID ' " );
G :: $DB -> query ( " DELETE FROM forums_last_read_topics WHERE TopicID = $OldPageID " );
} else {
2013-09-15 08:00:53 +00:00
if ( $NewPageID !== null ) {
2013-08-28 23:08:41 +00:00
G :: $DB -> query ( " UPDATE IGNORE users_subscriptions_comments SET PageID = ' $NewPageID ' WHERE Page = ' $Page ' AND PageID = ' $OldPageID ' " );
// last read handling
// 1) update all rows that have no key collisions (i.e. users that haven't previously read both pages or if there are only comments on one page)
G :: $DB -> query ( " UPDATE IGNORE users_comments_last_read SET PageID = ' $NewPageID ' WHERE Page = ' $Page ' AND PageID = $OldPageID " );
// 2) get all last read records with key collisions (i.e. there are records for one user for both PageIDs)
G :: $DB -> query ( "
SELECT UserID , MIN ( PostID )
FROM users_comments_last_read
WHERE Page = '$Page'
AND PageID IN ( $OldPageID , $NewPageID )
GROUP BY UserID
HAVING COUNT ( 1 ) = 2 " );
$Results = G :: $DB -> to_array ( false , MYSQLI_NUM );
// 3) update rows for those people found in 2) to the earlier post
foreach ( $Results as $Result ) {
G :: $DB -> query ( " UPDATE users_comments_last_read SET PostID = $Result[1] WHERE Page = ' $Page ' AND PageID = $NewPageID AND UserID = $Result[0] " );
}
}
G :: $DB -> query ( " DELETE FROM users_subscriptions_comments WHERE Page = ' $Page ' AND PageID = ' $OldPageID ' " );
G :: $DB -> query ( " DELETE FROM users_comments_last_read WHERE Page = ' $Page ' AND PageID = ' $OldPageID ' " );
}
G :: $DB -> set_query_id ( $QueryID );
}
/**
* Clear the quote notification cache for all subscribers of a forum thread or artist / collage / request / torrent comments .
* @ param string $Page 'forums' , 'artist' , 'collages' , 'requests' or 'torrents'
* @ param int $PageID TopicID , ArtistID , CollageID , RequestID or GroupID , respectively
*/
public static function flush_quote_notifications ( $Page , $PageID ) {
$QueryID = G :: $DB -> get_query_id ();
G :: $DB -> query ( " SELECT UserID FROM users_notify_quoted WHERE Page = ' $Page ' AND PageID = $PageID " );
$Subscribers = G :: $DB -> collect ( 'UserID' );
foreach ( $Subscribers as $Subscriber ) {
G :: $Cache -> delete_value ( 'notify_quoted_' . $Subscriber );
}
G :: $DB -> set_query_id ( $QueryID );
}
}