2 namespace wcf\system\conversation
;
3 use wcf\system\database\util\PreparedStatementConditionBuilder
;
4 use wcf\system\exception\NamedUserException
;
5 use wcf\system\exception\PermissionDeniedException
;
6 use wcf\system\user\storage\UserStorageHandler
;
7 use wcf\system\SingletonFactory
;
11 * Handles the number of conversations and unread conversations of the active user.
14 * @copyright 2001-2017 WoltLab GmbH
15 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
16 * @package WoltLabSuite\Core\System\Conversation
18 class ConversationHandler
extends SingletonFactory
{
20 * number of unread conversations
23 protected $unreadConversationCount = [];
26 * number of conversations
29 protected $conversationCount = [];
32 * Returns the number of unread conversations for given user.
34 * @param integer $userID
35 * @param boolean $skipCache
38 public function getUnreadConversationCount($userID = null, $skipCache = false) {
39 if ($userID === null) $userID = WCF
::getUser()->userID
;
41 if (!isset($this->unreadConversationCount
[$userID]) ||
$skipCache) {
42 $this->unreadConversationCount
[$userID] = 0;
45 UserStorageHandler
::getInstance()->loadStorage([$userID]);
48 $data = UserStorageHandler
::getInstance()->getStorage([$userID], 'unreadConversationCount');
50 // cache does not exist or is outdated
51 if ($data[$userID] === null ||
$skipCache) {
52 $conditionBuilder = new PreparedStatementConditionBuilder();
53 $conditionBuilder->add('conversation.conversationID = conversation_to_user.conversationID');
54 $conditionBuilder->add('conversation_to_user.participantID = ?', [$userID]);
55 $conditionBuilder->add('conversation_to_user.hideConversation = 0');
56 $conditionBuilder->add('conversation_to_user.lastVisitTime < conversation.lastPostTime');
58 $sql = "SELECT COUNT(*) AS count
59 FROM wcf".WCF_N
."_conversation_to_user conversation_to_user,
60 wcf".WCF_N
."_conversation conversation
61 ".$conditionBuilder->__toString();
62 $statement = WCF
::getDB()->prepareStatement($sql);
63 $statement->execute($conditionBuilder->getParameters());
64 $row = $statement->fetchArray();
65 $this->unreadConversationCount
[$userID] = $row['count'];
67 // update storage data
68 UserStorageHandler
::getInstance()->update($userID, 'unreadConversationCount', serialize($this->unreadConversationCount
[$userID]));
71 $this->unreadConversationCount
[$userID] = unserialize($data[$userID]);
75 return $this->unreadConversationCount
[$userID];
79 * Returns the number of conversations for given user.
81 * @param integer $userID
84 public function getConversationCount($userID = null) {
85 if ($userID === null) $userID = WCF
::getUser()->userID
;
87 if (!isset($this->conversationCount
[$userID])) {
88 $this->conversationCount
[$userID] = 0;
91 UserStorageHandler
::getInstance()->loadStorage([$userID]);
94 $data = UserStorageHandler
::getInstance()->getStorage([$userID], 'conversationCount');
96 // cache does not exist or is outdated
97 if ($data[$userID] === null) {
98 $conditionBuilder1 = new PreparedStatementConditionBuilder();
99 $conditionBuilder1->add('conversation_to_user.participantID = ?', [$userID]);
100 $conditionBuilder1->add('conversation_to_user.hideConversation IN (0,1)');
101 $conditionBuilder2 = new PreparedStatementConditionBuilder();
102 $conditionBuilder2->add('conversation.userID = ?', [$userID]);
103 $conditionBuilder2->add('conversation.isDraft = 1');
105 $sql = "SELECT (SELECT COUNT(*)
106 FROM wcf".WCF_N
."_conversation_to_user conversation_to_user
107 ".$conditionBuilder1->__toString().")
110 FROM wcf".WCF_N
."_conversation conversation
111 ".$conditionBuilder2->__toString().") AS count";
112 $statement = WCF
::getDB()->prepareStatement($sql);
113 $statement->execute(array_merge($conditionBuilder1->getParameters(), $conditionBuilder2->getParameters()));
114 $row = $statement->fetchArray();
115 $this->conversationCount
[$userID] = $row['count'];
117 // update storage data
118 UserStorageHandler
::getInstance()->update($userID, 'conversationCount', serialize($this->conversationCount
[$userID]));
121 $this->conversationCount
[$userID] = unserialize($data[$userID]);
125 return $this->conversationCount
[$userID];
129 * Enforces the flood control.
131 public function enforceFloodControl() {
132 $limit = WCF
::getSession()->getPermission('user.conversation.maxStartedConversationsPer24Hours');
136 else if ($limit == 0) {
137 // `0` is not a valid value, but the interface logic does not permit and exclusion
138 // while also allowing the special value `-1`. Therefore, `0` behaves like the
139 // 'canStartConversation' permission added in WoltLab Suite 5.2.
140 throw new PermissionDeniedException();
143 $sql = "SELECT COUNT(*) AS count, MIN(time) AS oldestDate
144 FROM wcf" . WCF_N
. "_conversation
147 $statement = WCF
::getDB()->prepareStatement($sql);
148 $statement->execute([
149 WCF
::getUser()->userID
,
152 $row = $statement->fetchSingleRow();
154 if ($row['count'] >= $limit) {
155 throw new NamedUserException(WCF
::getLanguage()->getDynamicVariable('wcf.conversation.error.floodControl', [
157 'notBefore' => $row['oldestDate'] +
86400,