5 use wcf\data\conversation\label\ConversationLabel
;
6 use wcf\data\conversation\label\ConversationLabelList
;
7 use wcf\data\conversation\UserConversationList
;
8 use wcf\system\clipboard\ClipboardHandler
;
9 use wcf\system\database\util\PreparedStatementConditionBuilder
;
10 use wcf\system\exception\IllegalLinkException
;
11 use wcf\system\page\PageLocationManager
;
13 use wcf\util\ArrayUtil
;
16 * Shows a list of conversations.
19 * @copyright 2001-2019 WoltLab GmbH
20 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
21 * @package WoltLabSuite\Core\Page
23 * @property UserConversationList $objectList
25 class ConversationListPage
extends SortablePage
30 public $defaultSortField = CONVERSATION_LIST_DEFAULT_SORT_FIELD
;
35 public $defaultSortOrder = CONVERSATION_LIST_DEFAULT_SORT_ORDER
;
40 public $validSortFields = ['subject', 'time', 'username', 'lastPostTime', 'replies', 'participants'];
45 public $itemsPerPage = CONVERSATIONS_PER_PAGE
;
50 public $loginRequired = true;
55 public $neededModules = ['MODULE_CONVERSATION'];
60 public $neededPermissions = ['user.conversation.canUseConversation'];
76 * @var ConversationLabelList
81 * number of conversations (no filter)
84 public $conversationCount = 0;
90 public $draftCount = 0;
93 * number of hidden conversations
96 public $hiddenCount = 0;
99 * number of sent conversations
102 public $outboxCount = 0;
108 public $participants = [];
113 public function readParameters()
115 parent
::readParameters();
117 if (isset($_REQUEST['filter'])) {
118 $this->filter
= $_REQUEST['filter'];
120 if (!\
in_array($this->filter
, UserConversationList
::$availableFilters)) {
125 /** @noinspection PhpUndefinedFieldInspection */
126 if (WCF
::getUser()->conversationsPerPage
) {
127 /** @noinspection PhpUndefinedFieldInspection */
128 $this->itemsPerPage
= WCF
::getUser()->conversationsPerPage
;
132 $this->labelList
= ConversationLabel
::getLabelsByUser();
133 if (isset($_REQUEST['labelID'])) {
134 $this->labelID
= \
intval($_REQUEST['labelID']);
137 foreach ($this->labelList
as $label) {
138 if ($label->labelID
== $this->labelID
) {
145 throw new IllegalLinkException();
149 if (isset($_REQUEST['participants'])) {
150 $this->participants
= \array_slice
(ArrayUtil
::trim(\
explode(',', $_REQUEST['participants'])), 0, 20);
157 protected function initObjectList()
159 $this->objectList
= new UserConversationList(WCF
::getUser()->userID
, $this->filter
, $this->labelID
);
160 $this->objectList
->setLabelList($this->labelList
);
162 if (!empty($this->participants
)) {
163 // The column `conversation_to_user.username` has no index, causing full table scans when
164 // trying to filter by it, therefore we'll read the user ids in advance.
165 $conditions = new PreparedStatementConditionBuilder();
166 $conditions->add('username IN (?)', [$this->participants
]);
167 $sql = "SELECT userID
168 FROM wcf" . WCF_N
. "_user
170 $statement = WCF
::getDB()->prepareStatement($sql);
171 $statement->execute($conditions->getParameters());
173 while ($userID = $statement->fetchColumn()) {
174 $userIDs[] = $userID;
177 if (!empty($userIDs)) {
178 // The condition is split into two branches in order to account for invisible participants.
179 // Invisible participants are only visible to the conversation starter and remain invisible
180 // until the write their first message.
182 // We need to protect these users from being exposed as participants by including them for
183 // any conversation that the current user has started. For all other conversations, users
184 // flagged with `isInvisible = 0` must be excluded.
186 // See https://github.com/WoltLab/com.woltlab.wcf.conversation/issues/131
187 $this->objectList
->getConditionBuilder()->add('
190 conversation.userID = ?
191 AND conversation.conversationID IN (
192 SELECT conversationID
193 FROM wcf' . WCF_N
. '_conversation_to_user
194 WHERE participantID IN (?)
195 GROUP BY conversationID
196 HAVING COUNT(conversationID) = ?
201 conversation.userID <> ?
202 AND conversation.conversationID IN (
203 SELECT conversationID
204 FROM wcf' . WCF_N
. '_conversation_to_user
205 WHERE participantID IN (?)
207 GROUP BY conversationID
208 HAVING COUNT(conversationID) = ?
212 // Parameters for the first condition.
213 WCF
::getUser()->userID
,
217 // Parameters for the second condition.
218 WCF
::getUser()->userID
,
230 public function readData()
232 // if sort field is `username`, `conversation.` has to prepended because `username`
233 // alone is ambiguous
234 if ($this->sortField
=== 'username') {
235 $this->sortField
= 'conversation.username';
240 // change back to old value
241 if ($this->sortField
=== 'conversation.username') {
242 $this->sortField
= 'username';
245 if ($this->filter
!= '') {
246 // `-1` = pseudo object id to have to pages with identifier `com.woltlab.wcf.conversation.ConversationList`
247 PageLocationManager
::getInstance()->addParentLocation('com.woltlab.wcf.conversation.ConversationList', -1);
251 if (!$this->labelID
&& empty($this->participants
)) {
252 switch ($this->filter
) {
254 $this->conversationCount
= $this->items
;
258 $this->draftCount
= $this->items
;
262 $this->hiddenCount
= $this->items
;
266 $this->outboxCount
= $this->items
;
271 if ($this->filter
!= '' ||
$this->labelID ||
!empty($this->participants
)) {
272 $conversationList = new UserConversationList(WCF
::getUser()->userID
, '');
273 $this->conversationCount
= $conversationList->countObjects();
275 if ($this->filter
!= 'draft' ||
$this->labelID ||
!empty($this->participants
)) {
276 $conversationList = new UserConversationList(WCF
::getUser()->userID
, 'draft');
277 $this->draftCount
= $conversationList->countObjects();
279 if ($this->filter
!= 'hidden' ||
$this->labelID ||
!empty($this->participants
)) {
280 $conversationList = new UserConversationList(WCF
::getUser()->userID
, 'hidden');
281 $this->hiddenCount
= $conversationList->countObjects();
283 if ($this->filter
!= 'outbox' ||
$this->labelID ||
!empty($this->participants
)) {
284 $conversationList = new UserConversationList(WCF
::getUser()->userID
, 'outbox');
285 $this->outboxCount
= $conversationList->countObjects();
292 public function assignVariables()
294 parent
::assignVariables();
296 WCF
::getTPL()->assign([
297 'filter' => $this->filter
,
298 'hasMarkedItems' => ClipboardHandler
::getInstance()->hasMarkedItems(
299 ClipboardHandler
::getInstance()->getObjectTypeID('com.woltlab.wcf.conversation.conversation')
301 'labelID' => $this->labelID
,
302 'labelList' => $this->labelList
,
303 'conversationCount' => $this->conversationCount
,
304 'draftCount' => $this->draftCount
,
305 'hiddenCount' => $this->hiddenCount
,
306 'outboxCount' => $this->outboxCount
,
307 'participants' => $this->participants
,
308 'validSortFields' => $this->validSortFields
,