Файл: library/XenForo/ControllerPublic/Conversation.php
Строк: 2635
<?php
/**
* Controller for conversation actions.
*
* @package XenForo_Conversation
*/
class XenForo_ControllerPublic_Conversation extends XenForo_ControllerPublic_Abstract
{
/**
* Pre-dispatch assurances.
*/
protected function _preDispatch($action)
{
$this->_assertRegistrationRequired();
}
/**
* Displays a list of visitor's conversations.
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionIndex()
{
$conversationId = $this->_input->filterSingle('conversation_id', XenForo_Input::UINT);
if ($conversationId)
{
return $this->responseReroute(__CLASS__, 'view');
}
$viewParams = $this->_getConversationListData();
$this->canonicalizePageNumber(
$viewParams['page'], $viewParams['conversationsPerPage'], $viewParams['totalConversations'],
'conversations'
);
return $this->responseView('XenForo_ViewPublic_Conversation_List', 'conversation_list', $viewParams);
}
public function actionStarred()
{
$viewParams = $this->_getConversationListData(array('is_starred' => 1));
$this->canonicalizePageNumber(
$viewParams['page'], $viewParams['conversationsPerPage'], $viewParams['totalConversations'],
'conversations/starred'
);
return $this->responseView('XenForo_ViewPublic_Conversation_Starred', 'conversation_list_starred', $viewParams);
}
public function actionYours()
{
$visitor = XenForo_Visitor::getInstance();
$viewParams = $this->_getConversationListData(array(
'search_type' => 'started_by',
'search_user' => $visitor['username'],
'search_user_id' => $visitor['user_id']
));
$this->canonicalizePageNumber(
$viewParams['page'], $viewParams['conversationsPerPage'], $viewParams['totalConversations'],
'conversations/yours'
);
return $this->responseView('XenForo_ViewPublic_Conversation_Yours', 'conversation_list_yours', $viewParams);
}
protected function _getConversationListData(array $extraConditions = array())
{
$visitor = XenForo_Visitor::getInstance();
$conversationModel = $this->_getConversationModel();
$conditions = $this->_getListConditions();
$originalConditions = $conditions;
$conditions = array_merge($conditions, $extraConditions);
$fetchOptions = $this->_getListFetchOptions();
$totalConversations = $conversationModel->countConversationsForUser($visitor['user_id'], $conditions);
$conversations = $conversationModel->getConversationsForUser($visitor['user_id'], $conditions, $fetchOptions);
$conversations = $conversationModel->prepareConversations($conversations);
$page = max(1, intval($fetchOptions['page']));
return array(
'conversations' => $conversations,
'page' => $fetchOptions['page'],
'conversationsPerPage' => $fetchOptions['perPage'],
'totalConversations' => $totalConversations,
'startOffset' => ($page - 1) * $fetchOptions['perPage'] + 1,
'endOffset' => ($page - 1) * $fetchOptions['perPage'] + count($conversations),
'ignoredNames' => $this->_getIgnoredContentUserNames($conversations),
'canStartConversation' => $conversationModel->canStartConversations(),
'search_type' => $conditions['search_type'],
'search_user' => $conditions['search_user'],
'pageNavParams' => array(
'search_type' => ($originalConditions['search_type'] ? $originalConditions['search_type'] : false),
'search_user' => ($originalConditions['search_user'] ? $originalConditions['search_user'] : false),
),
);
}
protected function _getListConditions()
{
$searchType = $this->_input->filterSingle('search_type', XenForo_Input::STRING);
$searchUser = $this->_input->filterSingle('search_user', XenForo_Input::STRING);
if ($searchUser && $user = $this->getModelFromCache('XenForo_Model_User')->getUserByName($searchUser))
{
$conditions = array(
'search_type' => $searchType,
'search_user' => $user['username'],
'search_user_id' => $user['user_id'],
);
}
else
{
$conditions = array(
'search_type' => '',
'search_user' => '',
);
}
return $conditions;
}
protected function _getListFetchOptions()
{
return array(
'page' => $this->_input->filterSingle('page', XenForo_Input::UINT),
'perPage' => XenForo_Application::get('options')->discussionsPerPage
);
}
public function actionPopup()
{
$visitor = XenForo_Visitor::getInstance();
$conversationModel = $this->_getConversationModel();
$maxDisplay = 10;
$conversationsUnread = $conversationModel->getConversationsForUser($visitor['user_id'],
array('is_unread' => true),
array(
'join' => XenForo_Model_Conversation::FETCH_LAST_MESSAGE_AVATAR,
'limit' => $maxDisplay
)
);
$totalUnread = count($conversationsUnread);
if ($totalUnread < $maxDisplay)
{
$cutOff = XenForo_Application::$time - 3600 * XenForo_Application::get('options')->conversationPopupExpiryHours;
$conversationsRead = $conversationModel->getConversationsForUser($visitor['user_id'],
array(
'is_unread' => false,
'last_message_date' => array('>', $cutOff)
),
array(
'join' => XenForo_Model_Conversation::FETCH_LAST_MESSAGE_AVATAR,
'limit' => $maxDisplay - $totalUnread
)
);
if ($totalUnread != $visitor['conversations_unread'])
{
$dw = XenForo_DataWriter::create('XenForo_DataWriter_User');
$dw->setExistingData($visitor['user_id']);
$dw->set('conversations_unread', $totalUnread);
$dw->save();
$visitor['conversations_unread'] = $totalUnread;
}
}
else
{
$conversationsRead = array();
}
$viewParams = array(
'conversationsUnread' => $conversationModel->prepareConversations($conversationsUnread),
'conversationsRead' => $conversationModel->prepareConversations($conversationsRead)
);
return $this->responseView('XenForo_ViewPublic_Conversation_ListPopup', 'conversation_list_popup', $viewParams);
}
/**
* Marks an unread conversation as read, or a read conversation as unread
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionToggleRead()
{
$conversationId = $this->_input->filterSingle('conversation_id', XenForo_Input::UINT);
$conversation = $this->_getConversationOrError($conversationId);
if ($this->isConfirmedPost())
{
$visitor = XenForo_Visitor::getInstance();
if ($conversation['isNew'])
{
$this->_getConversationModel()->markConversationAsRead(
$conversationId, $visitor->user_id, XenForo_Application::$time);
$redirectPhrase = 'conversation_marked_as_read';
}
else
{
$this->_getConversationModel()->markConversationAsUnread(
$conversationId, $visitor->user_id);
$redirectPhrase = 'conversation_marked_as_unread';
}
return $this->responseRedirect(
XenForo_ControllerResponse_Redirect::SUCCESS,
XenForo_Link::buildPublicLink('conversations'),
new XenForo_Phrase($redirectPhrase),
array(
'unread' => $conversation['isNew'] ? false : true,
'actionPhrase' => new XenForo_Phrase($conversation['isNew'] ? 'mark_as_unread' : 'mark_as_read'),
'counter' => $visitor->conversations_unread,
'counterFormatted' => XenForo_Locale::numberFormat($visitor->conversations_unread)
)
);
}
else
{
$viewParams = array('conversation' => $conversation);
return $this->responseView('XenForo_ViewPublic_Conversation_ToggleRead', 'conversation_toggle_read', $viewParams);
}
}
/**
* Toggles starred state for conversation
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionToggleStarred()
{
$conversationId = $this->_input->filterSingle('conversation_id', XenForo_Input::UINT);
$conversation = $this->_getConversationOrError($conversationId);
if ($this->isConfirmedPost())
{
$visitor = XenForo_Visitor::getInstance();
if ($conversation['is_starred'])
{
$this->_getConversationModel()->changeConversationStarState(
$conversationId, $visitor->user_id, false
);
$redirectPhrase = 'conversation_unstarred';
$actionPhrase = 'star_conversation';
$targetLink = 'conversations';
}
else
{
$this->_getConversationModel()->changeConversationStarState(
$conversationId, $visitor->user_id, true
);
$redirectPhrase = 'conversation_starred';
$actionPhrase = 'unstar_conversation';
$targetLink = 'conversations/starred';
}
return $this->responseRedirect(
XenForo_ControllerResponse_Redirect::SUCCESS,
XenForo_Link::buildPublicLink($targetLink),
new XenForo_Phrase($redirectPhrase),
array('actionPhrase' => new XenForo_Phrase($actionPhrase))
);
}
else
{
$viewParams = array('conversation' => $conversation);
return $this->responseView('XenForo_ViewPublic_Conversation_ToggleStarred', 'conversation_toggle_starred', $viewParams);
}
}
/**
* Displays a conversation.
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionView()
{
$conversationId = $this->_input->filterSingle('conversation_id', XenForo_Input::UINT);
$conversation = $this->_getConversationOrError($conversationId);
$page = $this->_input->filterSingle('page', XenForo_Input::UINT);
$messagesPerPage = XenForo_Application::get('options')->messagesPerPage;
$conversationModel = $this->_getConversationModel();
$recipients = $conversationModel->getConversationRecipients($conversationId);
$messages = $conversationModel->getConversationMessages($conversationId, array(
'perPage' => $messagesPerPage,
'page' => $page,
));
$conversation['showMarkRead'] = $conversation['isNew'];
$maxMessageDate = $conversationModel->getMaximumMessageDate($messages);
if ($maxMessageDate > $conversation['last_read_date'])
{
$conversationModel->markConversationAsRead(
$conversationId, XenForo_Visitor::getUserId(), $maxMessageDate, $conversation['last_message_date']
);
$conversation['showMarkRead'] = false;
}
$attachmentHash = null;
if (!empty($conversation['draft_extra']))
{
$draftExtra = @unserialize($conversation['draft_extra']);
if (!empty($draftExtra['attachment_hash']))
{
$attachmentHash = $draftExtra['attachment_hash'];
}
}
$attachmentParams = $conversationModel->getAttachmentParams($conversation, array(
'conversation_id' => $conversationId
), null, $attachmentHash);
$messages = $conversationModel->getAndMergeAttachmentsIntoConversationMessages($messages);
$messages = $conversationModel->prepareMessages($messages, $conversation);
$viewParams = array(
'conversation' => $conversation,
'recipients' => $recipients,
'canEditConversation' => $conversationModel->canEditConversation($conversation),
'canReplyConversation' => $conversationModel->canReplyToConversation($conversation),
'canInviteUsers' => $conversationModel->canInviteUsersToConversation($conversation),
'attachmentParams' => $attachmentParams,
'attachmentConstraints' => $this->getModelFromCache('XenForo_Model_Attachment')->getAttachmentConstraints(),
'canViewAttachments' => $conversationModel->canViewAttachmentOnConversation($conversation),
'messages' => $messages,
'lastMessage' => end($messages),
'page' => $page,
'messagesPerPage' => $messagesPerPage,
'totalMessages' => $conversation['reply_count'] + 1
);
return $this->responseView('XenForo_ViewPublic_Conversation_View', 'conversation_view', $viewParams);
}
/**
* Jumps to the first unread message in the conversation.
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionUnread()
{
$conversationId = $this->_input->filterSingle('conversation_id', XenForo_Input::UINT);
$conversation = $this->_getConversationOrError($conversationId);
if (!$conversation['last_read_date'])
{
return $this->responseRedirect(
XenForo_ControllerResponse_Redirect::RESOURCE_CANONICAL,
XenForo_Link::buildPublicLink('conversations', $conversation)
);
}
$conversationModel = $this->_getConversationModel();
if ($conversation['last_read_date'] >= $conversation['last_message_date'])
{
$firstUnread = false;
}
else
{
$firstUnread = $conversationModel->getNextMessageInConversation($conversationId, $conversation['last_read_date']);
}
if (!$firstUnread || $firstUnread['message_id'] == $conversation['last_message_id'])
{
$page = floor($conversation['reply_count'] / XenForo_Application::get('options')->messagesPerPage) + 1;
$messageId = $conversation['last_message_id'];
}
else
{
$messagesBefore = $conversationModel->countMessagesBeforeDateInConversation($conversationId, $firstUnread['message_date']);
$page = floor($messagesBefore / XenForo_Application::get('options')->messagesPerPage) + 1;
$messageId = $firstUnread['message_id'];
}
return $this->responseRedirect(
XenForo_ControllerResponse_Redirect::RESOURCE_CANONICAL,
XenForo_Link::buildPublicLink('conversations', $conversation, array('page' => $page)) . '#message-' . $messageId
);
}
/**
* Redirects to the correct conversation, page and anchor for the given message.
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionMessage()
{
$conversationModel = $this->_getConversationModel();
$messageId = $this->_input->filterSingle('message_id', XenForo_Input::UINT);
$message = $conversationModel->getConversationMessageById($messageId);
if (!$message)
{
return $this->responseError(new XenForo_Phrase('requested_conversation_not_found'));
}
if ($conversationId = $this->_input->filterSingle('conversation_id', XenForo_Input::UINT))
{
$conversation = $this->_getConversationOrError($conversationId);
if (!$message || $message['conversation_id'] != $conversationId)
{
return $this->responseRedirect(
XenForo_ControllerResponse_Redirect::RESOURCE_CANONICAL_PERMANENT,
XenForo_Link::buildPublicLink('conversations', $conversation)
);
}
}
else
{
$conversation = $this->_getConversationOrError($message['conversation_id']);
}
$params = array();
$messagesBefore = $conversationModel->countMessagesBeforeDateInConversation($message['conversation_id'], $message['message_date']);
$messagesPerPage = XenForo_Application::get('options')->messagesPerPage;
$page = floor($messagesBefore / $messagesPerPage) + 1;
if ($page > 1)
{
$params['page'] = $page;
}
return $this->responseRedirect(
XenForo_ControllerResponse_Redirect::RESOURCE_CANONICAL_PERMANENT,
XenForo_Link::buildPublicLink('conversations', $conversation, $params) . '#message-' . $message['message_id']
);
}
/**
* Displays a form to create a conversation.
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionAdd()
{
if (!$this->_getConversationModel()->canStartConversations($errorPhraseKey))
{
throw $this->getErrorOrNoPermissionResponseException($errorPhraseKey);
}
$to = $this->_input->filterSingle('to', XenForo_Input::STRING);
$title = $this->_input->filterSingle('title', XenForo_Input::STRING);
if ($to !== '' && strpos($to, ',') === false)
{
$toUser = $this->getModelFromCache('XenForo_Model_User')->getUserByName($to, array(
'join' => XenForo_Model_User::FETCH_USER_FULL
));
if (!$toUser)
{
return $this->responseError(new XenForo_Phrase('requested_user_not_found'), 404);
}
if (!$this->_getConversationModel()->canStartConversationWithUser($toUser, $errorPhraseKey))
{
if ($errorPhraseKey)
{
$error = new XenForo_Phrase($errorPhraseKey);
}
else
{
$error = new XenForo_Phrase('you_may_not_start_conversation_with_x_privacy_settings', array('name' => $toUser['username']));
}
return $this->responseError($error, 403);
}
$to = $toUser['username'];
}
$draft = $this->_getDraftModel()->getDraftByUserKey("conversation", XenForo_Visitor::getUserId());
$attachmentHash = null;
if ($draft)
{
$extra = @unserialize($draft['extra_data']);
if ($to && !empty($extra['recipients']) && $to != $extra['recipients'])
{
// our draft is to someone else
$draft = false;
}
else
{
if (!empty($extra['recipients']) && !$to)
{
$to = $extra['recipients'];
}
if (!empty($extra['title']) && !$title)
{
$title = $extra['title'];
}
if (!empty($extra['attachment_hash']))
{
$attachmentHash = $extra['attachment_hash'];
}
}
}
$attachmentParams = $this->_getConversationModel()->getAttachmentParams(array(), array(), null, $attachmentHash);
$viewParams = array(
'to' => $to,
'title' => $title,
'remaining' => $this->_getConversationModel()->allowedAdditionalConversationRecipients(array()),
'draft' => $draft,
'attachmentParams' => $attachmentParams,
'attachmentConstraints' => $this->getModelFromCache('XenForo_Model_Attachment')->getAttachmentConstraints(),
);
return $this->responseView('XenForo_ViewPublic_Conversation_Add', 'conversation_add', $viewParams);
}
/**
* Inserts a new conversation.
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionInsert()
{
$this->_assertPostOnly();
if (!$this->_getConversationModel()->canStartConversations($errorPhraseKey))
{
throw $this->getErrorOrNoPermissionResponseException($errorPhraseKey);
}
$input = $this->_input->filter(array(
'recipients' => XenForo_Input::STRING,
'title' => XenForo_Input::STRING,
'open_invite' => XenForo_Input::UINT,
'conversation_locked' => XenForo_Input::UINT,
'attachment_hash' => XenForo_Input::STRING
));
$input['message'] = $this->getHelper('Editor')->getMessageText('message', $this->_input);
$input['message'] = XenForo_Helper_String::autoLinkBbCode($input['message']);
$visitor = XenForo_Visitor::getInstance();
$conversationDw = XenForo_DataWriter::create('XenForo_DataWriter_ConversationMaster');
$conversationDw->setExtraData(XenForo_DataWriter_ConversationMaster::DATA_ACTION_USER, $visitor->toArray());
$conversationDw->setExtraData(XenForo_DataWriter_ConversationMaster::DATA_MESSAGE, $input['message']);
$conversationDw->set('user_id', $visitor['user_id']);
$conversationDw->set('username', $visitor['username']);
$conversationDw->set('title', $input['title']);
$conversationDw->set('open_invite', $input['open_invite']);
$conversationDw->set('conversation_open', $input['conversation_locked'] ? 0 : 1);
$conversationDw->addRecipientUserNames(explode(',', $input['recipients'])); // checks permissions
$messageDw = $conversationDw->getFirstMessageDw();
$messageDw->set('message', $input['message']);
$messageDw->setExtraData(XenForo_DataWriter_ConversationMessage::DATA_ATTACHMENT_HASH, $input['attachment_hash']);
$spamModel = $this->_getSpamPreventionModel();
if (!$conversationDw->hasErrors()
&& $spamModel->visitorRequiresSpamCheck()
)
{
$spamResult = $spamModel->checkMessageSpam($input['title'] . "n" . $input['message'], array(), $this->_request);
switch ($spamResult)
{
case XenForo_Model_SpamPrevention::RESULT_MODERATED:
case XenForo_Model_SpamPrevention::RESULT_DENIED;
$spamModel->logSpamTrigger('conversation', null);
$conversationDw->error(new XenForo_Phrase('your_content_cannot_be_submitted_try_later'));
break;
}
}
$conversationDw->preSave();
if (!$conversationDw->hasErrors())
{
$this->assertNotFlooding('conversation');
}
$conversationDw->save();
$conversation = $conversationDw->getMergedData();
$this->_getDraftModel()->deleteDraft('conversation');
$this->_getConversationModel()->markConversationAsRead(
$conversation['conversation_id'], XenForo_Visitor::getUserId(), XenForo_Application::$time
);
return $this->responseRedirect(
XenForo_ControllerResponse_Redirect::SUCCESS,
XenForo_Link::buildPublicLink('conversations', $conversation),
new XenForo_Phrase('your_conversation_has_been_created')
);
}
public function actionSaveDraft()
{
$this->_assertPostOnly();
$conversationId = $this->_input->filterSingle('conversation_id', XenForo_Input::UINT);
if ($conversationId)
{
$conversation = $this->_getConversationOrError($conversationId);
$this->_assertCanReplyToConversation($conversation);
$key = 'conversation-' . $conversationId;
$extra = $this->_input->filter(array(
'attachment_hash' => XenForo_Input::STRING
));
}
else
{
if (!$this->_getConversationModel()->canStartConversations($errorPhraseKey))
{
throw $this->getErrorOrNoPermissionResponseException($errorPhraseKey);
}
$conversation = false;
$key = 'conversation';
$extra = $this->_input->filter(array(
'recipients' => XenForo_Input::STRING,
'title' => XenForo_Input::STRING,
'open_invite' => XenForo_Input::UINT,
'conversation_locked' => XenForo_Input::UINT,
'attachment_hash' => XenForo_Input::STRING
));
}
$message = $this->getHelper('Editor')->getMessageText('message', $this->_input);
$forceDelete = $this->_input->filterSingle('delete_draft', XenForo_Input::BOOLEAN);
if (!strlen($message) || $forceDelete)
{
$draftSaved = false;
$draftDeleted = $this->_getDraftModel()->deleteDraft($key) || $forceDelete;
}
else
{
$this->_getDraftModel()->saveDraft($key, $message, $extra);
$draftSaved = true;
$draftDeleted = false;
}
$viewParams = array(
'conversation' => $conversation,
'draftSaved' => $draftSaved,
'draftDeleted' => $draftDeleted
);
return $this->responseView('XenForo_ViewPublic_Conversation_SaveDraft', '', $viewParams);
}
/**
* Displays a form to edit a conversation.
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionEdit()
{
$conversationId = $this->_input->filterSingle('conversation_id', XenForo_Input::UINT);
$conversation = $this->_getConversationOrError($conversationId);
$this->_assertCanEditConversation($conversation);
$viewParams = array(
'conversation' => $conversation
);
return $this->responseView('XenForo_ViewPublic_Conversation_Edit', 'conversation_edit', $viewParams);
}
/**
* Shows a preview of the conversation.
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionPreview()
{
$this->_assertPostOnly();
$message = $this->getHelper('Editor')->getMessageText('message', $this->_input);
$message = XenForo_Helper_String::autoLinkBbCode($message);
/** @var $taggingModel XenForo_Model_UserTagging */
$taggingModel = $this->getModelFromCache('XenForo_Model_UserTagging');
$taggingModel->getTaggedUsersInMessage($message, $message);
$viewParams = array(
'message' => $message
);
return $this->responseView('XenForo_ViewPublic_Conversation_Preview', 'conversation_preview', $viewParams);
}
/**
* Updates a conversation.
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionUpdate()
{
$this->_assertPostOnly();
$conversationId = $this->_input->filterSingle('conversation_id', XenForo_Input::UINT);
$conversation = $this->_getConversationOrError($conversationId);
$this->_assertCanEditConversation($conversation);
$input = $this->_input->filter(array(
'title' => XenForo_Input::STRING,
'open_invite' => XenForo_Input::UINT,
'conversation_locked' => XenForo_Input::UINT
));
$update = array(
'title' => $input['title'],
'open_invite' => $input['open_invite'],
'conversation_open' => ($input['conversation_locked'] ? 0 : 1)
);
$conversationDw = XenForo_DataWriter::create('XenForo_DataWriter_ConversationMaster');
$conversationDw->setExistingData($conversationId);
$conversationDw->bulkSet($update);
$conversationDw->save();
$conversation = $conversationDw->getMergedData();
return $this->responseRedirect(
XenForo_ControllerResponse_Redirect::SUCCESS,
XenForo_Link::buildPublicLink('conversations', $conversation)
);
}
/**
* Leave a (user's) conversation.
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionLeave()
{
$conversationId = $this->_input->filterSingle('conversation_id', XenForo_Input::UINT);
$conversation = $this->_getConversationOrError($conversationId);
$deleteType = $this->_input->filterSingle('delete_type', XenForo_Input::STRING);
if ($this->isConfirmedPost()) // delete the conversation
{
$this->_getConversationModel()->deleteConversationForUser(
$conversationId, XenForo_Visitor::getUserId(), $deleteType
);
return $this->responseRedirect(
XenForo_ControllerResponse_Redirect::SUCCESS,
XenForo_Link::buildPublicLink('conversations')
);
}
else
{
$viewParams = array(
'conversation' => $conversation
);
return $this->responseView(
'XenForo_ViewPublic_Conversation_Leave',
'conversation_leave',
$viewParams
);
}
}
/**
* Displays a form to edit a message in a conversation
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionEditMessage()
{
$vp = $this->_getEditViewParams();
$conversation = $vp['conversation'];
$conversationMessage = $vp['conversationMessage'];
$attachmentParams = $this->_getConversationModel()->getAttachmentParams($conversation, array(
'conversation_id' => $conversation['conversation_id']
));
$attachmentModel = $this->_getAttachmentModel();
$attachments = $attachmentModel->getAttachmentsByContentId('conversation_message', $conversationMessage['message_id']);
$viewParams = array(
'conversation' => $conversation,
'conversationMessage' => $conversationMessage,
'message' => XenForo_Helper_String::autoLinkBbCode($this->getHelper('Editor')->getMessageText('editMessage', $this->_input)),
'attachmentParams' => $attachmentParams,
'attachments' => $attachmentModel->prepareAttachments($attachments),
'attachmentConstraints' => $attachmentModel->getAttachmentConstraints()
);
if ($this->_input->inRequest('more_options'))
{
$viewParams['conversationMessage']['message'] = $this->getHelper('Editor')->getMessageText('message', $this->_input);
}
return $this->responseView(
'XenForo_ViewPublic_Conversation_EditMessage',
'conversation_message_edit',
$viewParams
);
}
/**
* Displays a simple overlay form to edit a message in a conversation
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionEditMessageInline()
{
return $this->responseView(
'XenForo_ViewPublic_Conversation_EditMessageInline',
'conversation_message_edit_inline',
$this->_getEditViewParams()
);
}
/**
* Previews the results of a message edit
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionEditMessagePreview()
{
$this->_assertPostOnly();
$viewParams = $this->_getEditViewParams();
$viewParams['message'] = XenForo_Helper_String::autoLinkBbCode(
$this->getHelper('Editor')->getMessageText('message', $this->_input)
);
return $this->responseView(
'XenForo_ViewPublic_Conversation_EditMessagePreview',
'conversation_message_edit_preview',
$viewParams
);
}
/**
* Fetch $viewParams for the two identical edit actions
*
* @return array $viewParams
*/
protected function _getEditViewParams()
{
$conversationId = $this->_input->filterSingle('conversation_id', XenForo_Input::UINT);
$messageId = $this->_input->filterSingle('m', XenForo_Input::UINT);
list($conversation, $conversationMessage) = $this->_getConversationAndMessageOrError($messageId, $conversationId);
$this->_assertCanEditMessageInConversation($conversationMessage, $conversation);
return array(
'conversation' => $conversation,
'conversationMessage' => $conversationMessage
);
}
/**
* Saves an edited message
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionSaveMessage()
{
if ($this->_input->inRequest('more_options'))
{
return $this->responseReroute(__CLASS__, 'editMessage');
}
$conversationId = $this->_input->filterSingle('conversation_id', XenForo_Input::UINT);
$messageId = $this->_input->filterSingle('m', XenForo_Input::UINT);
$attachmentHash = $this->_input->filterSingle('attachment_hash', XenForo_Input::STRING);
list($conversation, $conversationMessage) = $this->_getConversationAndMessageOrError($messageId, $conversationId);
$this->_assertCanEditMessageInConversation($conversationMessage, $conversation);
$message = $this->getHelper('Editor')->getMessageText('message', $this->_input);
$message = XenForo_Helper_String::autoLinkBbCode($message);
$dw = XenForo_DataWriter::create('XenForo_DataWriter_ConversationMessage');
$dw->setExistingData($messageId);
$dw->set('message', $message);
// this option prevents an error when editing the message of a deleted user
$dw->setOption(XenForo_DataWriter_ConversationMessage::OPTION_CHECK_SENDER_RECIPIENT, false);
$dw->setExtraData(XenForo_DataWriter_ConversationMessage::DATA_ATTACHMENT_HASH, $attachmentHash);
$dw->save();
if ($this->_noRedirect())
{
$conversationModel = $this->_getConversationModel();
$message = array_merge($conversationMessage, $dw->getMergedData());
$messages = $conversationModel->getAndMergeAttachmentsIntoConversationMessages(array($message['message_id'] => $message));
$message = reset($messages);
$viewParams = array(
'conversation' => $conversation,
'message' => $conversationModel->prepareMessage($message, $conversation),
'canReplyConversation' => $conversationModel->canReplyToConversation($conversation),
'canViewAttachments' => $conversationModel->canViewAttachmentOnConversation($conversation),
);
return $this->responseView(
'XenForo_ViewPublic_Conversation_ViewMessage',
'conversation_message',
$viewParams
);
}
else
{
return $this->responseRedirect(
XenForo_ControllerResponse_Redirect::SUCCESS,
XenForo_Link::buildPublicLink('conversations/message', $conversation, array('message_id' => $conversationMessage['message_id']))
);
}
}
/**
* Displays a form to add a reply to a conversation.
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionReply()
{
$conversationId = $this->_input->filterSingle('conversation_id', XenForo_Input::UINT);
$conversation = $this->_getConversationOrError($conversationId);
$this->_assertCanReplyToConversation($conversation);
if ($messageId = $this->_input->filterSingle('m', XenForo_Input::UINT)) // 'm' is a shortcut for 'message_id'
{
$conversationModel = $this->_getConversationModel();
if ($message = $conversationModel->getConversationMessageById($messageId))
{
if ($message['conversation_id'] != $conversationId)
{
return $this->responseError(new XenForo_Phrase('not_possible_to_reply_to_messages_not_same_conversation'));
}
$defaultMessage = $conversationModel->getQuoteForConversationMessage($message);
}
}
else if ($this->_input->inRequest('more_options'))
{
$message = array();
$defaultMessage = $this->getHelper('Editor')->getMessageText('message', $this->_input);
}
else
{
$message = array();
$defaultMessage = '';
}
$attachmentParams = $this->_getConversationModel()->getAttachmentParams($conversation, array(
'conversation_id' => $conversationId
));
if ($attachmentParams)
{
$attachmentModel = $this->getModelFromCache('XenForo_Model_Attachment');
$quickReplyAttachmentHash = $this->_input->filterSingle('attachment_hash', XenForo_Input::STRING);
$attachments = $attachmentModel->prepareAttachments(
$attachmentModel->getAttachmentsByTempHash($quickReplyAttachmentHash)
);
if ($attachments)
{
$attachmentParams['hash'] = $quickReplyAttachmentHash;
}
}
else
{
$attachments = array();
}
$viewParams = array(
'conversation' => $conversation,
'message' => $message,
'defaultMessage' => $defaultMessage,
'attachmentParams' => $attachmentParams,
'attachments' => $attachments,
'attachmentConstraints' => $this->getModelFromCache('XenForo_Model_Attachment')->getAttachmentConstraints(),
);
return $this->responseView('XenForo_ViewPublic_Conversation_Reply', 'conversation_reply', $viewParams);
}
/**
* Inserts a reply into a conversation.
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionInsertReply()
{
$this->_assertPostOnly();
if ($this->_input->inRequest('more_options'))
{
return $this->responseReroute(__CLASS__, 'reply');
}
$input = array();
$input['message'] = $this->getHelper('Editor')->getMessageText('message', $this->_input);
$input['message'] = XenForo_Helper_String::autoLinkBbCode($input['message']);
$conversationId = $this->_input->filterSingle('conversation_id', XenForo_Input::UINT);
$conversation = $this->_getConversationOrError($conversationId);
$this->_assertCanReplyToConversation($conversation);
$visitor = XenForo_Visitor::getInstance();
$attachmentHash = $this->_input->filterSingle('attachment_hash', XenForo_Input::STRING);
$messageDw = XenForo_DataWriter::create('XenForo_DataWriter_ConversationMessage');
$messageDw->setExtraData(XenForo_DataWriter_ConversationMessage::DATA_MESSAGE_SENDER, $visitor->toArray());
$messageDw->setExtraData(XenForo_DataWriter_ConversationMessage::DATA_ATTACHMENT_HASH, $attachmentHash);
$messageDw->set('conversation_id', $conversation['conversation_id']);
$messageDw->set('user_id', $visitor['user_id']);
$messageDw->set('username', $visitor['username']);
$messageDw->set('message', $input['message']);
$spamModel = $this->_getSpamPreventionModel();
if (!$messageDw->hasErrors()
&& $spamModel->visitorRequiresSpamCheck()
)
{
$spamResult = $spamModel->checkMessageSpam($input['message'], array(), $this->_request);
switch ($spamResult)
{
case XenForo_Model_SpamPrevention::RESULT_MODERATED:
case XenForo_Model_SpamPrevention::RESULT_DENIED;
$spamModel->logSpamTrigger('conversation_message', null);
$messageDw->error(new XenForo_Phrase('your_content_cannot_be_submitted_try_later'));
break;
}
}
$messageDw->preSave();
if (!$messageDw->hasErrors())
{
$this->assertNotFlooding('conversation');
}
$messageDw->save();
$message = $messageDw->getMergedData();
$this->_getDraftModel()->deleteDraft('conversation-' . $conversation['conversation_id']);
$conversationModel = $this->_getConversationModel();
if (!$this->_noRedirect() || !$this->_input->inRequest('last_date'))
{
$conversationModel->markConversationAsRead(
$conversation['conversation_id'], XenForo_Visitor::getUserId(), XenForo_Application::$time, 0, false
);
return $this->responseRedirect(
XenForo_ControllerResponse_Redirect::SUCCESS,
XenForo_Link::buildPublicLink('conversations/message', $conversation, array('message_id' => $message['message_id'])),
new XenForo_Phrase('your_message_has_been_posted')
);
}
else
{
$lastDate = $this->_input->filterSingle('last_date', XenForo_Input::UINT);
$limit = 3;
$messageFetchOptions = array(
'limit' => $limit + 1
);
$messages = $conversationModel->getNewestConversationMessagesAfterDate(
$conversationId, $lastDate, $messageFetchOptions
);
// We fetched one more message than needed. If more than $limit message were returned,
// we can show the 'there are more messages' notice
if (count($messages) > $limit)
{
$firstUnshown = $conversationModel->getNextMessageInConversation($conversationId, $lastDate);
// remove the extra post
array_pop($messages);
}
else
{
$firstUnshown = false;
}
if (!$firstUnshown || $firstUnshown['message_date'] < $conversation['last_read_date'])
{
$conversationModel->markConversationAsRead(
$conversation['conversation_id'], XenForo_Visitor::getUserId(), XenForo_Application::$time, 0, false
);
}
$messages = array_reverse($messages, true);
$messages = $conversationModel->prepareMessages($messages, $conversation);
$messages = $conversationModel->getAndMergeAttachmentsIntoConversationMessages($messages);
$viewParams = array(
'conversation' => $conversation,
'canReplyConversation' => $conversationModel->canReplyToConversation($conversation),
'canViewAttachments' => $conversationModel->canViewAttachmentOnConversation($conversation),
'firstUnshown' => $firstUnshown,
'messages' => $messages,
'lastMessage' => end($messages)
);
return $this->responseView(
'XenForo_ViewPublic_Conversation_ViewNewMessages',
'conversation_view_new_messages',
$viewParams
);
}
}
/**
* Displays a form to invite users to a conversation.
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionInvite()
{
$conversationId = $this->_input->filterSingle('conversation_id', XenForo_Input::UINT);
$conversation = $this->_getConversationOrError($conversationId);
$this->_assertCanInviteUsersToConversation($conversation);
$viewParams = array(
'conversation' => $conversation,
'remaining' => $this->_getConversationModel()->allowedAdditionalConversationRecipients($conversation)
);
return $this->responseView('XenForo_ViewPublic_Conversation_Invite', 'conversation_invite', $viewParams);
}
/**
* Invites users to a conversation.
*
* @return XenForo_ControllerResponse_Abstract
*/
public function actionInviteInsert()
{
$this->_assertPostOnly();
$emailConversationIncludeMessage = XenForo_Application::get('options')->emailConversationIncludeMessage;
$conversationId = $this->_input->filterSingle('conversation_id', XenForo_Input::UINT);
$conversation = $this->_getConversationOrError($conversationId, null, $emailConversationIncludeMessage);
$this->_assertCanInviteUsersToConversation($conversation);
$recipients = $this->_input->filterSingle('recipients', XenForo_Input::STRING);
/* @var $conversationDw XenForo_DataWriter_ConversationMaster */
$conversationDw = XenForo_DataWriter::create('XenForo_DataWriter_ConversationMaster');
$conversationDw->setExistingData($conversationId);
$conversationDw->setExtraData(XenForo_DataWriter_ConversationMaster::DATA_ACTION_USER, XenForo_Visitor::getInstance()->toArray());
$conversationDw->addRecipientUserNames(explode(',', $recipients));
if ($emailConversationIncludeMessage)
{
$conversationDw->setExtraData(XenForo_DataWriter_ConversationMaster::DATA_MESSAGE, $conversation['message']);
}
$conversationDw->save();
if ($this->_noRedirect())
{
$viewParams = array(
'conversation' => $conversation,
'recipients' => $this->_getConversationModel()->getConversationRecipients($conversationId)
);
return $this->responseView(
'XenForo_ViewPublic_Conversation_InviteInsert',
'conversation_recipients',
$viewParams
);
}
return $this->responseRedirect(
XenForo_ControllerResponse_Redirect::SUCCESS,
XenForo_Link::buildPublicLink('conversations', $conversation)
);
}
public function actionReport()
{
$messageId = $this->_input->filterSingle('message_id', XenForo_Input::UINT);
$conversationId = $this->_input->filterSingle('conversation_id', XenForo_Input::UINT);
list($conversation, $message) = $this->_getConversationAndMessageOrError($messageId, $conversationId);
if (!$this->_getConversationModel()->canReportMessage($message, $conversation, $errorPhraseKey))
{
throw $this->getErrorOrNoPermissionResponseException($errorPhraseKey);
}
if ($this->isConfirmedPost())
{
$reportMessage = $this->_input->filterSingle('message', XenForo_Input::STRING);
if (!$reportMessage)
{
return $this->responseError(new XenForo_Phrase('please_enter_reason_for_reporting_this_message'));
}
$this->assertNotFlooding('report');
$message['conversation'] = $conversation;
/* @var $reportModel XenForo_Model_Report */
$reportModel = XenForo_Model::create('XenForo_Model_Report');
$reportModel->reportContent('conversation_message', $message, $reportMessage);
return $this->responseRedirect(
XenForo_ControllerResponse_Redirect::SUCCESS,
XenForo_Link::buildPublicLink('conversations/message', $conversation, array('message_id' => $message['message_id'])),
new XenForo_Phrase('thank_you_for_reporting_this_message')
);
}
else
{
$viewParams = array(
'conversation' => $conversation,
'message' => $message,
);
return $this->responseView('XenForo_ViewPublic_Conversation_Report', 'conversation_message_report', $viewParams);
}
}
public function actionFindUser()
{
$this->_assertPostOnly();
$conversationModel = $this->_getConversationModel();
$userId = XenForo_Visitor::getUserId();
$q = $this->_input->filterSingle('q', XenForo_Input::STRING);
switch ($this->_input->filterSingle('search_type', XenForo_Input::STRING))
{
case 'started_by':
$users = $conversationModel->findConversationStartersForUser($userId, $q);
break;
case 'received_by':
$users = $conversationModel->findConversationRecipientsForUser($userId, $q);
break;
//case 'message_by':
// $users = $conversationModel->findConversationRespondersForUser($userId, $q);
// break;
default:
$users = array();
}
$viewParams = array(
'users' => $users
);
return $this->responseView('XenForo_ViewPublic_Member_Find', 'member_autocomplete', $viewParams);
}
/**
* Session activity details.
* @see XenForo_Controller::getSessionActivityDetailsForList()
*/
public static function getSessionActivityDetailsForList(array $activities)
{
return new XenForo_Phrase('engaged_in_conversation');
}
/**
* Gets the specified conversation for the specified user, or throws an error.
*
* @param integer $conversationId
* @param integer|null $userId If null, uses visitor
* @param boolean Fetch first message text with the conversation
*
* @return array
*/
protected function _getConversationOrError($conversationId, $userId = null, $fetchFirstMessage = false)
{
if ($userId === null)
{
$userId = XenForo_Visitor::getUserId();
}
$conversationModel = $this->_getConversationModel();
$fetchOptions = array();
if ($fetchFirstMessage)
{
$fetchOptions['join'] = XenForo_Model_Conversation::FETCH_FIRST_MESSAGE;
}
$fetchOptions['draftUserId'] = XenForo_Visitor::getUserId();
$conversation = $conversationModel->getConversationForUser($conversationId, $userId, $fetchOptions);
if (!$conversation)
{
throw $this->responseException($this->responseError(new XenForo_Phrase('requested_conversation_not_found'), 404));
}
return $conversationModel->prepareConversation($conversation);
}
/**
* Gets the specified conversation and message, or throws an error
*
* @param integer $messageId
* @param integer $conversationId
* @param integer|null $userId
*
* @return array [$conversation, $message]
*/
protected function _getConversationAndMessageOrError($messageId, $conversationId, $userId = null)
{
if ($userId === null)
{
$userId = XenForo_Visitor::getUserId();
}
$conversationModel = $this->_getConversationModel();
$conversation = $this->_getConversationOrError($conversationId, $userId);
$message = $conversationModel->getConversationMessageById($messageId);
if (!$message || $message['conversation_id'] != $conversation['conversation_id'])
{
throw $this->responseException($this->responseError(new XenForo_Phrase('requested_message_not_found'), 404));
}
return array(
$conversation,
$conversationModel->prepareMessage($message, $conversation)
);
}
/**
* Asserts that the currently browsing user can reply to this conversation.
*
* @param array $conversation
*/
protected function _assertCanReplyToConversation(array $conversation)
{
if (!$this->_getConversationModel()->canReplyToConversation($conversation, $errorPhraseKey))
{
throw $this->getErrorOrNoPermissionResponseException($errorPhraseKey);
}
}
/**
* Asserts that the currently browsing user can edit this conversation.
*
* @param array $conversation
*/
protected function _assertCanEditConversation(array $conversation)
{
if (!$this->_getConversationModel()->canEditConversation($conversation, $errorPhraseKey))
{
throw $this->getErrorOrNoPermissionResponseException($errorPhraseKey);
}
}
/**
* Asserts that the currently browsing user can invite users this conversation.
*
* @param array $conversation
*/
protected function _assertCanInviteUsersToConversation(array $conversation)
{
if (!$this->_getConversationModel()->canInviteUsersToConversation($conversation, $errorPhraseKey))
{
throw $this->getErrorOrNoPermissionResponseException($errorPhraseKey);
}
}
/**
* Asserts that the currently browsing user can edit the specified message
*
* @param array $message
* @param array $conversation
*/
protected function _assertCanEditMessageInConversation(array $message, array $conversation)
{
if (!$this->_getConversationModel()->canEditMessage($message, $conversation, $errorPhraseKey))
{
throw $this->getErrorOrNoPermissionResponseException($errorPhraseKey);
}
}
/**
* @return XenForo_Model_Conversation
*/
protected function _getConversationModel()
{
return $this->getModelFromCache('XenForo_Model_Conversation');
}
/**
* @return XenForo_Model_Attachment
*/
protected function _getAttachmentModel()
{
return $this->getModelFromCache('XenForo_Model_Attachment');
}
/**
* @return XenForo_Model_SpamPrevention
*/
protected function _getSpamPreventionModel()
{
return $this->getModelFromCache('XenForo_Model_SpamPrevention');
}
/**
* @return XenForo_Model_Draft
*/
protected function _getDraftModel()
{
return $this->getModelFromCache('XenForo_Model_Draft');
}
}