Remove obsolete template code
[GitHub/WoltLab/com.woltlab.wcf.conversation.git] / files / lib / page / ConversationPage.class.php
CommitLineData
9544b6b4
MW
1<?php
2namespace wcf\page;
2e0bc870 3use wcf\data\conversation\label\ConversationLabel;
9d25a4e3 4use wcf\data\conversation\label\ConversationLabelList;
9544b6b4 5use wcf\data\conversation\message\ConversationMessage;
65f1cc0b 6use wcf\data\conversation\message\ViewableConversationMessageList;
232cdc4b 7use wcf\data\conversation\Conversation;
9544b6b4 8use wcf\data\conversation\ConversationAction;
530c5f83 9use wcf\data\conversation\ConversationParticipantList;
2e0bc870 10use wcf\data\conversation\ViewableConversation;
83e23d22 11use wcf\data\modification\log\ConversationLogModificationLogList;
b2de9161 12use wcf\data\smiley\SmileyCache;
195a4249 13use wcf\data\user\UserProfile;
41c23899 14use wcf\system\attachment\AttachmentHandler;
a21c8732 15use wcf\system\bbcode\BBCodeHandler;
9544b6b4
MW
16use wcf\system\exception\IllegalLinkException;
17use wcf\system\exception\PermissionDeniedException;
2d181735 18use wcf\system\message\quote\MessageQuoteManager;
e298db3c 19use wcf\system\page\PageLocationManager;
2163ec8f 20use wcf\system\page\ParentPageLocation;
9544b6b4 21use wcf\system\request\LinkHandler;
a3273089 22use wcf\system\user\signature\SignatureCache;
9544b6b4
MW
23use wcf\system\WCF;
24use wcf\util\HeaderUtil;
41c23899 25use wcf\util\StringUtil;
9544b6b4
MW
26
27/**
28 * Shows a conversation.
61f754e0 29 *
9544b6b4 30 * @author Marcel Werk
4ddaa70e 31 * @copyright 2001-2019 WoltLab GmbH
9544b6b4 32 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
c032049e 33 * @package WoltLabSuite\Core\Page
7e95339f
MS
34 *
35 * @property ViewableConversationMessageList $objectList
9544b6b4
MW
36 */
37class ConversationPage extends MultipleLinkPage {
38 /**
65f1cc0b 39 * @inheritDoc
9544b6b4
MW
40 */
41 public $itemsPerPage = CONVERSATION_MESSAGES_PER_PAGE;
42
43 /**
65f1cc0b 44 * @inheritDoc
9544b6b4
MW
45 */
46 public $sortOrder = 'ASC';
47
48 /**
65f1cc0b 49 * @inheritDoc
9544b6b4 50 */
65f1cc0b 51 public $objectListClassName = ViewableConversationMessageList::class;
9544b6b4 52
84e18f05 53 /**
65f1cc0b 54 * @inheritDoc
84e18f05
MS
55 */
56 public $loginRequired = true;
57
c764783c 58 /**
65f1cc0b 59 * @inheritDoc
c764783c 60 */
65f1cc0b 61 public $neededModules = ['MODULE_CONVERSATION'];
c764783c
MW
62
63 /**
65f1cc0b 64 * @inheritDoc
c764783c 65 */
65f1cc0b 66 public $neededPermissions = ['user.conversation.canUseConversation'];
c764783c 67
9544b6b4
MW
68 /**
69 * conversation id
61f754e0 70 * @var integer
9544b6b4
MW
71 */
72 public $conversationID = 0;
73
74 /**
a208d1f4 75 * viewable conversation object
65f1cc0b 76 * @var ViewableConversation
9544b6b4 77 */
537bf61d 78 public $conversation;
9544b6b4 79
2e0bc870
AE
80 /**
81 * conversation label list
65f1cc0b 82 * @var ConversationLabelList
2e0bc870 83 */
537bf61d 84 public $labelList;
2e0bc870 85
9544b6b4
MW
86 /**
87 * message id
61f754e0 88 * @var integer
9544b6b4
MW
89 */
90 public $messageID = 0;
91
92 /**
93 * conversation message object
65f1cc0b 94 * @var ConversationMessage
9544b6b4 95 */
537bf61d 96 public $message;
9544b6b4 97
a208d1f4
AE
98 /**
99 * modification log list object
65f1cc0b 100 * @var ConversationLogModificationLogList
a208d1f4 101 */
537bf61d 102 public $modificationLogList;
a208d1f4 103
530c5f83
MW
104 /**
105 * list of participants
65f1cc0b 106 * @var ConversationParticipantList
530c5f83 107 */
537bf61d 108 public $participantList;
530c5f83 109
9544b6b4 110 /**
65f1cc0b 111 * @inheritDoc
9544b6b4
MW
112 */
113 public function readParameters() {
114 parent::readParameters();
115
116 if (isset($_REQUEST['id'])) $this->conversationID = intval($_REQUEST['id']);
117 if (isset($_REQUEST['messageID'])) $this->messageID = intval($_REQUEST['messageID']);
118 if ($this->messageID) {
119 $this->message = new ConversationMessage($this->messageID);
120 if (!$this->message->messageID) {
121 throw new IllegalLinkException();
122 }
c764783c 123 $this->conversationID = $this->message->conversationID;
9544b6b4
MW
124 }
125
126 $this->conversation = Conversation::getUserConversation($this->conversationID, WCF::getUser()->userID);
127 if ($this->conversation === null) {
128 throw new IllegalLinkException();
129 }
130 if (!$this->conversation->canRead()) {
131 throw new PermissionDeniedException();
132 }
133
2e0bc870
AE
134 // load labels
135 $this->labelList = ConversationLabel::getLabelsByUser();
136 $this->conversation = ViewableConversation::getViewableConversation($this->conversation, $this->labelList);
137
b41c9fd6
MS
138 // messages per page
139 /** @noinspection PhpUndefinedFieldInspection */
140 if (WCF::getUser()->conversationMessagesPerPage) {
141 /** @noinspection PhpUndefinedFieldInspection */
142 $this->itemsPerPage = WCF::getUser()->conversationMessagesPerPage;
143 }
ecadd37d 144
65f1cc0b 145 $this->canonicalURL = LinkHandler::getInstance()->getLink('Conversation', [
f6eb15c3 146 'object' => $this->conversation
65f1cc0b 147 ], ($this->pageNo ? 'pageNo=' . $this->pageNo : ''));
9544b6b4
MW
148 }
149
150 /**
65f1cc0b 151 * @inheritDoc
9544b6b4
MW
152 */
153 protected function initObjectList() {
154 parent::initObjectList();
155
65f1cc0b 156 $this->objectList->getConditionBuilder()->add('conversation_message.conversationID = ?', [$this->conversation->conversationID]);
28bd6cbd 157 $this->objectList->setConversation($this->conversation->getDecoratedObject());
9544b6b4 158
219838a1
AE
159 // handle visibility filter
160 if ($this->conversation->joinedAt > 0) $this->objectList->getConditionBuilder()->add('conversation_message.time >= ?', [$this->conversation->joinedAt]);
80f82b0f 161 if ($this->conversation->leftAt > 0) $this->objectList->getConditionBuilder()->add('conversation_message.time <= ?', [$this->conversation->leftAt]);
219838a1 162
9544b6b4
MW
163 // handle jump to
164 if ($this->action == 'lastPost') $this->goToLastPost();
165 if ($this->action == 'firstNew') $this->goToFirstNewPost();
166 if ($this->messageID) $this->goToPost();
167 }
168
169 /**
65f1cc0b 170 * @inheritDoc
9544b6b4
MW
171 */
172 public function readData() {
173 parent::readData();
174
175 // add breadcrumbs
f34884b9 176 if ($this->conversation->isDraft) {
2163ec8f
MS
177 // `-1` = pseudo object id to have to pages with identifier `com.woltlab.wcf.conversation.ConversationList`
178 PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.conversation.ConversationList', -1, new ParentPageLocation(
179 WCF::getLanguage()->get('wcf.conversation.folder.draft'),
180 LinkHandler::getInstance()->getLink('ConversationList', ['filter' => 'draft'])
181 ));
f34884b9 182 }
2163ec8f 183 PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.conversation.ConversationList');
9544b6b4
MW
184
185 // update last visit time count
8ab7c9b9
MS
186 if (
187 $this->conversation->isNew()
188 && (
189 $this->objectList->getMaxPostTime() > $this->conversation->lastVisitTime
190 || ($this->conversation->joinedAt && !count($this->objectList))
191 )
192 ) {
c0dd7a12
MW
193 $visitTime = $this->objectList->getMaxPostTime();
194 if ($visitTime == $this->conversation->lastPostTime) $visitTime = TIME_NOW;
65f1cc0b 195 $conversationAction = new ConversationAction([$this->conversation->getDecoratedObject()], 'markAsRead', ['visitTime' => $visitTime]);
9544b6b4
MW
196 $conversationAction->executeAction();
197 }
530c5f83
MW
198
199 // get participants
8a6ee075 200 $this->participantList = new ConversationParticipantList($this->conversationID, WCF::getUser()->userID, $this->conversation->userID == WCF::getUser()->userID);
530c5f83 201 $this->participantList->readObjects();
42335f61
AE
202
203 // init quote objects
65f1cc0b 204 $messageIDs = [];
42335f61
AE
205 foreach ($this->objectList as $message) {
206 $messageIDs[] = $message->messageID;
207 }
208 MessageQuoteManager::getInstance()->initObjects('com.woltlab.wcf.conversation.message', $messageIDs);
f7b9b1f3 209
a3273089
JR
210 $userIDs = [];
211 foreach ($this->objectList as $message) {
212 if ($message->userID) {
213 $userIDs[] = $message->userID;
214 }
215 }
216
195a4249
JR
217 // fetch special trophies
218 if (MODULE_TROPHY) {
195a4249
JR
219 if (!empty($userIDs)) {
220 UserProfile::prepareSpecialTrophies(array_unique($userIDs));
221 }
222 }
223
a3273089
JR
224 if (MODULE_USER_SIGNATURE) {
225 if (!empty($userIDs)) {
226 SignatureCache::getInstance()->cacheUserSignature($userIDs);
227 }
228 }
229
f7b9b1f3
MW
230 // set attachment permissions
231 if ($this->objectList->getAttachmentList() !== null) {
65f1cc0b 232 $this->objectList->getAttachmentList()->setPermissions([
f7b9b1f3 233 'canDownload' => true,
a480521b 234 'canViewPreview' => true
65f1cc0b 235 ]);
f7b9b1f3 236 }
a208d1f4
AE
237
238 // get timeframe for modifications
239 $this->objectList->rewind();
219838a1
AE
240 $startTime = ($this->conversation->joinedAt ?: $this->objectList->current()->time);
241 $endTime = ($this->conversation->leftAt ?: TIME_NOW);
a208d1f4
AE
242
243 $count = count($this->objectList);
a7e5e13c 244 if ($count > 1) {
a208d1f4 245 $this->objectList->seek($count - 1);
a7e5e13c
MW
246 if ($this->objectList->current()->time < $this->conversation->lastPostTime) {
247 $sql = "SELECT time
248 FROM wcf".WCF_N."_conversation_message
249 WHERE conversationID = ?
250 AND time > ?
251 ORDER BY time";
252 $statement = WCF::getDB()->prepareStatement($sql, 1);
eaf1c8eb 253 $statement->execute([$this->conversationID, $this->objectList->current()->time]);
a7e5e13c 254 $endTime = $statement->fetchSingleColumn() - 1;
d8838bd9 255 }
a208d1f4
AE
256 }
257 $this->objectList->rewind();
258
28484add
AE
259 // get invisible participants
260 $invisibleParticipantIDs = [];
261 if (WCF::getUser()->userID != $this->conversation->userID) {
262 foreach ($this->participantList as $participant) {
263 if ($participant->isInvisible) {
264 $invisibleParticipantIDs[] = $participant->userID;
265 }
266 }
267 }
268
a208d1f4 269 // load modification log entries
a7e5e13c 270 $this->modificationLogList = new ConversationLogModificationLogList($this->conversation->conversationID);
65f1cc0b 271 $this->modificationLogList->getConditionBuilder()->add("modification_log.time BETWEEN ? AND ?", [$startTime, $endTime]);
28484add
AE
272
273 if (!empty($invisibleParticipantIDs)) {
274 $this->modificationLogList->getConditionBuilder()->add("(modification_log.action <> ? OR modification_log.userID NOT IN (?))", ['leave', $invisibleParticipantIDs]);
275 }
276
a208d1f4 277 $this->modificationLogList->readObjects();
9544b6b4
MW
278 }
279
280 /**
65f1cc0b 281 * @inheritDoc
9544b6b4
MW
282 */
283 public function assignVariables() {
284 parent::assignVariables();
285
2d181735
AE
286 MessageQuoteManager::getInstance()->assignVariables();
287
41c23899
AE
288 $tmpHash = StringUtil::getRandomID();
289 $attachmentHandler = new AttachmentHandler('com.woltlab.wcf.conversation.message', 0, $tmpHash, 0);
290
65f1cc0b 291 WCF::getTPL()->assign([
41c23899
AE
292 'attachmentHandler' => $attachmentHandler,
293 'attachmentObjectID' => 0,
294 'attachmentObjectType' => 'com.woltlab.wcf.conversation.message',
295 'attachmentParentObjectID' => 0,
296 'tmpHash' => $tmpHash,
9544b6b4 297 'attachmentList' => $this->objectList->getAttachmentList(),
2e0bc870 298 'labelList' => $this->labelList,
a208d1f4 299 'modificationLogList' => $this->modificationLogList,
9544b6b4
MW
300 'sortOrder' => $this->sortOrder,
301 'conversation' => $this->conversation,
530c5f83 302 'conversationID' => $this->conversationID,
52971287 303 'participants' => $this->participantList->getObjects(),
cadc85bd 304 'defaultSmilies' => SmileyCache::getInstance()->getCategorySmilies()
65f1cc0b 305 ]);
a21c8732 306
dfecaf59 307 BBCodeHandler::getInstance()->setDisallowedBBCodes(explode(',', WCF::getSession()->getPermission('user.message.disallowedBBCodes')));
9544b6b4
MW
308 }
309
310 /**
311 * Calculates the position of a specific post in this conversation.
312 */
313 protected function goToPost() {
314 $conditionBuilder = clone $this->objectList->getConditionBuilder();
65f1cc0b 315 $conditionBuilder->add('time '.($this->sortOrder == 'ASC' ? '<=' : '>=').' ?', [$this->message->time]);
9544b6b4
MW
316
317 $sql = "SELECT COUNT(*) AS messages
a480521b 318 FROM wcf".WCF_N."_conversation_message conversation_message
9544b6b4 319 ".$conditionBuilder;
a21c8732
MS
320 $statement = WCF::getDB()->prepareStatement($sql);
321 $statement->execute($conditionBuilder->getParameters());
9544b6b4
MW
322 $row = $statement->fetchArray();
323 $this->pageNo = intval(ceil($row['messages'] / $this->itemsPerPage));
324 }
325
326 /**
327 * Gets the id of the last post in this conversation and forwards the user to this post.
328 */
329 protected function goToLastPost() {
4f13dcae 330 $sql = "SELECT conversation_message.messageID
a480521b 331 FROM wcf".WCF_N."_conversation_message conversation_message
9544b6b4 332 ".$this->objectList->getConditionBuilder()."
a480521b 333 ORDER BY time ".($this->sortOrder == 'ASC' ? 'DESC' : 'ASC');
249da2b9
MS
334 $statement = WCF::getDB()->prepareStatement($sql, 1);
335 $statement->execute($this->objectList->getConditionBuilder()->getParameters());
9544b6b4 336 $row = $statement->fetchArray();
65f1cc0b 337 HeaderUtil::redirect(LinkHandler::getInstance()->getLink('Conversation', [
655bead9 338 'encodeTitle' => true,
9544b6b4
MW
339 'object' => $this->conversation,
340 'messageID' => $row['messageID']
65f1cc0b 341 ]).'#message'.$row['messageID']);
9544b6b4
MW
342 exit;
343 }
344
345 /**
346 * Forwards the user to the first new message in this conversation.
347 */
348 protected function goToFirstNewPost() {
349 $conditionBuilder = clone $this->objectList->getConditionBuilder();
65f1cc0b 350 $conditionBuilder->add('time > ?', [$this->conversation->lastVisitTime]);
9544b6b4
MW
351
352 $sql = "SELECT conversation_message.messageID
a480521b 353 FROM wcf".WCF_N."_conversation_message conversation_message
9544b6b4 354 ".$conditionBuilder."
a480521b 355 ORDER BY time ASC";
a21c8732
MS
356 $statement = WCF::getDB()->prepareStatement($sql, 1);
357 $statement->execute($conditionBuilder->getParameters());
9544b6b4
MW
358 $row = $statement->fetchArray();
359 if ($row !== false) {
65f1cc0b 360 HeaderUtil::redirect(LinkHandler::getInstance()->getLink('Conversation', [
655bead9 361 'encodeTitle' => true,
9544b6b4
MW
362 'object' => $this->conversation,
363 'messageID' => $row['messageID']
65f1cc0b 364 ]).'#message'.$row['messageID']);
9544b6b4
MW
365 exit;
366 }
367 else {
368 $this->goToLastPost();
369 }
370 }
78fd78a7 371}