3 namespace wcf\system\conversation
;
5 use wcf\system\database\util\PreparedStatementConditionBuilder
;
6 use wcf\system\exception\NamedUserException
;
7 use wcf\system\exception\PermissionDeniedException
;
8 use wcf\system\flood\FloodControl
;
9 use wcf\system\SingletonFactory
;
10 use wcf\system\user\storage\UserStorageHandler
;
14 * Handles the number of conversations and unread conversations of the active user.
17 * @copyright 2001-2019 WoltLab GmbH
18 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
19 * @package WoltLabSuite\Core\System\Conversation
21 class ConversationHandler
extends SingletonFactory
24 * number of unread conversations
27 protected $unreadConversationCount = [];
30 * number of conversations
33 protected $conversationCount = [];
36 * Returns the number of unread conversations for given user.
39 * @param boolean $skipCache
42 public function getUnreadConversationCount($userID = null, $skipCache = false)
44 if ($userID === null) {
45 $userID = WCF
::getUser()->userID
;
48 if (!isset($this->unreadConversationCount
[$userID]) ||
$skipCache) {
49 $this->unreadConversationCount
[$userID] = 0;
52 UserStorageHandler
::getInstance()->loadStorage([$userID]);
55 $data = UserStorageHandler
::getInstance()->getStorage([$userID], 'unreadConversationCount');
57 // cache does not exist or is outdated
58 if ($data[$userID] === null ||
$skipCache) {
59 $conditionBuilder = new PreparedStatementConditionBuilder();
60 $conditionBuilder->add('conversation.conversationID = conversation_to_user.conversationID');
61 $conditionBuilder->add('conversation_to_user.participantID = ?', [$userID]);
62 $conditionBuilder->add('conversation_to_user.hideConversation = 0');
63 $conditionBuilder->add('conversation_to_user.lastVisitTime < conversation.lastPostTime');
64 $conditionBuilder->add('conversation_to_user.leftAt = 0');
66 $sql = "SELECT COUNT(*) AS count
67 FROM wcf" . WCF_N
. "_conversation_to_user conversation_to_user,
68 wcf" . WCF_N
. "_conversation conversation
69 " . $conditionBuilder;
70 $statement = WCF
::getDB()->prepareStatement($sql);
71 $statement->execute($conditionBuilder->getParameters());
72 $row = $statement->fetchArray();
73 $this->unreadConversationCount
[$userID] = $row['count'];
75 // update storage data
76 UserStorageHandler
::getInstance()->update(
78 'unreadConversationCount',
79 \
serialize($this->unreadConversationCount
[$userID])
82 $this->unreadConversationCount
[$userID] = \
unserialize($data[$userID]);
86 return $this->unreadConversationCount
[$userID];
90 * Returns the number of conversations for given user.
95 public function getConversationCount($userID = null)
97 if ($userID === null) {
98 $userID = WCF
::getUser()->userID
;
101 if (!isset($this->conversationCount
[$userID])) {
102 $this->conversationCount
[$userID] = 0;
105 UserStorageHandler
::getInstance()->loadStorage([$userID]);
108 $data = UserStorageHandler
::getInstance()->getStorage([$userID], 'conversationCount');
110 // cache does not exist or is outdated
111 if ($data[$userID] === null) {
112 $conditionBuilder1 = new PreparedStatementConditionBuilder();
113 $conditionBuilder1->add('conversation_to_user.participantID = ?', [$userID]);
114 $conditionBuilder1->add('conversation_to_user.hideConversation IN (0,1)');
115 $conditionBuilder2 = new PreparedStatementConditionBuilder();
116 $conditionBuilder2->add('conversation.userID = ?', [$userID]);
117 $conditionBuilder2->add('conversation.isDraft = 1');
121 FROM wcf" . WCF_N
. "_conversation_to_user conversation_to_user
122 " . $conditionBuilder1->__toString() . "
125 FROM wcf" . WCF_N
. "_conversation conversation
126 " . $conditionBuilder2->__toString() . "
128 $statement = WCF
::getDB()->prepareStatement($sql);
129 $statement->execute(\array_merge
(
130 $conditionBuilder1->getParameters(),
131 $conditionBuilder2->getParameters()
133 $row = $statement->fetchArray();
134 $this->conversationCount
[$userID] = $row['count'];
136 // update storage data
137 UserStorageHandler
::getInstance()->update(
140 \
serialize($this->conversationCount
[$userID])
143 $this->conversationCount
[$userID] = \
unserialize($data[$userID]);
147 return $this->conversationCount
[$userID];
151 * Enforces the flood control.
153 public function enforceFloodControl()
155 $limit = WCF
::getSession()->getPermission('user.conversation.maxStartedConversationsPer24Hours');
158 } elseif ($limit == 0) {
159 // `0` is not a valid value, but the interface logic does not permit and exclusion
160 // while also allowing the special value `-1`. Therefore, `0` behaves like the
161 // 'canStartConversation' permission added in WoltLab Suite 5.2.
162 throw new PermissionDeniedException();
165 $count = FloodControl
::getInstance()->countContent('com.woltlab.wcf.conversation', new \
DateInterval('P1D'));
166 if ($count['count'] >= $limit) {
167 throw new NamedUserException(WCF
::getLanguage()->getDynamicVariable('wcf.conversation.error.floodControl', [
168 'limit' => $count['count'],
169 'notBefore' => $count['earliestTime'] +
86400,