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