*.imlworkspace
.xml
-# Community Framework
+# WoltLab Suite
# Ignore packages build directly in the workspace. They can however be added manually via git add, if wanted.
*.tar
*.tar.gz
\ No newline at end of file
sudo: false
php:
- 5.6
- - 5.3
+ - 5.5
before_install:
- pyrus install pear/PHP_CodeSniffer
- phpenv rehash
--- /dev/null
+# Changelog
+
+## 3.0
+
+### 3.0.0 Alpha 1 (XXXX-YY-ZZ)
+
+* Only search active conversation when using search bar in a conversation.
+* Filter option for conversation participants on conversation list page.
+* Increased number of items in conversation drop down to 10.
+* Overhauled conversation drop down.
+* Changed label of wcf.conversation.lastVisitTime
+
+#### Documentation
+
+* `@property-read` tags for database table columns of classes extending `wcf\data\DatabaseObject`.
<import>
<!-- conversation -->
<action name="assignLabel">
- <actionclassname><![CDATA[wcf\system\clipboard\action\ConversationClipboardAction]]></actionclassname>
+ <actionclassname>wcf\system\clipboard\action\ConversationClipboardAction</actionclassname>
<showorder>1</showorder>
<pages>
- <page><![CDATA[wcf\page\ConversationListPage]]></page>
+ <page>wcf\page\ConversationListPage</page>
</pages>
</action>
<action name="markAsRead">
- <actionclassname><![CDATA[wcf\system\clipboard\action\ConversationClipboardAction]]></actionclassname>
+ <actionclassname>wcf\system\clipboard\action\ConversationClipboardAction</actionclassname>
<showorder>2</showorder>
<pages>
- <page><![CDATA[wcf\page\ConversationListPage]]></page>
+ <page>wcf\page\ConversationListPage</page>
</pages>
</action>
<action name="restore">
- <actionclassname><![CDATA[wcf\system\clipboard\action\ConversationClipboardAction]]></actionclassname>
+ <actionclassname>wcf\system\clipboard\action\ConversationClipboardAction</actionclassname>
<showorder>3</showorder>
<pages>
- <page><![CDATA[wcf\page\ConversationListPage]]></page>
+ <page>wcf\page\ConversationListPage</page>
</pages>
</action>
<action name="leave">
- <actionclassname><![CDATA[wcf\system\clipboard\action\ConversationClipboardAction]]></actionclassname>
+ <actionclassname>wcf\system\clipboard\action\ConversationClipboardAction</actionclassname>
<showorder>4</showorder>
<pages>
- <page><![CDATA[wcf\page\ConversationListPage]]></page>
+ <page>wcf\page\ConversationListPage</page>
</pages>
</action>
<action name="leavePermanently">
- <actionclassname><![CDATA[wcf\system\clipboard\action\ConversationClipboardAction]]></actionclassname>
+ <actionclassname>wcf\system\clipboard\action\ConversationClipboardAction</actionclassname>
<showorder>5</showorder>
<pages>
- <page><![CDATA[wcf\page\ConversationListPage]]></page>
+ <page>wcf\page\ConversationListPage</page>
</pages>
</action>
<action name="open">
- <actionclassname><![CDATA[wcf\system\clipboard\action\ConversationClipboardAction]]></actionclassname>
+ <actionclassname>wcf\system\clipboard\action\ConversationClipboardAction</actionclassname>
<showorder>6</showorder>
<pages>
- <page><![CDATA[wcf\page\ConversationListPage]]></page>
+ <page>wcf\page\ConversationListPage</page>
</pages>
</action>
<action name="close">
- <actionclassname><![CDATA[wcf\system\clipboard\action\ConversationClipboardAction]]></actionclassname>
+ <actionclassname>wcf\system\clipboard\action\ConversationClipboardAction</actionclassname>
<showorder>7</showorder>
<pages>
- <page><![CDATA[wcf\page\ConversationListPage]]></page>
+ <page>wcf\page\ConversationListPage</page>
</pages>
</action>
<!-- /conversation -->
--- /dev/null
+<?php
+/**
+ * Defines constants for autocompletion in IDEs. This file is not meant to be actively used anywhere!
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core
+ */
+
+// option constants
+define('MODULE_CONVERSATION', 1);
+define('CONVERSATIONS_PER_PAGE', 10);
+define('CONVERSATION_MESSAGES_PER_PAGE', 20);
+define('CONVERSATION_REPLY_SHOW_MESSAGES_MAX', 10);
+define('CONVERSATION_LIST_DEFAULT_SORT_FIELD', 'lastPostTime');
+define('CONVERSATION_LIST_DEFAULT_SORT_ORDER', 'DESC');
<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/coreObject.xsd">
<import>
<coreobject>
- <objectname><![CDATA[wcf\system\conversation\ConversationHandler]]></objectname>
+ <objectname>wcf\system\conversation\ConversationHandler</objectname>
</coreobject>
</import>
</data>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/maelstrom/eventListener.xsd">
- <import>
- <eventlistener>
- <eventclassname>wcf\data\user\UserAction</eventclassname>
- <eventname>rename</eventname>
- <listenerclassname>wcf\system\event\listener\ConversationUserActionRenameListener</listenerclassname>
- <environment>user</environment>
- </eventlistener>
- <eventlistener>
- <eventclassname>wcf\data\user\UserAction</eventclassname>
- <eventname>rename</eventname>
- <listenerclassname>wcf\system\event\listener\ConversationUserActionRenameListener</listenerclassname>
- <environment>admin</environment>
- </eventlistener>
- </import>
-</data>
--- /dev/null
+<?php
+use wcf\data\user\group\UserGroup;
+use wcf\system\WCF;
+
+/**
+ * @author Matthias Schmidt
+ * @copyright 2001-2015 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ */
+// set default mod permissions
+$group = new UserGroup(5);
+if ($group->groupID) {
+ $sql = "REPLACE INTO wcf".WCF_N."_user_group_option_value
+ (groupID, optionID, optionValue)
+ SELECT 5, optionID, 1
+ FROM wcf".WCF_N."_user_group_option
+ WHERE optionName LIKE 'mod.conversation.%'";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute();
+}
+
+$group = new UserGroup(6);
+if ($group->groupID) {
+ $sql = "REPLACE INTO wcf".WCF_N."_user_group_option_value
+ (groupID, optionID, optionValue)
+ SELECT 6, optionID, 1
+ FROM wcf".WCF_N."_user_group_option
+ WHERE optionName LIKE 'mod.conversation.%'";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute();
+}
+++ /dev/null
-<?php
-use wcf\data\user\group\UserGroup;
-use wcf\system\WCF;
-
-/**
- * @author Matthias Schmidt
- * @copyright 2001-2015 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- */
-// set default mod permissions
-$group = new UserGroup(5);
-if ($group->groupID) {
- $sql = "REPLACE INTO wcf".WCF_N."_user_group_option_value
- (groupID, optionID, optionValue)
- SELECT 5, optionID, 1
- FROM wcf".WCF_N."_user_group_option
- WHERE optionName LIKE 'mod.conversation.%'";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute();
-}
-
-$group = new UserGroup(6);
-if ($group->groupID) {
- $sql = "REPLACE INTO wcf".WCF_N."_user_group_option_value
- (groupID, optionID, optionValue)
- SELECT 6, optionID, 1
- FROM wcf".WCF_N."_user_group_option
- WHERE optionName LIKE 'mod.conversation.%'";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute();
-}
switch (key) {
case 'close':
- $('<li><span class="icon icon16 icon-lock jsTooltip jsIconLock" title="' + WCF.Language.get('wcf.global.state.closed') + '" /></li>').prependTo($conversation.find('.statusIcons'));
+ $('<li><span class="icon icon16 fa-lock jsTooltip jsIconLock" title="' + WCF.Language.get('wcf.global.state.closed') + '" /></li>').prependTo($conversation.find('.statusIcons'));
this._attributes[conversationID].isClosed = 1;
break;
// insert labels
for (var $i = 0, $length = data.length; $i < $length; $i++) {
var $label = $labels[data[$i]];
- $('<li><a href="' + $label.url + '" class="badge label' + ($label.cssClassName ? " " + $label.cssClassName : "") + '">' + WCF.String.escapeHTML($label.label) + '</a> </li>').appendTo($labelList);
+ $('<li><a href="' + $label.url + '" class="badge label' + ($label.cssClassName ? " " + $label.cssClassName : "") + '">' + WCF.String.escapeHTML($label.label) + '</a></li>').appendTo($labelList);
}
}
break;
return;
}
+ var container = $('.contentHeaderTitle > .contentHeaderMetaData');
+
switch (key) {
case 'close':
- $('<span class="icon icon16 icon-lock jsTooltip jsIconLock" title="' + WCF.Language.get('wcf.global.state.closed') + '" />').appendTo($('#content > header > h1'));
+ $('<li><span class="icon icon16 fa-lock jsIconLock" /> ' + WCF.Language.get('wcf.global.state.closed') + '</li>').appendTo(container);
this._attributes[conversationID].isClosed = 1;
break;
case 'labelIDs':
- var $container = $('.conversationHeadline');
+ var labelList = container.find('.labelList');
if (!data.length) {
- // remove all labels
- $container.find('ul.labelList').remove();
+ labelList.parent().remove();
}
else {
- var $labelList = $container.find('ul.labelList');
- if (!$labelList.length) {
- $labelList = $('<ul class="labelList" />').appendTo($container);
- }
+ var availableLabels = this.getAvailableLabels();
- // remove existing labels
- $labelList.empty();
+ if (!labelList.length) {
+ labelList = $('<li><span class="icon icon16 fa-tags"></span> <ul class="labelList"></ul></li>').prependTo(container);
+ labelList = labelList.children('ul');
+ }
- // add new labels
- for (var $i = 0, $length = data.length; $i < $length; $i++) {
- var $labelID = data[$i];
-
- for (var $j = 0, $innerLength = this.getAvailableLabels().length; $j < $innerLength; $j++) {
- var $label = this.getAvailableLabels()[$j];
- if ($label.labelID == $labelID) {
- $('<li><span class="label badge' + ($label.cssClassName ? " " + $label.cssClassName : "") + '">' + $label.label + '</span> </li>').appendTo($labelList);
-
- break;
+ var html = '';
+ data.forEach(function(labelId) {
+ availableLabels.forEach(function(label) {
+ if (label.labelID == labelId) {
+ html += '<li><span class="label badge' + (label.cssClassName ? ' ' + label.cssClassName : '') + '">' + label.label + '</span></li>';
}
- }
- }
+ });
+ });
+
+ labelList[0].innerHTML = html;
}
break;
case 'open':
- $('#content > header span.jsIconLock').remove();
+ container.find('.jsIconLock').parent().remove();
this._attributes[conversationID].isClosed = 0;
break;
/**
* Initializes a new WCF.Conversation.Clipboard object.
*
- * @param WCF.Conversation.EditorHandler editorHandler
+ * @param {WCF.Conversation.EditorHandler} editorHandler
*/
init: function(editorHandler) {
this._editorHandler = editorHandler;
- // bind listener
- $('.jsClipboardEditor').each($.proxy(function(index, container) {
- var $container = $(container);
- var $types = eval($container.data('types'));
- if (WCF.inArray('com.woltlab.wcf.conversation.conversation', $types)) {
- $container.on('clipboardAction', $.proxy(this._execute, this));
- $container.on('clipboardActionResponse', $.proxy(this._evaluateResponse, this));
- return false;
+ WCF.System.Event.addListener('com.woltlab.wcf.clipboard', 'com.woltlab.wcf.conversation.conversation', (function (data) {
+ if (data.responseData === null) {
+ this._execute(data.data.actionName, data.data.parameters);
+ }
+ else {
+ this._evaluateResponse(data.data.actionName, data.responseData);
}
- }, this));
+ }).bind(this));
},
/**
* Handles clipboard actions.
*
- * @param object event
- * @param string type
- * @param string actionName
- * @param object parameters
+ * @param {string} actionName
+ * @param {Object} parameters
*/
- _execute: function(event, type, actionName, parameters) {
- if (type === 'com.woltlab.wcf.conversation.conversation' && actionName === 'com.woltlab.wcf.conversation.conversation.assignLabel') {
+ _execute: function(actionName, parameters) {
+ if (actionName === 'com.woltlab.wcf.conversation.conversation.assignLabel') {
new WCF.Conversation.Label.Editor(this._editorHandler, null, parameters.objectIDs);
}
},
/**
* Evaluates AJAX responses.
*
- * @param object event
- * @param object data
- * @param string type
- * @param string actionName
- * @param object parameters
+ * @param {Object} data
+ * @param {string} actionName
*/
- _evaluateResponse: function(event, data, type, actionName, parameters) {
- if (type !== 'com.woltlab.wcf.conversation.conversation') {
- // ignore unreleated events
- return;
- }
-
+ _evaluateResponse: function(actionName, data) {
switch (actionName) {
case 'com.woltlab.wcf.conversation.conversation.leave':
case 'com.woltlab.wcf.conversation.conversation.leavePermanently':
case 'com.woltlab.wcf.conversation.conversation.close':
case 'com.woltlab.wcf.conversation.conversation.open':
- for (var $conversationID in data.returnValues.conversationData) {
- var $data = data.returnValues.conversationData[$conversationID];
-
- this._editorHandler.update($conversationID, ($data.isClosed ? 'close' : 'open'), $data);
+ //noinspection JSUnresolvedVariable
+ for (var conversationId in data.returnValues.conversationData) {
+ //noinspection JSUnresolvedVariable
+ if (data.returnValues.conversationData.hasOwnProperty(conversationId)) {
+ //noinspection JSUnresolvedVariable
+ var $data = data.returnValues.conversationData[conversationId];
+
+ this._editorHandler.update(conversationId, ($data.isClosed ? 'close' : 'open'), $data);
+ }
}
break;
}
switch (optionName) {
case 'addParticipants':
- new WCF.Conversation.AddParticipants($('#' + elementID).data('conversationID'));
+ require(['WoltLabSuite/Core/Conversation/Ui/Participant/Add'], function(UiParticipantAdd) {
+ new UiParticipantAdd(document.getElementById(elementID).getAttribute('data-conversation-id'));
+ });
break;
case 'assignLabel':
}
});
-/**
- * Provides methods to add new participants.
- *
- * @param integer conversationID
- */
-WCF.Conversation.AddParticipants = Class.extend({
- /**
- * conversation id
- * @var integer
- */
- _conversationID: 0,
-
- /**
- * dialog overlay
- * @var jQuery
- */
- _dialog: null,
-
- /**
- * action proxy
- * @var WCF.Action.Proxy
- */
- _proxy: null,
-
- /**
- * Initializes the WCF.Conversation.AddParticipants class
- *
- * @param integer conversationID
- */
- init: function(conversationID) {
- this._conversationID = conversationID;
-
- this._dialog = $('#conversationAddParticipants');
- if (!this._dialog.length) {
- this._dialog = $('<div id="conversationAddParticipants" />').hide().appendTo(document.body);
- }
-
- this._proxy = new WCF.Action.Proxy({
- autoSend: true,
- data: {
- actionName: 'getAddParticipantsForm',
- className: 'wcf\\data\\conversation\\ConversationAction',
- objectIDs: [ this._conversationID ]
- },
- success: $.proxy(this._success, this)
- });
- },
-
- /**
- * Handles successful AJAX requests.
- *
- * @param object data
- * @param string textStatus
- * @param jQuery jqXHR
- */
- _success: function(data, textStatus, jqXHR) {
- switch (data.returnValues.actionName) {
- case 'addParticipants':
- if (data.returnValues.errorMessage) {
- this._dialog.find('dl.jsAddParticipants').addClass('formError');
- this._dialog.find('dl.jsAddParticipants > dd small.innerError').remove();
- $('<small class="innerError">' + data.returnValues.errorMessage + '</small>').appendTo(this._dialog.find('dl.jsAddParticipants > dd'));
- return;
- }
-
- if (data.returnValues.count) {
- var $notification = new WCF.System.Notification(data.returnValues.successMessage);
- $notification.show();
- }
-
- this._dialog.find('dl.jsAddParticipants').removeClass('formError').find('small.innerError').remove();
- this._dialog.wcfDialog('close');
- break;
-
- case 'getAddParticipantsForm':
- this._renderForm(data);
- break;
- }
- },
-
- /**
- * Renders the 'add participants' form.
- *
- * @param object data
- */
- _renderForm: function(data) {
- this._dialog.html(data.returnValues.template);
- this._dialog.find('#addParticipants').disable().click($.proxy(this._submit, this));
-
- new WCF.Search.User('#participantsInput', null, false, data.returnValues.excludeSearchValues, true);
-
- var $participantsInput = $('#participantsInput');
- $participantsInput.keyup($.proxy(this._toggleSubmitButton, this));
-
- if ($.browser.mozilla && $.browser.touch) {
- $participantsInput.on('input', $.proxy(this._toggleSubmitButton, this));
- }
-
- this._dialog.wcfDialog({
- title: WCF.Language.get('wcf.conversation.edit.addParticipants')
- });
- },
-
- /**
- * Toggles the submit button if the input field contains a/no particiant.
- */
- _toggleSubmitButton: function() {
- var $submitButton = this._dialog.find('#addParticipants');
- if ($.trim($('#participantsInput').val()) === '') {
- $submitButton.disable();
- }
- else {
- $submitButton.enable();
- }
- },
-
- /**
- * Submits the form to add new participants.
- */
- _submit: function() {
- var $participants = $.trim($('#participantsInput').val());
- if ($participants == '') {
- this._dialog.wcfDialog('close');
- }
-
- this._proxy.setOption('data', {
- actionName: 'addParticipants',
- className: 'wcf\\data\\conversation\\ConversationAction',
- objectIDs: [ this._conversationID ],
- parameters: {
- participants: $participants
- }
- });
- this._proxy.sendRequest();
- }
-});
-
/**
* Provides methods to remove participants from conversations.
*
this._deletedLabelID = $('#conversationLabelManagementForm').data('labelID');
}
- }, this));
+ }, this), undefined, undefined, true);
},
/**
this.updateBadge(0);
this._loadData = true;
}).bind(this));
+
+ require(['EventHandler'], (function(EventHandler) {
+ EventHandler.add('com.woltlab.wcf.UserMenuMobile', 'more', (function(data) {
+ if (data.identifier === 'com.woltlab.wcf.conversation') {
+ this.toggle();
+ }
+ }).bind(this));
+ }).bind(this));
},
/**
_initDropdown: function() {
var $dropdown = this._super();
- $('<li><a href="' + this._options.newConversationLink + '" title="' + this._options.newConversation + '" class="jsTooltip"><span class="icon icon16 fa-plus" /></a></li>').appendTo($dropdown.getLinkList());
+ $('<li><a href="' + this._options.newConversationLink + '" title="' + this._options.newConversation + '" class="jsTooltip"><span class="icon icon24 fa-plus" /></a></li>').appendTo($dropdown.getLinkList());
return $dropdown;
},
}
});
-/**
- * Provides an AJAX-based quick reply for conversations.
- */
-WCF.Conversation.QuickReply = WCF.Message.QuickReply.extend({
- /**
- * @see WCF.Message.QuickReply.init()
- */
- init: function(quoteManager) {
- this._super(true, quoteManager);
- },
-
- /**
- * @see WCF.Message.QuickReply._getClassName()
- */
- _getClassName: function() {
- return 'wcf\\data\\conversation\\message\\ConversationMessageAction';
- },
-
- /**
- * @see WCF.Message.QuickReply._getObjectID()
- * @returns
- */
- _getObjectID: function() {
- return this._container.data('conversationID');
- }
-});
-
/**
* Marks one conversation as read.
*/
-WCF.Conversation={},WCF.Conversation.EditorHandler=Class.extend({_attributes:{},_conversations:{},_permissions:{},init:function(availableLabels){this._conversations={};var self=this;$(".conversation").each(function(index,conversation){var $conversation=$(conversation),$conversationID=$conversation.data("conversationID");if(!self._conversations[$conversationID]){self._conversations[$conversationID]=$conversation;var $labelIDs=eval($conversation.data("labelIDs"));self._attributes[$conversationID]={isClosed:$conversation.data("isClosed")?!0:!1,labelIDs:$labelIDs},self._permissions[$conversationID]={canAddParticipants:$conversation.data("canAddParticipants")?!0:!1,canCloseConversation:$conversation.data("canCloseConversation")?!0:!1}}})},getPermission:function(e,a){return void 0===this._permissions[e][a]?!1:this._permissions[e][a]?!0:!1},getValue:function(e,a){switch(a){case"labelIDs":return void 0===this._attributes[e].labelIDs&&(this._attributes[e].labelIDs=[]),this._attributes[e].labelIDs;case"isClosed":return this._attributes[e].isClosed?!0:!1}},countAvailableLabels:function(){return this.getAvailableLabels().length},getAvailableLabels:function(){var e=[];return WCF.Dropdown.getDropdownMenu("conversationLabelFilter").children(".scrollableDropdownMenu").children("li").each(function(a,t){var n=$(t);if(n.hasClass("dropdownDivider"))return!1;var s=n.find("span");e.push({cssClassName:s.data("cssClassName"),labelID:s.data("labelID"),label:s.text()})}),e},update:function(e,a,t){if(!this._conversations[e])return void console.debug("[WCF.Conversation.EditorHandler] Unknown conversation id '"+e+"'");var n=this._conversations[e];switch(a){case"close":$('<li><span class="icon icon16 icon-lock jsTooltip jsIconLock" title="'+WCF.Language.get("wcf.global.state.closed")+'" /></li>').prependTo(n.find(".statusIcons")),this._attributes[e].isClosed=1;break;case"labelIDs":var s={};WCF.Dropdown.getDropdownMenu("conversationLabelFilter").find("li > a > span").each(function(e,a){var t=$(a);s[t.data("labelID")]={cssClassName:t.data("cssClassName"),label:t.text(),url:t.parent().attr("href")}});var i=n.find(".columnSubject > .labelList");if(t.length){i.length||(i=$('<ul class="labelList" />').prependTo(n.find(".columnSubject"))),i.empty();for(var o=0,l=t.length;l>o;o++){var r=s[t[o]];$('<li><a href="'+r.url+'" class="badge label'+(r.cssClassName?" "+r.cssClassName:"")+'">'+WCF.String.escapeHTML(r.label)+"</a> </li>").appendTo(i)}}else i.length&&i.remove();break;case"open":n.find(".statusIcons li").each(function(e,a){var t=$(a);return t.children("span.jsIconLock").length?(t.remove(),!1):void 0}),this._attributes[e].isClosed=0}WCF.Clipboard.reload()}}),WCF.Conversation.EditorHandlerConversation=WCF.Conversation.EditorHandler.extend({_availableLabels:null,init:function(e){this._availableLabels=e||[],this._super()},getAvailableLabels:function(){return this._availableLabels},update:function(e,a,t){if(!this._conversations[e])return void console.debug("[WCF.Conversation.EditorHandler] Unknown conversation id '"+e+"'");switch(a){case"close":$('<span class="icon icon16 icon-lock jsTooltip jsIconLock" title="'+WCF.Language.get("wcf.global.state.closed")+'" />').appendTo($("#content > header > h1")),this._attributes[e].isClosed=1;break;case"labelIDs":var n=$(".conversationHeadline");if(t.length){var s=n.find("ul.labelList");s.length||(s=$('<ul class="labelList" />').appendTo(n)),s.empty();for(var i=0,o=t.length;o>i;i++)for(var l=t[i],r=0,c=this.getAvailableLabels().length;c>r;r++){var d=this.getAvailableLabels()[r];if(d.labelID==l){$('<li><span class="label badge'+(d.cssClassName?" "+d.cssClassName:"")+'">'+d.label+"</span> </li>").appendTo(s);break}}}else n.find("ul.labelList").remove();break;case"open":$("#content > header span.jsIconLock").remove(),this._attributes[e].isClosed=0}}}),WCF.Conversation.Clipboard=Class.extend({_editorHandler:null,init:function(editorHandler){this._editorHandler=editorHandler,$(".jsClipboardEditor").each($.proxy(function(index,container){var $container=$(container),$types=eval($container.data("types"));return WCF.inArray("com.woltlab.wcf.conversation.conversation",$types)?($container.on("clipboardAction",$.proxy(this._execute,this)),$container.on("clipboardActionResponse",$.proxy(this._evaluateResponse,this)),!1):void 0},this))},_execute:function(e,a,t,n){"com.woltlab.wcf.conversation.conversation"===a&&"com.woltlab.wcf.conversation.conversation.assignLabel"===t&&new WCF.Conversation.Label.Editor(this._editorHandler,null,n.objectIDs)},_evaluateResponse:function(e,a,t,n){if("com.woltlab.wcf.conversation.conversation"===t)switch(n){case"com.woltlab.wcf.conversation.conversation.leave":case"com.woltlab.wcf.conversation.conversation.leavePermanently":case"com.woltlab.wcf.conversation.conversation.markAsRead":case"com.woltlab.wcf.conversation.conversation.restore":window.location.reload();break;case"com.woltlab.wcf.conversation.conversation.close":case"com.woltlab.wcf.conversation.conversation.open":for(var s in a.returnValues.conversationData){var i=a.returnValues.conversationData[s];this._editorHandler.update(s,i.isClosed?"close":"open",i)}}}}),WCF.Conversation.InlineEditor=WCF.InlineEditor.extend({_editorHandler:null,_environment:"conversation",_setOptions:function(){this._options=[{label:WCF.Language.get("wcf.conversation.edit.close"),optionName:"close"},{label:WCF.Language.get("wcf.conversation.edit.open"),optionName:"open"},{label:WCF.Language.get("wcf.conversation.edit.assignLabel"),optionName:"assignLabel"},{optionName:"divider"},{label:WCF.Language.get("wcf.conversation.edit.addParticipants"),optionName:"addParticipants"},{label:WCF.Language.get("wcf.conversation.edit.leave"),optionName:"leave"}]},setEditorHandler:function(e,a){this._editorHandler=e,this._environment="list"==a?"list":"conversation"},_getTriggerElement:function(e){return e.find(".jsConversationInlineEditor")},_validate:function(e,a){var t=$("#"+e).data("conversationID");switch(a){case"addParticipants":return this._editorHandler.getPermission(t,"canAddParticipants");case"assignLabel":return this._editorHandler.countAvailableLabels()?!0:!1;case"close":case"open":return this._editorHandler.getPermission(t,"canCloseConversation")?"close"===a?!this._editorHandler.getValue(t,"isClosed"):this._editorHandler.getValue(t,"isClosed"):!1;case"leave":return!0}return!1},_execute:function(e,a){if(!this._validate(e,a))return!1;switch(a){case"addParticipants":new WCF.Conversation.AddParticipants($("#"+e).data("conversationID"));break;case"assignLabel":new WCF.Conversation.Label.Editor(this._editorHandler,e);break;case"close":case"open":this._updateConversation(e,a,{isClosed:"close"===a?1:0});break;case"leave":new WCF.Conversation.Leave([$("#"+e).data("conversationID")],this._environment)}},_updateConversation:function(e,a,t){var n=this._elements[e].data("conversationID");switch(a){case"close":case"open":this._updateData.push({elementID:e,optionName:a,data:t}),this._proxy.setOption("data",{actionName:a,className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[n]}),this._proxy.sendRequest()}},_updateState:function(){for(var e=0,a=this._updateData.length;a>e;e++){var t=this._updateData[e],n=this._elements[t.elementID].data("conversationID");switch(t.optionName){case"close":this._editorHandler.update(n,"close",t.data);break;case"open":this._editorHandler.update(n,"open",t.data)}}}}),WCF.Conversation.Leave=Class.extend({_conversationIDs:[],_dialog:null,_environment:"",_proxy:null,init:function(e,a){this._conversationIDs=e,this._dialog=null,this._environment=a,this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),this._loadDialog()},_loadDialog:function(){this._proxy.setOption("data",{actionName:"getLeaveForm",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:this._conversationIDs}),this._proxy.sendRequest()},_success:function(e){switch(e.returnValues.actionName){case"getLeaveForm":this._showDialog(e);break;case"hideConversation":"conversation"===this._environment?window.location=e.returnValues.redirectURL:window.location.reload()}},_showDialog:function(e){null===this._dialog&&(this._dialog=$("#leaveDialog"),this._dialog.length||(this._dialog=$('<div id="leaveDialog" />').hide().appendTo(document.body))),this._dialog.html(e.returnValues.template),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.leave.title")}),this._dialog.wcfDialog("render"),this._dialog.find("#hideConversation").click($.proxy(this._click,this))},_click:function(){var e=this._dialog.find("input[type=radio]:checked");1===e.length&&(this._proxy.setOption("data",{actionName:"hideConversation",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:this._conversationIDs,parameters:{hideConversation:e.val()}}),this._proxy.sendRequest())}}),WCF.Conversation.AddParticipants=Class.extend({_conversationID:0,_dialog:null,_proxy:null,init:function(e){this._conversationID=e,this._dialog=$("#conversationAddParticipants"),this._dialog.length||(this._dialog=$('<div id="conversationAddParticipants" />').hide().appendTo(document.body)),this._proxy=new WCF.Action.Proxy({autoSend:!0,data:{actionName:"getAddParticipantsForm",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[this._conversationID]},success:$.proxy(this._success,this)})},_success:function(e){switch(e.returnValues.actionName){case"addParticipants":if(e.returnValues.errorMessage)return this._dialog.find("dl.jsAddParticipants").addClass("formError"),this._dialog.find("dl.jsAddParticipants > dd small.innerError").remove(),void $('<small class="innerError">'+e.returnValues.errorMessage+"</small>").appendTo(this._dialog.find("dl.jsAddParticipants > dd"));if(e.returnValues.count){var a=new WCF.System.Notification(e.returnValues.successMessage);a.show()}this._dialog.find("dl.jsAddParticipants").removeClass("formError").find("small.innerError").remove(),this._dialog.wcfDialog("close");break;case"getAddParticipantsForm":this._renderForm(e)}},_renderForm:function(e){this._dialog.html(e.returnValues.template),this._dialog.find("#addParticipants").disable().click($.proxy(this._submit,this)),new WCF.Search.User("#participantsInput",null,!1,e.returnValues.excludeSearchValues,!0);var a=$("#participantsInput");a.keyup($.proxy(this._toggleSubmitButton,this)),$.browser.mozilla&&$.browser.touch&&a.on("input",$.proxy(this._toggleSubmitButton,this)),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.edit.addParticipants")})},_toggleSubmitButton:function(){var e=this._dialog.find("#addParticipants");""===$.trim($("#participantsInput").val())?e.disable():e.enable()},_submit:function(){var e=$.trim($("#participantsInput").val());""==e&&this._dialog.wcfDialog("close"),this._proxy.setOption("data",{actionName:"addParticipants",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[this._conversationID],parameters:{participants:e}}),this._proxy.sendRequest()}}),WCF.Conversation.RemoveParticipant=WCF.Action.Delete.extend({_conversationID:0,init:function(e){this._conversationID=e,this._super("wcf\\data\\conversation\\ConversationAction",".jsParticipant")},_sendRequest:function(e){this.proxy.setOption("data",{actionName:"removeParticipant",className:this._className,objectIDs:[this._conversationID],parameters:{userID:$(e).data("objectID")}}),this.proxy.sendRequest()},_success:function(e){var a=e.returnValues.userID;for(var t in this._containers){var n=$("#"+this._containers[t]);n.find(".jsDeleteButton").data("objectID")==a&&(n.find(".userLink").addClass("conversationLeft"),n.find(".jsDeleteButton").remove())}}}),WCF.Conversation.Label={},WCF.Conversation.Label.Editor=Class.extend({_conversationIDs:0,_dialog:null,_editorHandler:null,_notification:null,_proxy:null,init:function(e,a,t){this._conversationIDs=a?[$("#"+a).data("conversationID")]:t,this._dialog=null,this._editorHandler=e,this._notification=new WCF.System.Notification(WCF.Language.get("wcf.global.success.edit")),this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),this._loadDialog()},_loadDialog:function(){this._proxy.setOption("data",{actionName:"getLabelForm",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",parameters:{conversationIDs:this._conversationIDs}}),this._proxy.sendRequest()},_success:function(e){switch(e.returnValues.actionName){case"assignLabel":this._assignLabels(e);break;case"getLabelForm":this._renderDialog(e)}},_renderDialog:function(e){null===this._dialog&&(this._dialog=$("#conversationLabelForm"),this._dialog.length||(this._dialog=$('<div id="conversationLabelForm" />').hide().appendTo(document.body))),this._dialog.html(e.returnValues.template),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.label.assignLabels")}),this._dialog.wcfDialog("render"),$("#assignLabels").click($.proxy(this._save,this))},_save:function(){var e=[];this._dialog.find("input").each(function(a,t){var n=$(t);n.is(":checked")&&e.push(n.data("labelID"))}),this._proxy.setOption("data",{actionName:"assignLabel",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",parameters:{conversationIDs:this._conversationIDs,labelIDs:e}}),this._proxy.sendRequest()},_assignLabels:function(e){for(var a=0,t=this._conversationIDs.length;t>a;a++)this._editorHandler.update(this._conversationIDs[a],"labelIDs",e.returnValues.labelIDs);this._dialog.wcfDialog("close"),this._notification.show()}}),WCF.Conversation.Label.Manager=Class.extend({_deletedLabelID:0,_dialog:null,_labels:null,_link:"",_notification:"",_proxy:null,_maxLabels:0,_labelCount:0,init:function(e){this._deletedLabelID=0,this._maxLabels=0,this._labelCount=0,this._link=e,this._labels=WCF.Dropdown.getDropdownMenu("conversationLabelFilter").children(".scrollableDropdownMenu"),$("#manageLabel").click($.proxy(this._click,this)),this._notification=new WCF.System.Notification(WCF.Language.get("wcf.conversation.label.management.addLabel.success")),this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)})},_click:function(){this._proxy.setOption("data",{actionName:"getLabelManagement",className:"wcf\\data\\conversation\\ConversationAction"}),this._proxy.sendRequest()},_success:function(e){if(null===this._dialog&&(this._dialog=$('<div id="labelManagement" />').hide().appendTo(document.body)),e.returnValues&&e.returnValues.actionName)switch(e.returnValues.actionName){case"add":this._insertLabel(e);break;case"getLabelManagement":this._maxLabels=parseInt(e.returnValues.maxLabels),this._labelCount=parseInt(e.returnValues.labelCount),this._dialog.empty().html(e.returnValues.template),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.label.management")}),this._dialog.wcfDialog("render"),this._bindListener()}else if(this._deletedLabelID){var a=new RegExp("(\\?|&)labelID="+this._deletedLabelID);window.location=window.location.toString().replace(a,"")}else window.location.reload()},_insertLabel:function(e){var a=$('<li><a href="'+this._link+"&labelID="+e.returnValues.labelID+'"><span class="badge label'+(e.returnValues.cssClassName?" "+e.returnValues.cssClassName:"")+'">'+e.returnValues.label+"</span></a></li>");a.find("a > span").data("labelID",e.returnValues.labelID).data("cssClassName",e.returnValues.cssClassName),this._labels.append(a),this._notification.show(),this._labelCount++,this._labelCount>=this._maxLabels&&$("#conversationLabelManagementForm").hide()},_bindListener:function(){$("#labelName").on("keyup keydown keypress",$.proxy(this._updateLabels,this)),$.browser.mozilla&&$.browser.touch&&$("#labelName").on("input",$.proxy(this._updateLabels,this)),this._labelCount>=this._maxLabels&&($("#conversationLabelManagementForm").hide(),this._dialog.wcfDialog("render")),$("#addLabel").disable().click($.proxy(this._addLabel,this)),$("#editLabel").disable(),this._dialog.find(".conversationLabelList a.label").click($.proxy(this._edit,this))},_edit:function(e){this._labelCount>=this._maxLabels&&($("#conversationLabelManagementForm").show(),this._dialog.wcfDialog("render"));var a=$(e.currentTarget),t=WCF.Language.get("wcf.conversation.label.management.editLabel").replace(/#labelName#/,WCF.String.escapeHTML(a.text()));$("#conversationLabelManagementForm").data("labelID",a.data("labelID")).children("legend").html(t),$("#labelName").val(a.text()).trigger("keyup");var n=a.data("cssClassName");$("#labelManagementList input").each(function(e,a){var t=$(a);t.val()==n&&t.attr("checked","checked")}),$("#addLabel").hide(),$("#editLabel").show().click($.proxy(this._editLabel,this)),$("#deleteLabel").show().click($.proxy(this._deleteLabel,this))},_editLabel:function(){this._proxy.setOption("data",{actionName:"update",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",objectIDs:[$("#conversationLabelManagementForm").data("labelID")],parameters:{data:{cssClassName:$("#labelManagementList input:checked").val(),label:$("#labelName").val()}}}),this._proxy.sendRequest()},_deleteLabel:function(){var e=WCF.Language.get("wcf.conversation.label.management.deleteLabel.confirmMessage").replace(/#labelName#/,$("#labelName").val());WCF.System.Confirmation.show(e,$.proxy(function(e){"confirm"===e&&(this._proxy.setOption("data",{actionName:"delete",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",objectIDs:[$("#conversationLabelManagementForm").data("labelID")]}),this._proxy.sendRequest(),this._deletedLabelID=$("#conversationLabelManagementForm").data("labelID"))},this))},_updateLabels:function(){var e=$.trim($("#labelName").val());e?$("#addLabel, #editLabel").enable():($("#addLabel, #editLabel").disable(),e=WCF.Language.get("wcf.conversation.label.placeholder")),$("#labelManagementList").find("span.label").text(e)},_addLabel:function(){var e=$("#labelName").val(),a=$("#labelManagementList input:checked").val();this._proxy.setOption("data",{actionName:"add",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",parameters:{data:{cssClassName:a,labelName:e}}}),this._proxy.sendRequest(),this._dialog.wcfDialog("close")}}),WCF.Conversation.Preview=WCF.Popover.extend({_proxy:null,init:function(){this._super(".conversationLink"),this._proxy=new WCF.Action.Proxy({showLoadingOverlay:!1}),WCF.DOMNodeInsertedHandler.addCallback("WCF.Conversation.Preview",$.proxy(this._initContainers,this))},_loadContent:function(){var e=$("#"+this._activeElementID);this._proxy.setOption("data",{actionName:"getMessagePreview",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[e.data("conversationID")]});var a=this._activeElementID,t=this;this._proxy.setOption("success",function(e){t._insertContent(a,e.returnValues.template,!0)}),this._proxy.sendRequest()}}),WCF.User.Panel.Conversation=WCF.User.Panel.Abstract.extend({init:function(e){e.enableMarkAsRead=!0,this._super($("#unreadConversations"),"unreadConversations",e),WCF.System.Event.addListener("com.woltlab.wcf.conversation.userPanel","reset",function(){this.resetItems(),this.updateBadge(0),this._loadData=!0}.bind(this))},_initDropdown:function(){var e=this._super();return $('<li><a href="'+this._options.newConversationLink+'" title="'+this._options.newConversation+'" class="jsTooltip"><span class="icon icon16 fa-plus" /></a></li>').appendTo(e.getLinkList()),e},_load:function(){this._proxy.setOption("data",{actionName:"getMixedConversationList",className:"wcf\\data\\conversation\\ConversationAction"}),this._proxy.sendRequest()},_markAsRead:function(e,a){this._proxy.setOption("data",{actionName:"markAsRead",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[a]}),this._proxy.sendRequest()},_markAllAsRead:function(){this._proxy.setOption("data",{actionName:"markAllAsRead",className:"wcf\\data\\conversation\\ConversationAction"}),this._proxy.sendRequest()}}),WCF.Conversation.QuickReply=WCF.Message.QuickReply.extend({init:function(e){this._super(!0,e)},_getClassName:function(){return"wcf\\data\\conversation\\message\\ConversationMessageAction"},_getObjectID:function(){return this._container.data("conversationID")}}),WCF.Conversation.MarkAsRead=Class.extend({_proxy:null,init:function(){this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),$(document).on("dblclick",".conversationList .new .columnAvatar",$.proxy(this._dblclick,this))},_dblclick:function(e){this._proxy.setOption("data",{actionName:"markAsRead",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[$(e.currentTarget).parents("tr:eq(0)").data("conversationID")]}),this._proxy.sendRequest()},_success:function(e){$(".conversationList .new").each(function(a,t){var n=$(t);WCF.inArray(n.data("conversationID"),e.objectIDs)&&(n.removeClass("new"),n.find(".firstNewPost").parent().remove(),n.find(".columnAvatar").off("dblclick"))})}}),WCF.Conversation.MarkAllAsRead=Class.extend({_proxy:null,init:function(){this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),$(".markAllAsReadButton").click($.proxy(this._click,this))},_click:function(e){e.preventDefault(),this._proxy.setOption("data",{actionName:"markAllAsRead",className:"wcf\\data\\conversation\\ConversationAction"}),this._proxy.sendRequest()},_success:function(){WCF.System.Event.fireEvent("com.woltlab.wcf.conversation.userPanel","reset");var e=$(".conversationList");e.find(".new").removeClass("new"),e.find(".columnAvatar").off("dblclick")}}),WCF.Conversation.Message={},WCF.Conversation.Message.InlineEditor=WCF.Message.InlineEditor.extend({init:function(e,a){this._super(e,!0,a)},_getClassName:function(){return"wcf\\data\\conversation\\message\\ConversationMessageAction"}}),WCF.Conversation.Message.QuoteHandler=WCF.Message.Quote.Handler.extend({init:function(e){this._super(e,"wcf\\data\\conversation\\message\\ConversationMessageAction","com.woltlab.wcf.conversation.message",".message",".messageBody",".messageBody > div > div.messageText",!0)}});
\ No newline at end of file
+WCF.Conversation={},WCF.Conversation.EditorHandler=Class.extend({_attributes:{},_conversations:{},_permissions:{},init:function(availableLabels){this._conversations={};var self=this;$(".conversation").each(function(index,conversation){var $conversation=$(conversation),$conversationID=$conversation.data("conversationID");if(!self._conversations[$conversationID]){self._conversations[$conversationID]=$conversation;var $labelIDs=eval($conversation.data("labelIDs"));self._attributes[$conversationID]={isClosed:$conversation.data("isClosed")?!0:!1,labelIDs:$labelIDs},self._permissions[$conversationID]={canAddParticipants:$conversation.data("canAddParticipants")?!0:!1,canCloseConversation:$conversation.data("canCloseConversation")?!0:!1}}})},getPermission:function(e,a){return void 0===this._permissions[e][a]?!1:this._permissions[e][a]?!0:!1},getValue:function(e,a){switch(a){case"labelIDs":return void 0===this._attributes[e].labelIDs&&(this._attributes[e].labelIDs=[]),this._attributes[e].labelIDs;case"isClosed":return this._attributes[e].isClosed?!0:!1}},countAvailableLabels:function(){return this.getAvailableLabels().length},getAvailableLabels:function(){var e=[];return WCF.Dropdown.getDropdownMenu("conversationLabelFilter").children(".scrollableDropdownMenu").children("li").each(function(a,t){var n=$(t);if(n.hasClass("dropdownDivider"))return!1;var s=n.find("span");e.push({cssClassName:s.data("cssClassName"),labelID:s.data("labelID"),label:s.text()})}),e},update:function(e,a,t){if(!this._conversations[e])return void console.debug("[WCF.Conversation.EditorHandler] Unknown conversation id '"+e+"'");var n=this._conversations[e];switch(a){case"close":$('<li><span class="icon icon16 fa-lock jsTooltip jsIconLock" title="'+WCF.Language.get("wcf.global.state.closed")+'" /></li>').prependTo(n.find(".statusIcons")),this._attributes[e].isClosed=1;break;case"labelIDs":var s={};WCF.Dropdown.getDropdownMenu("conversationLabelFilter").find("li > a > span").each(function(e,a){var t=$(a);s[t.data("labelID")]={cssClassName:t.data("cssClassName"),label:t.text(),url:t.parent().attr("href")}});var i=n.find(".columnSubject > .labelList");if(t.length){i.length||(i=$('<ul class="labelList" />').prependTo(n.find(".columnSubject"))),i.empty();for(var o=0,l=t.length;l>o;o++){var r=s[t[o]];$('<li><a href="'+r.url+'" class="badge label'+(r.cssClassName?" "+r.cssClassName:"")+'">'+WCF.String.escapeHTML(r.label)+"</a></li>").appendTo(i)}}else i.length&&i.remove();break;case"open":n.find(".statusIcons li").each(function(e,a){var t=$(a);return t.children("span.jsIconLock").length?(t.remove(),!1):void 0}),this._attributes[e].isClosed=0}WCF.Clipboard.reload()}}),WCF.Conversation.EditorHandlerConversation=WCF.Conversation.EditorHandler.extend({_availableLabels:null,init:function(e){this._availableLabels=e||[],this._super()},getAvailableLabels:function(){return this._availableLabels},update:function(e,a,t){if(!this._conversations[e])return void console.debug("[WCF.Conversation.EditorHandler] Unknown conversation id '"+e+"'");var n=$(".contentHeaderTitle > .contentHeaderMetaData");switch(a){case"close":$('<li><span class="icon icon16 fa-lock jsIconLock" /> '+WCF.Language.get("wcf.global.state.closed")+"</li>").appendTo(n),this._attributes[e].isClosed=1;break;case"labelIDs":var s=n.find(".labelList");if(t.length){var i=this.getAvailableLabels();s.length||(s=$('<li><span class="icon icon16 fa-tags"></span> <ul class="labelList"></ul></li>').prependTo(n),s=s.children("ul"));var o="";t.forEach(function(e){i.forEach(function(a){a.labelID==e&&(o+='<li><span class="label badge'+(a.cssClassName?" "+a.cssClassName:"")+'">'+a.label+"</span></li>")})}),s[0].innerHTML=o}else s.parent().remove();break;case"open":n.find(".jsIconLock").parent().remove(),this._attributes[e].isClosed=0}}}),WCF.Conversation.Clipboard=Class.extend({_editorHandler:null,init:function(e){this._editorHandler=e,WCF.System.Event.addListener("com.woltlab.wcf.clipboard","com.woltlab.wcf.conversation.conversation",function(e){null===e.responseData?this._execute(e.data.actionName,e.data.parameters):this._evaluateResponse(e.data.actionName,e.responseData)}.bind(this))},_execute:function(e,a){"com.woltlab.wcf.conversation.conversation.assignLabel"===e&&new WCF.Conversation.Label.Editor(this._editorHandler,null,a.objectIDs)},_evaluateResponse:function(e,a){switch(e){case"com.woltlab.wcf.conversation.conversation.leave":case"com.woltlab.wcf.conversation.conversation.leavePermanently":case"com.woltlab.wcf.conversation.conversation.markAsRead":case"com.woltlab.wcf.conversation.conversation.restore":window.location.reload();break;case"com.woltlab.wcf.conversation.conversation.close":case"com.woltlab.wcf.conversation.conversation.open":for(var t in a.returnValues.conversationData)if(a.returnValues.conversationData.hasOwnProperty(t)){var n=a.returnValues.conversationData[t];this._editorHandler.update(t,n.isClosed?"close":"open",n)}}}}),WCF.Conversation.InlineEditor=WCF.InlineEditor.extend({_editorHandler:null,_environment:"conversation",_setOptions:function(){this._options=[{label:WCF.Language.get("wcf.conversation.edit.close"),optionName:"close"},{label:WCF.Language.get("wcf.conversation.edit.open"),optionName:"open"},{label:WCF.Language.get("wcf.conversation.edit.assignLabel"),optionName:"assignLabel"},{optionName:"divider"},{label:WCF.Language.get("wcf.conversation.edit.addParticipants"),optionName:"addParticipants"},{label:WCF.Language.get("wcf.conversation.edit.leave"),optionName:"leave"}]},setEditorHandler:function(e,a){this._editorHandler=e,this._environment="list"==a?"list":"conversation"},_getTriggerElement:function(e){return e.find(".jsConversationInlineEditor")},_validate:function(e,a){var t=$("#"+e).data("conversationID");switch(a){case"addParticipants":return this._editorHandler.getPermission(t,"canAddParticipants");case"assignLabel":return this._editorHandler.countAvailableLabels()?!0:!1;case"close":case"open":return this._editorHandler.getPermission(t,"canCloseConversation")?"close"===a?!this._editorHandler.getValue(t,"isClosed"):this._editorHandler.getValue(t,"isClosed"):!1;case"leave":return!0}return!1},_execute:function(e,a){if(!this._validate(e,a))return!1;switch(a){case"addParticipants":require(["WoltLabSuite/Core/Conversation/Ui/Participant/Add"],function(a){new a(document.getElementById(e).getAttribute("data-conversation-id"))});break;case"assignLabel":new WCF.Conversation.Label.Editor(this._editorHandler,e);break;case"close":case"open":this._updateConversation(e,a,{isClosed:"close"===a?1:0});break;case"leave":new WCF.Conversation.Leave([$("#"+e).data("conversationID")],this._environment)}},_updateConversation:function(e,a,t){var n=this._elements[e].data("conversationID");switch(a){case"close":case"open":this._updateData.push({elementID:e,optionName:a,data:t}),this._proxy.setOption("data",{actionName:a,className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[n]}),this._proxy.sendRequest()}},_updateState:function(){for(var e=0,a=this._updateData.length;a>e;e++){var t=this._updateData[e],n=this._elements[t.elementID].data("conversationID");switch(t.optionName){case"close":this._editorHandler.update(n,"close",t.data);break;case"open":this._editorHandler.update(n,"open",t.data)}}}}),WCF.Conversation.Leave=Class.extend({_conversationIDs:[],_dialog:null,_environment:"",_proxy:null,init:function(e,a){this._conversationIDs=e,this._dialog=null,this._environment=a,this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),this._loadDialog()},_loadDialog:function(){this._proxy.setOption("data",{actionName:"getLeaveForm",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:this._conversationIDs}),this._proxy.sendRequest()},_success:function(e){switch(e.returnValues.actionName){case"getLeaveForm":this._showDialog(e);break;case"hideConversation":"conversation"===this._environment?window.location=e.returnValues.redirectURL:window.location.reload()}},_showDialog:function(e){null===this._dialog&&(this._dialog=$("#leaveDialog"),this._dialog.length||(this._dialog=$('<div id="leaveDialog" />').hide().appendTo(document.body))),this._dialog.html(e.returnValues.template),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.leave.title")}),this._dialog.wcfDialog("render"),this._dialog.find("#hideConversation").click($.proxy(this._click,this))},_click:function(){var e=this._dialog.find("input[type=radio]:checked");1===e.length&&(this._proxy.setOption("data",{actionName:"hideConversation",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:this._conversationIDs,parameters:{hideConversation:e.val()}}),this._proxy.sendRequest())}}),WCF.Conversation.RemoveParticipant=WCF.Action.Delete.extend({_conversationID:0,init:function(e){this._conversationID=e,this._super("wcf\\data\\conversation\\ConversationAction",".jsParticipant")},_sendRequest:function(e){this.proxy.setOption("data",{actionName:"removeParticipant",className:this._className,objectIDs:[this._conversationID],parameters:{userID:$(e).data("objectID")}}),this.proxy.sendRequest()},_success:function(e){var a=e.returnValues.userID;for(var t in this._containers){var n=$("#"+this._containers[t]);n.find(".jsDeleteButton").data("objectID")==a&&(n.find(".userLink").addClass("conversationLeft"),n.find(".jsDeleteButton").remove())}}}),WCF.Conversation.Label={},WCF.Conversation.Label.Editor=Class.extend({_conversationIDs:0,_dialog:null,_editorHandler:null,_notification:null,_proxy:null,init:function(e,a,t){this._conversationIDs=a?[$("#"+a).data("conversationID")]:t,this._dialog=null,this._editorHandler=e,this._notification=new WCF.System.Notification(WCF.Language.get("wcf.global.success.edit")),this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),this._loadDialog()},_loadDialog:function(){this._proxy.setOption("data",{actionName:"getLabelForm",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",parameters:{conversationIDs:this._conversationIDs}}),this._proxy.sendRequest()},_success:function(e){switch(e.returnValues.actionName){case"assignLabel":this._assignLabels(e);break;case"getLabelForm":this._renderDialog(e)}},_renderDialog:function(e){null===this._dialog&&(this._dialog=$("#conversationLabelForm"),this._dialog.length||(this._dialog=$('<div id="conversationLabelForm" />').hide().appendTo(document.body))),this._dialog.html(e.returnValues.template),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.label.assignLabels")}),this._dialog.wcfDialog("render"),$("#assignLabels").click($.proxy(this._save,this))},_save:function(){var e=[];this._dialog.find("input").each(function(a,t){var n=$(t);n.is(":checked")&&e.push(n.data("labelID"))}),this._proxy.setOption("data",{actionName:"assignLabel",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",parameters:{conversationIDs:this._conversationIDs,labelIDs:e}}),this._proxy.sendRequest()},_assignLabels:function(e){for(var a=0,t=this._conversationIDs.length;t>a;a++)this._editorHandler.update(this._conversationIDs[a],"labelIDs",e.returnValues.labelIDs);this._dialog.wcfDialog("close"),this._notification.show()}}),WCF.Conversation.Label.Manager=Class.extend({_deletedLabelID:0,_dialog:null,_labels:null,_link:"",_notification:"",_proxy:null,_maxLabels:0,_labelCount:0,init:function(e){this._deletedLabelID=0,this._maxLabels=0,this._labelCount=0,this._link=e,this._labels=WCF.Dropdown.getDropdownMenu("conversationLabelFilter").children(".scrollableDropdownMenu"),$("#manageLabel").click($.proxy(this._click,this)),this._notification=new WCF.System.Notification(WCF.Language.get("wcf.conversation.label.management.addLabel.success")),this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)})},_click:function(){this._proxy.setOption("data",{actionName:"getLabelManagement",className:"wcf\\data\\conversation\\ConversationAction"}),this._proxy.sendRequest()},_success:function(e){if(null===this._dialog&&(this._dialog=$('<div id="labelManagement" />').hide().appendTo(document.body)),e.returnValues&&e.returnValues.actionName)switch(e.returnValues.actionName){case"add":this._insertLabel(e);break;case"getLabelManagement":this._maxLabels=parseInt(e.returnValues.maxLabels),this._labelCount=parseInt(e.returnValues.labelCount),this._dialog.empty().html(e.returnValues.template),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.label.management")}),this._dialog.wcfDialog("render"),this._bindListener()}else if(this._deletedLabelID){var a=new RegExp("(\\?|&)labelID="+this._deletedLabelID);window.location=window.location.toString().replace(a,"")}else window.location.reload()},_insertLabel:function(e){var a=$('<li><a href="'+this._link+"&labelID="+e.returnValues.labelID+'"><span class="badge label'+(e.returnValues.cssClassName?" "+e.returnValues.cssClassName:"")+'">'+e.returnValues.label+"</span></a></li>");a.find("a > span").data("labelID",e.returnValues.labelID).data("cssClassName",e.returnValues.cssClassName),this._labels.append(a),this._notification.show(),this._labelCount++,this._labelCount>=this._maxLabels&&$("#conversationLabelManagementForm").hide()},_bindListener:function(){$("#labelName").on("keyup keydown keypress",$.proxy(this._updateLabels,this)),$.browser.mozilla&&$.browser.touch&&$("#labelName").on("input",$.proxy(this._updateLabels,this)),this._labelCount>=this._maxLabels&&($("#conversationLabelManagementForm").hide(),this._dialog.wcfDialog("render")),$("#addLabel").disable().click($.proxy(this._addLabel,this)),$("#editLabel").disable(),this._dialog.find(".conversationLabelList a.label").click($.proxy(this._edit,this))},_edit:function(e){this._labelCount>=this._maxLabels&&($("#conversationLabelManagementForm").show(),this._dialog.wcfDialog("render"));var a=$(e.currentTarget),t=WCF.Language.get("wcf.conversation.label.management.editLabel").replace(/#labelName#/,WCF.String.escapeHTML(a.text()));$("#conversationLabelManagementForm").data("labelID",a.data("labelID")).children("legend").html(t),$("#labelName").val(a.text()).trigger("keyup");var n=a.data("cssClassName");$("#labelManagementList input").each(function(e,a){var t=$(a);t.val()==n&&t.attr("checked","checked")}),$("#addLabel").hide(),$("#editLabel").show().click($.proxy(this._editLabel,this)),$("#deleteLabel").show().click($.proxy(this._deleteLabel,this))},_editLabel:function(){this._proxy.setOption("data",{actionName:"update",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",objectIDs:[$("#conversationLabelManagementForm").data("labelID")],parameters:{data:{cssClassName:$("#labelManagementList input:checked").val(),label:$("#labelName").val()}}}),this._proxy.sendRequest()},_deleteLabel:function(){var e=WCF.Language.get("wcf.conversation.label.management.deleteLabel.confirmMessage").replace(/#labelName#/,$("#labelName").val());WCF.System.Confirmation.show(e,$.proxy(function(e){"confirm"===e&&(this._proxy.setOption("data",{actionName:"delete",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",objectIDs:[$("#conversationLabelManagementForm").data("labelID")]}),this._proxy.sendRequest(),this._deletedLabelID=$("#conversationLabelManagementForm").data("labelID"))},this),void 0,void 0,!0)},_updateLabels:function(){var e=$.trim($("#labelName").val());e?$("#addLabel, #editLabel").enable():($("#addLabel, #editLabel").disable(),e=WCF.Language.get("wcf.conversation.label.placeholder")),$("#labelManagementList").find("span.label").text(e)},_addLabel:function(){var e=$("#labelName").val(),a=$("#labelManagementList input:checked").val();this._proxy.setOption("data",{actionName:"add",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",parameters:{data:{cssClassName:a,labelName:e}}}),this._proxy.sendRequest(),this._dialog.wcfDialog("close")}}),WCF.Conversation.Preview=WCF.Popover.extend({_proxy:null,init:function(){this._super(".conversationLink"),this._proxy=new WCF.Action.Proxy({showLoadingOverlay:!1}),WCF.DOMNodeInsertedHandler.addCallback("WCF.Conversation.Preview",$.proxy(this._initContainers,this))},_loadContent:function(){var e=$("#"+this._activeElementID);this._proxy.setOption("data",{actionName:"getMessagePreview",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[e.data("conversationID")]});var a=this._activeElementID,t=this;this._proxy.setOption("success",function(e){t._insertContent(a,e.returnValues.template,!0)}),this._proxy.sendRequest()}}),WCF.User.Panel.Conversation=WCF.User.Panel.Abstract.extend({init:function(e){e.enableMarkAsRead=!0,this._super($("#unreadConversations"),"unreadConversations",e),WCF.System.Event.addListener("com.woltlab.wcf.conversation.userPanel","reset",function(){this.resetItems(),this.updateBadge(0),this._loadData=!0}.bind(this)),require(["EventHandler"],function(e){e.add("com.woltlab.wcf.UserMenuMobile","more",function(e){"com.woltlab.wcf.conversation"===e.identifier&&this.toggle()}.bind(this))}.bind(this))},_initDropdown:function(){var e=this._super();return $('<li><a href="'+this._options.newConversationLink+'" title="'+this._options.newConversation+'" class="jsTooltip"><span class="icon icon24 fa-plus" /></a></li>').appendTo(e.getLinkList()),e},_load:function(){this._proxy.setOption("data",{actionName:"getMixedConversationList",className:"wcf\\data\\conversation\\ConversationAction"}),this._proxy.sendRequest()},_markAsRead:function(e,a){this._proxy.setOption("data",{actionName:"markAsRead",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[a]}),this._proxy.sendRequest()},_markAllAsRead:function(){this._proxy.setOption("data",{actionName:"markAllAsRead",className:"wcf\\data\\conversation\\ConversationAction"}),this._proxy.sendRequest()}}),WCF.Conversation.MarkAsRead=Class.extend({_proxy:null,init:function(){this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),$(document).on("dblclick",".conversationList .new .columnAvatar",$.proxy(this._dblclick,this))},_dblclick:function(e){this._proxy.setOption("data",{actionName:"markAsRead",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[$(e.currentTarget).parents("tr:eq(0)").data("conversationID")]}),this._proxy.sendRequest()},_success:function(e){$(".conversationList .new").each(function(a,t){var n=$(t);WCF.inArray(n.data("conversationID"),e.objectIDs)&&(n.removeClass("new"),n.find(".firstNewPost").parent().remove(),n.find(".columnAvatar").off("dblclick"))})}}),WCF.Conversation.MarkAllAsRead=Class.extend({_proxy:null,init:function(){this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),$(".markAllAsReadButton").click($.proxy(this._click,this))},_click:function(e){e.preventDefault(),this._proxy.setOption("data",{actionName:"markAllAsRead",className:"wcf\\data\\conversation\\ConversationAction"}),this._proxy.sendRequest()},_success:function(){WCF.System.Event.fireEvent("com.woltlab.wcf.conversation.userPanel","reset");var e=$(".conversationList");e.find(".new").removeClass("new"),e.find(".columnAvatar").off("dblclick")}}),WCF.Conversation.Message={},WCF.Conversation.Message.InlineEditor=WCF.Message.InlineEditor.extend({init:function(e,a){this._super(e,!0,a)},_getClassName:function(){return"wcf\\data\\conversation\\message\\ConversationMessageAction"}}),WCF.Conversation.Message.QuoteHandler=WCF.Message.Quote.Handler.extend({init:function(e){this._super(e,"wcf\\data\\conversation\\message\\ConversationMessageAction","com.woltlab.wcf.conversation.message",".message",".messageBody",".messageBody > div > div.messageText",!0)}});
\ No newline at end of file
--- /dev/null
+define("WoltLabSuite/Core/Conversation/Ui/Participant/Add",["Ajax","Language","Ui/Dialog","Ui/Notification","WoltLabSuite/Core/Ui/ItemList/User"],function(t,e,i,a,n){"use strict";function s(t){this.init(t)}return s.prototype={init:function(e){this._conversationId=e,t.api(this,{actionName:"getAddParticipantsForm"})},_ajaxSetup:function(){return{data:{className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[this._conversationId]}}},_ajaxSuccess:function(t){switch(t.actionName){case"addParticipants":this._handleResponse(t);break;case"getAddParticipantsForm":this._render(t)}},_handleResponse:function(t){t.returnValues.count&&a.show(t.returnValues.successMessage,window.location.reload.bind(window.location)),i.close(this)},_render:function(t){i.open(this,t.returnValues.template);var e=document.getElementById("addParticipants");e.disabled=!0,n.init("participantsInput",{callbackChange:function(t,i){e.disabled=0===i.length},excludedSearchValues:t.returnValues.excludedSearchValues,maxItems:t.returnValues.maxItems}),e.addEventListener("click",this._submit.bind(this))},_submit:function(){for(var e=n.getValues("participantsInput"),i=[],a=0,s=e.length;s>a;a++)i.push(e[a].value);t.api(this,{actionName:"addParticipants",parameters:{participants:i}})},_dialogSetup:function(){return{id:"conversationAddParticipants",options:{title:e.get("wcf.conversation.edit.addParticipants")},source:null}}},s});
\ No newline at end of file
--- /dev/null
+/**
+ * Adds participants to an existing conversation.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module WoltLabSuite/Core/Conversation/Ui/Participant/Add
+ */
+define(['Ajax', 'Language', 'Ui/Dialog', 'Ui/Notification', 'WoltLabSuite/Core/Ui/ItemList/User'], function(Ajax, Language, UiDialog, UiNotification, UiItemListUser) {
+ "use strict";
+
+ /**
+ * @constructor
+ * @param {int} conversationId conversation id
+ */
+ function UiParticipantAdd(conversationId) { this.init(conversationId); }
+ UiParticipantAdd.prototype = {
+ /**
+ * Manages the form to add one or more participants to an existing conversation.
+ *
+ * @param {int} conversationId conversation id
+ */
+ init: function(conversationId) {
+ this._conversationId = conversationId;
+
+ Ajax.api(this, {
+ actionName: 'getAddParticipantsForm'
+ });
+ },
+
+ _ajaxSetup: function() {
+ return {
+ data: {
+ className: 'wcf\\data\\conversation\\ConversationAction',
+ objectIDs: [ this._conversationId ]
+ }
+ };
+ },
+
+ /**
+ * Handles successful Ajax requests.
+ *
+ * @param {Object} data response data
+ */
+ _ajaxSuccess: function(data) {
+ switch (data.actionName) {
+ case 'addParticipants':
+ this._handleResponse(data);
+ break;
+
+ case 'getAddParticipantsForm':
+ this._render(data);
+ break;
+ }
+ },
+
+ /**
+ * Shows the success message and closes the dialog overlay.
+ *
+ * @param {Object} data response data
+ */
+ _handleResponse: function(data) {
+ //noinspection JSUnresolvedVariable
+ if (data.returnValues.count) {
+ //noinspection JSUnresolvedVariable
+ UiNotification.show(data.returnValues.successMessage, window.location.reload.bind(window.location));
+ }
+
+ UiDialog.close(this);
+ },
+
+ /**
+ * Renders the dialog to add participants.
+ *
+ * @param {object} data response data
+ */
+ _render: function(data) {
+ //noinspection JSUnresolvedVariable
+ UiDialog.open(this, data.returnValues.template);
+
+ var buttonSubmit = document.getElementById('addParticipants');
+ buttonSubmit.disabled = true;
+
+ //noinspection JSUnresolvedVariable
+ UiItemListUser.init('participantsInput', {
+ callbackChange: function(elementId, values) { buttonSubmit.disabled = (values.length === 0); },
+ excludedSearchValues: data.returnValues.excludedSearchValues,
+ maxItems: data.returnValues.maxItems
+ });
+
+ buttonSubmit.addEventListener('click', this._submit.bind(this));
+ },
+
+ /**
+ * Sends a request to add participants.
+ */
+ _submit: function() {
+ var values = UiItemListUser.getValues('participantsInput'), participants = [];
+ for (var i = 0, length = values.length; i < length; i++) {
+ participants.push(values[i].value);
+ }
+
+ Ajax.api(this, {
+ actionName: 'addParticipants',
+ parameters: {
+ participants: participants
+ }
+ });
+ },
+
+ _dialogSetup: function() {
+ return {
+ id: 'conversationAddParticipants',
+ options: {
+ title: Language.get('wcf.conversation.edit.addParticipants')
+ },
+ source: null
+ };
+ }
+ };
+
+ return UiParticipantAdd;
+});
--- /dev/null
+(function () {
+ var config;
+ config = {
+ name: "WoltLabSuite/_Meta",
+ out: "WoltLabSuite.Core.Conversation.min.js",
+ useStrict: true,
+ preserveLicenseComments: false,
+ optimize: 'uglify2',
+ uglify2: {},
+ excludeShallow: [
+ 'WoltLabSuite/_Meta'
+ ],
+ rawText: {
+ 'WoltLabSuite/_Meta': 'define([], function() {});'
+ },
+ onBuildRead: function(moduleName, path, contents) {
+ if (!process.versions.node) {
+ throw new Error('You need to run node.js');
+ }
+
+ if (moduleName === 'WoltLabSuite/_Meta') {
+ if (global.allModules == undefined) {
+ var fs = module.require('fs'),
+ path = module.require('path');
+ global.allModules = [];
+
+ var queue = ['WoltLabSuite'];
+ var folder;
+ while (folder = queue.shift()) {
+ var files = fs.readdirSync(folder);
+ for (var i = 0; i < files.length; i++) {
+ var filename = path.join(folder, files[i]);
+ if (filename === 'WoltLabSuite/Core/Acp') continue;
+
+ if (path.extname(filename) == '.js') {
+ global.allModules.push(filename);
+ }
+ else if (fs.statSync(filename).isDirectory()) {
+ queue.push(filename);
+ }
+ }
+ }
+ }
+
+ return 'define([' + global.allModules.map(function (item) { return "'" + item.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/\.js$/, '') + "'"; }).join(', ') + '], function() { });';
+ }
+
+ return contents;
+ }
+ };
+
+ var _isSupportedBuildUrl = require._isSupportedBuildUrl;
+ require._isSupportedBuildUrl = function (url) {
+ var result = _isSupportedBuildUrl(url);
+ if (!result) return result;
+ if (Object.keys(config.rawText).map(function (item) { return process.cwd() + '/' + item + '.js'; }).indexOf(url) !== -1) return result;
+
+ var fs = module.require('fs');
+ try {
+ fs.statSync(url);
+ }
+ catch (e) {
+ console.log('Unable to find module:', url, 'ignoring.');
+
+ return false;
+ }
+ return true;
+ };
+
+ return config;
+})();
--- /dev/null
+!function(){var e;e={name:"WoltLabSuite/_Meta",out:"WoltLabSuite.Core.Conversation.min.js",useStrict:!0,preserveLicenseComments:!1,optimize:"uglify2",uglify2:{},excludeShallow:["WoltLabSuite/_Meta"],rawText:{"WoltLabSuite/_Meta":"define([], function() {});"},onBuildRead:function(e,r,t){if(!process.versions.node)throw new Error("You need to run node.js");if("WoltLabSuite/_Meta"===e){if(void 0==global.allModules){var o=module.require("fs"),r=module.require("path");global.allModules=[];for(var i,n=["WoltLabSuite"];i=n.shift();)for(var u=o.readdirSync(i),l=0;l<u.length;l++){var a=r.join(i,u[l]);"WoltLabSuite/Core/Acp"!==a&&(".js"==r.extname(a)?global.allModules.push(a):o.statSync(a).isDirectory()&&n.push(a))}}return"define(["+global.allModules.map(function(e){return"'"+e.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(/\.js$/,"")+"'"}).join(", ")+"], function() { });"}return t}};var r=require._isSupportedBuildUrl;return require._isSupportedBuildUrl=function(t){var o=r(t);if(!o)return o;if(-1!==Object.keys(e.rawText).map(function(e){return process.cwd()+"/"+e+".js"}).indexOf(t))return o;var i=module.require("fs");try{i.statSync(t)}catch(e){return console.log("Unable to find module:",t,"ignoring."),!1}return!0},e}();
\ No newline at end of file
use wcf\data\conversation\message\ConversationMessage;
use wcf\data\user\UserProfile;
use wcf\data\DatabaseObject;
-use wcf\system\breadcrumb\Breadcrumb;
-use wcf\system\breadcrumb\IBreadcrumbProvider;
+use wcf\data\ITitledLinkObject;
use wcf\system\conversation\ConversationHandler;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\exception\UserInputException;
* Represents a conversation.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation
+ *
+ * @property-read integer $conversationID
+ * @property-read string $subject
+ * @property-read integer $time
+ * @property-read integer $firstMessageID
+ * @property-read integer|null $userID
+ * @property-read string $username
+ * @property-read integer $lastPostTime
+ * @property-read integer|null $lastPosterID
+ * @property-read string $lastPoster
+ * @property-read integer $replies
+ * @property-read integer $attachments
+ * @property-read integer $participants
+ * @property-read string $participantSummary
+ * @property-read integer $participantCanInvite
+ * @property-read integer $isClosed
+ * @property-read integer $isDraft
+ * @property-read string $draftData
+ * @property-read integer|null $participantID
+ * @property-read integer|null $hideConversation
+ * @property-read integer|null $isInvisible
+ * @property-read integer|null $lastVisitTime
*/
-class Conversation extends DatabaseObject implements IBreadcrumbProvider, IRouteController {
- /**
- * @see \wcf\data\DatabaseObject::$databaseTableName
- */
- protected static $databaseTableName = 'conversation';
-
- /**
- * @see \wcf\data\DatabaseObject::$databaseIndexName
- */
- protected static $databaseTableIndexName = 'conversationID';
-
+class Conversation extends DatabaseObject implements IRouteController, ITitledLinkObject {
/**
* default participation state
* @var integer
/**
* first message object
- * @var \wcf\data\conversation\message\ConversationMessage
+ * @var ConversationMessage
*/
- protected $firstMessage = null;
+ protected $firstMessage;
/**
- * @see \wcf\system\request\IRouteController::getTitle()
+ * @inheritDoc
*/
public function getTitle() {
return $this->subject;
}
/**
- * @see \wcf\system\breadcrumb\IBreadcrumbProvider::getBreadcrumb()
+ * @inheritDoc
*/
- public function getBreadcrumb() {
- return new Breadcrumb($this->subject, LinkHandler::getInstance()->getLink('Conversation', array(
- 'object' => $this
- )));
+ public function getLink() {
+ return LinkHandler::getInstance()->getLink('Conversation', ['object' => $this]);
}
/**
/**
* Returns true if the active user doesn't have read the given message.
*
- * @param \wcf\data\conversation\message\ConversationMessage $message
+ * @param ConversationMessage $message
* @return boolean
*/
public function isNewMessage(ConversationMessage $message) {
/**
* Loads participation data for given user id (default: current user) on runtime.
- * You should use \wcf\data\conversation\Conversation::getUserConversation() instead if possible.
+ * You should use Conversation::getUserConversation() instead if possible.
*
* @param integer $userID
*/
WHERE participantID = ?
AND conversationID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($userID, $this->conversationID));
+ $statement->execute([$userID, $this->conversationID]);
$row = $statement->fetchArray();
if ($row !== false) {
$this->data = array_merge($this->data, $row);
*
* @param integer $conversationID
* @param integer $userID
- * @return \wcf\data\conversation\Conversation
+ * @return Conversation
*/
public static function getUserConversation($conversationID, $userID) {
$sql = "SELECT conversation_to_user.*, conversation.*
ON (conversation_to_user.participantID = ? AND conversation_to_user.conversationID = conversation.conversationID)
WHERE conversation.conversationID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($userID, $conversationID));
+ $statement->execute([$userID, $conversationID]);
$row = $statement->fetchArray();
if ($row !== false) {
return new Conversation(null, $row);
/**
* Returns a list of user conversations.
*
- * @param array<integer> $conversationIDs
+ * @param integer[] $conversationIDs
* @param integer $userID
- * @return array<\wcf\data\conversation\Conversation>
+ * @return Conversation[]
*/
public static function getUserConversations(array $conversationIDs, $userID) {
$conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('conversation.conversationID IN (?)', array($conversationIDs));
+ $conditionBuilder->add('conversation.conversationID IN (?)', [$conversationIDs]);
$sql = "SELECT conversation_to_user.*, conversation.*
FROM wcf".WCF_N."_conversation conversation
LEFT JOIN wcf".WCF_N."_conversation_to_user conversation_to_user
".$conditionBuilder;
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute($conditionBuilder->getParameters());
- $conversations = array();
+ $conversations = [];
while ($row = $statement->fetchArray()) {
$conversations[$row['conversationID']] = new Conversation(null, $row);
}
-
+
return $conversations;
}
/**
* Returns the first message in this conversation.
*
- * @return \wcf\data\conversation\message\ConversationMessage
+ * @return ConversationMessage
*/
public function getFirstMessage() {
if ($this->firstMessage === null) {
/**
* Sets the first message.
*
- * @param \wcf\data\conversation\message\ConversationMessage $message
+ * @param ConversationMessage $message
*/
public function setFirstMessage(ConversationMessage $message) {
$this->firstMessage = $message;
* Returns a list of the ids of all participants.
*
* @param boolean $excludeLeftParticipants
- * @return array<integer>
+ * @return integer[]
*/
public function getParticipantIDs($excludeLeftParticipants = false) {
$conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID = ?", array($this->conversationID));
- if ($excludeLeftParticipants) $conditions->add("hideConversation <> ?", array(self::STATE_LEFT));
+ $conditions->add("conversationID = ?", [$this->conversationID]);
+ if ($excludeLeftParticipants) $conditions->add("hideConversation <> ?", [self::STATE_LEFT]);
$sql = "SELECT participantID
FROM wcf".WCF_N."_conversation_to_user
".$conditions;
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute($conditions->getParameters());
- $participantIDs = array();
- while ($row = $statement->fetchArray()) {
- $participantIDs[] = $row['participantID'];
- }
- return $participantIDs;
+ return $statement->fetchAll(\PDO::FETCH_COLUMN);
}
/**
* Returns a list of the usernames of all participants.
*
- * @return array<string>
+ * @return string[]
*/
public function getParticipantNames() {
- $participants = array();
$sql = "SELECT user_table.username
FROM wcf".WCF_N."_conversation_to_user conversation_to_user
LEFT JOIN wcf".WCF_N."_user user_table
ON (user_table.userID = conversation_to_user.participantID)
WHERE conversationID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($this->conversationID));
- while ($row = $statement->fetchArray()) {
- $participants[] = $row['username'];
- }
+ $statement->execute([$this->conversationID]);
- return $participants;
+ return $statement->fetchAll(\PDO::FETCH_COLUMN);
}
/**
WHERE conversationID = ?
AND participantID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($this->conversationID, $this->userID));
+ $statement->execute([$this->conversationID, $this->userID]);
$row = $statement->fetchArray();
if ($row !== false) {
if ($row['hideConversation'] != self::STATE_LEFT) return true;
* Returns true if given user id (default: current user) is participant
* of all given conversation ids.
*
- * @param array<integer> $conversationIDs
- * @param integer $userID
+ * @param integer[] $conversationIDs
+ * @param integer $userID
* @return boolean
*/
public static function isParticipant(array $conversationIDs, $userID = null) {
// check if user is the initial author
$conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID IN (?)", array($conversationIDs));
- $conditions->add("userID = ?", array($userID));
+ $conditions->add("conversationID IN (?)", [$conversationIDs]);
+ $conditions->add("userID = ?", [$userID]);
$sql = "SELECT conversationID
FROM wcf".WCF_N."_conversation
// check for participation
if (!empty($conversationIDs)) {
$conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID IN (?)", array($conversationIDs));
- $conditions->add("participantID = ?", array($userID));
- $conditions->add("hideConversation <> ?", array(self::STATE_LEFT));
+ $conditions->add("conversationID IN (?)", [$conversationIDs]);
+ $conditions->add("participantID = ?", [$userID]);
+ $conditions->add("hideConversation <> ?", [self::STATE_LEFT]);
$sql = "SELECT conversationID
FROM wcf".WCF_N."_conversation_to_user
/**
* Validates the participants.
*
- * @param string $participants
+ * @param mixed $participants
* @param string $field
- * @param array<integer> $existingParticipants
+ * @param integer[] $existingParticipants
* @return array $result
+ * @throws UserInputException
*/
- public static function validateParticipants($participants, $field = 'participants', array $existingParticipants = array()) {
- $result = array();
- $error = array();
+ public static function validateParticipants($participants, $field = 'participants', array $existingParticipants = []) {
+ $result = [];
+ $error = [];
// loop through participants and check their settings
- $participantList = UserProfile::getUserProfilesByUsername(ArrayUtil::trim(explode(',', $participants)));
+ $participantList = UserProfile::getUserProfilesByUsername((is_array($participants) ? $participants : ArrayUtil::trim(explode(',', $participants))));
// load user storage at once to avoid multiple queries
- $userIDs = array();
+ $userIDs = [];
foreach ($participantList as $user) {
if ($user) {
$userIDs[] = $user->userID;
$existingParticipants[] = $result[] = $user->userID;
}
catch (UserInputException $e) {
- $error[] = array('type' => $e->getType(), 'username' => $participant);
+ $error[] = ['type' => $e->getType(), 'username' => $participant];
}
}
/**
* Validates the given participant.
*
- * @param \wcf\data\user\UserProfile $user
- * @param string $field
+ * @param UserProfile $user
+ * @param string $field
+ * @throws UserInputException
*/
public static function validateParticipant(UserProfile $user, $field = 'participants') {
// check participant's settings and permissions
if (!WCF::getSession()->getPermission('user.profile.cannotBeIgnored')) {
// check if user wants to receive any conversations
+ /** @noinspection PhpUndefinedFieldInspection */
if ($user->canSendConversation == 2) {
throw new UserInputException($field, 'doesNotAcceptConversation');
}
// check if user only wants to receive conversations by
// users they are following and if the active user is followed
// by the relevant user
+ /** @noinspection PhpUndefinedFieldInspection */
if ($user->canSendConversation == 1 && !$user->isFollowing(WCF::getUser()->userID)) {
throw new UserInputException($field, 'doesNotAcceptConversation');
}
* Executes conversation-related actions.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation
+ *
+ * @method ConversationEditor[] getObjects()
+ * @method ConversationEditor getSingleObject()
*/
class ConversationAction extends AbstractDatabaseObjectAction implements IClipboardAction, IVisitableObjectAction {
/**
- * @see \wcf\data\AbstractDatabaseObjectAction::$className
+ * @inheritDoc
*/
- protected $className = 'wcf\data\conversation\ConversationEditor';
+ protected $className = ConversationEditor::class;
/**
* conversation object
- * @var \wcf\data\conversation\ConversationEditor
+ * @var ConversationEditor
*/
- protected $conversation = null;
+ protected $conversation;
/**
* list of conversation data modifications
- * @var array<array>
+ * @var mixed[][]
*/
- protected $conversationData = array();
+ protected $conversationData = [];
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\data\AbstractDatabaseObjectAction::create()
+ * @inheritDoc
+ * @return Conversation
*/
public function create() {
// create conversation
if (isset($this->parameters['attachmentHandler']) && $this->parameters['attachmentHandler'] !== null) {
$data['attachments'] = count($this->parameters['attachmentHandler']);
}
- $conversation = call_user_func(array($this->className, 'create'), $data);
+ $conversation = call_user_func([$this->className, 'create'], $data);
$conversationEditor = new ConversationEditor($conversation);
if (!$conversation->isDraft) {
// save participants
- $conversationEditor->updateParticipants((!empty($this->parameters['participants']) ? $this->parameters['participants'] : array()), (!empty($this->parameters['invisibleParticipants']) ? $this->parameters['invisibleParticipants'] : array()));
+ $conversationEditor->updateParticipants((!empty($this->parameters['participants']) ? $this->parameters['participants'] : []), (!empty($this->parameters['invisibleParticipants']) ? $this->parameters['invisibleParticipants'] : []));
// add author
- $conversationEditor->updateParticipants(array($data['userID']));
+ $conversationEditor->updateParticipants([$data['userID']]);
// update conversation count
UserStorageHandler::getInstance()->reset($conversation->getParticipantIDs(), 'conversationCount');
WHERE participantID = ?
AND conversationID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($data['time'], $data['userID'], $conversation->conversationID));
+ $statement->execute([$data['time'], $data['userID'], $conversation->conversationID]);
}
else {
// update conversation count
- UserStorageHandler::getInstance()->reset(array($data['userID']), 'conversationCount');
+ UserStorageHandler::getInstance()->reset([$data['userID']], 'conversationCount');
}
// update participant summary
$messageData['userID'] = $this->parameters['data']['userID'];
$messageData['username'] = $this->parameters['data']['username'];
- $messageAction = new ConversationMessageAction(array(), 'create', array(
+ $messageAction = new ConversationMessageAction([], 'create', [
'data' => $messageData,
'conversation' => $conversation,
'isFirstPost' => true,
- 'attachmentHandler' => (isset($this->parameters['attachmentHandler']) ? $this->parameters['attachmentHandler'] : null)
- ));
+ 'attachmentHandler' => isset($this->parameters['attachmentHandler']) ? $this->parameters['attachmentHandler'] : null,
+ 'htmlInputProcessor' => isset($this->parameters['htmlInputProcessor']) ? $this->parameters['htmlInputProcessor'] : null
+ ]);
$resultValues = $messageAction->executeAction();
// update first message id
- $conversationEditor->update(array(
+ $conversationEditor->update([
'firstMessageID' => $resultValues['returnValues']->messageID
- ));
+ ]);
$conversation->setFirstMessage($resultValues['returnValues']);
if (!$conversation->isDraft) {
// fire notification event
- $notificationRecipients = array_merge((!empty($this->parameters['participants']) ? $this->parameters['participants'] : array()), (!empty($this->parameters['invisibleParticipants']) ? $this->parameters['invisibleParticipants'] : array()));
- UserNotificationHandler::getInstance()->fireEvent('conversation', 'com.woltlab.wcf.conversation.notification', new ConversationUserNotificationObject($conversation), $notificationRecipients);
+ $notificationRecipients = array_merge((!empty($this->parameters['participants']) ? $this->parameters['participants'] : []), (!empty($this->parameters['invisibleParticipants']) ? $this->parameters['invisibleParticipants'] : []));
+ UserNotificationHandler::getInstance()->fireEvent(
+ 'conversation',
+ 'com.woltlab.wcf.conversation.notification',
+ new ConversationUserNotificationObject($conversation),
+ $notificationRecipients
+ );
}
return $conversation;
}
/**
- * @see \wcf\data\IDeleteAction::delete()
+ * @inheritDoc
*/
public function delete() {
// deletes messages
$messageList = new ConversationMessageList();
- $messageList->getConditionBuilder()->add('conversation_message.conversationID IN (?)', array($this->objectIDs));
+ $messageList->getConditionBuilder()->add('conversation_message.conversationID IN (?)', [$this->objectIDs]);
$messageList->readObjectIDs();
$action = new ConversationMessageAction($messageList->getObjectIDs(), 'delete');
$action->executeAction();
if (!empty($this->objectIDs)) {
// delete notifications
- UserNotificationHandler::getInstance()->deleteNotifications('conversation', 'com.woltlab.wcf.conversation.notification', array(), $this->objectIDs);
+ UserNotificationHandler::getInstance()->removeNotifications('com.woltlab.wcf.conversation.notification', $this->objectIDs);
// remove modification logs
- ConversationModificationLogHandler::getInstance()->remove($this->objectIDs);
+ ConversationModificationLogHandler::getInstance()->deleteLogs($this->objectIDs);
}
}
/**
- * @see \wcf\data\AbstractDatabaseObjectAction::update()
+ * @inheritDoc
*/
public function update() {
- if (!isset($this->parameters['participants'])) $this->parameters['participants'] = array();
- if (!isset($this->parameters['invisibleParticipants'])) $this->parameters['invisibleParticipants'] = array();
+ if (!isset($this->parameters['participants'])) $this->parameters['participants'] = [];
+ if (!isset($this->parameters['invisibleParticipants'])) $this->parameters['invisibleParticipants'] = [];
// count participants
if (!empty($this->parameters['participants'])) {
parent::update();
- foreach ($this->objects as $conversation) {
- // partipants
+ foreach ($this->getObjects() as $conversation) {
+ // participants
if (!empty($this->parameters['participants']) || !empty($this->parameters['invisibleParticipants'])) {
// get current participants
$participantIDs = $conversation->getParticipantIDs();
- $conversation->updateParticipants((!empty($this->parameters['participants']) ? $this->parameters['participants'] : array()), (!empty($this->parameters['invisibleParticipants']) ? $this->parameters['invisibleParticipants'] : array()));
+ $conversation->updateParticipants((!empty($this->parameters['participants']) ? $this->parameters['participants'] : []), (!empty($this->parameters['invisibleParticipants']) ? $this->parameters['invisibleParticipants'] : []));
$conversation->updateParticipantSummary();
// check if new participants have been added
UserStorageHandler::getInstance()->reset($newParticipantIDs, 'conversationCount');
// fire notification event
- UserNotificationHandler::getInstance()->fireEvent('conversation', 'com.woltlab.wcf.conversation.notification', new ConversationUserNotificationObject($conversation->getDecoratedObject()), $newParticipantIDs);
+ UserNotificationHandler::getInstance()->fireEvent(
+ 'conversation',
+ 'com.woltlab.wcf.conversation.notification',
+ new ConversationUserNotificationObject($conversation->getDecoratedObject()),
+ $newParticipantIDs
+ );
}
}
if (isset($this->parameters['data']['isDraft'])) {
if ($conversation->isDraft && !$this->parameters['data']['isDraft']) {
// add author
- $conversation->updateParticipants(array($conversation->userID));
+ $conversation->updateParticipants([$conversation->userID]);
// update conversation count
UserStorageHandler::getInstance()->reset($conversation->getParticipantIDs(), 'unreadConversationCount');
}
/**
- * @see \wcf\data\IVisitableObjectAction::markAsRead()
+ * @inheritDoc
*/
public function markAsRead() {
if (empty($this->parameters['visitTime'])) {
$this->readObjects();
}
- $conversationIDs = array();
+ $conversationIDs = [];
$sql = "UPDATE wcf".WCF_N."_conversation_to_user
SET lastVisitTime = ?
WHERE participantID = ?
AND conversationID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
WCF::getDB()->beginTransaction();
- foreach ($this->objects as $conversation) {
- $statement->execute(array(
+ foreach ($this->getObjects() as $conversation) {
+ $statement->execute([
$this->parameters['visitTime'],
WCF::getUser()->userID,
$conversation->conversationID
- ));
+ ]);
$conversationIDs[] = $conversation->conversationID;
}
WCF::getDB()->commitTransaction();
// reset storage
- UserStorageHandler::getInstance()->reset(array(WCF::getUser()->userID), 'unreadConversationCount');
+ UserStorageHandler::getInstance()->reset([WCF::getUser()->userID], 'unreadConversationCount');
// mark notifications as confirmed
if (!empty($conversationIDs)) {
// conversation start notification
$conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('notification.eventID = ?', array(UserNotificationHandler::getInstance()->getEvent('com.woltlab.wcf.conversation.notification', 'conversation')->eventID));
+ $conditionBuilder->add('notification.eventID = ?', [UserNotificationHandler::getInstance()->getEvent('com.woltlab.wcf.conversation.notification', 'conversation')->eventID]);
$conditionBuilder->add('notification.objectID = conversation.conversationID');
- $conditionBuilder->add('notification.userID = ?', array(WCF::getUser()->userID));
- $conditionBuilder->add('conversation.conversationID IN (?)', array($conversationIDs));
- $conditionBuilder->add('conversation.time <= ?', array($this->parameters['visitTime']));
+ $conditionBuilder->add('notification.userID = ?', [WCF::getUser()->userID]);
+ $conditionBuilder->add('conversation.conversationID IN (?)', [$conversationIDs]);
+ $conditionBuilder->add('conversation.time <= ?', [$this->parameters['visitTime']]);
$sql = "SELECT conversation.conversationID
FROM wcf".WCF_N."_conversation conversation,
".$conditionBuilder;
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute($conditionBuilder->getParameters());
- $notificationObjectIDs = array();
- while ($row = $statement->fetchArray()) {
- $notificationObjectIDs[] = $row['conversationID'];
- }
+ $notificationObjectIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
if (!empty($notificationObjectIDs)) {
- UserNotificationHandler::getInstance()->markAsConfirmed('conversation', 'com.woltlab.wcf.conversation.notification', array(WCF::getUser()->userID), $notificationObjectIDs);
+ UserNotificationHandler::getInstance()->markAsConfirmed('conversation', 'com.woltlab.wcf.conversation.notification', [WCF::getUser()->userID], $notificationObjectIDs);
}
// conversation reply notification
$conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('notification.eventID = ?', array(UserNotificationHandler::getInstance()->getEvent('com.woltlab.wcf.conversation.message.notification', 'conversationMessage')->eventID));
+ $conditionBuilder->add('notification.eventID = ?', [UserNotificationHandler::getInstance()->getEvent('com.woltlab.wcf.conversation.message.notification', 'conversationMessage')->eventID]);
$conditionBuilder->add('notification.objectID = conversation_message.messageID');
- $conditionBuilder->add('notification.userID = ?', array(WCF::getUser()->userID));
- $conditionBuilder->add('conversation_message.conversationID IN (?)', array($conversationIDs));
- $conditionBuilder->add('conversation_message.time <= ?', array($this->parameters['visitTime']));
+ $conditionBuilder->add('notification.userID = ?', [WCF::getUser()->userID]);
+ $conditionBuilder->add('conversation_message.conversationID IN (?)', [$conversationIDs]);
+ $conditionBuilder->add('conversation_message.time <= ?', [$this->parameters['visitTime']]);
$sql = "SELECT conversation_message.messageID
FROM wcf".WCF_N."_conversation_message conversation_message,
".$conditionBuilder;
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute($conditionBuilder->getParameters());
- $notificationObjectIDs = array();
- while ($row = $statement->fetchArray()) {
- $notificationObjectIDs[] = $row['messageID'];
- }
+ $notificationObjectIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
if (!empty($notificationObjectIDs)) {
- UserNotificationHandler::getInstance()->markAsConfirmed('conversationMessage', 'com.woltlab.wcf.conversation.message.notification', array(WCF::getUser()->userID), $notificationObjectIDs);
+ UserNotificationHandler::getInstance()->markAsConfirmed('conversationMessage', 'com.woltlab.wcf.conversation.message.notification', [WCF::getUser()->userID], $notificationObjectIDs);
}
}
$this->unmarkItems($conversationIDs);
}
- $returnValues = array(
+ $returnValues = [
'totalCount' => ConversationHandler::getInstance()->getUnreadConversationCount(null, true)
- );
+ ];
if (count($conversationIDs) == 1) {
$returnValues['markAsRead'] = reset($conversationIDs);
}
/**
- * @see \wcf\data\IVisitableObjectAction::validateMarkAsRead()
+ * @inheritDoc
*/
public function validateMarkAsRead() {
// visitTime might not be in the future
}
// check participation
- $conversationIDs = array();
- foreach ($this->objects as $conversation) {
+ $conversationIDs = [];
+ foreach ($this->getObjects() as $conversation) {
$conversationIDs[] = $conversation->conversationID;
}
SET lastVisitTime = ?
WHERE participantID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
+ $statement->execute([
TIME_NOW,
WCF::getUser()->userID
- ));
+ ]);
// reset storage
- UserStorageHandler::getInstance()->reset(array(WCF::getUser()->userID), 'unreadConversationCount');
+ UserStorageHandler::getInstance()->reset([WCF::getUser()->userID], 'unreadConversationCount');
- // delete obsolete notifications
- UserNotificationHandler::getInstance()->deleteNotifications('conversation', 'com.woltlab.wcf.conversation.notification', array(WCF::getUser()->userID));
- UserNotificationHandler::getInstance()->deleteNotifications('conversationMessage', 'com.woltlab.wcf.conversation.message.notification', array(WCF::getUser()->userID));
+ // confirm obsolete notifications
+ UserNotificationHandler::getInstance()->markAsConfirmed('conversation', 'com.woltlab.wcf.conversation.notification', [WCF::getUser()->userID]);
+ UserNotificationHandler::getInstance()->markAsConfirmed('conversationMessage', 'com.woltlab.wcf.conversation.message.notification', [WCF::getUser()->userID]);
- return array(
+ return [
'markAllAsRead' => true
- );
+ ];
}
/**
* Validates the markAllAsRead action.
*/
- public function validateMarkAllAsRead() {}
+ public function validateMarkAllAsRead() {
+ // does nothing
+ }
/**
* Validates user access for label management.
*/
- public function validateGetLabelmanagement() {
+ public function validateGetLabelManagement() {
if (!WCF::getSession()->getPermission('user.conversation.canUseConversation')) {
throw new PermissionDeniedException();
}
* @return array
*/
public function getLabelManagement() {
- WCF::getTPL()->assign(array(
+ WCF::getTPL()->assign([
'cssClassNames' => ConversationLabel::getLabelCssClassNames(),
'labelList' => ConversationLabel::getLabelsByUser()
- ));
+ ]);
- return array(
+ return [
'actionName' => 'getLabelManagement',
'template' => WCF::getTPL()->fetch('conversationLabelManagement'),
'maxLabels' => WCF::getSession()->getPermission('user.conversation.maxLabels'),
'labelCount' => count(ConversationLabel::getLabelsByUser())
- );
+ ];
}
/**
*/
public function validateGetMessagePreview() {
$this->conversation = $this->getSingleObject();
- if (!Conversation::isParticipant(array($this->conversation->conversationID))) {
+ if (!Conversation::isParticipant([$this->conversation->conversationID])) {
throw new PermissionDeniedException();
}
}
/**
* Returns a preview of a message in a specific conversation.
*
- * @return array
+ * @return string[]
*/
public function getMessagePreview() {
$messageList = new SimplifiedViewableConversationMessageList();
- $messageList->getConditionBuilder()->add("conversation_message.messageID = ?", array($this->conversation->firstMessageID));
+ $messageList->getConditionBuilder()->add("conversation_message.messageID = ?", [$this->conversation->firstMessageID]);
$messageList->readObjects();
$messages = $messageList->getObjects();
- WCF::getTPL()->assign(array(
+ WCF::getTPL()->assign([
'message' => reset($messages)
- ));
- return array(
+ ]);
+ return [
'template' => WCF::getTPL()->fetch('conversationMessagePreview')
- );
+ ];
}
/**
}
// validate ownership
- foreach ($this->objects as $conversation) {
+ foreach ($this->getObjects() as $conversation) {
if ($conversation->isClosed || ($conversation->userID != WCF::getUser()->userID)) {
throw new PermissionDeniedException();
}
/**
* Closes conversations.
*
- * @return array<array>
+ * @return mixed[][]
*/
public function close() {
- foreach ($this->objects as $conversation) {
- $conversation->update(array('isClosed' => 1));
+ foreach ($this->getObjects() as $conversation) {
+ $conversation->update(['isClosed' => 1]);
$this->addConversationData($conversation->getDecoratedObject(), 'isClosed', 1);
ConversationModificationLogHandler::getInstance()->close($conversation->getDecoratedObject());
}
// validate ownership
- foreach ($this->objects as $conversation) {
+ foreach ($this->getObjects() as $conversation) {
if (!$conversation->isClosed || ($conversation->userID != WCF::getUser()->userID)) {
throw new PermissionDeniedException();
}
/**
* Opens conversations.
*
- * @return array<array>
+ * @return mixed[][]
*/
public function open() {
- foreach ($this->objects as $conversation) {
- $conversation->update(array('isClosed' => 0));
+ foreach ($this->getObjects() as $conversation) {
+ $conversation->update(['isClosed' => 0]);
$this->addConversationData($conversation->getDecoratedObject(), 'isClosed', 0);
ConversationModificationLogHandler::getInstance()->open($conversation->getDecoratedObject());
WHERE conversationID = ?
AND participantID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
+ $statement->execute([
current($this->objectIDs),
WCF::getUser()->userID
- ));
+ ]);
$row = $statement->fetchArray();
WCF::getTPL()->assign('hideConversation', $row['hideConversation']);
- return array(
+ return [
'actionName' => 'getLeaveForm',
'template' => WCF::getTPL()->fetch('conversationLeave')
- );
+ ];
}
/**
* Validates parameters to hide conversations.
*/
public function validateHideConversation() {
- $this->parameters['hideConversation'] = (isset($this->parameters['hideConversation'])) ? intval($this->parameters['hideConversation']) : null;
- if ($this->parameters['hideConversation'] === null || !in_array($this->parameters['hideConversation'], array(Conversation::STATE_DEFAULT, Conversation::STATE_HIDDEN, Conversation::STATE_LEFT))) {
+ $this->parameters['hideConversation'] = isset($this->parameters['hideConversation']) ? intval($this->parameters['hideConversation']) : null;
+ if ($this->parameters['hideConversation'] === null || !in_array($this->parameters['hideConversation'], [Conversation::STATE_DEFAULT, Conversation::STATE_HIDDEN, Conversation::STATE_LEFT])) {
throw new UserInputException('hideConversation');
}
/**
* Hides or restores conversations.
*
- * @return array
+ * @return string[]
*/
public function hideConversation() {
$sql = "UPDATE wcf".WCF_N."_conversation_to_user
WCF::getDB()->beginTransaction();
foreach ($this->objectIDs as $conversationID) {
- $statement->execute(array(
+ $statement->execute([
$this->parameters['hideConversation'],
$conversationID,
WCF::getUser()->userID
- ));
+ ]);
}
WCF::getDB()->commitTransaction();
// reset user's conversation counters if user leaves conversation
// permanently
if ($this->parameters['hideConversation'] == Conversation::STATE_LEFT) {
- UserStorageHandler::getInstance()->reset(array(WCF::getUser()->userID), 'conversationCount');
- UserStorageHandler::getInstance()->reset(array(WCF::getUser()->userID), 'unreadConversationCount');
+ UserStorageHandler::getInstance()->reset([WCF::getUser()->userID], 'conversationCount');
+ UserStorageHandler::getInstance()->reset([WCF::getUser()->userID], 'unreadConversationCount');
}
// add modification log entry
if ($this->parameters['hideConversation'] == Conversation::STATE_LEFT) {
if (empty($this->objects)) $this->readObjects();
- foreach ($this->objects as $conversation) {
+ foreach ($this->getObjects() as $conversation) {
ConversationModificationLogHandler::getInstance()->leave($conversation->getDecoratedObject());
}
}
// delete conversation if all users have left it
$conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('conversation.conversationID IN (?)', array($this->objectIDs));
+ $conditionBuilder->add('conversation.conversationID IN (?)', [$this->objectIDs]);
$conditionBuilder->add('conversation_to_user.conversationID IS NULL');
- $conversationIDs = array();
$sql = "SELECT DISTINCT conversation.conversationID
FROM wcf".WCF_N."_conversation conversation
LEFT JOIN wcf".WCF_N."_conversation_to_user conversation_to_user
".$conditionBuilder;
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute($conditionBuilder->getParameters());
- while ($row = $statement->fetchArray()) {
- $conversationIDs[] = $row['conversationID'];
- }
+ $conversationIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
+
if (!empty($conversationIDs)) {
$action = new ConversationAction($conversationIDs, 'delete');
$action->executeAction();
}
}
- return array(
+ return [
'actionName' => 'hideConversation',
'redirectURL' => LinkHandler::getInstance()->getLink('ConversationList')
- );
+ ];
}
/**
}
/**
- * Returns a mixed conversation list with up to 5 unread conversations.
+ * Returns a mixed conversation list with up to 10 unread conversations.
*
- * @return array<mixed>
+ * @return mixed[][]
*/
public function getMixedConversationList() {
+ $sqlSelect = ' , (SELECT participantID FROM wcf'.WCF_N.'_conversation_to_user WHERE conversationID = conversation.conversationID AND participantID <> conversation.userID AND isInvisible = 0 ORDER BY username, participantID LIMIT 1) AS otherParticipantID
+ , (SELECT username FROM wcf'.WCF_N.'_conversation_to_user WHERE conversationID = conversation.conversationID AND participantID <> conversation.userID AND isInvisible = 0 ORDER BY username, participantID LIMIT 1) AS otherParticipant';
+
$unreadConversationList = new UserConversationList(WCF::getUser()->userID);
+ $unreadConversationList->sqlSelects .= $sqlSelect;
$unreadConversationList->getConditionBuilder()->add('conversation_to_user.lastVisitTime < conversation.lastPostTime');
- $unreadConversationList->sqlLimit = 5;
+ $unreadConversationList->sqlLimit = 10;
$unreadConversationList->sqlOrderBy = 'conversation.lastPostTime DESC';
$unreadConversationList->readObjects();
- $conversations = array();
+ $conversations = [];
$count = 0;
foreach ($unreadConversationList as $conversation) {
$conversations[] = $conversation;
$count++;
}
- if ($count < 5) {
+ if ($count < 10) {
$conversationList = new UserConversationList(WCF::getUser()->userID);
+ $conversationList->sqlSelects .= $sqlSelect;
$conversationList->getConditionBuilder()->add('conversation_to_user.lastVisitTime >= conversation.lastPostTime');
- $conversationList->sqlLimit = (5 - $count);
+ $conversationList->sqlLimit = (10 - $count);
$conversationList->sqlOrderBy = 'conversation.lastPostTime DESC';
$conversationList->readObjects();
}
}
- WCF::getTPL()->assign(array(
+ WCF::getTPL()->assign([
'conversations' => $conversations
- ));
+ ]);
$totalCount = ConversationHandler::getInstance()->getUnreadConversationCount();
- if ($count < 5 && $count < $totalCount) {
- UserStorageHandler::getInstance()->reset(array(WCF::getUser()->userID), 'unreadConversationCount');
+ if ($count < 10 && $count < $totalCount) {
+ UserStorageHandler::getInstance()->reset([WCF::getUser()->userID], 'unreadConversationCount');
}
- return array(
+ return [
'template' => WCF::getTPL()->fetch('conversationListUserPanel'),
'totalCount' => $totalCount
- );
+ ];
}
/**
*/
public function validateGetAddParticipantsForm() {
$this->conversation = $this->getSingleObject();
- if (!Conversation::isParticipant(array($this->conversation->conversationID)) || !$this->conversation->canAddParticipants()) {
+ if (!Conversation::isParticipant([$this->conversation->conversationID]) || !$this->conversation->canAddParticipants()) {
throw new PermissionDeniedException();
}
}
* @return array
*/
public function getAddParticipantsForm() {
- return array(
- 'actionName' => 'getAddParticipantsForm',
- 'excludeSearchValues' => $this->conversation->getParticipantNames(),
+ return [
+ 'excludedSearchValues' => $this->conversation->getParticipantNames(),
+ 'maxItems' => WCF::getSession()->getPermission('user.conversation.maxParticipants') - $this->conversation->participants,
'template' => WCF::getTPL()->fetch('conversationAddParticipants')
- );
+ ];
}
/**
$this->validateGetAddParticipantsForm();
// validate participants
- $this->readString('participants');
+ $this->readStringArray('participants');
}
/**
$errorMessage = '';
foreach ($e->getType() as $type) {
if (!empty($errorMessage)) $errorMessage .= ' ';
- $errorMessage .= WCF::getLanguage()->getDynamicVariable('wcf.conversation.participants.error.'.$type['type'], array('errorData' => array('username' => $type['username'])));
+ $errorMessage .= WCF::getLanguage()->getDynamicVariable('wcf.conversation.participants.error.'.$type['type'], ['errorData' => ['username' => $type['username']]]);
}
- return array(
+ return [
'actionName' => 'addParticipants',
'errorMessage' => $errorMessage
- );
+ ];
}
// validate limit
$newCount = $this->conversation->participants + count($participantIDs);
if ($newCount > WCF::getSession()->getPermission('user.conversation.maxParticipants')) {
- return array(
+ return [
'actionName' => 'addParticipants',
'errorMessage' => WCF::getLanguage()->getDynamicVariable('wcf.conversation.participants.error.tooManyParticipants')
- );
+ ];
}
$count = 0;
$successMessage = '';
if (!empty($participantIDs)) {
// check for already added participants
- $data = array();
if ($this->conversation->isDraft) {
$draftData = unserialize($this->conversation->draftData);
$draftData['participants'] = array_merge($draftData['participants'], $participantIDs);
- $data = array('data' => array('draftData' => serialize($draftData)));
+ $data = ['data' => ['draftData' => serialize($draftData)]];
}
else {
- $data = array('participants' => $participantIDs);
+ $data = ['participants' => $participantIDs];
}
- $conversationAction = new ConversationAction(array($this->conversation), 'update', $data);
+ $conversationAction = new ConversationAction([$this->conversation], 'update', $data);
$conversationAction->executeAction();
$count = count($participantIDs);
- $successMessage = WCF::getLanguage()->getDynamicVariable('wcf.conversation.edit.addParticipants.success', array('count' => $count));
+ $successMessage = WCF::getLanguage()->getDynamicVariable('wcf.conversation.edit.addParticipants.success', ['count' => $count]);
ConversationModificationLogHandler::getInstance()->addParticipants($this->conversation->getDecoratedObject(), $participantIDs);
}
}
- return array(
- 'actionName' => 'addParticipants',
+ return [
'count' => $count,
'successMessage' => $successMessage
- );
+ ];
}
/**
}
// validate participants
- if ($this->parameters['userID'] == WCF::getUser()->userID || !Conversation::isParticipant(array($this->conversation->conversationID)) || !Conversation::isParticipant(array($this->conversation->conversationID), $this->parameters['userID'])) {
+ if ($this->parameters['userID'] == WCF::getUser()->userID || !Conversation::isParticipant([$this->conversation->conversationID]) || !Conversation::isParticipant([$this->conversation->conversationID], $this->parameters['userID'])) {
throw new PermissionDeniedException();
}
ConversationModificationLogHandler::getInstance()->removeParticipant($this->conversation->getDecoratedObject(), $this->parameters['userID']);
// reset storage
- UserStorageHandler::getInstance()->reset(array($this->parameters['userID']), 'unreadConversationCount');
+ UserStorageHandler::getInstance()->reset([$this->parameters['userID']], 'unreadConversationCount');
- return array(
+ return [
'userID' => $this->parameters['userID']
- );
+ ];
}
/**
// collect number of messages for each conversation
$conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('conversation_message.conversationID IN (?)', array($this->objectIDs));
+ $conditionBuilder->add('conversation_message.conversationID IN (?)', [$this->objectIDs]);
$sql = "SELECT conversationID, COUNT(messageID) AS messages, SUM(attachments) AS attachments
FROM wcf".WCF_N."_conversation_message conversation_message
".$conditionBuilder."
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute($conditionBuilder->getParameters());
- $objectIDs = array();
+ $objectIDs = [];
while ($row = $statement->fetchArray()) {
if (!$row['messages']) {
continue;
}
$objectIDs[] = $row['conversationID'];
- $conversationEditor = new ConversationEditor(new Conversation(null, array(
+ $conversationEditor = new ConversationEditor(new Conversation(null, [
'conversationID' => $row['conversationID']
- )));
- $conversationEditor->update(array(
+ ]));
+ $conversationEditor->update([
'attachments' => $row['attachments'],
'replies' => $row['messages'] - 1
- ));
+ ]);
$conversationEditor->updateFirstMessage();
$conversationEditor->updateLastMessage();
}
/**
* Adds conversation modification data.
*
- * @param \wcf\data\conversation\Conversation $conversation
- * @param string $key
- * @param mixed $value
+ * @param Conversation $conversation
+ * @param string $key
+ * @param mixed $value
*/
protected function addConversationData(Conversation $conversation, $key, $value) {
if (!isset($this->conversationData[$conversation->conversationID])) {
- $this->conversationData[$conversation->conversationID] = array();
+ $this->conversationData[$conversation->conversationID] = [];
}
$this->conversationData[$conversation->conversationID][$key] = $value;
/**
* Returns conversation data.
*
- * @return array<array>
+ * @return mixed[][]
*/
protected function getConversationData() {
- return array(
+ return [
'conversationData' => $this->conversationData
- );
+ ];
}
/**
* Unmarks conversations.
*
- * @param array<integer> $conversationIDs
+ * @param integer[] $conversationIDs
*/
- protected function unmarkItems(array $conversationIDs = array()) {
+ protected function unmarkItems(array $conversationIDs = []) {
if (empty($conversationIDs)) {
$conversationIDs = $this->objectIDs;
}
* Extends the conversation object with functions to create, update and delete conversations.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation
+ *
+ * @method static Conversation create(array $parameters = [])
+ * @method Conversation getDecoratedObject()
+ * @mixin Conversation
*/
class ConversationEditor extends DatabaseObjectEditor {
/**
- * @see \wcf\data\DatabaseObjectEditor::$baseClass
+ * @inheritDoc
*/
- protected static $baseClass = 'wcf\data\conversation\Conversation';
+ protected static $baseClass = Conversation::class;
/**
* Adds a new message to this conversation.
*
- * @param \wcf\data\conversation\message\ConversationMessage $message
+ * @param ConversationMessage $message
*/
public function addMessage(ConversationMessage $message) {
- $data = array(
+ $this->update([
'lastPoster' => $message->username,
'lastPostTime' => $message->time,
'lastPosterID' => $message->userID,
'replies' => $this->replies + 1,
'attachments' => $this->attachments + $message->attachments
- );
-
- $this->update($data);
+ ]);
}
/**
WHERE conversationID = ?
AND participantID <> ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($this->conversationID, $this->userID));
+ $statement->execute([$this->conversationID, $this->userID]);
}
/**
* Updates the participants of this conversation.
*
- * @param array<integer> $participantIDs
- * @param array<integer> $invisibleParticipantIDs
+ * @param integer[] $participantIDs
+ * @param integer[] $invisibleParticipantIDs
*/
- public function updateParticipants(array $participantIDs, array $invisibleParticipantIDs = array()) {
- $usernames = array();
+ public function updateParticipants(array $participantIDs, array $invisibleParticipantIDs = []) {
+ $usernames = [];
if (!empty($participantIDs) || !empty($invisibleParticipantIDs)) {
$conditions = new PreparedStatementConditionBuilder();
- $conditions->add("userID IN (?)", array(array_merge($participantIDs, $invisibleParticipantIDs)));
+ $conditions->add("userID IN (?)", [array_merge($participantIDs, $invisibleParticipantIDs)]);
$sql = "SELECT userID, username
FROM wcf".WCF_N."_user
$statement = WCF::getDB()->prepareStatement($sql);
foreach ($participantIDs as $userID) {
- $statement->execute(array(
+ $statement->execute([
$this->conversationID,
$userID,
$usernames[$userID],
0
- ));
+ ]);
}
WCF::getDB()->commitTransaction();
}
$statement = WCF::getDB()->prepareStatement($sql);
foreach ($invisibleParticipantIDs as $userID) {
- $statement->execute(array(
+ $statement->execute([
$this->conversationID,
$userID,
$usernames[$userID],
1
- ));
+ ]);
}
WCF::getDB()->commitTransaction();
}
)
WHERE conversation.conversationID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
+ $statement->execute([
Conversation::STATE_LEFT,
$this->userID,
0,
$this->conversationID
- ));
+ ]);
}
/**
* Updates the participant summary of this conversation.
*/
public function updateParticipantSummary() {
- $users = array();
$sql = "SELECT participantID AS userID, hideConversation, username
FROM wcf".WCF_N."_conversation_to_user
WHERE conversationID = ?
AND isInvisible = 0
ORDER BY username";
$statement = WCF::getDB()->prepareStatement($sql, 5);
- $statement->execute(array($this->conversationID, $this->userID));
- while ($row = $statement->fetchArray()) {
- $users[] = $row;
- }
+ $statement->execute([$this->conversationID, $this->userID]);
- $this->update(array(
- 'participantSummary' => serialize($users)
- ));
+ $this->update(['participantSummary' => serialize($statement->fetchAll(\PDO::FETCH_ASSOC))]);
}
/**
WHERE conversationID = ?
AND participantID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
+ $statement->execute([
2,
$this->conversationID,
$userID
- ));
+ ]);
// decrease participant count unless it is the author
if ($userID != $this->userID) {
- $this->updateCounters(array(
+ $this->updateCounters([
'participants' => -1
- ));
+ ]);
}
}
WHERE conversationID = ?
ORDER BY time ASC";
$statement = WCF::getDB()->prepareStatement($sql, 1);
- $statement->execute(array(
+ $statement->execute([
$this->conversationID
- ));
+ ]);
- $this->update(array(
+ $this->update([
'firstMessageID' => $statement->fetchColumn()
- ));
+ ]);
}
/**
WHERE conversationID = ?
ORDER BY time DESC";
$statement = WCF::getDB()->prepareStatement($sql, 1);
- $statement->execute(array(
+ $statement->execute([
$this->conversationID
- ));
+ ]);
$row = $statement->fetchArray();
- $this->update(array(
+ $this->update([
'lastPostTime' => $row['time'],
'lastPosterID' => $row['userID'],
'lastPoster' => $row['username']
- ));
+ ]);
}
/**
* Updates the participant summary of the given conversations.
*
- * @param array<integer> $conversationIDs
+ * @param integer[] $conversationIDs
*/
public static function updateParticipantSummaries(array $conversationIDs) {
$conversationList = new ConversationList();
- $conversationList->getConditionBuilder()->add('conversation.conversationID IN (?)', array($conversationIDs));
+ $conversationList->setObjectIDs($conversationIDs);
$conversationList->readObjects();
foreach ($conversationList as $conversation) {
/**
* Updates the participant counts of the given conversations.
*
- * @param array<integer> $conversationIDs
+ * @param integer[] $conversationIDs
*/
public static function updateParticipantCounts(array $conversationIDs) {
$conversationList = new ConversationList();
- $conversationList->getConditionBuilder()->add('conversation.conversationID IN (?)', array($conversationIDs));
+ $conversationList->setObjectIDs($conversationIDs);
$conversationList->readObjects();
foreach ($conversationList as $conversation) {
* Represents a list of conversations.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation
+ *
+ * @method Conversation current()
+ * @method Conversation[] getObjects()
+ * @method Conversation|null search($objectID)
+ * @property Conversation[] $objects
*/
class ConversationList extends DatabaseObjectList {
/**
- * @see \wcf\data\DatabaseObjectList::$className
+ * @inheritDoc
*/
- public $className = 'wcf\data\conversation\Conversation';
+ public $className = Conversation::class;
}
<?php
namespace wcf\data\conversation;
-use wcf\data\user\User;
use wcf\data\user\UserProfile;
use wcf\data\user\UserProfileList;
use wcf\system\WCF;
* Represents a list of conversation participants.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation
*/
class ConversationParticipantList extends UserProfileList {
/**
public $conversationID = 0;
/**
- * @see \wcf\data\DatabaseObjectList::$sqlLimit
+ * @inheritDoc
*/
public $sqlLimit = 0;
* Creates a new ConversationParticipantList object.
*
* @param integer $conversationID
+ * @param integer $userID
* @param boolean $isAuthor true if given user is the author of this conversation
*/
public function __construct($conversationID, $userID = 0, $isAuthor = false) {
parent::__construct();
$this->conversationID = $conversationID;
- $this->getConditionBuilder()->add('conversation_to_user.conversationID = ?', array($conversationID));
+ $this->getConditionBuilder()->add('conversation_to_user.conversationID = ?', [$conversationID]);
if (!$isAuthor) {
if ($userID) {
- $this->getConditionBuilder()->add('conversation_to_user.isInvisible = 0 OR conversation_to_user.participantID = ?', array($userID));
+ $this->getConditionBuilder()->add('conversation_to_user.isInvisible = 0 OR conversation_to_user.participantID = ?', [$userID]);
}
else {
$this->getConditionBuilder()->add('conversation_to_user.isInvisible = 0');
$this->sqlJoins .= " LEFT JOIN wcf".WCF_N."_conversation_to_user conversation_to_user ON (conversation_to_user.participantID = user_table.userID AND conversation_to_user.conversationID = ".$conversationID.")";
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\data\DatabaseObjectList::countObjects()
+ * @inheritDoc
*/
public function countObjects() {
$sql = "SELECT COUNT(*) AS count
return $row['count'];
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\data\DatabaseObjectList::readObjectIDs()
+ * @inheritDoc
*/
public function readObjectIDs() {
- $this->objectIDs = array();
+ $this->objectIDs = [];
$sql = "SELECT conversation_to_user.participantID AS objectID
FROM wcf".WCF_N."_conversation_to_user conversation_to_user
".$this->sqlConditionJoins."
".(!empty($this->sqlOrderBy) ? "ORDER BY ".$this->sqlOrderBy : '');
$statement = WCF::getDB()->prepareStatement($sql, $this->sqlLimit, $this->sqlOffset);
$statement->execute($this->getConditionBuilder()->getParameters());
- while ($row = $statement->fetchArray()) {
- $this->objectIDs[] = $row['objectID'];
- }
+ $this->objectIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
}
/**
- * @see \wcf\data\user\UserProfileList::readObjects()
+ * @inheritDoc
*/
public function readObjects() {
parent::readObjects();
WHERE conversationID = ?
AND participantID IS NULL";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($this->conversationID));
+ $statement->execute([$this->conversationID]);
$i = 0;
while ($row = $statement->fetchArray()) {
// create fake user profiles
- $user = new User(null, array('userID' => 0, 'username' => $row['username']));
- $this->objects['x'.(++$i)] = new UserProfile($user);
+ $this->objects['x'.(++$i)] = UserProfile::getGuestUserProfile($row['username']);
$this->indexToObject[] = 'x'.$i;
}
}
* Represents a conversation for RSS feeds.
*
* @author Alexander Ebert
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation
+ *
+ * @method Conversation getDecoratedObject()
+ * @mixin Conversation
*/
class FeedConversation extends DatabaseObjectDecorator implements IFeedEntry {
/**
- * @see \wcf\data\DatabaseObjectDecorator::$baseClass
+ * @inheritDoc
*/
- protected static $baseClass = 'wcf\data\conversation\Conversation';
+ protected static $baseClass = Conversation::class;
/**
- * @see \wcf\data\ILinkableObject::getLink()
+ * @inheritDoc
*/
public function getLink() {
- return LinkHandler::getInstance()->getLink('Conversation', array(
+ return LinkHandler::getInstance()->getLink('Conversation', [
'object' => $this->getDecoratedObject(),
- 'appendSession' => false,
'encodeTitle' => true
- ));
+ ]);
}
/**
- * @see \wcf\data\ITitledObject::getTitle()
+ * @inheritDoc
*/
public function getTitle() {
return $this->getDecoratedObject()->getTitle();
}
/**
- * @see \wcf\data\IMessage::getFormattedMessage()
+ * @inheritDoc
*/
public function getFormattedMessage() {
return '';
}
/**
- * @see \wcf\data\IMessage::getMessage()
+ * @inheritDoc
*/
public function getMessage() {
return '';
}
/**
- * @see \wcf\data\IMessage::getExcerpt()
+ * @inheritDoc
*/
public function getExcerpt($maxLength = 255) {
return '';
}
/**
- * @see \wcf\data\IMessage::getUserID()
+ * @inheritDoc
*/
public function getUserID() {
return $this->getDecoratedObject()->lastPosterID;
}
/**
- * @see \wcf\data\IMessage::getUsername()
+ * @inheritDoc
*/
public function getUsername() {
return $this->getDecoratedObject()->lastPoster;
}
/**
- * @see \wcf\data\IMessage::getTime()
+ * @inheritDoc
*/
public function getTime() {
return $this->getDecoratedObject()->lastPostTime;
}
/**
- * @see \wcf\data\IMessage::__toString()
+ * @inheritDoc
*/
public function __toString() {
return $this->getFormattedMessage();
}
/**
- * @see \wcf\data\IFeedEntry::getComments()
+ * @inheritDoc
*/
public function getComments() {
return $this->replies;
}
/**
- * @see \wcf\data\IFeedEntry::getCategories()
+ * @inheritDoc
*/
public function getCategories() {
- return array();
+ return [];
}
/**
- * @see \wcf\data\IMessage::isVisible()
+ * @inheritDoc
*/
public function isVisible() {
return $this->canRead();
* Represents a list of conversations for RSS feeds.
*
* @author Alexander Ebert
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation
+ *
+ * @method FeedConversation current()
+ * @method FeedConversation[] getObjects()
+ * @method FeedConversation|null search($objectID)
+ * @property FeedConversation[] $objects
*/
class FeedConversationList extends ConversationList {
/**
- * @see \wcf\data\DatabaseObjectList::$decoratorClassName
+ * @inheritDoc
*/
- public $decoratorClassName = 'wcf\data\conversation\FeedConversation';
+ public $decoratorClassName = FeedConversation::class;
/**
- * @see \wcf\data\DatabaseObjectList::$sqlOrderBy
+ * @inheritDoc
*/
public $sqlOrderBy = 'conversation.lastPostTime DESC';
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\data\DatabaseObjectList::readObjectIDs()
+ * @inheritDoc
*/
public function readObjectIDs() {
- $this->objectIDs = array();
$sql = "SELECT conversation_to_user.conversationID AS objectID
FROM wcf".WCF_N."_conversation_to_user conversation_to_user
".$this->sqlConditionJoins."
".(!empty($this->sqlOrderBy) ? "ORDER BY ".$this->sqlOrderBy : '');
$statement = WCF::getDB()->prepareStatement($sql, $this->sqlLimit, $this->sqlOffset);
$statement->execute($this->getConditionBuilder()->getParameters());
- while ($row = $statement->fetchArray()) {
- $this->objectIDs[] = $row['objectID'];
- }
+ $this->objectIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
}
/**
- * @see \wcf\data\DatabaseObjectList::readObjects()
+ * @inheritDoc
*/
public function readObjects() {
if ($this->objectIDs === null) {
namespace wcf\data\conversation;
use wcf\data\conversation\label\ConversationLabel;
use wcf\data\conversation\label\ConversationLabelList;
+use wcf\system\cache\runtime\UserProfileRuntimeCache;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\WCF;
* Represents a list of conversations.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation
+ *
+ * @method ViewableConversation current()
+ * @method ViewableConversation[] getObjects()
+ * @method ViewableConversation|null search($objectID)
+ * @property ViewableConversation[] $objects
*/
class UserConversationList extends ConversationList {
/**
* list of available filters
- * @var array<string>
+ * @var string[]
*/
- public static $availableFilters = array('hidden', 'draft', 'outbox');
+ public static $availableFilters = ['hidden', 'draft', 'outbox'];
/**
* active filter
/**
* label list object
- * @var \wcf\data\conversation\label\ConversationLabelList
+ * @var ConversationLabelList
*/
- public $labelList = null;
+ public $labelList;
/**
- * @see \wcf\data\DatabaseObjectList::$decoratorClassName
+ * @inheritDoc
*/
- public $decoratorClassName = 'wcf\data\conversation\ViewableConversation';
+ public $decoratorClassName = ViewableConversation::class;
/**
* Creates a new UserConversationList
// apply filter
if ($this->filter == 'draft') {
- $this->getConditionBuilder()->add('conversation.userID = ?', array($userID));
+ $this->getConditionBuilder()->add('conversation.userID = ?', [$userID]);
$this->getConditionBuilder()->add('conversation.isDraft = 1');
}
else {
- $this->getConditionBuilder()->add('conversation_to_user.participantID = ?', array($userID));
- $this->getConditionBuilder()->add('conversation_to_user.hideConversation = ?', array(($this->filter == 'hidden' ? 1 : 0)));
+ $this->getConditionBuilder()->add('conversation_to_user.participantID = ?', [$userID]);
+ $this->getConditionBuilder()->add('conversation_to_user.hideConversation = ?', [$this->filter == 'hidden' ? 1 : 0]);
$this->sqlConditionJoins = "LEFT JOIN wcf".WCF_N."_conversation conversation ON (conversation.conversationID = conversation_to_user.conversationID)";
- if ($this->filter == 'outbox') $this->getConditionBuilder()->add('conversation.userID = ?', array($userID));
+ if ($this->filter == 'outbox') $this->getConditionBuilder()->add('conversation.userID = ?', [$userID]);
}
// filter by label id
SELECT conversationID
FROM wcf".WCF_N."_conversation_label_to_object
WHERE labelID = ?
- )", array($labelID));
+ )", [$labelID]);
}
// own posts
if (!empty($this->sqlSelects)) $this->sqlSelects .= ',';
$this->sqlSelects .= "conversation_to_user.*";
$this->sqlJoins .= "LEFT JOIN wcf".WCF_N."_conversation_to_user conversation_to_user ON (conversation_to_user.participantID = ".$userID." AND conversation_to_user.conversationID = conversation.conversationID)";
-
- // get avatars
- if (!empty($this->sqlSelects)) $this->sqlSelects .= ',';
- $this->sqlSelects .= "user_avatar.*, user_table.email, user_table.disableAvatar, user_table.enableGravatar, user_table.gravatarFileExtension";
- $this->sqlJoins .= " LEFT JOIN wcf".WCF_N."_user user_table ON (user_table.userID = conversation.userID)";
- $this->sqlJoins .= " LEFT JOIN wcf".WCF_N."_user_avatar user_avatar ON (user_avatar.avatarID = user_table.avatarID)";
-
- if (!empty($this->sqlSelects)) $this->sqlSelects .= ',';
- $this->sqlSelects .= "lastposter_avatar.avatarID AS lastPosterAvatarID, lastposter_avatar.avatarName AS lastPosterAvatarName, lastposter_avatar.avatarExtension AS lastPosterAvatarExtension, lastposter_avatar.width AS lastPosterAvatarWidth, lastposter_avatar.height AS lastPosterAvatarHeight,";
- $this->sqlSelects .= "lastposter.email AS lastPosterEmail, lastposter.disableAvatar AS lastPosterDisableAvatar, lastposter.enableGravatar AS lastPosterEnableGravatar, lastposter.gravatarFileExtension AS lastPosterGravatarFileExtension";
- $this->sqlJoins .= " LEFT JOIN wcf".WCF_N."_user lastposter ON (lastposter.userID = conversation.lastPosterID)";
- $this->sqlJoins .= " LEFT JOIN wcf".WCF_N."_user_avatar lastposter_avatar ON (lastposter_avatar.avatarID = lastposter.avatarID)";
}
/**
* Sets the label list of the user the conversations belong to.
*
- * @param \wcf\data\conversation\label\ConversationLabelList $labelList
+ * @param ConversationLabelList $labelList
*/
public function setLabelList(ConversationLabelList $labelList) {
$this->labelList = $labelList;
}
/**
- * @see \wcf\data\DatabaseObjectList::countObjects()
+ * @inheritDoc
*/
public function countObjects() {
if ($this->filter == 'draft') return parent::countObjects();
}
/**
- * @see \wcf\data\DatabaseObjectList::readObjectIDs()
+ * @inheritDoc
*/
public function readObjectIDs() {
- if ($this->filter == 'draft') return parent::readObjectIDs();
+ if ($this->filter == 'draft') {
+ parent::readObjectIDs();
+
+ return;
+ }
- $this->objectIDs = array();
$sql = "SELECT conversation_to_user.conversationID AS objectID
FROM wcf".WCF_N."_conversation_to_user conversation_to_user
".$this->sqlConditionJoins."
".(!empty($this->sqlOrderBy) ? "ORDER BY ".$this->sqlOrderBy : '');
$statement = WCF::getDB()->prepareStatement($sql, $this->sqlLimit, $this->sqlOffset);
$statement->execute($this->getConditionBuilder()->getParameters());
- while ($row = $statement->fetchArray()) {
- $this->objectIDs[] = $row['objectID'];
- }
+ $this->objectIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
}
/**
- * @see \wcf\data\DatabaseObjectList::readObjects()
+ * @inheritDoc
*/
public function readObjects() {
if ($this->objectIDs === null) {
if (!empty($this->objects)) {
$labels = $this->loadLabelAssignments();
+ $userIDs = [];
foreach ($this->objects as $conversationID => $conversation) {
if (isset($labels[$conversationID])) {
foreach ($labels[$conversationID] as $label) {
$conversation->assignLabel($label);
}
}
+
+ if ($conversation->userID) {
+ $userIDs[] = $conversation->userID;
+ }
+ if ($conversation->lastPosterID) {
+ $userIDs[] = $conversation->lastPosterID;
+ }
+ }
+
+ if (!empty($userIDs)) {
+ UserProfileRuntimeCache::getInstance()->cacheObjectIDs($userIDs);
}
}
}
/**
* Returns a list of conversation labels.
*
- * @return array<\wcf\data\conversation\label\ConversationLabel>
+ * @return ConversationLabel[]
*/
protected function getLabels() {
if ($this->labelList === null) {
/**
* Returns label assignments per conversation.
*
- * @return array<array>
+ * @return ConversationLabel[][]
*/
protected function loadLabelAssignments() {
$labels = $this->getLabels();
if (empty($labels)) {
- return array();
+ return [];
}
$conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID IN (?)", array(array_keys($this->objects)));
- $conditions->add("labelID IN (?)", array(array_keys($labels)));
+ $conditions->add("conversationID IN (?)", [array_keys($this->objects)]);
+ $conditions->add("labelID IN (?)", [array_keys($labels)]);
$sql = "SELECT labelID, conversationID
FROM wcf".WCF_N."_conversation_label_to_object
".$conditions;
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute($conditions->getParameters());
- $data = array();
+ $data = [];
while ($row = $statement->fetchArray()) {
if (!isset($data[$row['conversationID']])) {
- $data[$row['conversationID']] = array();
+ $data[$row['conversationID']] = [];
}
$data[$row['conversationID']][$row['labelID']] = $labels[$row['labelID']];
use wcf\data\user\User;
use wcf\data\user\UserProfile;
use wcf\data\DatabaseObjectDecorator;
+use wcf\data\TLegacyUserPropertyAccess;
+use wcf\system\cache\runtime\UserProfileRuntimeCache;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\WCF;
* Represents a viewable conversation.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation
+ *
+ * @method Conversation getDecoratedObject()
+ * @mixin Conversation
+ * @property-read integer|null $otherParticipantID
+ * @property-read string|null $otherParticipant
*/
class ViewableConversation extends DatabaseObjectDecorator {
+ use TLegacyUserPropertyAccess;
+
/**
* participant summary
* @var string
*/
- protected $__participantSummary = null;
+ protected $__participantSummary;
/**
* user profile object
- * @var \wcf\data\user\UserProfile
+ * @var UserProfile
*/
- protected $userProfile = null;
+ protected $userProfile;
/**
* last poster's profile
- * @var \wcf\data\user\UserProfile
+ * @var UserProfile
*/
- protected $lastPosterProfile = null;
+ protected $lastPosterProfile;
/**
- * @see \wcf\data\DatabaseObjectDecorator::$baseClass
+ * other participant's profile
+ * @var UserProfile
*/
- protected static $baseClass = 'wcf\data\conversation\Conversation';
+ protected $otherParticipantProfile;
/**
* list of assigned labels
- * @var array<\wcf\data\conversation\label\ConversationLabel>
+ * @var ConversationLabel[]
+ */
+ protected $labels = [];
+
+ /**
+ * @inheritDoc
+ */
+ protected static $baseClass = Conversation::class;
+
+ /**
+ * maps legacy direct access to last poster's user profile data to the real
+ * user profile property names
+ * @var string[]
+ * @deprecated
*/
- protected $labels = array();
+ protected static $__lastUserAvatarPropertyMapping = [
+ 'lastPosterAvatarID' => 'avatarID',
+ 'lastPosterAvatarName' => 'avatarName',
+ 'lastPosterAvatarExtension' => 'avatarExtension',
+ 'lastPosterAvatarWidth' => 'width',
+ 'lastPosterAvatarHeight' => 'height',
+ 'lastPosterEmail' => 'email',
+ 'lastPosterDisableAvatar' => 'disableAvatar',
+ 'lastPosterEnableGravatar' => 'enableGravatar',
+ 'lastPosterGravatarFileExtension' => 'gravatarFileExtension',
+ 'lastPosterAvatarFileHash' => 'fileHash'
+ ];
+
+ /**
+ * @inheritDoc
+ * @deprecated
+ */
+ public function __get($name) {
+ $value = parent::__get($name);
+ if ($value !== null) {
+ return $value;
+ }
+ else if (array_key_exists($name, $this->object->data)) {
+ return null;
+ }
+
+ /** @noinspection PhpVariableVariableInspection */
+ $value = $this->getUserProfile()->$name;
+ if ($value !== null) {
+ return $value;
+ }
+
+ if (isset(static::$__lastUserAvatarPropertyMapping[$name])) {
+ return $this->getLastPosterProfile()->getAvatar()->{static::$__lastUserAvatarPropertyMapping[$name]};
+ }
+
+ return null;
+ }
/**
* Returns the user profile object.
*
- * @return \wcf\data\user\UserProfile
+ * @return UserProfile
*/
public function getUserProfile() {
if ($this->userProfile === null) {
- $this->userProfile = new UserProfile(new User(null, $this->getDecoratedObject()->data));
+ if ($this->userID) {
+ $this->userProfile = UserProfileRuntimeCache::getInstance()->getObject($this->userID);
+ }
+ else {
+ $this->userProfile = UserProfile::getGuestUserProfile($this->username);
+ }
}
return $this->userProfile;
/**
* Returns the last poster's profile object.
*
- * @return \wcf\data\user\UserProfile
+ * @return UserProfile
*/
public function getLastPosterProfile() {
if ($this->lastPosterProfile === null) {
- if ($this->userID && $this->userID == $this->lastPosterID) {
- $this->lastPosterProfile = $this->getUserProfile();
+ if ($this->lastPosterID) {
+ $this->lastPosterProfile = UserProfileRuntimeCache::getInstance()->getObject($this->lastPosterID);
}
else {
- $this->lastPosterProfile = new UserProfile(new User(null, array(
- 'userID' => $this->lastPosterID,
- 'username' => $this->lastPoster,
- 'avatarID' => $this->lastPosterAvatarID,
- 'avatarName' => $this->lastPosterAvatarName,
- 'avatarExtension' => $this->lastPosterAvatarExtension,
- 'width' => $this->lastPosterAvatarWidth,
- 'height' => $this->lastPosterAvatarHeight,
- 'email' => $this->lastPosterEmail,
- 'disableAvatar' => $this->lastPosterDisableAvatar,
- 'enableGravatar' => $this->lastPosterEnableGravatar,
- 'gravatarFileExtension' => $this->lastPosterGravatarFileExtension
- )));
+ $this->lastPosterProfile = UserProfile::getGuestUserProfile($this->lastPoster);
}
}
* @return integer
*/
public function getPages() {
+ /** @noinspection PhpUndefinedFieldInspection */
if (WCF::getUser()->conversationMessagesPerPage) {
+ /** @noinspection PhpUndefinedFieldInspection */
$messagesPerPage = WCF::getUser()->conversationMessagesPerPage;
}
else {
/**
* Returns a summary of the participants.
*
- * @return array<\wcf\data\user\User>
+ * @return User[]
*/
public function getParticipantSummary() {
if ($this->__participantSummary === null) {
- $this->__participantSummary = array();
+ $this->__participantSummary = [];
if ($this->participantSummary) {
$data = unserialize($this->participantSummary);
if ($data !== false) {
foreach ($data as $userData) {
- $this->__participantSummary[] = new User(null, array(
+ $this->__participantSummary[] = new User(null, [
'userID' => $userData['userID'],
'username' => $userData['username'],
'hideConversation' => $userData['hideConversation']
- ));
+ ]);
}
}
}
return $this->__participantSummary;
}
+ /**
+ * Returns the other participant's profile object.
+ *
+ * @return UserProfile
+ */
+ public function getOtherParticipantProfile() {
+ if ($this->otherParticipantProfile === null) {
+ if ($this->otherParticipantID) {
+ $this->otherParticipantProfile = UserProfileRuntimeCache::getInstance()->getObject($this->otherParticipantID);
+ }
+ else {
+ $this->otherParticipantProfile = UserProfile::getGuestUserProfile($this->otherParticipant);
+ }
+ }
+
+ return $this->otherParticipantProfile;
+ }
+
/**
* Assigns a label.
*
- * @param \wcf\data\conversation\label\ConversationLabel $label
+ * @param ConversationLabel $label
*/
public function assignLabel(ConversationLabel $label) {
$this->labels[$label->labelID] = $label;
/**
* Returns a list of assigned labels.
*
- * @return array<\wcf\data\conversation\label\ConversationLabel>
+ * @return ConversationLabel[]
*/
public function getAssignedLabels() {
return $this->labels;
/**
* Converts a conversation into a viewable conversation.
*
- * @param \wcf\data\conversation\Conversation $conversation
- * @param \wcf\data\conversation\label\ConversationLabelList $labelList
- * @return \wcf\data\conversation\ViewableConversation
+ * @param Conversation $conversation
+ * @param ConversationLabelList $labelList
+ * @return ViewableConversation
*/
public static function getViewableConversation(Conversation $conversation, ConversationLabelList $labelList = null) {
$conversation = new ViewableConversation($conversation);
$labels = $labelList->getObjects();
if (!empty($labels)) {
$conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID = ?", array($conversation->conversationID));
- $conditions->add("labelID IN (?)", array(array_keys($labels)));
+ $conditions->add("conversationID = ?", [$conversation->conversationID]);
+ $conditions->add("labelID IN (?)", [array_keys($labels)]);
$sql = "SELECT labelID
FROM wcf".WCF_N."_conversation_label_to_object
".$conditions;
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute($conditions->getParameters());
- $data = array();
while ($row = $statement->fetchArray()) {
$conversation->assignLabel($labels[$row['labelID']]);
}
* Represents a conversation label.
*
* @author Marcel Werk
- * @copyright 2009-2012 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation.label
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation\Label
+ *
+ * @property-read integer $labelID
+ * @property-read integer $userID
+ * @property-read string $label
+ * @property-read string $cssClassName
*/
class ConversationLabel extends DatabaseObject {
- /**
- * @see \wcf\data\DatabaseObject::$databaseTableName
- */
- protected static $databaseTableName = 'conversation_label';
-
- /**
- * @see \wcf\data\DatabaseObject::$databaseIndexName
- */
- protected static $databaseTableIndexName = 'labelID';
-
/**
* list of pre-defined css class names
- * @var array<string>
+ * @var string[]
*/
- public static $availableCssClassNames = array(
+ public static $availableCssClassNames = [
'yellow',
'orange',
'brown',
'black',
'none' /* not a real value */
- );
+ ];
/**
* Returns a list of conversation labels for given user id.
*
* @param integer $userID
- * @return \wcf\data\conversation\label\ConversationLabelList
+ * @return ConversationLabelList
*/
public static function getLabelsByUser($userID = null) {
if ($userID === null) $userID = WCF::getUser()->userID;
$labelList = new ConversationLabelList();
- $labelList->getConditionBuilder()->add("conversation_label.userID = ?", array($userID));
+ $labelList->getConditionBuilder()->add("conversation_label.userID = ?", [$userID]);
$labelList->readObjects();
return $labelList;
/**
* Returns a list of available CSS class names.
*
- * @return array<string>
+ * @return string[]
*/
public static function getLabelCssClassNames() {
return self::$availableCssClassNames;
* Executes label-related actions.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation.label
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation\Label
+ *
+ * @method ConversationLabel create()
+ * @method ConversationLabelEditor[] getObjects()
+ * @method ConversationLabelEditor getSingleObject()
*/
class ConversationLabelAction extends AbstractDatabaseObjectAction {
/**
- * @see \wcf\data\AbstractDatabaseObjectAction::$className
+ * @inheritDoc
*/
- protected $className = 'wcf\data\conversation\label\ConversationLabelEditor';
+ protected $className = ConversationLabelEditor::class;
/**
- * @see \wcf\data\AbstractDatabaseObjectAction::$permissionsDelete
+ * @inheritDoc
*/
- protected $permissionsDelete = array('user.conversation.canUseConversation');
+ protected $permissionsDelete = ['user.conversation.canUseConversation'];
/**
- * @see \wcf\data\AbstractDatabaseObjectAction::$permissionsUpdate
+ * @inheritDoc
*/
- protected $permissionsUpdate = array('user.conversation.canUseConversation');
+ protected $permissionsUpdate = ['user.conversation.canUseConversation'];
/**
* conversation object
- * @var \wcf\data\conversation\Conversation
+ * @var Conversation
*/
- public $conversation = null;
+ public $conversation;
/**
* conversation label list object
- * @var \wcf\data\conversation\label\ConversationLabelList
+ * @var ConversationLabelList
*/
- public $labelList = null;
+ public $labelList;
/**
- * @see \wcf\data\AbstractDatabaseObjectAction::validateUpdate()
+ * @inheritDoc
*/
public function validateUpdate() {
parent::validateUpdate();
}
/**
- * @see \wcf\data\AbstractDatabaseObjectAction::validateDelete()
+ * @inheritDoc
*/
public function validateDelete() {
parent::validateDelete();
* @return array
*/
public function add() {
- $label = ConversationLabelEditor::create(array(
+ $label = ConversationLabelEditor::create([
'userID' => WCF::getUser()->userID,
'label' => $this->parameters['data']['labelName'],
'cssClassName' => $this->parameters['data']['cssClassName']
- ));
+ ]);
- return array(
+ return [
'actionName' => 'add',
'cssClassName' => $label->cssClassName,
'label' => StringUtil::encodeHTML($label->label),
'labelID' => $label->labelID
- );
+ ];
}
/**
}
// validate conversation id
- $this->parameters['conversationIDs'] = (isset($this->parameters['conversationIDs'])) ? ArrayUtil::toIntegerArray($this->parameters['conversationIDs']) : array();
+ $this->parameters['conversationIDs'] = isset($this->parameters['conversationIDs']) ? ArrayUtil::toIntegerArray($this->parameters['conversationIDs']) : [];
if (empty($this->parameters['conversationIDs'])) {
throw new UserInputException('conversationID');
}
*/
public function getLabelForm() {
// read assigned labels
- $labelIDs = array();
+ $labelIDs = [];
foreach ($this->labelList as $label) {
$labelIDs[] = $label->labelID;
}
- $assignedLabels = array();
+ $assignedLabels = [];
// read assigned labels if editing single conversation
if (count($this->parameters['conversationIDs']) == 1) {
$conversationID = current($this->parameters['conversationIDs']);
$conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID = ?", array($conversationID));
- $conditions->add("labelID IN (?)", array($labelIDs));
+ $conditions->add("conversationID = ?", [$conversationID]);
+ $conditions->add("labelID IN (?)", [$labelIDs]);
$sql = "SELECT labelID
FROM wcf".WCF_N."_conversation_label_to_object
".$conditions;
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute($conditions->getParameters());
- $assignedLabels = array();
- while ($row = $statement->fetchArray()) {
- $assignedLabels[] = $row['labelID'];
- }
+ $assignedLabels = $statement->fetchAll(\PDO::FETCH_COLUMN);
}
- WCF::getTPL()->assign(array(
+ WCF::getTPL()->assign([
'assignedLabels' => $assignedLabels,
'conversation' => $this->conversation,
'labelList' => $this->labelList
- ));
+ ]);
- return array(
+ return [
'actionName' => 'getLabelForm',
'template' => WCF::getTPL()->fetch('conversationLabelAssignment')
- );
+ ];
}
/**
$this->validateGetLabelForm();
// validate given labels
- $this->parameters['labelIDs'] = (isset($this->parameters['labelIDs']) && is_array($this->parameters['labelIDs'])) ? ArrayUtil::toIntegerArray($this->parameters['labelIDs']) : array();
+ $this->parameters['labelIDs'] = (isset($this->parameters['labelIDs']) && is_array($this->parameters['labelIDs'])) ? ArrayUtil::toIntegerArray($this->parameters['labelIDs']) : [];
if (!empty($this->parameters['labelIDs'])) {
foreach ($this->parameters['labelIDs'] as $labelID) {
$isValid = false;
*/
public function assignLabel() {
// remove previous labels (if any)
- $labelIDs = array();
+ $labelIDs = [];
foreach ($this->labelList as $label) {
$labelIDs[] = $label->labelID;
}
$conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID IN (?)", array($this->parameters['conversationIDs']));
- $conditions->add("labelID IN (?)", array($labelIDs));
+ $conditions->add("conversationID IN (?)", [$this->parameters['conversationIDs']]);
+ $conditions->add("labelID IN (?)", [$labelIDs]);
$sql = "DELETE FROM wcf".WCF_N."_conversation_label_to_object
".$conditions;
WCF::getDB()->beginTransaction();
foreach ($this->parameters['labelIDs'] as $labelID) {
foreach ($this->parameters['conversationIDs'] as $conversationID) {
- $statement->execute(array(
+ $statement->execute([
$labelID,
$conversationID
- ));
+ ]);
}
}
WCF::getDB()->commitTransaction();
}
}
- return array(
+ return [
'actionName' => 'assignLabel',
'labelIDs' => $this->parameters['labelIDs']
- );
+ ];
}
}
* Extends the label object with functions to create, update and delete labels.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation.label
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation\Label
+ *
+ * @method static ConversationLabel create(array $parameters = [])
+ * @method ConversationLabel getDecoratedObject()
+ * @mixin ConversationLabel
*/
class ConversationLabelEditor extends DatabaseObjectEditor {
/**
- * @see \wcf\data\DatabaseObjectEditor::$baseClass
+ * @inheritDoc
*/
- protected static $baseClass = 'wcf\data\conversation\label\ConversationLabel';
+ protected static $baseClass = ConversationLabel::class;
}
* Represents a list of conversation labels.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation.label
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation\Label
+ *
+ * @method ConversationLabel current()
+ * @method ConversationLabel[] getObjects()
+ * @method ConversationLabel|null search($objectID)
+ * @property ConversationLabel[] $objects
*/
class ConversationLabelList extends DatabaseObjectList {
/**
- * @see \wcf\data\DatabaseObjectList::$className
+ * @inheritDoc
*/
- public $className = 'wcf\data\conversation\label\ConversationLabel';
+ public $className = ConversationLabel::class;
}
use wcf\data\conversation\Conversation;
use wcf\data\DatabaseObject;
use wcf\data\IMessage;
-use wcf\system\bbcode\MessageParser;
-use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
+use wcf\data\TUserContent;
+use wcf\system\html\output\HtmlOutputProcessor;
use wcf\system\request\LinkHandler;
use wcf\system\WCF;
use wcf\util\StringUtil;
* Represents a conversation message.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation.message
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation\Message
+ *
+ * @property-read integer $messageID
+ * @property-read integer $conversationID
+ * @property-read integer|null $userID
+ * @property-read string $username
+ * @property-read string $message
+ * @property-read integer $time
+ * @property-read integer $attachments
+ * @property-read integer $enableHtml
+ * @property-read string $ipAddress
+ * @property-read integer $lastEditTime
+ * @property-read integer $editCount
+ * @property-read integer $hasEmbeddedObjects
*/
class ConversationMessage extends DatabaseObject implements IMessage {
- /**
- * @see \wcf\data\DatabaseObject::$databaseTableName
- */
- protected static $databaseTableName = 'conversation_message';
-
- /**
- * @see \wcf\data\DatabaseObject::$databaseIndexName
- */
- protected static $databaseTableIndexName = 'messageID';
+ use TUserContent;
/**
* conversation object
- * @var \wcf\data\conversation\Conversation
+ * @var Conversation
*/
- protected $conversation = null;
+ protected $conversation;
/**
- * @see \wcf\data\IMessage::getFormattedMessage()
+ * @inheritDoc
*/
public function getFormattedMessage() {
- // assign embedded objects
- MessageEmbeddedObjectManager::getInstance()->setActiveMessage('com.woltlab.wcf.conversation.message', $this->messageID);
+ $processor = new HtmlOutputProcessor();
+ $processor->process($this->message, 'com.woltlab.wcf.conversation.message', $this->messageID);
- // parse and return message
- MessageParser::getInstance()->setOutputType('text/html');
- return MessageParser::getInstance()->parse($this->message, $this->enableSmilies, $this->enableHtml, $this->enableBBCodes);
+ return $processor->getHtml();
}
/**
* @return string
*/
public function getSimplifiedFormattedMessage() {
- MessageParser::getInstance()->setOutputType('text/simplified-html');
- return MessageParser::getInstance()->parse($this->message, $this->enableSmilies, $this->enableHtml, $this->enableBBCodes);
+ $processor = new HtmlOutputProcessor();
+ $processor->setOutputType('text/simplified-html');
+ $processor->process($this->message, 'com.woltlab.wcf.conversation.message', $this->messageID);
+
+ return $processor->getHtml();
}
/**
* Assigns and returns the embedded attachments.
*
* @param boolean $ignoreCache
- * @return \wcf\data\attachment\GroupedAttachmentList
+ * @return GroupedAttachmentList
*/
public function getAttachments($ignoreCache = false) {
if (MODULE_ATTACHMENT == 1 && ($this->attachments || $ignoreCache)) {
$attachmentList = new GroupedAttachmentList('com.woltlab.wcf.conversation.message');
- $attachmentList->getConditionBuilder()->add('attachment.objectID IN (?)', array($this->messageID));
+ $attachmentList->getConditionBuilder()->add('attachment.objectID IN (?)', [$this->messageID]);
$attachmentList->readObjects();
- $attachmentList->setPermissions(array(
+ $attachmentList->setPermissions([
'canDownload' => true,
'canViewPreview' => true
- ));
+ ]);
if ($ignoreCache && !count($attachmentList)) {
return null;
}
/**
- * Returns an excerpt of this message.
- *
- * @param string $maxLength
- * @return string
+ * @inheritDoc
*/
public function getExcerpt($maxLength = 255) {
return StringUtil::truncateHTML($this->getSimplifiedFormattedMessage(), $maxLength);
}
/**
- * Returns a text-only version of this message.
+ * Returns a version of this message optimized for use in emails.
*
+ * @param string $mimeType Either 'text/plain' or 'text/html'
* @return string
*/
- public function getMailText() {
- MessageParser::getInstance()->setOutputType('text/simplified-html');
- $message = MessageParser::getInstance()->parse($this->message, $this->enableSmilies, $this->enableHtml, $this->enableBBCodes);
+ public function getMailText($mimeType = 'text/plain') {
+ switch ($mimeType) {
+ case 'text/plain':
+ $processor = new HtmlOutputProcessor();
+ $processor->setOutputType('text/plain');
+ $processor->process($this->message, 'com.woltlab.wcf.conversation.message', $this->messageID);
+
+ return $processor->getHtml();
+ case 'text/html':
+ return $this->getSimplifiedFormattedMessage();
+ }
- return MessageParser::getInstance()->stripHTML($message);
+ throw new \LogicException('Unreachable');
}
/**
* Returns the conversation of this message.
*
- * @return \wcf\data\conversation\Conversation
+ * @return Conversation
*/
public function getConversation() {
if ($this->conversation === null) {
/**
* Sets the conversation of this message.
*
- * @param \wcf\data\conversation\Conversation $conversation
+ * @param Conversation $conversation
*/
public function setConversation(Conversation $conversation) {
if ($this->conversationID == $conversation->conversationID) {
}
/**
- * @see \wcf\data\IMessage::getMessage()
+ * @inheritDoc
*/
public function getMessage() {
return $this->message;
}
/**
- * @see \wcf\data\ILinkableObject::getLink()
+ * @inheritDoc
*/
public function getLink() {
- return LinkHandler::getInstance()->getLink('Conversation', array(
+ return LinkHandler::getInstance()->getLink('Conversation', [
'object' => $this->getConversation(),
'messageID' => $this->messageID
- ), '#message'.$this->messageID);
+ ], '#message'.$this->messageID);
}
/**
- * @see \wcf\data\IMessage::getTime()
- */
- public function getTime() {
- return $this->time;
- }
-
- /**
- * @see \wcf\data\ITitledObject::getTitle()
+ * @inheritDoc
*/
public function getTitle() {
if ($this->messageID == $this->getConversation()->firstMessageID) {
}
/**
- * @see \wcf\data\IMessage::getUserID()
- */
- public function getUserID() {
- return $this->userID;
- }
-
- /**
- * @see \wcf\data\IMessage::getUsername()
- */
- public function getUsername() {
- return $this->username;
- }
-
- /**
- * @see \wcf\data\IMessage::isVisible()
+ * @inheritDoc
*/
public function isVisible() {
return true;
}
/**
- * @see \wcf\data\IMessage::__toString()
+ * @inheritDoc
*/
public function __toString() {
return $this->getFormattedMessage();
use wcf\data\IMessageQuoteAction;
use wcf\system\attachment\AttachmentHandler;
use wcf\system\bbcode\BBCodeHandler;
-use wcf\system\bbcode\BBCodeParser;
-use wcf\system\bbcode\PreParser;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\exception\UserInputException;
+use wcf\system\html\input\HtmlInputProcessor;
use wcf\system\message\censorship\Censorship;
use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
use wcf\system\message\quote\MessageQuoteManager;
use wcf\system\user\notification\UserNotificationHandler;
use wcf\system\user\storage\UserStorageHandler;
use wcf\system\WCF;
-use wcf\util\MessageUtil;
use wcf\util\StringUtil;
/**
* Executes conversation message-related actions.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation.message
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation\Message
+ *
+ * @method ConversationMessageEditor[] getObjects()
+ * @method ConversationMessageEditor getSingleObject()
*/
class ConversationMessageAction extends AbstractDatabaseObjectAction implements IAttachmentMessageQuickReplyAction, IMessageInlineEditorAction, IMessageQuoteAction {
/**
- * @see \wcf\data\AbstractDatabaseObjectAction::$className
+ * @inheritDoc
*/
- protected $className = 'wcf\data\conversation\message\ConversationMessageEditor';
+ protected $className = ConversationMessageEditor::class;
/**
* conversation object
- * @var \wcf\data\conversation\Conversation
+ * @var Conversation
*/
- public $conversation = null;
+ public $conversation;
+
+ /**
+ * @var HtmlInputProcessor
+ */
+ public $htmlInputProcessor;
/**
* conversation message object
- * @var \wcf\data\conversation\message\ConversationMessage
+ * @var ConversationMessage
*/
- public $message = null;
+ public $message;
/**
- * @see \wcf\data\AbstractDatabaseObjectAction::create()
+ * @inheritDoc
+ * @return ConversationMessage
*/
public function create() {
+ if (!isset($this->parameters['data']['enableHtml'])) $this->parameters['data']['enableHtml'] = 1;
+
// count attachments
if (isset($this->parameters['attachmentHandler']) && $this->parameters['attachmentHandler'] !== null) {
$this->parameters['data']['attachments'] = count($this->parameters['attachmentHandler']);
}
}
+ if (!empty($this->parameters['htmlInputProcessor'])) {
+ /** @noinspection PhpUndefinedMethodInspection */
+ $this->parameters['data']['message'] = $this->parameters['htmlInputProcessor']->getHtml();
+ }
+
// create message
+ /** @var ConversationMessage $message */
$message = parent::create();
$messageEditor = new ConversationMessageEditor($message);
// get conversation
- $conversation = (isset($this->parameters['converation']) ? $this->parameters['converation'] : new Conversation($message->conversationID));
+ $conversation = (isset($this->parameters['conversation']) ? $this->parameters['conversation'] : new Conversation($message->conversationID));
$conversationEditor = new ConversationEditor($conversation);
if (empty($this->parameters['isFirstPost'])) {
// fire notification event
if (!$conversation->isDraft) {
- $notificationRecipients = array_diff($conversation->getParticipantIDs(true), array($message->userID)); // don't notify message author
+ $notificationRecipients = array_diff($conversation->getParticipantIDs(true), [$message->userID]); // don't notify message author
if (!empty($notificationRecipients)) {
- UserNotificationHandler::getInstance()->fireEvent('conversationMessage', 'com.woltlab.wcf.conversation.message.notification', new ConversationMessageUserNotificationObject($message), $notificationRecipients);
+ UserNotificationHandler::getInstance()->fireEvent(
+ 'conversationMessage',
+ 'com.woltlab.wcf.conversation.message.notification',
+ new ConversationMessageUserNotificationObject($message),
+ $notificationRecipients
+ );
}
}
WHERE participantID = ?
AND conversationID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($message->userID, $conversation->conversationID));
+ $statement->execute([$message->userID, $conversation->conversationID]);
$conversationEditor->updateParticipantSummary();
$conversationEditor->updateParticipantCount();
WHERE conversationID = ?
AND hideConversation = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
+ $statement->execute([
Conversation::STATE_DEFAULT,
$conversation->conversationID,
Conversation::STATE_HIDDEN
- ));
+ ]);
}
// reset storage
UserStorageHandler::getInstance()->reset($conversation->getParticipantIDs(), 'unreadConversationCount');
// update search index
- SearchIndexManager::getInstance()->add('com.woltlab.wcf.conversation.message', $message->messageID, $message->message, (!empty($this->parameters['isFirstPost']) ? $conversation->subject : ''), $message->time, $message->userID, $message->username);
+ SearchIndexManager::getInstance()->set(
+ 'com.woltlab.wcf.conversation.message',
+ $message->messageID,
+ $message->message,
+ !empty($this->parameters['isFirstPost']) ? $conversation->subject : '',
+ $message->time,
+ $message->userID,
+ $message->username
+ );
// update attachments
if (isset($this->parameters['attachmentHandler']) && $this->parameters['attachmentHandler'] !== null) {
+ /** @noinspection PhpUndefinedMethodInspection */
$this->parameters['attachmentHandler']->updateObjectID($message->messageID);
}
// save embedded objects
- if (MessageEmbeddedObjectManager::getInstance()->registerObjects('com.woltlab.wcf.conversation.message', $message->messageID, $message->message)) {
- $messageEditor->update(array(
- 'hasEmbeddedObjects' => 1
- ));
+ if (!empty($this->parameters['htmlInputProcessor'])) {
+ /** @noinspection PhpUndefinedMethodInspection */
+ $this->parameters['htmlInputProcessor']->setObjectID($message->messageID);
+
+ if (MessageEmbeddedObjectManager::getInstance()->registerObjects($this->parameters['htmlInputProcessor'])) {
+ $messageEditor->update(['hasEmbeddedObjects' => 1]);
+ }
}
// clear quotes
}
/**
- * @see \wcf\data\AbstractDatabaseObjectAction::update()
+ * @inheritDoc
*/
public function update() {
// count attachments
$this->parameters['data']['attachments'] = count($this->parameters['attachmentHandler']);
}
+ if (!empty($this->parameters['htmlInputProcessor'])) {
+ /** @noinspection PhpUndefinedMethodInspection */
+ $this->parameters['data']['message'] = $this->parameters['htmlInputProcessor']->getHtml();
+ }
+
parent::update();
// update search index / embedded objects
if (isset($this->parameters['data']) && isset($this->parameters['data']['message'])) {
- foreach ($this->objects as $message) {
+ foreach ($this->getObjects() as $message) {
$conversation = $message->getConversation();
- SearchIndexManager::getInstance()->update('com.woltlab.wcf.conversation.message', $message->messageID, $this->parameters['data']['message'], ($conversation->firstMessageID == $message->messageID ? $conversation->subject : ''), $message->time, $message->userID, $message->username);
+ SearchIndexManager::getInstance()->set(
+ 'com.woltlab.wcf.conversation.message',
+ $message->messageID,
+ $this->parameters['data']['message'],
+ $conversation->firstMessageID == $message->messageID ? $conversation->subject : '',
+ $message->time,
+ $message->userID,
+ $message->username
+ );
- if ($message->hasEmbeddedObjects != MessageEmbeddedObjectManager::getInstance()->registerObjects('com.woltlab.wcf.conversation.message', $message->messageID, $this->parameters['data']['message'])) {
- $message->update(array(
- 'hasEmbeddedObjects' => ($message->hasEmbeddedObjects ? 0 : 1)
- ));
+ if (!empty($this->parameters['htmlInputProcessor'])) {
+ /** @noinspection PhpUndefinedMethodInspection */
+ $this->parameters['htmlInputProcessor']->setObjectID($message->messageID);
+
+ if ($message->hasEmbeddedObjects != MessageEmbeddedObjectManager::getInstance()->registerObjects($this->parameters['htmlInputProcessor'])) {
+ $message->update(['hasEmbeddedObjects' => $message->hasEmbeddedObjects ? 0 : 1]);
+ }
}
}
}
}
/**
- * @see \wcf\data\AbstractDatabaseObjectAction::delete()
+ * @inheritDoc
*/
public function delete() {
$count = parent::delete();
- $attachmentMessageIDs = $conversationIDs = array();
- foreach ($this->objects as $message) {
+ $attachmentMessageIDs = $conversationIDs = [];
+ foreach ($this->getObjects() as $message) {
if (!in_array($message->conversationID, $conversationIDs)) {
$conversationIDs[] = $message->conversationID;
}
if (!empty($this->objectIDs)) {
// delete notifications
- UserNotificationHandler::getInstance()->deleteNotifications('conversationMessage', 'com.woltlab.wcf.conversation.message.notification', array(), $this->objectIDs);
+ UserNotificationHandler::getInstance()->removeNotifications('com.woltlab.wcf.conversation.message.notification', $this->objectIDs);
// update search index
SearchIndexManager::getInstance()->delete('com.woltlab.wcf.conversation.message', $this->objectIDs);
}
/**
- * @see \wcf\data\IMessageQuickReply::validateQuickReply()
+ * @inheritDoc
*/
public function validateQuickReply() {
- QuickReplyManager::getInstance()->setAllowedBBCodes(explode(',', WCF::getSession()->getPermission('user.message.allowedBBCodes')));
- QuickReplyManager::getInstance()->validateParameters($this, $this->parameters, 'wcf\data\conversation\Conversation');
+ QuickReplyManager::getInstance()->setDisallowedBBCodes(explode(',', WCF::getSession()->getPermission('user.message.disallowedBBCodes')));
+ QuickReplyManager::getInstance()->validateParameters($this, $this->parameters, Conversation::class);
}
/**
- * @see \wcf\data\IMessageQuickReply::quickReply()
+ * @inheritDoc
*/
public function quickReply() {
return QuickReplyManager::getInstance()->createMessage(
$this,
$this->parameters,
- 'wcf\data\conversation\ConversationAction',
+ ConversationAction::class,
CONVERSATION_LIST_DEFAULT_SORT_ORDER,
'conversationMessageList'
);
}
/**
- * @see \wcf\data\IExtendedMessageQuickReplyAction::validateJumpToExtended()
+ * @inheritDoc
*/
public function validateJumpToExtended() {
$this->readInteger('containerID');
if (!$this->conversation->conversationID) {
throw new UserInputException('containerID');
}
- else if ($this->conversation->isClosed || !Conversation::isParticipant(array($this->conversation->conversationID))) {
+ else if ($this->conversation->isClosed || !Conversation::isParticipant([$this->conversation->conversationID])) {
throw new PermissionDeniedException();
}
}
/**
- * @see \wcf\data\IExtendedMessageQuickReplyAction::jumpToExtended()
+ * @inheritDoc
*/
public function jumpToExtended() {
// quick reply
if ($this->message === null) {
QuickReplyManager::getInstance()->setMessage('conversation', $this->conversation->conversationID, $this->parameters['message']);
- $url = LinkHandler::getInstance()->getLink('ConversationMessageAdd', array('id' => $this->conversation->conversationID));
+ $url = LinkHandler::getInstance()->getLink('ConversationMessageAdd', ['id' => $this->conversation->conversationID]);
}
else {
// editing message
QuickReplyManager::getInstance()->setMessage('conversationMessage', $this->message->messageID, $this->parameters['message']);
- $url = LinkHandler::getInstance()->getLink('ConversationMessageEdit', array('id' => $this->message->messageID));
+ $url = LinkHandler::getInstance()->getLink('ConversationMessageEdit', ['id' => $this->message->messageID]);
}
if (!empty($this->parameters['tmpHash'])) {
}
// redirect
- return array(
+ return [
'url' => $url
- );
+ ];
}
/**
- * @see \wcf\data\IMessageInlineEditorAction::validateBeginEdit()
+ * @inheritDoc
*/
public function validateBeginEdit() {
$this->readInteger('containerID');
throw new UserInputException('containerID');
}
- if ($this->conversation->isClosed || !Conversation::isParticipant(array($this->conversation->conversationID))) {
+ if ($this->conversation->isClosed || !Conversation::isParticipant([$this->conversation->conversationID])) {
throw new PermissionDeniedException();
}
if (!$this->message->canEdit()) {
throw new PermissionDeniedException();
}
+
+ BBCodeHandler::getInstance()->setDisallowedBBCodes(explode(',', WCF::getSession()->getPermission('user.message.disallowedBBCodes')));
}
/**
- * @see \wcf\data\IMessageInlineEditorAction::beginEdit()
+ * @inheritDoc
*/
public function beginEdit() {
- BBCodeHandler::getInstance()->setAllowedBBCodes(explode(',', WCF::getSession()->getPermission('user.message.allowedBBCodes')));
-
- WCF::getTPL()->assign(array(
+ WCF::getTPL()->assign([
'defaultSmilies' => SmileyCache::getInstance()->getCategorySmilies(),
'message' => $this->message,
'permissionCanUseSmilies' => 'user.message.canUseSmilies',
'wysiwygSelector' => 'messageEditor'.$this->message->messageID
- ));
+ ]);
if (MODULE_ATTACHMENT) {
$tmpHash = StringUtil::getRandomID();
$attachmentHandler = new AttachmentHandler('com.woltlab.wcf.conversation.message', $this->message->messageID, $tmpHash);
$attachmentList = $attachmentHandler->getAttachmentList();
- WCF::getTPL()->assign(array(
+ WCF::getTPL()->assign([
'attachmentHandler' => $attachmentHandler,
'attachmentList' => $attachmentList->getObjects(),
'attachmentObjectID' => $this->message->messageID,
'attachmentObjectType' => 'com.woltlab.wcf.conversation.message',
'attachmentParentObjectID' => 0,
'tmpHash' => $tmpHash
- ));
+ ]);
}
- return array(
+ return [
'actionName' => 'beginEdit',
'template' => WCF::getTPL()->fetch('conversationMessageInlineEditor')
- );
+ ];
}
/**
- * @see \wcf\data\IMessageInlineEditorAction::validateSave()
+ * @inheritDoc
*/
public function validateSave() {
$this->readString('message', true, 'data');
if (empty($this->parameters['data']['message'])) {
- throw new UserInputException('message', WCF::getLanguage()->get('wcf.global.form.error.empty'));
+ throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.global.form.error.empty'));
}
$this->validateBeginEdit();
- $this->validateMessage($this->conversation, $this->parameters['data']['message']);
+
+ $this->validateMessage($this->conversation, $this->getHtmlInputProcessor($this->parameters['data']['message'], $this->message->messageID));
}
/**
- * @see \wcf\data\IMessageInlineEditorAction::save()
+ * @inheritDoc
*/
public function save() {
- $data = array(
- 'message' => PreParser::getInstance()->parse(MessageUtil::stripCrap($this->parameters['data']['message']), explode(',', WCF::getSession()->getPermission('user.message.allowedBBCodes')))
- );
+ $data = [];
+
if (!$this->message->getConversation()->isDraft) {
$data['lastEditTime'] = TIME_NOW;
$data['editCount'] = $this->message->editCount + 1;
}
// execute update action
- $action = new ConversationMessageAction(array($this->message), 'update', array('data' => $data));
+ $action = new ConversationMessageAction([$this->message], 'update', [
+ 'data' => $data,
+ 'htmlInputProcessor' => $this->getHtmlInputProcessor()
+ ]);
$action->executeAction();
// load new message
$this->message = new ConversationMessage($this->message->messageID);
$this->message->getAttachments();
+ $attachmentList = null;
if (MODULE_ATTACHMENT) {
$attachmentList = $this->message->getAttachments(true);
$count = 0;
if ($attachmentList !== null) {
- // set permisions
- $attachmentList->setPermissions(array(
+ // set permissions
+ $attachmentList->setPermissions([
'canDownload' => true,
'canViewPreview' => true
- ));
+ ]);
$count = count($attachmentList);
}
// update count to reflect number of attachments after edit
if ($count != $this->message->attachments) {
$messageEditor = new ConversationMessageEditor($this->message);
- $messageEditor->update(array('attachments' => $count));
+ $messageEditor->update(['attachments' => $count]);
}
}
// load embedded objects
- MessageEmbeddedObjectManager::getInstance()->loadObjects('com.woltlab.wcf.conversation.message', array($this->message->messageID));
+ MessageEmbeddedObjectManager::getInstance()->loadObjects('com.woltlab.wcf.conversation.message', [$this->message->messageID]);
- $data = array(
+ $data = [
'actionName' => 'save',
'message' => $this->message->getFormattedMessage()
- );
+ ];
if (MODULE_ATTACHMENT) {
- WCF::getTPL()->assign(array(
+ WCF::getTPL()->assign([
'attachmentList' => $attachmentList,
'objectID' => $this->message->messageID
- ));
+ ]);
$data['attachmentList'] = WCF::getTPL()->fetch('attachments');
}
}
/**
- * @see \wcf\data\IMessageQuickReply::validateContainer()
+ * @inheritDoc
*/
public function validateContainer(DatabaseObject $conversation) {
+ /** @var Conversation $conversation */
+
if (!$conversation->conversationID) {
throw new UserInputException('objectID');
}
}
/**
- * @see \wcf\data\IMessageQuickReplyAction::validateMessage()
+ * @inheritDoc
*/
- public function validateMessage(DatabaseObject $container, $message) {
+ public function validateMessage(DatabaseObject $container, HtmlInputProcessor $htmlInputProcessor) {
+ $message = $htmlInputProcessor->getTextContent();
if (mb_strlen($message) > WCF::getSession()->getPermission('user.conversation.maxLength')) {
- throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.message.error.tooLong', array('maxTextLength' => WCF::getSession()->getPermission('user.conversation.maxLength'))));
+ throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.message.error.tooLong', ['maxTextLength' => WCF::getSession()->getPermission('user.conversation.maxLength')]));
}
// search for disallowed bbcodes
- $disallowedBBCodes = BBCodeParser::getInstance()->validateBBCodes($message, explode(',', WCF::getSession()->getPermission('user.message.allowedBBCodes')));
+ $disallowedBBCodes = $htmlInputProcessor->validate();
if (!empty($disallowedBBCodes)) {
- throw new UserInputException('text', WCF::getLanguage()->getDynamicVariable('wcf.message.error.disallowedBBCodes', array('disallowedBBCodes' => $disallowedBBCodes)));
+ throw new UserInputException('text', WCF::getLanguage()->getDynamicVariable('wcf.message.error.disallowedBBCodes', ['disallowedBBCodes' => $disallowedBBCodes]));
}
// search for censored words
if (ENABLE_CENSORSHIP) {
$result = Censorship::getInstance()->test($message);
if ($result) {
- throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.message.error.censoredWordsFound', array('censoredWords' => $result)));
+ throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.message.error.censoredWordsFound', ['censoredWords' => $result]));
}
}
}
/**
- * @see \wcf\data\IMessageQuickReplyAction::getMessageList()
+ * @inheritDoc
*/
public function getMessageList(DatabaseObject $conversation, $lastMessageTime) {
+ /** @var Conversation $conversation */
+
$messageList = new ViewableConversationMessageList();
$messageList->setConversation($conversation);
- $messageList->getConditionBuilder()->add("conversation_message.conversationID = ?", array($conversation->conversationID));
- $messageList->getConditionBuilder()->add("conversation_message.time > ?", array($lastMessageTime));
+ $messageList->getConditionBuilder()->add("conversation_message.conversationID = ?", [$conversation->conversationID]);
+ $messageList->getConditionBuilder()->add("conversation_message.time > ?", [$lastMessageTime]);
$messageList->sqlOrderBy = "conversation_message.time ".CONVERSATION_LIST_DEFAULT_SORT_ORDER;
$messageList->readObjects();
}
/**
- * @see \wcf\data\IMessageQuickReply::getPageNo()
+ * @inheritDoc
*/
public function getPageNo(DatabaseObject $conversation) {
+ /** @var Conversation $conversation */
+
$sql = "SELECT COUNT(*) AS count
FROM wcf".WCF_N."_conversation_message
WHERE conversationID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($conversation->conversationID));
+ $statement->execute([$conversation->conversationID]);
$count = $statement->fetchArray();
- return array(intval(ceil($count['count'] / CONVERSATION_MESSAGES_PER_PAGE)), $count['count']);
+ return [intval(ceil($count['count'] / CONVERSATION_MESSAGES_PER_PAGE)), $count['count']];
}
/**
- * @see \wcf\data\IMessageQuickReply::getRedirectUrl()
+ * @inheritDoc
*/
public function getRedirectUrl(DatabaseObject $conversation, DatabaseObject $message) {
- return LinkHandler::getInstance()->getLink('Conversation', array(
+ /** @var ConversationMessage $message */
+ return LinkHandler::getInstance()->getLink('Conversation', [
'object' => $conversation,
'messageID' => $message->messageID
- )).'#message'.$message->messageID;
+ ]).'#message'.$message->messageID;
}
/**
- * @see \wcf\data\IMessageQuoteAction::validateSaveFullQuote()
+ * @inheritDoc
*/
public function validateSaveFullQuote() {
$this->message = $this->getSingleObject();
- if (!Conversation::isParticipant(array($this->message->conversationID))) {
+ if (!Conversation::isParticipant([$this->message->conversationID])) {
throw new PermissionDeniedException();
}
}
/**
- * @see \wcf\data\IMessageQuoteAction::saveFullQuote()
+ * @inheritDoc
*/
public function saveFullQuote() {
$quoteID = MessageQuoteManager::getInstance()->addQuote(
);
if ($quoteID === false) {
- $removeQuoteID = MessageQuoteManager::getInstance()->getQuoteID('com.woltlab.wcf.conversation.message', $this->message->messageID, $this->message->getExcerpt(), $this->message->getMessage());
+ $removeQuoteID = MessageQuoteManager::getInstance()->getQuoteID(
+ 'com.woltlab.wcf.conversation.message',
+ $this->message->messageID,
+ $this->message->getExcerpt(),
+ $this->message->getMessage()
+ );
MessageQuoteManager::getInstance()->removeQuote($removeQuoteID);
}
- $returnValues = array(
+ $returnValues = [
'count' => MessageQuoteManager::getInstance()->countQuotes(),
- 'fullQuoteMessageIDs' => MessageQuoteManager::getInstance()->getFullQuoteObjectIDs(array('com.woltlab.wcf.conversation.message'))
- );
+ 'fullQuoteMessageIDs' => MessageQuoteManager::getInstance()->getFullQuoteObjectIDs(['com.woltlab.wcf.conversation.message'])
+ ];
if ($quoteID) {
$returnValues['renderedQuote'] = MessageQuoteManager::getInstance()->getQuoteComponents($quoteID);
}
/**
- * @see \wcf\data\IMessageQuoteAction::validateSaveQuote()
+ * @inheritDoc
*/
public function validateSaveQuote() {
$this->readString('message');
$this->readBoolean('renderQuote', true);
$this->message = $this->getSingleObject();
- if (!Conversation::isParticipant(array($this->message->conversationID))) {
+ if (!Conversation::isParticipant([$this->message->conversationID])) {
throw new PermissionDeniedException();
}
}
/**
- * @see \wcf\data\IMessageQuoteAction::saveQuote()
+ * @inheritDoc
*/
public function saveQuote() {
- $quoteID = MessageQuoteManager::getInstance()->addQuote('com.woltlab.wcf.conversation.message', $this->message->conversationID, $this->message->messageID, $this->parameters['message'], false);
+ $quoteID = MessageQuoteManager::getInstance()->addQuote(
+ 'com.woltlab.wcf.conversation.message',
+ $this->message->conversationID,
+ $this->message->messageID,
+ $this->parameters['message'],
+ false
+ );
- $returnValues = array(
+ $returnValues = [
'count' => MessageQuoteManager::getInstance()->countQuotes(),
- 'fullQuoteMessageIDs' => MessageQuoteManager::getInstance()->getFullQuoteObjectIDs(array('com.woltlab.wcf.conversation.message'))
- );
+ 'fullQuoteMessageIDs' => MessageQuoteManager::getInstance()->getFullQuoteObjectIDs(['com.woltlab.wcf.conversation.message'])
+ ];
if ($this->parameters['renderQuote']) {
$returnValues['renderedQuote'] = MessageQuoteManager::getInstance()->getQuoteComponents($quoteID);
}
/**
- * @see \wcf\data\IMessageQuoteAction::validateGetRenderedQuotes()
+ * @inheritDoc
*/
public function validateGetRenderedQuotes() {
$this->readInteger('parentObjectID');
}
/**
- * @see \wcf\data\IMessageQuoteAction::getRenderedQuotes()
+ * @inheritDoc
*/
public function getRenderedQuotes() {
$quotes = MessageQuoteManager::getInstance()->getQuotesByParentObjectID('com.woltlab.wcf.conversation.message', $this->conversation->conversationID);
- return array(
+ return [
'template' => implode("\n\n", $quotes)
- );
+ ];
}
/**
- * @see \wcf\data\IAttachmentMessageQuickReplyAction::getAttachmentHandler()
+ * @inheritDoc
*/
public function getAttachmentHandler(DatabaseObject $conversation) {
return new AttachmentHandler('com.woltlab.wcf.conversation.message', 0, $this->parameters['tmpHash']);
}
+
+ /**
+ * @inheritDoc
+ */
+ public function getHtmlInputProcessor($message = null, $objectID = 0) {
+ if ($message === null) {
+ return $this->htmlInputProcessor;
+ }
+
+ $this->htmlInputProcessor = new HtmlInputProcessor();
+ $this->htmlInputProcessor->process($message, 'com.woltlab.wcf.conversation.message', $objectID);
+
+ return $this->htmlInputProcessor;
+ }
}
* Extends the message object with functions to create, update and delete messages.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation.message
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation\Message
+ *
+ * @method static ConversationMessage create(array $parameters = [])
+ * @method ConversationMessage getDecoratedObject()
+ * @mixin ConversationMessage
*/
class ConversationMessageEditor extends DatabaseObjectEditor {
/**
- * @see \wcf\data\DatabaseObjectEditor::$baseClass
+ * @inheritDoc
*/
- protected static $baseClass = 'wcf\data\conversation\message\ConversationMessage';
+ protected static $baseClass = ConversationMessage::class;
}
* Represents a list of conversation messages.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation.message
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation\Message
+ *
+ * @method ConversationMessage current()
+ * @method ConversationMessage[] getObjects()
+ * @method ConversationMessage|null search($objectID)
+ * @property ConversationMessage[] $objects
*/
class ConversationMessageList extends DatabaseObjectList {
/**
- * @see \wcf\data\DatabaseObjectList::$className
+ * @inheritDoc
*/
- public $className = 'wcf\data\conversation\message\ConversationMessage';
+ public $className = ConversationMessage::class;
}
* Represents a list of search result.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation.message
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation\Message
+ *
+ * @property-read string|null $subject
*/
class SearchResultConversationMessage extends ViewableConversationMessage implements ISearchResultObject {
/**
* conversation object
- * @var \wcf\data\conversation\Conversation
+ * @var Conversation
*/
- public $conversation = null;
+ public $conversation;
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
* Returns the conversation object.
*
- * @return \wcf\data\conversation\Conversation
+ * @return Conversation
*/
public function getConversation() {
if ($this->conversation === null) {
- $this->conversation = new Conversation(null, array(
+ $this->conversation = new Conversation(null, [
'conversationID' => $this->conversationID,
'subject' => $this->subject
- ));
+ ]);
}
return $this->conversation;
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\data\conversation\message\ConversationMessage::getFormattedMessage()
+ * @inheritDoc
*/
public function getFormattedMessage() {
return SearchResultTextParser::getInstance()->parse($this->getDecoratedObject()->getSimplifiedFormattedMessage());
}
/**
- * @see \wcf\data\search\ISearchResultObject::getSubject()
+ * @inheritDoc
*/
public function getSubject() {
return $this->subject;
}
/**
- * @see \wcf\data\search\ISearchResultObject::getLink()
+ * @inheritDoc
*/
public function getLink($query = '') {
if ($query) {
- return LinkHandler::getInstance()->getLink('Conversation', array(
+ return LinkHandler::getInstance()->getLink('Conversation', [
'object' => $this->getConversation(),
'messageID' => $this->messageID,
'highlight' => urlencode($query)
- ), '#message'.$this->messageID);
+ ], '#message'.$this->messageID);
}
return $this->getDecoratedObject()->getLink();
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\data\search\ISearchResultObject::getTime()
+ * @inheritDoc
*/
public function getTime() {
return $this->time;
}
/**
- * @see \wcf\data\search\ISearchResultObject::getObjectTypeName()
+ * @inheritDoc
*/
public function getObjectTypeName() {
return 'com.woltlab.wcf.conversation.message';
}
/**
- * @see \wcf\data\search\ISearchResultObject::getContainerTitle()
+ * @inheritDoc
*/
public function getContainerTitle() {
return '';
}
/**
- * @see \wcf\data\search\ISearchResultObject::getContainerLink()
+ * @inheritDoc
*/
public function getContainerLink() {
return '';
* Represents a list of search results.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation.message
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation\Message
+ *
+ * @method SearchResultConversationMessage current()
+ * @method SearchResultConversationMessage[] getObjects()
+ * @method SearchResultConversationMessage|null search($objectID)
+ * @property SearchResultConversationMessage[] $objects
*/
class SearchResultConversationMessageList extends SimplifiedViewableConversationMessageList {
/**
- * @see \wcf\data\DatabaseObjectList::$decoratorClassName
+ * @inheritDoc
*/
- public $decoratorClassName = 'wcf\data\conversation\message\SearchResultConversationMessage';
+ public $decoratorClassName = SearchResultConversationMessage::class;
/**
* Creates a new SearchResultConversationMessageList object.
* Disables the loading of attachments and embedded objects by default.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation.message
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation\Message
*/
class SimplifiedViewableConversationMessageList extends ViewableConversationMessageList {
/**
- * @see \wcf\data\conversation\message\ViewableConversationMessageList::$attachmentLoading
+ * @inheritDoc
*/
protected $attachmentLoading = false;
/**
- * @see \wcf\data\conversation\message\ViewableConversationMessageList::$embeddedObjectLoading
+ * @inheritDoc
*/
protected $embeddedObjectLoading = false;
}
<?php
namespace wcf\data\conversation\message;
-use wcf\data\user\User;
use wcf\data\user\UserProfile;
use wcf\data\DatabaseObjectDecorator;
+use wcf\data\TLegacyUserPropertyAccess;
+use wcf\system\cache\runtime\UserProfileRuntimeCache;
/**
* Represents a viewable conversation message.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation.message
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation\Message
+ *
+ * @method ConversationMessage getDecoratedObject()
+ * @mixin ConversationMessage
*/
class ViewableConversationMessage extends DatabaseObjectDecorator {
+ use TLegacyUserPropertyAccess;
+
/**
- * @see \wcf\data\DatabaseObjectDecorator::$baseClass
+ * @inheritDoc
*/
- protected static $baseClass = 'wcf\data\conversation\message\ConversationMessage';
+ protected static $baseClass = ConversationMessage::class;
/**
* user profile object
- * @var \wcf\data\user\UserProfile
+ * @var UserProfile
*/
- protected $userProfile = null;
+ protected $userProfile;
/**
* Returns the user profile object.
*
- * @return \wcf\data\user\UserProfile
+ * @return UserProfile
*/
public function getUserProfile() {
if ($this->userProfile === null) {
- $this->userProfile = new UserProfile(new User(null, $this->getDecoratedObject()->data));
+ if ($this->userID) {
+ $this->userProfile = UserProfileRuntimeCache::getInstance()->getObject($this->userID);
+ }
+ else {
+ $this->userProfile = UserProfile::getGuestUserProfile($this->username);
+ }
}
return $this->userProfile;
* Returns the viewable conversation message with the given id.
*
* @param integer $messageID
- * @return \wcf\data\conversation\message\ViewableConversationMessage
+ * @return ViewableConversationMessage
*/
public static function getViewableConversationMessage($messageID) {
$messageList = new ViewableConversationMessageList();
- $messageList->setObjectIDs(array($messageID));
+ $messageList->setObjectIDs([$messageID]);
$messageList->readObjects();
return $messageList->search($messageID);
use wcf\data\attachment\GroupedAttachmentList;
use wcf\data\conversation\Conversation;
use wcf\data\object\type\ObjectTypeCache;
+use wcf\system\cache\runtime\UserProfileRuntimeCache;
use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
/**
* Represents a list of viewable conversation messages.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.conversation.message
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Conversation\Message
+ *
+ * @method ViewableConversationMessage current()
+ * @method ViewableConversationMessage[] getObjects()
+ * @method ViewableConversationMessage|null search($objectID)
+ * @property ViewableConversationMessage[] $objects
*/
class ViewableConversationMessageList extends ConversationMessageList {
/**
- * @see \wcf\data\DatabaseObjectList::$sqlOrderBy
+ * @inheritDoc
*/
public $sqlOrderBy = 'conversation_message.time';
/**
- * @see \wcf\data\DatabaseObjectList::$decoratorClassName
+ * @inheritDoc
*/
- public $decoratorClassName = 'wcf\data\conversation\message\ViewableConversationMessage';
+ public $decoratorClassName = ViewableConversationMessage::class;
/**
* attachment object ids
- * @var array<integer>
+ * @var integer[]
*/
- public $attachmentObjectIDs = array();
+ public $attachmentObjectIDs = [];
/**
* ids of the messages with embedded objects
- * @var array<integer>
+ * @var integer[]
*/
- public $embeddedObjectMessageIDs = array();
+ public $embeddedObjectMessageIDs = [];
/**
* attachment list
- * @var \wcf\data\attachment\GroupedAttachmentList
+ * @var GroupedAttachmentList
*/
- protected $attachmentList = null;
+ protected $attachmentList;
/**
* max post time
/**
* conversation object
- * @var \wcf\data\conversation\Conversation
+ * @var Conversation
*/
- protected $conversation = null;
+ protected $conversation;
/**
- * Creates a new ViewableConversationMessageList object.
- */
- public function __construct() {
- parent::__construct();
-
- $this->sqlSelects .= "user_option_value.*, user_table.*";
- $this->sqlJoins .= " LEFT JOIN wcf".WCF_N."_user user_table ON (user_table.userID = conversation_message.userID)";
- $this->sqlJoins .= " LEFT JOIN wcf".WCF_N."_user_option_value user_option_value ON (user_option_value.userID = user_table.userID)";
-
- // get avatars
- if (!empty($this->sqlSelects)) $this->sqlSelects .= ',';
- $this->sqlSelects .= "user_avatar.*";
- $this->sqlJoins .= " LEFT JOIN wcf".WCF_N."_user_avatar user_avatar ON (user_avatar.avatarID = user_table.avatarID)";
- }
-
- /**
- * @see \wcf\data\DatabaseObjectList::readObjects()
+ * @inheritDoc
*/
public function readObjects() {
if ($this->objectIDs === null) {
parent::readObjects();
+ $userIDs = [];
foreach ($this->objects as $message) {
if ($message->time > $this->maxPostTime) {
$this->maxPostTime = $message->time;
if ($message->hasEmbeddedObjects) {
$this->embeddedObjectMessageIDs[] = $message->messageID;
}
+ if ($message->userID) {
+ $userIDs[] = $message->userID;
+ }
+ }
+
+ if (!empty($userIDs)) {
+ UserProfileRuntimeCache::getInstance()->cacheObjectIDs($userIDs);
}
if ($this->embeddedObjectLoading) {
if (!empty($this->embeddedObjectMessageIDs)) {
// add message objects to attachment object cache to save SQL queries
ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.attachment.objectType', 'com.woltlab.wcf.conversation.message')->getProcessor()->setCachedObjects($this->objects);
-
+
// load embedded objects
MessageEmbeddedObjectManager::getInstance()->loadObjects('com.woltlab.wcf.conversation.message', $this->embeddedObjectMessageIDs);
}
public function readAttachments() {
if (MODULE_ATTACHMENT == 1 && !empty($this->attachmentObjectIDs)) {
$this->attachmentList = new GroupedAttachmentList('com.woltlab.wcf.conversation.message');
- $this->attachmentList->getConditionBuilder()->add('attachment.objectID IN (?)', array($this->attachmentObjectIDs));
+ $this->attachmentList->getConditionBuilder()->add('attachment.objectID IN (?)', [$this->attachmentObjectIDs]);
$this->attachmentList->readObjects();
}
}
/**
* Returns the list of attachments.
*
- * @return \wcf\data\attachment\GroupedAttachmentList
+ * @return GroupedAttachmentList
*/
public function getAttachmentList() {
return $this->attachmentList;
/**
* Sets active conversation.
*
- * @param \wcf\data\conversation\Conversation $conversation
+ * @param Conversation $conversation
*/
public function setConversation(Conversation $conversation) {
$this->conversation = $conversation;
<?php
namespace wcf\data\modification\log;
-use wcf\data\conversation\Conversation;
+use wcf\system\cache\runtime\UserProfileRuntimeCache;
use wcf\system\log\modification\ConversationModificationLogHandler;
use wcf\system\WCF;
* Represents a list of modification logs for conversation log page.
*
* @author Alexander Ebert
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.modification.log
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Modification\Log
+ *
+ * @method ViewableConversationModificationLog current()
+ * @method ViewableConversationModificationLog[] getObjects()
+ * @method ViewableConversationModificationLog|null search($objectID)
+ * @property ViewableConversationModificationLog[] $objects
*/
class ConversationLogModificationLogList extends ModificationLogList {
/**
- * @see \wbb\data\DatabaseObjectList::__construct()
+ * @inheritDoc
*/
public function __construct($conversationID) {
parent::__construct();
// set conditions
- $this->getConditionBuilder()->add('modification_log.objectTypeID = ?', array(ConversationModificationLogHandler::getInstance()->getObjectType('com.woltlab.wcf.conversation.conversation')->objectTypeID));
- $this->getConditionBuilder()->add('modification_log.objectID = ?', array($conversationID));
+ $this->getConditionBuilder()->add('modification_log.objectTypeID = ?', [ConversationModificationLogHandler::getInstance()->getObjectType('com.woltlab.wcf.conversation.conversation')->objectTypeID]);
+ $this->getConditionBuilder()->add('modification_log.objectID = ?', [$conversationID]);
}
-
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\data\DatabaseObjectList::readObjects()
+ * @inheritDoc
*/
public function readObjects() {
- $sql = "SELECT user_avatar.*,
- user_table.email, user_table.enableGravatar, user_table.disableAvatar, user_table.gravatarFileExtension,
- modification_log.*
- FROM wcf".WCF_N."_modification_log modification_log
- LEFT JOIN wcf".WCF_N."_user user_table ON (user_table.userID = modification_log.userID)
- LEFT JOIN wcf".WCF_N."_user_avatar user_avatar ON (user_avatar.avatarID = user_table.avatarID)
+ $sql = "SELECT modification_log.*
+ FROM wcf".WCF_N."_modification_log modification_log
".$this->getConditionBuilder()."
".(!empty($this->sqlOrderBy) ? "ORDER BY ".$this->sqlOrderBy : '');
$statement = WCF::getDB()->prepareStatement($sql, $this->sqlLimit, $this->sqlOffset);
$this->objects = $statement->fetchObjects(($this->objectClassName ?: $this->className));
// use table index as array index
- $objects = array();
+ $objects = $userIDs = [];
foreach ($this->objects as $object) {
$objectID = $object->{$this->getDatabaseTableIndexName()};
$objects[$objectID] = $object;
$this->indexToObject[] = $objectID;
+
+ if ($object->userID) {
+ $userIDs[] = $object->userID;
+ }
}
$this->objectIDs = $this->indexToObject;
$this->objects = $objects;
+ if (!empty($userIDs)) {
+ UserProfileRuntimeCache::getInstance()->cacheObjectIDs($userIDs);
+ }
+
foreach ($this->objects as &$object) {
$object = new ViewableConversationModificationLog($object);
}
* will be returned and removed from collection.
*
* @param integer $time
- * @return array<\wcf\data\modification\log\ViewableConversationModificationLog>
+ * @return ViewableConversationModificationLog[]
*/
public function getEntriesUntil($time) {
- $entries = array();
+ $entries = [];
foreach ($this->objects as $index => $entry) {
if ($entry->time < $time) {
$entries[] = $entry;
<?php
namespace wcf\data\modification\log;
-use wcf\data\user\User;
use wcf\data\user\UserProfile;
use wcf\data\DatabaseObjectDecorator;
+use wcf\data\TLegacyUserPropertyAccess;
+use wcf\system\cache\runtime\UserProfileRuntimeCache;
use wcf\system\WCF;
/**
* Provides a viewable conversation modification log.
*
* @author Alexander Ebert
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage data.modification.log
- * @category Community Framework
+ * @package WoltLabSuite\Core\Data\Modification\Log
+ *
+ * @method ModificationLog getDecoratedObject()
+ * @mixin ModificationLog
*/
class ViewableConversationModificationLog extends DatabaseObjectDecorator {
+ use TLegacyUserPropertyAccess;
+
/**
- * @see \wcf\data\DatabaseObjectDecorator::$baseClass
+ * @inheritDoc
*/
- protected static $baseClass = 'wcf\data\modification\log\ModificationLog';
+ protected static $baseClass = ModificationLog::class;
/**
* user profile object
- * @var \wcf\data\user\UserProfile
+ * @var UserProfile
*/
- protected $userProfile = null;
+ protected $userProfile;
/**
* Returns readable representation of current log entry.
+ *
+ * @return string
*/
public function __toString() {
- return WCF::getLanguage()->getDynamicVariable('wcf.conversation.log.conversation.'.$this->action, array('additionalData' => $this->additionalData));
+ return WCF::getLanguage()->getDynamicVariable('wcf.conversation.log.conversation.'.$this->action, ['additionalData' => $this->additionalData]);
}
/**
* Returns the profile object of the user who created the modification entry.
*
- * @return \wcf\data\user\UserProfile
+ * @return UserProfile
*/
public function getUserProfile() {
if ($this->userProfile === null) {
- $this->userProfile = new UserProfile(new User(null, $this->getDecoratedObject()->data));
+ if ($this->userID) {
+ $this->userProfile = UserProfileRuntimeCache::getInstance()->getObject($this->userID);
+ }
+ else {
+ $this->userProfile = UserProfile::getGuestUserProfile($this->username);
+ }
}
return $this->userProfile;
namespace wcf\form;
use wcf\data\conversation\Conversation;
use wcf\data\conversation\ConversationAction;
-use wcf\data\user\UserProfile;
-use wcf\system\breadcrumb\Breadcrumb;
+use wcf\system\cache\runtime\UserProfileRuntimeCache;
use wcf\system\conversation\ConversationHandler;
use wcf\system\exception\IllegalLinkException;
use wcf\system\exception\NamedUserException;
use wcf\system\exception\UserInputException;
use wcf\system\message\quote\MessageQuoteManager;
+use wcf\system\page\PageLocationManager;
use wcf\system\request\LinkHandler;
use wcf\system\WCF;
use wcf\util\HeaderUtil;
* Shows the conversation form.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage form
- * @category Community Framework
+ * @package WoltLabSuite\Core\Form
*/
class ConversationAddForm extends MessageForm {
/**
- * @see \wcf\page\AbstractPage::$enableTracking
+ * @inheritDoc
*/
- public $enableTracking = true;
+ public $attachmentObjectType = 'com.woltlab.wcf.conversation.message';
/**
- * @see \wcf\form\MessageForm::$attachmentObjectType
+ * @inheritDoc
*/
- public $attachmentObjectType = 'com.woltlab.wcf.conversation.message';
+ public $loginRequired = true;
/**
- * @see \wcf\page\AbstractPage::$loginRequired
+ * @inheritDoc
*/
- public $loginRequired = true;
+ public $messageObjectType = 'com.woltlab.wcf.conversation.message';
/**
- * @see \wcf\page\AbstractPage::$neededModules
+ * @inheritDoc
*/
- public $neededModules = array('MODULE_CONVERSATION');
+ public $neededModules = ['MODULE_CONVERSATION'];
/**
- * @see \wcf\page\AbstractPage::$neededPermissions
+ * @inheritDoc
*/
- public $neededPermissions = array('user.conversation.canUseConversation');
+ public $neededPermissions = ['user.conversation.canUseConversation'];
/**
* participants (comma separated user names)
/**
* participants (user ids)
- * @var array<integer>
+ * @var integer[]
*/
- public $participantIDs = array();
+ public $participantIDs = [];
/**
* invisible participants (user ids)
- * @var array<integer>
+ * @var integer[]
*/
- public $invisibleParticipantIDs = array();
+ public $invisibleParticipantIDs = [];
/**
- * @see \wcf\page\IPage::readParameters()
+ * @inheritDoc
*/
public function readParameters() {
parent::readParameters();
if (isset($_REQUEST['userID'])) {
$userID = intval($_REQUEST['userID']);
- $user = UserProfile::getUserProfile($userID);
+ $user = UserProfileRuntimeCache::getInstance()->getObject($userID);
if ($user === null || $user->userID == WCF::getUser()->userID) {
throw new IllegalLinkException();
}
Conversation::validateParticipant($user);
}
catch (UserInputException $e) {
- throw new NamedUserException(WCF::getLanguage()->getDynamicVariable('wcf.conversation.participants.error.'.$e->getType(), array('errorData' => array('username' => $user->username))));
+ throw new NamedUserException(WCF::getLanguage()->getDynamicVariable('wcf.conversation.participants.error.'.$e->getType(), ['errorData' => ['username' => $user->username]]));
}
$this->participants = $user->username;
}
/**
- * @see \wcf\form\IForm::readFormParameters()
+ * @inheritDoc
*/
public function readFormParameters() {
parent::readFormParameters();
}
/**
- * @see \wcf\form\IForm::validate()
+ * @inheritDoc
*/
public function validate() {
if (empty($this->participants) && empty($this->invisibleParticipants) && !$this->draft) {
}
/**
- * @see \wcf\form\IForm::save()
+ * @inheritDoc
*/
public function save() {
parent::save();
// save conversation
- $data = array_merge($this->additionalFields, array(
+ $data = array_merge($this->additionalFields, [
'subject' => $this->subject,
'time' => TIME_NOW,
'userID' => WCF::getUser()->userID,
'username' => WCF::getUser()->username,
- 'isDraft' => ($this->draft ? 1 : 0),
+ 'isDraft' => $this->draft ? 1 : 0,
'participantCanInvite' => $this->participantCanInvite
- ));
+ ]);
if ($this->draft) {
- $data['draftData'] = serialize(array(
+ $data['draftData'] = serialize([
'participants' => $this->participantIDs,
'invisibleParticipants' => $this->invisibleParticipantIDs
- ));
+ ]);
}
- $conversationData = array(
+ $conversationData = [
'data' => $data,
'attachmentHandler' => $this->attachmentHandler,
- 'messageData' => array(
- 'message' => $this->text,
- 'enableBBCodes' => $this->enableBBCodes,
- 'enableHtml' => $this->enableHtml,
- 'enableSmilies' => $this->enableSmilies,
- 'showSignature' => $this->showSignature
- )
- );
+ 'htmlInputProcessor' => $this->htmlInputProcessor,
+ 'messageData' => []
+ ];
if (!$this->draft) {
$conversationData['participants'] = $this->participantIDs;
$conversationData['invisibleParticipants'] = $this->invisibleParticipantIDs;
}
- $this->objectAction = new ConversationAction(array(), 'create', $conversationData);
+ $this->objectAction = new ConversationAction([], 'create', $conversationData);
$resultValues = $this->objectAction->executeAction();
MessageQuoteManager::getInstance()->saved();
$this->saved();
// forward
- HeaderUtil::redirect(LinkHandler::getInstance()->getLink('Conversation', array(
+ HeaderUtil::redirect(LinkHandler::getInstance()->getLink('Conversation', [
'object' => $resultValues['returnValues']
- )));
+ ]));
exit;
}
/**
- * @see \wcf\page\IPage::readData()
+ * @inheritDoc
*/
public function readData() {
parent::readData();
// add breadcrumbs
- WCF::getBreadcrumbs()->add(new Breadcrumb(WCF::getLanguage()->get('wcf.conversation.conversations'), LinkHandler::getInstance()->getLink('ConversationList')));
+ PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.conversation.ConversationList');
}
/**
- * @see \wcf\page\IPage::assignVariables()
+ * @inheritDoc
*/
public function assignVariables() {
parent::assignVariables();
MessageQuoteManager::getInstance()->assignVariables();
- WCF::getTPL()->assign(array(
+ WCF::getTPL()->assign([
'participantCanInvite' => $this->participantCanInvite,
'participants' => $this->participants,
'invisibleParticipants' => $this->invisibleParticipants
- ));
+ ]);
}
}
+++ /dev/null
-<?php
-namespace wcf\form;
-use wcf\data\conversation\message\ConversationMessage;
-use wcf\data\conversation\message\ConversationMessageAction;
-use wcf\data\conversation\message\ViewableConversationMessageList;
-use wcf\data\conversation\Conversation;
-use wcf\system\breadcrumb\Breadcrumb;
-use wcf\system\exception\IllegalLinkException;
-use wcf\system\exception\PermissionDeniedException;
-use wcf\system\message\quote\MessageQuoteManager;
-use wcf\system\message\QuickReplyManager;
-use wcf\system\request\LinkHandler;
-use wcf\system\WCF;
-use wcf\util\HeaderUtil;
-
-/**
- * Shows the conversation reply form.
- *
- * @author Marcel Werk
- * @copyright 2009-2012 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage form
- * @category Community Framework
- */
-class ConversationMessageAddForm extends MessageForm {
- /**
- * @see \wcf\page\AbstractPage::$enableTracking
- */
- public $enableTracking = true;
-
- /**
- * @see \wcf\form\MessageForm::$attachmentObjectType
- */
- public $attachmentObjectType = 'com.woltlab.wcf.conversation.message';
-
- /**
- * @see \wcf\page\AbstractPage::$loginRequired
- */
- public $loginRequired = true;
-
- /**
- * @see \wcf\page\AbstractPage::$neededModules
- */
- public $neededModules = array('MODULE_CONVERSATION');
-
- /**
- * @see \wcf\page\AbstractPage::$neededPermissions
- */
- public $neededPermissions = array('user.conversation.canUseConversation');
-
- /**
- * conversation id
- * @var integer
- */
- public $conversationID = 0;
-
- /**
- * conversation
- * @var \wcf\data\conversation\Conversation
- */
- public $conversation = null;
-
- /**
- * message list
- * @var \wcf\data\conversation\message\ConversationMessageList
- */
- public $messageList = null;
-
- /**
- * @see \wcf\form\IPage::readParameters()
- */
- public function readParameters() {
- parent::readParameters();
-
- if (isset($_REQUEST['id'])) $this->conversationID = intval($_REQUEST['id']);
- $this->conversation = Conversation::getUserConversation($this->conversationID, WCF::getUser()->userID);
- if ($this->conversation === null) {
- throw new IllegalLinkException();
- }
- if (!$this->conversation->canRead() || $this->conversation->isClosed) {
- throw new PermissionDeniedException();
- }
-
- // quotes
- MessageQuoteManager::getInstance()->readParameters();
- }
-
- /**
- * @see \wcf\form\IForm::readFormParameters()
- */
- public function readFormParameters() {
- parent::readFormParameters();
-
- // quotes
- MessageQuoteManager::getInstance()->readFormParameters();
- }
-
- /**
- * @see \wcf\form\MessageForm::validateSubject()
- */
- protected function validateSubject() {}
-
- /**
- * @see \wcf\page\IPage::readData()
- */
- public function readData() {
- parent::readData();
-
- if (empty($_POST)) {
- // check for quick reply message
- $this->text = QuickReplyManager::getInstance()->getMessage('conversation', $this->conversation->conversationID);
- if (empty($this->text)) {
- if (MessageQuoteManager::getInstance()->getQuoteMessageID()) {
- $message = new ConversationMessage(MessageQuoteManager::getInstance()->getQuoteMessageID());
- if (!$message->messageID) {
- throw new IllegalLinkException();
- }
-
- if ($message->conversationID == $this->conversation->conversationID) {
- $message->setConversation($this->conversation);
- $this->text = MessageQuoteManager::getInstance()->renderQuote($message, $message->message);
- }
- }
-
- if (empty($this->text)) {
- // get all message ids from current conversation
- $sql = "SELECT messageID
- FROM wcf".WCF_N."_conversation_message
- WHERE conversationID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($this->conversation->conversationID));
- $messageIDs = array();
- while ($row = $statement->fetchArray()) {
- $messageIDs[] = $row['messageID'];
- }
-
- $renderedQuotes = MessageQuoteManager::getInstance()->getQuotesByObjectIDs('com.woltlab.wcf.conversation.message', $messageIDs);
- if (!empty($renderedQuotes)) {
- $this->text = implode("\n", $renderedQuotes);
- }
- }
- }
- }
-
- // add breadcrumbs
- WCF::getBreadcrumbs()->add(new Breadcrumb(WCF::getLanguage()->get('wcf.conversation.conversations'), LinkHandler::getInstance()->getLink('ConversationList')));
- WCF::getBreadcrumbs()->add($this->conversation->getBreadcrumb());
-
- // get message list
- $this->messageList = new ViewableConversationMessageList();
- $this->messageList->setConversation($this->conversation);
- $this->messageList->sqlLimit = CONVERSATION_REPLY_SHOW_MESSAGES_MAX;
- $this->messageList->sqlOrderBy = 'conversation_message.time DESC';
- $this->messageList->getConditionBuilder()->add('conversation_message.conversationID = ?', array($this->conversation->conversationID));
- $this->messageList->readObjects();
- }
-
- /**
- * @see \wcf\form\IForm::save()
- */
- public function save() {
- parent::save();
-
- // save message
- $data = array_merge($this->additionalFields, array(
- 'conversationID' => $this->conversationID,
- 'message' => $this->text,
- 'time' => TIME_NOW,
- 'userID' => WCF::getUser()->userID,
- 'username' => WCF::getUser()->username,
- 'enableBBCodes' => $this->enableBBCodes,
- 'enableHtml' => $this->enableHtml,
- 'enableSmilies' => $this->enableSmilies,
- 'showSignature' => $this->showSignature
- ));
-
- $messageData = array(
- 'data' => $data,
- 'attachmentHandler' => $this->attachmentHandler
- );
-
- $this->objectAction = new ConversationMessageAction(array(), 'create', $messageData);
- $resultValues = $this->objectAction->executeAction();
-
- MessageQuoteManager::getInstance()->saved();
-
- $this->saved();
-
- // forward
- HeaderUtil::redirect(LinkHandler::getInstance()->getLink('Conversation', array(
- 'object' => $this->conversation,
- 'messageID' => $resultValues['returnValues']->messageID
- )).'#message'.$resultValues['returnValues']->messageID);
- exit;
- }
-
- /**
- * @see \wcf\page\IPage::assignVariables()
- */
- public function assignVariables() {
- parent::assignVariables();
-
- MessageQuoteManager::getInstance()->assignVariables();
-
- WCF::getTPL()->assign(array(
- 'conversation' => $this->conversation,
- 'conversationID' => $this->conversationID,
- 'items' => $this->messageList->countObjects(),
- 'messages' => $this->messageList->getObjects(),
- 'attachmentList' => $this->messageList->getAttachmentList()
- ));
- }
-
- /**
- * @see \wcf\page\ITrackablePage::getObjectType()
- */
- public function getObjectType() {
- return 'com.woltlab.wcf.conversation';
- }
-
- /**
- * @see \wcf\page\ITrackablePage::getObjectID()
- */
- public function getObjectID() {
- return $this->conversationID;
- }
-}
+++ /dev/null
-<?php
-namespace wcf\form;
-use wcf\data\conversation\message\ConversationMessage;
-use wcf\data\conversation\message\ConversationMessageAction;
-use wcf\data\conversation\message\ViewableConversationMessageList;
-use wcf\data\conversation\ConversationAction;
-use wcf\data\user\UserProfile;
-use wcf\system\breadcrumb\Breadcrumb;
-use wcf\system\exception\IllegalLinkException;
-use wcf\system\exception\PermissionDeniedException;
-use wcf\system\request\LinkHandler;
-use wcf\system\WCF;
-use wcf\util\HeaderUtil;
-
-/**
- * Shows the conversation message edit form.
- *
- * @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage form
- * @category Community Framework
- */
-class ConversationMessageEditForm extends ConversationAddForm {
- /**
- * @see \wcf\page\AbstractPage::$templateName
- */
- public $templateName = 'conversationMessageEdit';
-
- /**
- * message id
- * @var integer
- */
- public $messageID = 0;
-
- /**
- * message object
- * @var \wcf\data\conversation\message\ConversationMessage
- */
- public $message = null;
-
- /**
- * conversation id
- * @var integer
- */
- public $conversationID = 0;
-
- /**
- * conversation
- * @var \wcf\data\conversation\Conversation
- */
- public $conversation = null;
-
- /**
- * message list
- * @var \wcf\data\conversation\message\ConversationMessageList
- */
- public $messageList = null;
-
- /**
- * true if current message is first message
- * @var boolean
- */
- public $isFirstMessage = false;
-
- /**
- * @see \wcf\form\IPage::readParameters()
- */
- public function readParameters() {
- MessageForm::readParameters();
-
- if (isset($_REQUEST['id'])) $this->messageID = intval($_REQUEST['id']);
- $this->message = new ConversationMessage($this->messageID);
- if (!$this->message->messageID) {
- throw new IllegalLinkException();
- }
- if (!$this->message->canEdit()) {
- throw new PermissionDeniedException();
- }
- // get conversation
- $this->conversationID = $this->message->conversationID;
- $this->conversation = $this->message->getConversation();
-
- if ($this->conversation->firstMessageID == $this->message->messageID) {
- $this->isFirstMessage = true;
- }
-
- // set attachment object id
- $this->attachmentObjectID = $this->message->messageID;
- }
-
- /**
- * @see \wcf\form\IForm::readFormParameters()
- */
- public function readFormParameters() {
- parent::readFormParameters();
-
- if (!$this->conversation->isDraft) $this->draft = 0;
- }
-
- /**
- * @see \wcf\form\IForm::validate()
- */
- public function validate() {
- if ($this->isFirstMessage && $this->conversation->isDraft) parent::validate();
- else MessageForm::validate();
- }
-
- /**
- * @see \wcf\form\MessageForm::validateSubject()
- */
- protected function validateSubject() {
- if ($this->isFirstMessage) parent::validateSubject();
- }
-
- /**
- * @see \wcf\form\IForm::save()
- */
- public function save() {
- MessageForm::save();
-
- // save message
- $data = array_merge($this->additionalFields, array(
- 'message' => $this->text,
- 'enableBBCodes' => $this->enableBBCodes,
- 'enableHtml' => $this->enableHtml,
- 'enableSmilies' => $this->enableSmilies,
- 'showSignature' => $this->showSignature
- ));
- if ($this->conversation->isDraft && !$this->draft) {
- $data['time'] = TIME_NOW;
- }
- if (!$this->draft) {
- $data['lastEditTime'] = TIME_NOW;
- $data['editCount'] = $this->message->editCount + 1;
- }
- $messageData = array(
- 'data' => $data,
- 'attachmentHandler' => $this->attachmentHandler
- );
- $this->objectAction = new ConversationMessageAction(array($this->message), 'update', $messageData);
- $this->objectAction->executeAction();
-
- // update conversation
- if ($this->isFirstMessage) {
- $data = array(
- 'subject' => $this->subject,
- 'isDraft' => ($this->draft ? 1 : 0),
- 'participantCanInvite' => $this->participantCanInvite
- );
- if ($this->draft) {
- $data['draftData'] = serialize(array(
- 'participants' => $this->participantIDs,
- 'invisibleParticipants' => $this->invisibleParticipantIDs
- ));
- }
-
- $conversationData = array(
- 'data' => $data
- );
- if ($this->conversation->isDraft && !$this->draft) {
- $conversationData['participants'] = $this->participantIDs;
- $conversationData['invisibleParticipants'] = $this->invisibleParticipantIDs;
-
- $conversationData['data']['time'] = $conversationData['data']['lastPostTime'] = TIME_NOW;
- }
-
- $conversationAction = new ConversationAction(array($this->conversation), 'update', $conversationData);
- $conversationAction->executeAction();
- }
- $this->saved();
-
- // forward
- HeaderUtil::redirect(LinkHandler::getInstance()->getLink('Conversation', array(
- 'object' => $this->conversation,
- 'messageID' => $this->messageID
- )).'#message'.$this->messageID);
- exit;
- }
-
- /**
- * @see \wcf\page\IPage::readData()
- */
- public function readData() {
- MessageForm::readData();
-
- if (empty($_POST)) {
- $this->text = $this->message->message;
-
- if ($this->isFirstMessage) {
- $this->participantCanInvite = $this->conversation->participantCanInvite;
- $this->subject = $this->conversation->subject;
-
- if ($this->conversation->isDraft && $this->conversation->draftData) {
- $draftData = @unserialize($this->conversation->draftData);
- if (!empty($draftData['participants'])) {
- foreach (UserProfile::getUserProfiles($draftData['participants']) as $user) {
- if (!empty($this->participants)) $this->participants .= ', ';
- $this->participants .= $user->username;
- }
- }
- if (!empty($draftData['invisibleParticipants'])) {
- foreach (UserProfile::getUserProfiles($draftData['invisibleParticipants']) as $user) {
- if (!empty($this->invisibleParticipants)) $this->invisibleParticipants .= ', ';
- $this->invisibleParticipants .= $user->username;
- }
- }
- }
- }
- }
-
- // add breadcrumbs
- WCF::getBreadcrumbs()->add(new Breadcrumb(WCF::getLanguage()->get('wcf.conversation.conversations'), LinkHandler::getInstance()->getLink('ConversationList')));
- WCF::getBreadcrumbs()->add($this->conversation->getBreadcrumb());
-
- // get message list
- $this->messageList = new ViewableConversationMessageList();
- $this->messageList->setConversation($this->conversation);
- $this->messageList->sqlLimit = CONVERSATION_REPLY_SHOW_MESSAGES_MAX;
- $this->messageList->sqlOrderBy = 'conversation_message.time DESC';
- $this->messageList->getConditionBuilder()->add('conversation_message.conversationID = ?', array($this->message->conversationID));
- $this->messageList->getConditionBuilder()->add("conversation_message.messageID <> ?", array($this->message->messageID));
- $this->messageList->readObjects();
- }
-
- /**
- * @see \wcf\page\IPage::assignVariables()
- */
- public function assignVariables() {
- parent::assignVariables();
-
- WCF::getTPL()->assign(array(
- 'messageID' => $this->messageID,
- 'message' => $this->message,
- 'conversationID' => $this->conversationID,
- 'conversation' => $this->conversation,
- 'isFirstMessage' => $this->isFirstMessage,
- 'items' => $this->messageList->countObjects(),
- 'messages' => $this->messageList->getObjects(),
- 'attachmentList' => $this->messageList->getAttachmentList()
- ));
- }
-
- /**
- * @see \wcf\page\ITrackablePage::getObjectType()
- */
- public function getObjectType() {
- return 'com.woltlab.wcf.conversation';
- }
-
- /**
- * @see \wcf\page\ITrackablePage::getObjectID()
- */
- public function getObjectID() {
- return $this->conversationID;
- }
-}
* Shows most recent conversations.
*
* @author Alexander Ebert
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage page
- * @category Community Framework
+ * @package WoltLabSuite\Core\Page
*/
class ConversationFeedPage extends AbstractFeedPage {
/**
- * @see \wcf\page\AbstractPage::$loginRequired
+ * @inheritDoc
*/
public $loginRequired = true;
/**
- * @see \wcf\page\IPage::readData()
+ * @inheritDoc
*/
public function readData() {
parent::readData();
$this->items = new FeedConversationList();
- $this->items->getConditionBuilder()->add('conversation_to_user.participantID = ?', array(WCF::getUser()->userID));
- $this->items->getConditionBuilder()->add('conversation_to_user.hideConversation = ?', array(0));
+ $this->items->getConditionBuilder()->add('conversation_to_user.participantID = ?', [WCF::getUser()->userID]);
+ $this->items->getConditionBuilder()->add('conversation_to_user.hideConversation = ?', [0]);
$this->items->sqlConditionJoins = "LEFT JOIN wcf".WCF_N."_conversation conversation ON (conversation.conversationID = conversation_to_user.conversationID)";
$this->items->sqlLimit = 20;
$this->items->readObjects();
<?php
namespace wcf\page;
use wcf\data\conversation\label\ConversationLabel;
+use wcf\data\conversation\label\ConversationLabelList;
use wcf\data\conversation\UserConversationList;
-use wcf\system\breadcrumb\Breadcrumb;
use wcf\system\clipboard\ClipboardHandler;
use wcf\system\exception\IllegalLinkException;
-use wcf\system\request\LinkHandler;
+use wcf\system\page\PageLocationManager;
use wcf\system\WCF;
+use wcf\util\ArrayUtil;
/**
* Shows a list of conversations.
*
* @author Marcel Werk
- * @copyright 2001-2012 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage page
- * @category Community Framework
+ * @package WoltLabSuite\Core\Page
+ *
+ * @property UserConversationList $objectList
*/
class ConversationListPage extends SortablePage {
/**
- * @see \wcf\page\AbstractPage::$enableTracking
- */
- public $enableTracking = true;
-
- /**
- * @see \wcf\page\SortablePage::$defaultSortField
+ * @inheritDoc
*/
public $defaultSortField = CONVERSATION_LIST_DEFAULT_SORT_FIELD;
/**
- * @see \wcf\page\SortablePage::$defaultSortOrder
+ * @inheritDoc
*/
public $defaultSortOrder = CONVERSATION_LIST_DEFAULT_SORT_ORDER;
/**
- * @see \wcf\page\SortablePage::$validSortFields
+ * @inheritDoc
*/
- public $validSortFields = array('subject', 'time', 'username', 'lastPostTime', 'replies', 'participants');
+ public $validSortFields = ['subject', 'time', 'username', 'lastPostTime', 'replies', 'participants'];
/**
- * @see \wcf\page\MultipleLinkPage::$itemsPerPage
+ * @inheritDoc
*/
public $itemsPerPage = CONVERSATIONS_PER_PAGE;
/**
- * @see \wcf\page\AbstractPage::$loginRequired
+ * @inheritDoc
*/
public $loginRequired = true;
/**
- * @see \wcf\page\AbstractPage::$neededModules
+ * @inheritDoc
*/
- public $neededModules = array('MODULE_CONVERSATION');
+ public $neededModules = ['MODULE_CONVERSATION'];
/**
- * @see \wcf\page\AbstractPage::$neededPermissions
+ * @inheritDoc
*/
- public $neededPermissions = array('user.conversation.canUseConversation');
+ public $neededPermissions = ['user.conversation.canUseConversation'];
/**
* list filter
/**
* label list object
- * @var \wcf\data\conversation\label\ConversationLabelList
+ * @var ConversationLabelList
*/
- public $labelList = null;
+ public $labelList;
/**
* number of conversations (no filter)
public $outboxCount = 0;
/**
- * @see \wcf\page\IPage::readParameters()
+ * participant that
+ * @var string[]
+ */
+ public $participants = [];
+
+ /**
+ * @inheritDoc
*/
public function readParameters() {
parent::readParameters();
if (!in_array($this->filter, UserConversationList::$availableFilters)) $this->filter = '';
// user settings
- if (WCF::getUser()->conversationsPerPage) $this->itemsPerPage = WCF::getUser()->conversationsPerPage;
+ /** @noinspection PhpUndefinedFieldInspection */
+ if (WCF::getUser()->conversationsPerPage) {
+ /** @noinspection PhpUndefinedFieldInspection */
+ $this->itemsPerPage = WCF::getUser()->conversationsPerPage;
+ }
// labels
$this->labelList = ConversationLabel::getLabelsByUser();
throw new IllegalLinkException();
}
}
+
+ if (isset($_REQUEST['participants'])) $this->participants = ArrayUtil::trim(explode(',', $_REQUEST['participants']));
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\page\MultipleLinkPage::initObjectList()
+ * @inheritDoc
*/
protected function initObjectList() {
$this->objectList = new UserConversationList(WCF::getUser()->userID, $this->filter, $this->labelID);
$this->objectList->setLabelList($this->labelList);
+
+ if (!empty($this->participants)) {
+ $this->objectList->getConditionBuilder()->add('conversation.conversationID IN (SELECT conversationID FROM wcf'.WCF_N.'_conversation_to_user WHERE username IN (?) GROUP BY conversationID HAVING COUNT(conversationID) = ?)', [
+ $this->participants,
+ count($this->participants)
+ ]);
+ }
}
/**
- * @see \wcf\page\IPage::readData()
+ * @inheritDoc
*/
public function readData() {
// if sort field is `username`, `conversation.` has to prepended because `username`
}
if ($this->filter != '') {
- // add breadcrumbs
- WCF::getBreadcrumbs()->add(new Breadcrumb(WCF::getLanguage()->get('wcf.conversation.conversations'), LinkHandler::getInstance()->getLink('ConversationList')));
+ // `-1` = pseudo object id to have to pages with identifier `com.woltlab.wcf.conversation.ConversationList`
+ PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.conversation.ConversationList', -1);
}
// read stats
- if (!$this->labelID) {
+ if (!$this->labelID && empty($this->participants)) {
switch ($this->filter) {
case '':
$this->conversationCount = $this->items;
}
}
- if ($this->filter != '' || $this->labelID) {
+ if ($this->filter != '' || $this->labelID || !empty($this->participants)) {
$conversationList = new UserConversationList(WCF::getUser()->userID, '');
$this->conversationCount = $conversationList->countObjects();
}
- if ($this->filter != 'draft' || $this->labelID) {
+ if ($this->filter != 'draft' || $this->labelID || !empty($this->participants)) {
$conversationList = new UserConversationList(WCF::getUser()->userID, 'draft');
$this->draftCount = $conversationList->countObjects();
}
- if ($this->filter != 'hidden' || $this->labelID) {
+ if ($this->filter != 'hidden' || $this->labelID || !empty($this->participants)) {
$conversationList = new UserConversationList(WCF::getUser()->userID, 'hidden');
$this->hiddenCount = $conversationList->countObjects();
}
- if ($this->filter != 'outbox' || $this->labelID) {
+ if ($this->filter != 'outbox' || $this->labelID || !empty($this->participants)) {
$conversationList = new UserConversationList(WCF::getUser()->userID, 'outbox');
$this->outboxCount = $conversationList->countObjects();
}
}
/**
- * @see \wcf\page\IPage::assignVariables()
+ * @inheritDoc
*/
public function assignVariables() {
parent::assignVariables();
- WCF::getTPL()->assign(array(
+ WCF::getTPL()->assign([
'filter' => $this->filter,
'hasMarkedItems' => ClipboardHandler::getInstance()->hasMarkedItems(ClipboardHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.conversation.conversation')),
'labelID' => $this->labelID,
'conversationCount' => $this->conversationCount,
'draftCount' => $this->draftCount,
'hiddenCount' => $this->hiddenCount,
- 'outboxCount' => $this->outboxCount
- ));
+ 'outboxCount' => $this->outboxCount,
+ 'participants' => $this->participants
+ ]);
}
}
<?php
namespace wcf\page;
use wcf\data\conversation\label\ConversationLabel;
+use wcf\data\conversation\label\ConversationLabelList;
use wcf\data\conversation\message\ConversationMessage;
+use wcf\data\conversation\message\ViewableConversationMessageList;
use wcf\data\conversation\Conversation;
use wcf\data\conversation\ConversationAction;
use wcf\data\conversation\ConversationParticipantList;
use wcf\data\smiley\SmileyCache;
use wcf\system\attachment\AttachmentHandler;
use wcf\system\bbcode\BBCodeHandler;
-use wcf\system\breadcrumb\Breadcrumb;
use wcf\system\exception\IllegalLinkException;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\message\quote\MessageQuoteManager;
+use wcf\system\page\PageLocationManager;
+use wcf\system\page\ParentPageLocation;
use wcf\system\request\LinkHandler;
use wcf\system\WCF;
use wcf\util\HeaderUtil;
* Shows a conversation.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage page
- * @category Community Framework
+ * @package WoltLabSuite\Core\Page
+ *
+ * @property ViewableConversationMessageList $objectList
*/
class ConversationPage extends MultipleLinkPage {
/**
- * @see \wcf\page\AbstractPage::$enableTracking
- */
- public $enableTracking = true;
-
- /**
- * @see \wcf\page\MultipleLinkPage::$itemsPerPage
+ * @inheritDoc
*/
public $itemsPerPage = CONVERSATION_MESSAGES_PER_PAGE;
/**
- * @see \wcf\page\MultipleLinkPage::$sortOrder
+ * @inheritDoc
*/
public $sortOrder = 'ASC';
/**
- * @see \wcf\page\MultipleLinkPage::$objectListClassName
+ * @inheritDoc
*/
- public $objectListClassName = 'wcf\data\conversation\message\ViewableConversationMessageList';
+ public $objectListClassName = ViewableConversationMessageList::class;
/**
- * @see \wcf\page\AbstractPage::$loginRequired
+ * @inheritDoc
*/
public $loginRequired = true;
/**
- * @see \wcf\page\AbstractPage::$neededModules
+ * @inheritDoc
*/
- public $neededModules = array('MODULE_CONVERSATION');
+ public $neededModules = ['MODULE_CONVERSATION'];
/**
- * @see \wcf\page\AbstractPage::$neededPermissions
+ * @inheritDoc
*/
- public $neededPermissions = array('user.conversation.canUseConversation');
+ public $neededPermissions = ['user.conversation.canUseConversation'];
/**
* conversation id
/**
* viewable conversation object
- * @var \wcf\data\conversation\ViewableConversation
+ * @var ViewableConversation
*/
- public $conversation = null;
+ public $conversation;
/**
* conversation label list
- * @var \wcf\data\conversation\label\ConversationLabelList
+ * @var ConversationLabelList
*/
- public $labelList = null;
+ public $labelList;
/**
* message id
/**
* conversation message object
- * @var \wcf\data\conversation\message\ConversationMessage
+ * @var ConversationMessage
*/
- public $message = null;
+ public $message;
/**
* modification log list object
- * @var \wcf\data\wcf\data\modification\log\ConversationLogModificationLogList
+ * @var ConversationLogModificationLogList
*/
- public $modificationLogList = null;
+ public $modificationLogList;
/**
* list of participants
- * @var \wcf\data\conversation\ConversationParticipantList
+ * @var ConversationParticipantList
*/
- public $participantList = null;
+ public $participantList;
/**
- * @see \wcf\page\IPage::readParameters()
+ * @inheritDoc
*/
public function readParameters() {
parent::readParameters();
$this->labelList = ConversationLabel::getLabelsByUser();
$this->conversation = ViewableConversation::getViewableConversation($this->conversation, $this->labelList);
- // posts per page
- if (WCF::getUser()->conversationMessagesPerPage) $this->itemsPerPage = WCF::getUser()->conversationMessagesPerPage;
+ // messages per page
+ /** @noinspection PhpUndefinedFieldInspection */
+ if (WCF::getUser()->conversationMessagesPerPage) {
+ /** @noinspection PhpUndefinedFieldInspection */
+ $this->itemsPerPage = WCF::getUser()->conversationMessagesPerPage;
+ }
- $this->canonicalURL = LinkHandler::getInstance()->getLink('Conversation', array(
+ $this->canonicalURL = LinkHandler::getInstance()->getLink('Conversation', [
'object' => $this->conversation
- ), ($this->pageNo ? 'pageNo=' . $this->pageNo : ''));
+ ], ($this->pageNo ? 'pageNo=' . $this->pageNo : ''));
}
/**
- * @see \wcf\page\MultipleLinkPage::initObjectList()
+ * @inheritDoc
*/
protected function initObjectList() {
parent::initObjectList();
- $this->objectList->getConditionBuilder()->add('conversation_message.conversationID = ?', array($this->conversation->conversationID));
+ $this->objectList->getConditionBuilder()->add('conversation_message.conversationID = ?', [$this->conversation->conversationID]);
$this->objectList->setConversation($this->conversation->getDecoratedObject());
// handle jump to
}
/**
- * @see \wcf\page\IPage::readData()
+ * @inheritDoc
*/
public function readData() {
parent::readData();
// add breadcrumbs
- WCF::getBreadcrumbs()->add(new Breadcrumb(WCF::getLanguage()->get('wcf.conversation.conversations'), LinkHandler::getInstance()->getLink('ConversationList')));
if ($this->conversation->isDraft) {
- WCF::getBreadcrumbs()->add(new Breadcrumb(WCF::getLanguage()->get('wcf.conversation.folder.draft'), LinkHandler::getInstance()->getLink('ConversationList', array(
- 'filter' => 'draft'
- ))));
+ // `-1` = pseudo object id to have to pages with identifier `com.woltlab.wcf.conversation.ConversationList`
+ PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.conversation.ConversationList', -1, new ParentPageLocation(
+ WCF::getLanguage()->get('wcf.conversation.folder.draft'),
+ LinkHandler::getInstance()->getLink('ConversationList', ['filter' => 'draft'])
+ ));
}
+ PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.conversation.ConversationList');
// update last visit time count
if ($this->conversation->isNew() && $this->objectList->getMaxPostTime() > $this->conversation->lastVisitTime) {
$visitTime = $this->objectList->getMaxPostTime();
if ($visitTime == $this->conversation->lastPostTime) $visitTime = TIME_NOW;
- $conversationAction = new ConversationAction(array($this->conversation->getDecoratedObject()), 'markAsRead', array('visitTime' => $visitTime));
+ $conversationAction = new ConversationAction([$this->conversation->getDecoratedObject()], 'markAsRead', ['visitTime' => $visitTime]);
$conversationAction->executeAction();
}
// get participants
- $this->participantList = new ConversationParticipantList($this->conversationID, WCF::getUser()->userID, ($this->conversation->userID == WCF::getUser()->userID));
+ $this->participantList = new ConversationParticipantList($this->conversationID, WCF::getUser()->userID, $this->conversation->userID == WCF::getUser()->userID);
$this->participantList->readObjects();
// init quote objects
- $messageIDs = array();
+ $messageIDs = [];
foreach ($this->objectList as $message) {
$messageIDs[] = $message->messageID;
}
// set attachment permissions
if ($this->objectList->getAttachmentList() !== null) {
- $this->objectList->getAttachmentList()->setPermissions(array(
+ $this->objectList->getAttachmentList()->setPermissions([
'canDownload' => true,
'canViewPreview' => true
- ));
+ ]);
}
// get timeframe for modifications
AND time > ?
ORDER BY time";
$statement = WCF::getDB()->prepareStatement($sql, 1);
- $statement->execute(array($this->conversationID, $this->objectList->current()->time));
+ $statement->execute([$this->conversationID, $this->objectList->current()->time]);
$endTime = $statement->fetchSingleColumn() - 1;
}
}
// load modification log entries
$this->modificationLogList = new ConversationLogModificationLogList($this->conversation->conversationID);
- $this->modificationLogList->getConditionBuilder()->add("modification_log.time BETWEEN ? AND ?", array($startTime, $endTime));
+ $this->modificationLogList->getConditionBuilder()->add("modification_log.time BETWEEN ? AND ?", [$startTime, $endTime]);
$this->modificationLogList->readObjects();
}
/**
- * @see \wcf\page\IPage::assignVariables()
+ * @inheritDoc
*/
public function assignVariables() {
parent::assignVariables();
$tmpHash = StringUtil::getRandomID();
$attachmentHandler = new AttachmentHandler('com.woltlab.wcf.conversation.message', 0, $tmpHash, 0);
- WCF::getTPL()->assign(array(
+ WCF::getTPL()->assign([
'attachmentHandler' => $attachmentHandler,
'attachmentObjectID' => 0,
'attachmentObjectType' => 'com.woltlab.wcf.conversation.message',
'conversation' => $this->conversation,
'conversationID' => $this->conversationID,
'participants' => $this->participantList->getObjects(),
- 'defaultSmilies' => SmileyCache::getInstance()->getCategorySmilies(),
- 'permissionCanUseSmilies' => 'user.message.canUseSmilies'
- ));
+ 'defaultSmilies' => SmileyCache::getInstance()->getCategorySmilies()
+ ]);
- BBCodeHandler::getInstance()->setAllowedBBCodes(explode(',', WCF::getSession()->getPermission('user.message.allowedBBCodes')));
+ BBCodeHandler::getInstance()->setDisallowedBBCodes(explode(',', WCF::getSession()->getPermission('user.message.disallowedBBCodes')));
}
/**
*/
protected function goToPost() {
$conditionBuilder = clone $this->objectList->getConditionBuilder();
- $conditionBuilder->add('time '.($this->sortOrder == 'ASC' ? '<=' : '>=').' ?', array($this->message->time));
+ $conditionBuilder->add('time '.($this->sortOrder == 'ASC' ? '<=' : '>=').' ?', [$this->message->time]);
$sql = "SELECT COUNT(*) AS messages
FROM wcf".WCF_N."_conversation_message conversation_message
$statement = WCF::getDB()->prepareStatement($sql, 1);
$statement->execute($this->objectList->getConditionBuilder()->getParameters());
$row = $statement->fetchArray();
- HeaderUtil::redirect(LinkHandler::getInstance()->getLink('Conversation', array(
+ HeaderUtil::redirect(LinkHandler::getInstance()->getLink('Conversation', [
'encodeTitle' => true,
'object' => $this->conversation,
'messageID' => $row['messageID']
- )).'#message'.$row['messageID']);
+ ]).'#message'.$row['messageID']);
exit;
}
*/
protected function goToFirstNewPost() {
$conditionBuilder = clone $this->objectList->getConditionBuilder();
- $conditionBuilder->add('time > ?', array($this->conversation->lastVisitTime));
+ $conditionBuilder->add('time > ?', [$this->conversation->lastVisitTime]);
$sql = "SELECT conversation_message.messageID
FROM wcf".WCF_N."_conversation_message conversation_message
$statement->execute($conditionBuilder->getParameters());
$row = $statement->fetchArray();
if ($row !== false) {
- HeaderUtil::redirect(LinkHandler::getInstance()->getLink('Conversation', array(
+ HeaderUtil::redirect(LinkHandler::getInstance()->getLink('Conversation', [
'encodeTitle' => true,
'object' => $this->conversation,
'messageID' => $row['messageID']
- )).'#message'.$row['messageID']);
+ ]).'#message'.$row['messageID']);
exit;
}
else {
$this->goToLastPost();
}
}
-
- /**
- * @see \wcf\page\ITrackablePage::getObjectType()
- */
- public function getObjectType() {
- return 'com.woltlab.wcf.conversation';
- }
-
- /**
- * @see \wcf\page\ITrackablePage::getObjectID()
- */
- public function getObjectID() {
- return $this->conversationID;
- }
}
* Attachment object type implementation for conversations.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.attachment
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\Attachment
+ *
+ * @method ConversationMessage getObject($objectID)
*/
class ConversationMessageAttachmentObjectType extends AbstractAttachmentObjectType {
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\system\attachment\IAttachmentObjectType::getMaxSize()
+ * @inheritDoc
*/
public function getMaxSize() {
return WCF::getSession()->getPermission('user.conversation.maxAttachmentSize');
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\system\attachment\IAttachmentObjectType::getAllowedExtensions()
+ * @inheritDoc
*/
public function getAllowedExtensions() {
return ArrayUtil::trim(explode("\n", WCF::getSession()->getPermission('user.conversation.allowedAttachmentExtensions')));
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\system\attachment\IAttachmentObjectType::getMaxCount()
+ * @inheritDoc
*/
public function getMaxCount() {
return WCF::getSession()->getPermission('user.conversation.maxAttachmentCount');
}
/**
- * @see \wcf\system\attachment\IAttachmentObjectType::canDownload()
+ * @inheritDoc
*/
public function canDownload($objectID) {
if ($objectID) {
}
/**
- * @see \wcf\system\attachment\IAttachmentObjectType::canUpload()
+ * @inheritDoc
*/
public function canUpload($objectID, $parentObjectID = 0) {
if (!WCF::getSession()->getPermission('user.conversation.canUploadAttachment')) {
}
/**
- * @see \wcf\system\attachment\IAttachmentObjectType::canDelete()
+ * @inheritDoc
*/
public function canDelete($objectID) {
if ($objectID) {
}
/**
- * @see \wcf\system\attachment\IAttachmentObjectType::cacheObjects()
+ * @inheritDoc
*/
public function cacheObjects(array $objectIDs) {
$messageList = new ConversationMessageList();
$messageList->setObjectIDs($objectIDs);
$messageList->readObjects();
- $conversationIDs = array();
+ $conversationIDs = [];
foreach ($messageList as $message) {
$conversationIDs[] = $message->conversationID;
}
}
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\system\attachment\IAttachmentObjectType::setPermissions()
+ * @inheritDoc
*/
public function setPermissions(array $attachments) {
- $messageIDs = array();
+ $messageIDs = [];
foreach ($attachments as $attachment) {
// set default permissions
- $attachment->setPermissions(array(
+ $attachment->setPermissions([
'canDownload' => false,
'canViewPreview' => false
- ));
+ ]);
if ($this->getObject($attachment->objectID) === null) {
$messageIDs[] = $attachment->objectID;
if (($message = $this->getObject($attachment->objectID)) !== null) {
if (!$message->getConversation()->canRead()) continue;
- $attachment->setPermissions(array(
+ $attachment->setPermissions([
'canDownload' => true,
'canViewPreview' => true
- ));
+ ]);
}
else if ($attachment->tmpHash != '' && $attachment->userID == WCF::getUser()->userID) {
- $attachment->setPermissions(array(
+ $attachment->setPermissions([
'canDownload' => true,
'canViewPreview' => true
- ));
+ ]);
}
}
}
--- /dev/null
+<?php
+namespace wcf\system\cache\runtime;
+use wcf\data\conversation\Conversation;
+use wcf\data\conversation\ConversationList;
+
+/**
+ * Runtime cache implementation for conversations.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Cache\Runtime
+ * @since 3.0
+ *
+ * @method Conversation[] getCachedObjects()
+ * @method Conversation getObject($objectID)
+ * @method Conversation[] getObjects(array $objectIDs)
+ */
+class ConversationRuntimeCache extends AbstractRuntimeCache {
+ /**
+ * @inheritDoc
+ */
+ protected $listClassName = ConversationList::class;
+}
--- /dev/null
+<?php
+namespace wcf\system\cache\runtime;
+use wcf\data\conversation\Conversation;
+use wcf\data\conversation\UserConversationList;
+use wcf\system\WCF;
+
+/**
+ * Runtime cache implementation for conversation fetched using UserConversationList.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Cache\Runtime
+ * @since 3.0
+ *
+ * @method Conversation[] getCachedObjects()
+ * @method Conversation getObject($objectID)
+ * @method Conversation[] getObjects(array $objectIDs)
+ */
+class UserConversationRuntimeCache extends AbstractRuntimeCache {
+ /**
+ * @inheritDoc
+ */
+ protected $listClassName = UserConversationList::class;
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+ /**
+ * @inheritDoc
+ */
+ protected function getObjectList() {
+ return new UserConversationList(WCF::getUser()->userID);
+ }
+}
<?php
namespace wcf\system\clipboard\action;
use wcf\data\clipboard\action\ClipboardAction;
+use wcf\data\conversation\Conversation;
+use wcf\data\conversation\ConversationAction;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\WCF;
* Prepares clipboard editor items for conversations.
*
* @author Alexander Ebert
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.clipboard.action
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\Clipboard\Action
*/
class ConversationClipboardAction extends AbstractClipboardAction {
/**
- * @see \wcf\system\clipboard\action\AbstractClipboardAction::$actionClassActions
+ * @inheritDoc
*/
- protected $actionClassActions = array('close', 'markAsRead', 'open');
+ protected $actionClassActions = ['close', 'markAsRead', 'open'];
/**
* list of conversations
- * @var array<\wcf\data\conversation\Conversation>
+ * @var Conversation[]
*/
- public $conversations = null;
+ public $conversations;
/**
- * @see \wcf\system\clipboard\action\AbstractClipboardAction::$supportedActions
+ * @inheritDoc
*/
- protected $supportedActions = array('assignLabel', 'close', 'leave', 'leavePermanently', 'markAsRead', 'open', 'restore');
+ protected $supportedActions = ['assignLabel', 'close', 'leave', 'leavePermanently', 'markAsRead', 'open', 'restore'];
/**
- * @see \wcf\system\clipboard\action\IClipboardAction::execute()
+ * @inheritDoc
*/
public function execute(array $objects, ClipboardAction $action) {
if ($this->conversations === null) {
FROM wcf".WCF_N."_conversation_label
WHERE userID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(WCF::getUser()->userID));
+ $statement->execute([WCF::getUser()->userID]);
$row = $statement->fetchArray();
if ($row['count'] == 0) {
return null;
break;
case 'leave':
- $item->addInternalData('parameters', array('hideConversation' => 1));
+ $item->addInternalData('parameters', ['hideConversation' => 1]);
$item->addParameter('actionName', 'hideConversation');
$item->addParameter('className', $this->getClassName());
break;
case 'leavePermanently':
$item->addParameter('objectIDs', array_keys($this->conversations));
- $item->addInternalData('parameters', array('hideConversation' => 2));
+ $item->addInternalData('parameters', ['hideConversation' => 2]);
$item->addParameter('actionName', 'hideConversation');
$item->addParameter('className', $this->getClassName());
break;
$item->addParameter('objectIDs', array_keys($this->conversations));
$item->addParameter('actionName', 'markAsRead');
$item->addParameter('className', $this->getClassName());
- $item->addInternalData('confirmMessage', WCF::getLanguage()->getDynamicVariable('wcf.clipboard.item.com.woltlab.wcf.conversation.conversation.markAsRead.confirmMessage', array(
+ $item->addInternalData('confirmMessage', WCF::getLanguage()->getDynamicVariable('wcf.clipboard.item.com.woltlab.wcf.conversation.conversation.markAsRead.confirmMessage', [
'count' => $item->getCount()
- )));
+ ]));
break;
case 'restore':
- $item->addInternalData('parameters', array('hideConversation' => 0));
+ $item->addInternalData('parameters', ['hideConversation' => 0]);
$item->addParameter('actionName', 'hideConversation');
$item->addParameter('className', $this->getClassName());
break;
}
/**
- * @see \wcf\system\clipboard\action\IClipboardAction::getClassName()
+ * @inheritDoc
*/
public function getClassName() {
- return 'wcf\data\conversation\ConversationAction';
+ return ConversationAction::class;
}
/**
- * @see \wcf\system\clipboard\action\IClipboardAction::getTypeName()
+ * @inheritDoc
*/
public function getTypeName() {
return 'com.woltlab.wcf.conversation.conversation';
/**
* Returns a list of conversations with user participation.
*
- * @param array<\wcf\data\conversation\Conversation>
- * @return array<\wcf\data\conversation\Conversation>
+ * @param Conversation[] $conversations
*/
protected function validateParticipation(array $conversations) {
- $conversationIDs = array();
+ $conversationIDs = [];
// validate ownership
foreach ($conversations as $conversation) {
// validate participation as non-owner
if (!empty($conversationIDs)) {
$conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID IN (?)", array($conversationIDs));
- $conditions->add("participantID = ?", array(WCF::getUser()->userID));
+ $conditions->add("conversationID IN (?)", [$conversationIDs]);
+ $conditions->add("participantID = ?", [WCF::getUser()->userID]);
$sql = "SELECT conversationID
FROM wcf".WCF_N."_conversation_to_user
/**
* Validates if user may close the given conversations.
*
- * @return array<integer>
+ * @return integer[]
*/
protected function validateClose() {
- $conversationIDs = array();
+ $conversationIDs = [];
foreach ($this->conversations as $conversation) {
if (!$conversation->isClosed && $conversation->userID == WCF::getUser()->userID) {
/**
* Validates conversations available for leaving.
*
- * @return array<integer>
+ * @return integer[]
*/
public function validateLeave() {
- $tmpIDs = array();
+ $tmpIDs = [];
foreach ($this->conversations as $conversation) {
$tmpIDs[] = $conversation->conversationID;
}
$conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID IN (?)", array($tmpIDs));
- $conditions->add("participantID = ?", array(WCF::getUser()->userID));
- $conditions->add("hideConversation <> ?", array(1));
+ $conditions->add("conversationID IN (?)", [$tmpIDs]);
+ $conditions->add("participantID = ?", [WCF::getUser()->userID]);
+ $conditions->add("hideConversation <> ?", [1]);
$sql = "SELECT conversationID
FROM wcf".WCF_N."_conversation_to_user
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute($conditions->getParameters());
- $conversationIDs = array();
- while ($row = $statement->fetchArray()) {
- $conversationIDs[] = $row['conversationID'];
- }
-
- return $conversationIDs;
+ return $statement->fetchAll(\PDO::FETCH_COLUMN);
}
/**
* Validates conversations applicable for mark as read.
*
- * @return array<integer>
+ * @return integer[]
*/
public function validateMarkAsRead() {
- $conversationIDs = array();
+ $conversationIDs = [];
$conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID IN (?)", array(array_keys($this->conversations)));
- $conditions->add("participantID = ?", array(WCF::getUser()->userID));
+ $conditions->add("conversationID IN (?)", [array_keys($this->conversations)]);
+ $conditions->add("participantID = ?", [WCF::getUser()->userID]);
$sql = "SELECT conversationID, lastVisitTime
FROM wcf".WCF_N."_conversation_to_user
".$conditions;
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute($conditions->getParameters());
- $lastVisitTime = array();
+ $lastVisitTime = [];
while ($row = $statement->fetchArray()) {
$lastVisitTime[$row['conversationID']] = $row['lastVisitTime'];
}
/**
* Validates if user may open the given conversations.
*
- * @return array<integer>
+ * @return integer[]
*/
protected function validateOpen() {
- $conversationIDs = array();
+ $conversationIDs = [];
foreach ($this->conversations as $conversation) {
if ($conversation->isClosed && $conversation->userID == WCF::getUser()->userID) {
/**
* Validates conversations available for restore.
*
- * @return array<integer>
+ * @return integer[]
*/
public function validateRestore() {
- $tmpIDs = array();
+ $tmpIDs = [];
foreach ($this->conversations as $conversation) {
$tmpIDs[] = $conversation->conversationID;
}
$conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID IN (?)", array($tmpIDs));
- $conditions->add("participantID = ?", array(WCF::getUser()->userID));
- $conditions->add("hideConversation <> ?", array(0));
+ $conditions->add("conversationID IN (?)", [$tmpIDs]);
+ $conditions->add("participantID = ?", [WCF::getUser()->userID]);
+ $conditions->add("hideConversation <> ?", [0]);
$sql = "SELECT conversationID
FROM wcf".WCF_N."_conversation_to_user
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute($conditions->getParameters());
- $conversationIDs = array();
- while ($row = $statement->fetchArray()) {
- $conversationIDs[] = $row['conversationID'];
- }
-
- return $conversationIDs;
+ return $statement->fetchAll(\PDO::FETCH_COLUMN);
}
}
* Handles the number of conversations and unread conversations of the active user.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.conversation
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\Conversation
*/
class ConversationHandler extends SingletonFactory {
/**
* number of unread conversations
- * @var array<integer>
+ * @var integer[]
*/
- protected $unreadConversationCount = array();
+ protected $unreadConversationCount = [];
/**
* number of conversations
- * @var array<integer>
+ * @var integer[]
*/
- protected $conversationCount = array();
+ protected $conversationCount = [];
/**
* Returns the number of unread conversations for given user.
$this->unreadConversationCount[$userID] = 0;
// load storage data
- UserStorageHandler::getInstance()->loadStorage(array($userID));
+ UserStorageHandler::getInstance()->loadStorage([$userID]);
// get ids
- $data = UserStorageHandler::getInstance()->getStorage(array($userID), 'unreadConversationCount');
+ $data = UserStorageHandler::getInstance()->getStorage([$userID], 'unreadConversationCount');
// cache does not exist or is outdated
if ($data[$userID] === null || $skipCache) {
$conditionBuilder = new PreparedStatementConditionBuilder();
$conditionBuilder->add('conversation.conversationID = conversation_to_user.conversationID');
- $conditionBuilder->add('conversation_to_user.participantID = ?', array($userID));
+ $conditionBuilder->add('conversation_to_user.participantID = ?', [$userID]);
$conditionBuilder->add('conversation_to_user.hideConversation = 0');
$conditionBuilder->add('conversation_to_user.lastVisitTime < conversation.lastPostTime');
$this->conversationCount[$userID] = 0;
// load storage data
- UserStorageHandler::getInstance()->loadStorage(array($userID));
+ UserStorageHandler::getInstance()->loadStorage([$userID]);
// get ids
- $data = UserStorageHandler::getInstance()->getStorage(array($userID), 'conversationCount');
+ $data = UserStorageHandler::getInstance()->getStorage([$userID], 'conversationCount');
// cache does not exist or is outdated
if ($data[$userID] === null) {
$conditionBuilder1 = new PreparedStatementConditionBuilder();
- $conditionBuilder1->add('conversation_to_user.participantID = ?', array($userID));
+ $conditionBuilder1->add('conversation_to_user.participantID = ?', [$userID]);
$conditionBuilder1->add('conversation_to_user.hideConversation IN (0,1)');
$conditionBuilder2 = new PreparedStatementConditionBuilder();
- $conditionBuilder2->add('conversation.userID = ?', array($userID));
+ $conditionBuilder2->add('conversation.userID = ?', [$userID]);
$conditionBuilder2->add('conversation.isDraft = 1');
$sql = "SELECT (SELECT COUNT(*)
<?php
namespace wcf\system\event\listener;
-use wcf\system\WCF;
/**
- * Updates the stored username on user rename.
+ * Updates the stored username during user rename.
*
* @author Alexander Ebert
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.event.listener
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\Event\Listener
*/
-class ConversationUserActionRenameListener implements IParameterizedEventListener {
+class ConversationUserActionRenameListener extends AbstractUserActionRenameListener {
/**
- * @see \wcf\system\event\listener\IParameterizedEventListener::execute()
+ * @inheritDoc
*/
- public function execute($eventObj, $className, $eventName, array &$parameters) {
- $objects = $eventObj->getObjects();
- $userID = $objects[0]->userID;
-
- $actionParameters = $eventObj->getParameters();
- $username = $actionParameters['data']['username'];
-
- WCF::getDB()->beginTransaction();
-
- // conversations
- $sql = "UPDATE wcf".WCF_N."_conversation
- SET username = ?
- WHERE userID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($username, $userID));
-
- $sql = "UPDATE wcf".WCF_N."_conversation
- SET lastPoster = ?
- WHERE lastPosterID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($username, $userID));
-
- // conversation messages
- $sql = "UPDATE wcf".WCF_N."_conversation_message
- SET username = ?
- WHERE userID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($username, $userID));
-
- WCF::getDB()->commitTransaction();
- }
+ protected $databaseTables = [
+ 'wcf{WCF_N}_conversation',
+ 'wcf{WCF_N}_conversation_message',
+ [
+ 'name' => 'wcf{WCF_N}_conversation',
+ 'userID' => 'lastPosterID',
+ 'username' => 'lastPoster'
+ ]
+ ];
}
<?php
namespace wcf\system\event\listener;
-use wcf\system\database\util\PreparedStatementConditionBuilder;
-use wcf\system\WCF;
/**
* Merges user conversations.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.event.listener
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\Event\Listener
*/
-class ConversationUserMergeListener implements IParameterizedEventListener {
+class ConversationUserMergeListener extends AbstractUserMergeListener {
/**
- * @see \wcf\system\event\listener\IParameterizedEventListener::execute()
+ * @inheritDoc
*/
- public function execute($eventObj, $className, $eventName, array &$parameters) {
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("userID IN (?)", array($eventObj->mergedUserIDs));
- $parameters = array_merge(array(
- $eventObj->destinationUserID,
- $eventObj->users[$eventObj->destinationUserID]->username
- ), $conditions->getParameters());
-
- // conversation
- $sql = "UPDATE wcf".WCF_N."_conversation
- SET userID = ?,
- username = ?
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($parameters);
-
- $participantConditions = new PreparedStatementConditionBuilder();
- $participantConditions->add("lastPosterID IN (?)", array($eventObj->mergedUserIDs));
- $sql = "UPDATE wcf".WCF_N."_conversation
- SET lastPosterID = ?,
- lastPoster = ?
- ".$participantConditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($parameters); // can still use $parameters, even though $participantConditions != $conditions
-
- // conversation_to_user
- $participantConditions = new PreparedStatementConditionBuilder();
- $participantConditions->add("participantID IN (?)", array($eventObj->mergedUserIDs));
- $sql = "UPDATE IGNORE wcf".WCF_N."_conversation_to_user
- SET participantID = ?,
- username = ?
- ".$participantConditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($parameters); // can still use $parameters, even though $participantConditions != $conditions
-
- // conversation_message
- $sql = "UPDATE wcf".WCF_N."_conversation_message
- SET userID = ?,
- username = ?
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($parameters);
-
- // conversation_label
- $sql = "UPDATE wcf".WCF_N."_conversation_label
- SET userID = ?
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array_merge(array($eventObj->destinationUserID), $conditions->getParameters()));
- }
+ protected $databaseTables = [
+ 'wcf{WCF_N}_conversation',
+ 'wcf{WCF_N}_conversation_message',
+ [
+ 'name' => 'wcf{WCF_N}_conversation_label',
+ 'username' => null
+ ],
+ [
+ 'name' => 'wcf{WCF_N}_conversation_to_user',
+ 'userID' => 'participantID',
+ 'username' => null,
+ 'ignore' => true
+ ]
+ ];
}
* Imports conversation attachments.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.importer
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\Importer
*/
class ConversationAttachmentImporter extends AbstractAttachmentImporter {
/**
}
/**
- * @see \wcf\system\importer\IImporter::import()
+ * @inheritDoc
*/
- public function import($oldID, array $data, array $additionalData = array()) {
+ public function import($oldID, array $data, array $additionalData = []) {
$data['objectID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.conversation.message', $data['objectID']);
if (!$data['objectID']) return 0;
if (($newMessage = $this->fixEmbeddedAttachments($messageObj->message, $oldID, $attachmentID)) !== false) {
$editor = new ConversationMessageEditor($messageObj);
- $editor->update(array(
+ $editor->update([
'message' => $newMessage
- ));
+ ]);
}
}
* Imports conversations.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.importer
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\Importer
*/
class ConversationImporter extends AbstractImporter {
/**
- * @see \wcf\system\importer\AbstractImporter::$className
+ * @inheritDoc
*/
- protected $className = 'wcf\data\conversation\Conversation';
+ protected $className = Conversation::class;
/**
- * @see \wcf\system\importer\IImporter::import()
+ * @inheritDoc
*/
- public function import($oldID, array $data, array $additionalData = array()) {
+ public function import($oldID, array $data, array $additionalData = []) {
$oldUserID = $data['userID'];
$data['userID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.user', $data['userID']);
// add author
if (empty($data['isDraft'])) {
- ImportHandler::getInstance()->getImporter('com.woltlab.wcf.conversation.user')->import(0, array(
+ ImportHandler::getInstance()->getImporter('com.woltlab.wcf.conversation.user')->import(0, [
'conversationID' => $oldID,
'participantID' => $oldUserID,
'username' => $data['username'],
'hideConversation' => 0,
'isInvisible' => 0,
'lastVisitTime' => $data['time']
- ), array('labelIDs' => array()));
+ ], ['labelIDs' => []]);
}
return $conversation->conversationID;
<?php
namespace wcf\system\importer;
+use wcf\data\conversation\label\ConversationLabel;
use wcf\data\conversation\label\ConversationLabelAction;
/**
* Imports conversation labels.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.importer
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\Importer
*/
class ConversationLabelImporter extends AbstractImporter {
/**
- * @see \wcf\system\importer\AbstractImporter::$className
+ * @inheritDoc
*/
- protected $className = 'wcf\data\conversation\label\ConversationLabel';
+ protected $className = ConversationLabel::class;
/**
- * @see \wcf\system\importer\IImporter::import()
+ * @inheritDoc
*/
- public function import($oldID, array $data, array $additionalData = array()) {
+ public function import($oldID, array $data, array $additionalData = []) {
$data['userID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.user', $data['userID']);
if (!$data['userID']) return 0;
- $action = new ConversationLabelAction(array(), 'create', array(
+ $action = new ConversationLabelAction([], 'create', [
'data' => $data
- ));
+ ]);
$returnValues = $action->executeAction();
$newID = $returnValues['returnValues']->labelID;
* Imports conversation messages.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.importer
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\Importer
*/
class ConversationMessageImporter extends AbstractImporter {
/**
- * @see \wcf\system\importer\AbstractImporter::$className
+ * @inheritDoc
*/
- protected $className = 'wcf\data\conversation\message\ConversationMessage';
+ protected $className = ConversationMessage::class;
/**
- * @see \wcf\system\importer\IImporter::import()
+ * @inheritDoc
*/
- public function import($oldID, array $data, array $additionalData = array()) {
+ public function import($oldID, array $data, array $additionalData = []) {
$data['conversationID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.conversation', $data['conversationID']);
if (!$data['conversationID']) return 0;
$data['userID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.user', $data['userID']);
* Imports conversation users.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.importer
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\Importer
*/
class ConversationUserImporter extends AbstractImporter {
/**
- * @see \wcf\system\importer\IImporter::import()
+ * @inheritDoc
*/
- public function import($oldID, array $data, array $additionalData = array()) {
+ public function import($oldID, array $data, array $additionalData = []) {
$data['conversationID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.conversation', $data['conversationID']);
if (!$data['conversationID']) return 0;
$data['participantID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.user', $data['participantID']);
isInvisible = IF(isInvisible AND VALUES(isInvisible),1,0),
lastVisitTime = GREATEST(lastVisitTime,VALUES(lastVisitTime))";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
+ $statement->execute([
$data['conversationID'],
$data['participantID'],
$data['username'],
$data['hideConversation'],
$data['isInvisible'],
$data['lastVisitTime']
- ));
+ ]);
// save labels
if ($data['participantID'] && !empty($additionalData['labelIDs'])) {
$statement = WCF::getDB()->prepareStatement($sql);
foreach ($additionalData['labelIDs'] as $labelID) {
$labelID = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.conversation.label', $labelID);
- if ($labelID) $statement->execute(array($labelID, $data['conversationID']));
+ if ($labelID) $statement->execute([$labelID, $data['conversationID']]);
}
}
* Handles conversation modification logs.
*
* @author Alexander Ebert
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.log.modification
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\Log\Modification
*/
-class ConversationModificationLogHandler extends ModificationLogHandler {
+class ConversationModificationLogHandler extends AbstractModificationLogHandler {
+ /**
+ * @inheritDoc
+ */
+ protected $objectTypeName = 'com.woltlab.wcf.conversation.conversation';
+
/**
* Adds a log entry for newly added conversation participants.
*
- * @param \wcf\data\conversation\Conversation $conversation
- * @param array<integer> $participantIDs
+ * @param Conversation $conversation
+ * @param integer[] $participantIDs
*/
public function addParticipants(Conversation $conversation, array $participantIDs) {
- $participants = array();
+ $participants = [];
$userList = new UserList();
$userList->setObjectIDs($participantIDs);
$userList->readObjects();
foreach ($userList as $user) {
- $participants[] = array(
+ $participants[] = [
'userID' => $user->userID,
'username' => $user->username
- );
+ ];
}
- $this->add($conversation, 'addParticipants', array(
+ $this->add($conversation, 'addParticipants', [
'participants' => $participants
- ));
+ ]);
}
/**
* Adds a log entry for conversation close.
*
- * @param \wcf\data\conversation\Conversation $conversation
+ * @param Conversation $conversation
*/
public function close(Conversation $conversation) {
$this->add($conversation, 'close');
/**
* Adds a log entry for conversation open.
*
- * @param \wcf\data\conversation\Conversation $conversation
+ * @param Conversation $conversation
*/
public function open(Conversation $conversation) {
$this->add($conversation, 'open');
/**
* Adds a log entry for conversation leave.
*
- * @param \wcf\data\conversation\Conversation $conversation
+ * @param Conversation $conversation
*/
public function leave(Conversation $conversation) {
$this->add($conversation, 'leave');
/**
* Adds a log entry for a removed participant.
*
- * @param \wcf\data\conversation\Conversation $conversation
- * @param integer $userID
+ * @param Conversation $conversation
+ * @param integer $userID
*/
public function removeParticipant(Conversation $conversation, $userID) {
$user = new User($userID);
- $this->add($conversation, 'removeParticipant', array(
+ $this->add($conversation, 'removeParticipant', [
'userID' => $userID,
'username' => $user->username
- ));
+ ]);
}
/**
* Adds a conversation modification log entry.
*
- * @param \wcf\data\conversation\Conversation $conversation
- * @param string $action
- * @param array $additionalData
+ * @param Conversation $conversation
+ * @param string $action
+ * @param array $additionalData
*/
- public function add(Conversation $conversation, $action, array $additionalData = array()) {
- parent::_add('com.woltlab.wcf.conversation.conversation', $conversation->conversationID, $action, $additionalData);
+ public function add(Conversation $conversation, $action, array $additionalData = []) {
+ $this->createLog($action, $conversation->conversationID, null, $additionalData);
}
/**
* Removes the conversation log entries of the conversations with the given
* ids.
*
- * @param array<integer> $objectIDs
+ * @param integer[] $objectIDs
+ * @deprecated 3.0, use deleteLogs()
*/
public function remove(array $objectIDs) {
- parent::_remove('com.woltlab.wcf.conversation.conversation', $objectIDs);
+ $this->deleteLogs($objectIDs);
}
}
* IMessageQuoteHandler implementation for conversation messages.
*
* @author Alexander Ebert
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.message.quote
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\Message\Quote
*/
class ConversationMessageQuoteHandler extends AbstractMessageQuoteHandler {
/**
- * @see \wcf\system\message\quote\AbstractMessageQuoteHandler::getMessages()
+ * @inheritDoc
*/
protected function getMessages(array $data) {
// read messages
$messageList = new ConversationMessageList();
- $messageList->getConditionBuilder()->add("conversation_message.messageID IN (?)", array(array_keys($data)));
+ $messageList->setObjectIDs(array_keys($data));
$messageList->readObjects();
$messages = $messageList->getObjects();
// read conversations
- $conversationIDs = $validMessageIDs = array();
+ $conversationIDs = $validMessageIDs = [];
foreach ($messages as $message) {
$conversationIDs[] = $message->conversationID;
$validMessageIDs[] = $message->messageID;
}
- $quotedMessages = array();
+ $quotedMessages = [];
if (!empty($conversationIDs)) {
$conversationList = new ConversationList();
- $conversationList->getConditionBuilder()->add("conversation.conversationID IN (?)", array($conversationIDs));
+ $conversationList->setObjectIDs($conversationIDs);
$conversationList->readObjects();
$conversations = $conversationList->getObjects();
// check for orphaned quotes
if (count($validMessageIDs) != count($data)) {
- $orphanedQuoteIDs = array();
+ $orphanedQuoteIDs = [];
foreach ($data as $messageID => $quoteIDs) {
if (!in_array($messageID, $validMessageIDs)) {
foreach (array_keys($quoteIDs) as $quoteID) {
* An implementation of IModerationQueueReportHandler for conversation messages.
*
* @author Alexander Ebert
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.moderation.queue
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\Moderation\Queue
*/
class ConversationMessageModerationQueueReportHandler extends AbstractModerationQueueHandler implements IModerationQueueReportHandler {
/**
- * @see \wcf\system\moderation\queue\AbstractModerationQueueHandler::$className
+ * @inheritDoc
*/
- protected $className = 'wcf\data\conversation\message\ConversationMessage';
+ protected $className = ConversationMessage::class;
/**
- * @see \wcf\system\moderation\queue\AbstractModerationQueueHandler::$definitionName
+ * @inheritDoc
*/
protected $definitionName = 'com.woltlab.wcf.moderation.report';
/**
- * @see \wcf\system\moderation\queue\AbstractModerationQueueHandler::$objectType
+ * @inheritDoc
*/
protected $objectType = 'com.woltlab.wcf.conversation.message';
/**
* list of conversation message
- * @var array<\wcf\data\conversation\message\ConversationMessage>
+ * @var ConversationMessage[]
*/
- protected static $messages = array();
+ protected static $messages = [];
/**
- * @see \wcf\system\moderation\queue\AbstractModerationQueueHandler::$requiredPermission
+ * @inheritDoc
*/
protected $requiredPermission = 'mod.conversation.canModerateConversation';
/**
- * @see \wcf\system\moderation\queue\IModerationQueueHandler::assignQueues()
+ * @inheritDoc
*/
public function assignQueues(array $queues) {
- $assignments = array();
+ $assignments = [];
foreach ($queues as $queue) {
$assignUser = false;
if (WCF::getSession()->getPermission('mod.conversation.canModerateConversation')) {
}
/**
- * @see \wcf\system\moderation\queue\report\IModerationQueueReportHandler::canReport()
+ * @inheritDoc
*/
public function canReport($objectID) {
if (!$this->isValid($objectID)) {
return false;
}
- if (!Conversation::isParticipant(array($this->getMessage($objectID)->conversationID))) {
+ if (!Conversation::isParticipant([$this->getMessage($objectID)->conversationID])) {
return false;
}
}
/**
- * @see \wcf\system\moderation\queue\IModerationQueueHandler::getContainerID()
+ * @inheritDoc
*/
public function getContainerID($objectID) {
return 0;
}
/**
- * @see \wcf\system\moderation\queue\report\IModerationQueueReportHandler::getReportedContent()
+ * @inheritDoc
*/
public function getReportedContent(ViewableModerationQueue $queue) {
- WCF::getTPL()->assign(array(
- 'message' => ViewableConversationMessage::getViewableConversationMessage($queue->getAffectedObject()->messageID)
- ));
+ /** @noinspection PhpParamsInspection */
+ WCF::getTPL()->assign([
+ 'message' => new ViewableConversationMessage($queue->getAffectedObject())
+ ]);
return WCF::getTPL()->fetch('moderationConversationMessage');
}
/**
- * @see \wcf\system\moderation\queue\report\IModerationQueueReportHandler::getReportedObject()
+ * @inheritDoc
*/
public function getReportedObject($objectID) {
if ($this->isValid($objectID)) {
}
/**
- * @see \wcf\system\moderation\queue\IModerationQueueHandler::isValid()
+ * @inheritDoc
*/
public function isValid($objectID) {
if ($this->getMessage($objectID) === null) {
* Returns a conversation message object by message id or null if message id is invalid.
*
* @param integer $objectID
- * @return \wcf\data\conversation\message\ConversationMessage
+ * @return ConversationMessage
*/
protected function getMessage($objectID) {
if (!array_key_exists($objectID, self::$messages)) {
}
/**
- * @see \wcf\system\moderation\queue\IModerationQueueHandler::populate()
+ * @inheritDoc
*/
public function populate(array $queues) {
- $objectIDs = array();
+ $objectIDs = [];
foreach ($queues as $object) {
$objectIDs[] = $object->objectID;
}
}
// fetch conversations
- $conversationIDs = array();
+ $conversationIDs = [];
foreach ($messages as $message) {
$conversationIDs[] = $message->conversationID;
}
}
/**
- * @see \wcf\system\moderation\queue\IModerationQueueHandler::removeContent()
+ * @inheritDoc
*/
public function removeContent(ModerationQueue $queue, $message) {
if ($this->isValid($queue->objectID)) {
- $messageAction = new ConversationMessageAction(array($this->getMessage($queue->objectID)), 'delete');
+ $messageAction = new ConversationMessageAction([$this->getMessage($queue->objectID)], 'delete');
$messageAction->executeAction();
}
}
--- /dev/null
+<?php
+namespace wcf\system\page\handler;
+use wcf\system\conversation\ConversationHandler;
+use wcf\system\WCF;
+
+/**
+ * Page handler implementation for the conversation list.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Page\Handler
+ * @since 3.0
+ */
+class ConversationListPageHandler extends AbstractMenuPageHandler {
+ /** @noinspection PhpMissingParentCallCommonInspection */
+ /**
+ * @inheritDoc
+ */
+ public function getOutstandingItemCount($objectID = null) {
+ return ConversationHandler::getInstance()->getUnreadConversationCount();
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+ /**
+ * @inheritDoc
+ */
+ public function isVisible($objectID = null) {
+ return WCF::getUser()->userID != 0;
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\page\handler;
+
+/**
+ * Default implementation of a board-related page handler.
+ *
+ * Only use this class when you need the online location handling for a board-related page.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Page\Handler
+ * @since 3.0
+ */
+class DefaultConversationRelatedPageHandler extends AbstractMenuPageHandler implements IOnlineLocationPageHandler {
+ use TConversationOnlineLocationPageHandler;
+}
--- /dev/null
+<?php
+namespace wcf\system\page\handler;
+use wcf\data\page\Page;
+use wcf\data\user\online\UserOnline;
+use wcf\system\cache\runtime\UserConversationRuntimeCache;
+use wcf\system\WCF;
+
+/**
+ * Implementation of the online location-related page handler methods for conversations.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Page\Handler
+ * @since 3.0
+ */
+trait TConversationOnlineLocationPageHandler {
+ use TOnlineLocationPageHandler;
+
+ /**
+ * Returns the textual description if a user is currently online viewing this page.
+ *
+ * @see IOnlineLocationPageHandler::getOnlineLocation()
+ *
+ * @param Page $page visited page
+ * @param UserOnline $user user online object with request data
+ * @return string
+ */
+ public function getOnlineLocation(Page $page, UserOnline $user) {
+ if ($user->pageObjectID === null) {
+ return '';
+ }
+
+ $conversation = UserConversationRuntimeCache::getInstance()->getObject($user->pageObjectID);
+ if ($conversation === null || !$conversation->canRead()) {
+ return '';
+ }
+
+ return WCF::getLanguage()->getDynamicVariable('wcf.page.onlineLocation.'.$page->identifier, ['conversation' => $conversation]);
+ }
+
+ /**
+ * Prepares fetching all necessary data for the textual description if a user is currently online
+ * viewing this page.
+ *
+ * @see IOnlineLocationPageHandler::prepareOnlineLocation()
+ *
+ * @param Page $page visited page
+ * @param UserOnline $user user online object with request data
+ */
+ public function prepareOnlineLocation(/** @noinspection PhpUnusedParameterInspection */Page $page, UserOnline $user) {
+ if ($user->pageObjectID !== null) {
+ UserConversationRuntimeCache::getInstance()->cacheObjectID($user->pageObjectID);
+ }
+ }
+}
<?php
namespace wcf\system\search;
+use wcf\data\conversation\message\SearchResultConversationMessage;
use wcf\data\conversation\message\SearchResultConversationMessageList;
+use wcf\data\conversation\Conversation;
use wcf\form\IForm;
+use wcf\form\SearchForm;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\WCF;
* An implementation of ISearchableObjectType for searching in conversations.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.search
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\Search
*/
class ConversationMessageSearch extends AbstractSearchableObjectType {
+ /**
+ * id of the searched conversation
+ * @var integer
+ */
+ public $conversationID = 0;
+
+ /**
+ * searched conversation
+ * @var Conversation
+ */
+ public $conversation;
+
/**
* message data cache
- * @var array<\wcf\data\conversation\message\SearchResultConversationMessage>
+ * @var SearchResultConversationMessage[]
*/
- public $messageCache = array();
+ public $messageCache = [];
/**
- * @see \wcf\system\search\ISearchableObjectType::cacheObjects()
+ * @inheritDoc
*/
public function cacheObjects(array $objectIDs, array $additionalData = null) {
$messageList = new SearchResultConversationMessageList();
- $messageList->getConditionBuilder()->add('conversation_message.messageID IN (?)', array($objectIDs));
+ $messageList->setObjectIDs($objectIDs);
$messageList->readObjects();
foreach ($messageList->getObjects() as $message) {
$this->messageCache[$message->messageID] = $message;
}
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\system\search\ISearchableObjectType::getObject()
+ * @inheritDoc
+ */
+ public function getAdditionalData() {
+ return [
+ 'conversationID' => $this->conversationID
+ ];
+ }
+
+ /**
+ * @inheritDoc
*/
public function getObject($objectID) {
if (isset($this->messageCache[$objectID])) return $this->messageCache[$objectID];
return null;
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\system\search\ISearchableObjectType::getJoins()
+ * @inheritDoc
*/
public function getJoins() {
return "JOIN wcf".WCF_N."_conversation_to_user conversation_to_user ON (conversation_to_user.participantID = ".WCF::getUser()->userID." AND conversation_to_user.conversationID = ".$this->getTableName().".conversationID)
- LEFT JOIN wcf".WCF_N."_conversation conversation ON (conversation.conversationID = ".$this->getTableName().".conversationID)";
+ LEFT JOIN wcf".WCF_N."_conversation conversation ON (conversation.conversationID = ".$this->getTableName().".conversationID)";
}
/**
- * @see \wcf\system\search\ISearchableObjectType::getTableName()
+ * @inheritDoc
*/
public function getTableName() {
return 'wcf'.WCF_N.'_conversation_message';
}
/**
- * @see \wcf\system\search\ISearchableObjectType::getIDFieldName()
+ * @inheritDoc
*/
public function getIDFieldName() {
return $this->getTableName().'.messageID';
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\system\search\ISearchableObjectType::getSubjectFieldName()
+ * @inheritDoc
*/
public function getSubjectFieldName() {
return 'conversation.subject';
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\system\search\ISearchableObjectType::getConditions()
+ * @inheritDoc
*/
public function getConditions(IForm $form = null) {
$conditionBuilder = new PreparedStatementConditionBuilder();
$conditionBuilder->add('conversation_to_user.hideConversation IN (0,1)');
+ if (isset($_POST['conversationID'])) {
+ $this->conversationID = intval($_POST['conversationID']);
+
+ $conditionBuilder->add('conversation.conversationID = ?', [$this->conversationID]);
+ }
+
return $conditionBuilder;
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\system\search\ISearchableObjectType::isAccessible()
+ * @inheritDoc
*/
public function isAccessible() {
return (WCF::getUser()->userID ? true : false);
}
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+ /**
+ * @inheritDoc
+ */
+ public function getFormTemplateName() {
+ if ($this->conversation) {
+ return 'searchConversationMessage';
+ }
+
+ return null;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function show(IForm $form = null) {
+ /** @var SearchForm $form */
+
+ // get existing values
+ if ($form !== null && isset($form->searchData['additionalData']['com.woltlab.wcf.conversation.message']['conversationID'])) {
+ $this->conversationID = $form->searchData['additionalData']['com.woltlab.wcf.conversation.message']['conversationID'];
+
+ if ($this->conversationID) {
+ $this->conversation = Conversation::getUserConversation($this->conversationID, WCF::getUser()->userID);
+
+ if ($this->conversation === null || !$this->conversation->canRead()) {
+ $this->conversationID = 0;
+ $this->conversation = null;
+ }
+ }
+ }
+
+ WCF::getTPL()->assign('searchedConversation', $this->conversation);
+ }
}
* Stat handler implementation for conversation messages.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.stat
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\Stat
*/
class ConversationMessageStatDailyHandler extends AbstractStatDailyHandler {
/**
- * @see \wcf\system\stat\IStatDailyHandler::getData()
+ * @inheritDoc
*/
public function getData($date) {
- return array(
+ return [
'counter' => $this->getCounter($date, 'wcf'.WCF_N.'_conversation_message', 'time'),
'total' => $this->getTotal($date, 'wcf'.WCF_N.'_conversation_message', 'time')
- );
+ ];
}
}
* Stat handler implementation for conversations.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.stat
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\Stat
*/
class ConversationStatDailyHandler extends AbstractStatDailyHandler {
/**
- * @see \wcf\system\stat\IStatDailyHandler::getData()
+ * @inheritDoc
*/
public function getData($date) {
- return array(
+ return [
'counter' => $this->getCounter($date, 'wcf'.WCF_N.'_conversation', 'time'),
'total' => $this->getTotal($date, 'wcf'.WCF_N.'_conversation', 'time')
- );
+ ];
}
}
<?php
namespace wcf\system\user\notification\event;
+use wcf\system\email\Email;
use wcf\system\request\LinkHandler;
-use wcf\system\user\notification\event\AbstractUserNotificationEvent;
+use wcf\system\user\notification\object\ConversationMessageUserNotificationObject;
/**
* User notification event for conversation messages.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.user.notification.event
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\User\Notification\Event
+ *
+ * @method ConversationMessageUserNotificationObject getUserNotificationObject()
*/
class ConversationMessageUserNotificationEvent extends AbstractUserNotificationEvent {
/**
- * @see \wcf\system\user\notification\event\AbstractUserNotificationEvent::$stackable
+ * @inheritDoc
*/
protected $stackable = true;
/**
- * @see \wcf\system\user\notification\event\IUserNotificationEvent::getMessage()
+ * @inheritDoc
*/
public function getTitle() {
$count = count($this->getAuthors());
if ($count > 1) {
- return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message.title.stacked', array('count' => $count));
+ return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message.title.stacked', ['count' => $count]);
}
return $this->getLanguage()->get('wcf.user.notification.conversation.message.title');
}
/**
- * @see \wcf\system\user\notification\event\IUserNotificationEvent::getMessage()
+ * @inheritDoc
*/
public function getMessage() {
$authors = array_values($this->getAuthors());
$count = count($authors);
if ($count > 1) {
- return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message.message.stacked', array(
+ return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message.message.stacked', [
'author' => $this->author,
'authors' => $authors,
'count' => $count,
'message' => $this->userNotificationObject,
'others' => $count - 1
- ));
+ ]);
}
- return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message.message', array(
+ return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message.message', [
'author' => $this->author,
'message' => $this->userNotificationObject
- ));
+ ]);
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\system\user\notification\event\IUserNotificationEvent::getEmailMessage()
+ * @inheritDoc
*/
public function getEmailMessage($notificationType = 'instant') {
- return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message.mail', array(
- 'message' => $this->userNotificationObject,
- 'author' => $this->author,
- 'notificationType' => $notificationType
- ));
+ $messageID = '<com.woltlab.wcf.conversation.notification/'.$this->getUserNotificationObject()->getConversation()->conversationID.'@'.Email::getHost().'>';
+
+ return [
+ 'template' => 'email_notification_conversationMessage',
+ 'application' => 'wcf',
+ 'in-reply-to' => [$messageID],
+ 'references' => [$messageID]
+ ];
}
/**
- * @see \wcf\system\user\notification\event\IUserNotificationEvent::getLink()
+ * @inheritDoc
*/
public function getLink() {
- return LinkHandler::getInstance()->getLink('Conversation', array(
- 'object' => $this->userNotificationObject->getConversation(),
- 'messageID' => $this->userNotificationObject->messageID
- ), '#message'.$this->userNotificationObject->messageID);
+ return LinkHandler::getInstance()->getLink('Conversation', [
+ 'object' => $this->getUserNotificationObject()->getConversation(),
+ 'messageID' => $this->getUserNotificationObject()->messageID
+ ], '#message'.$this->getUserNotificationObject()->messageID);
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\system\user\notification\event\IUserNotificationEvent::getEventHash()
+ * @inheritDoc
*/
public function getEventHash() {
- return sha1($this->eventID . '-' . $this->userNotificationObject->conversationID);
+ return sha1($this->eventID . '-' . $this->getUserNotificationObject()->conversationID);
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\system\user\notification\event\IUserNotificationEvent::checkAccess()
+ * @inheritDoc
*/
public function checkAccess() {
- return $this->userNotificationObject->getConversation()->canRead();
+ return $this->getUserNotificationObject()->getConversation()->canRead();
}
}
<?php
namespace wcf\system\user\notification\event;
use wcf\system\request\LinkHandler;
-use wcf\system\user\notification\event\AbstractUserNotificationEvent;
+use wcf\system\user\notification\object\ConversationUserNotificationObject;
/**
* User notification event for conversations.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.user.notification.event
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\User\Notification\Event
+ *
+ * @method ConversationUserNotificationObject getUserNotificationObject()
*/
class ConversationUserNotificationEvent extends AbstractUserNotificationEvent {
/**
- * @see \wcf\system\user\notification\event\IUserNotificationEvent::getMessage()
+ * @inheritDoc
*/
public function getTitle() {
return $this->getLanguage()->get('wcf.user.notification.conversation.title');
}
/**
- * @see \wcf\system\user\notification\event\IUserNotificationEvent::getMessage()
+ * @inheritDoc
*/
public function getMessage() {
- return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message', array(
+ return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message', [
'author' => $this->author,
'conversation' => $this->userNotificationObject
- ));
+ ]);
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\system\user\notification\event\IUserNotificationEvent::getEmailMessage()
+ * @inheritDoc
*/
public function getEmailMessage($notificationType = 'instant') {
- return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.mail', array(
- 'conversation' => $this->userNotificationObject,
- 'author' => $this->author,
- 'notificationType' => $notificationType
- ));
+ return [
+ 'message-id' => 'com.woltlab.wcf.conversation.notification/'.$this->getUserNotificationObject()->conversationID,
+ 'template' => 'email_notification_conversation',
+ 'application' => 'wcf'
+ ];
}
/**
- * @see \wcf\system\user\notification\event\IUserNotificationEvent::getLink()
+ * @inheritDoc
*/
public function getLink() {
- return LinkHandler::getInstance()->getLink('Conversation', array('object' => $this->userNotificationObject));
+ return LinkHandler::getInstance()->getLink('Conversation', ['object' => $this->userNotificationObject]);
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\system\user\notification\event\IUserNotificationEvent::checkAccess()
+ * @inheritDoc
*/
public function checkAccess() {
- return $this->userNotificationObject->canRead();
+ return $this->getUserNotificationObject()->canRead();
}
}
<?php
namespace wcf\system\user\notification\object;
+use wcf\data\conversation\message\ConversationMessage;
use wcf\data\DatabaseObjectDecorator;
use wcf\system\request\LinkHandler;
* Notification object for conversations.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.user.notification.object
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\User\Notification\Object
+ *
+ * @method ConversationMessage getDecoratedObject()
+ * @mixin ConversationMessage
*/
class ConversationMessageUserNotificationObject extends DatabaseObjectDecorator implements IStackableUserNotificationObject {
/**
- * @see \wcf\data\DatabaseObjectDecorator::$baseClass
+ * @inheritDoc
*/
- protected static $baseClass = 'wcf\data\conversation\message\ConversationMessage';
+ protected static $baseClass = ConversationMessage::class;
/**
- * @see \wcf\system\user\notification\object\IUserNotificationObject::getTitle()
+ * @inheritDoc
*/
public function getTitle() {
return $this->getConversation()->subject;
}
/**
- * @see \wcf\system\user\notification\object\IUserNotificationObject::getURL()
+ * @inheritDoc
*/
public function getURL() {
- return LinkHandler::getInstance()->getLink('Conversation', array(
+ return LinkHandler::getInstance()->getLink('Conversation', [
'object' => $this->getConversation(),
'messageID' => $this->messageID
- )).'#message'.$this->messageID;
+ ]).'#message'.$this->messageID;
}
/**
- * @see \wcf\system\user\notification\object\IUserNotificationObject::getAuthorID()
+ * @inheritDoc
*/
public function getAuthorID() {
return $this->userID;
}
/**
- * @see \wcf\system\user\notification\object\IStackableUserNotificationObject::getRelatedObjectID()
+ * @inheritDoc
*/
public function getRelatedObjectID() {
return $this->conversationID;
<?php
namespace wcf\system\user\notification\object;
+use wcf\data\conversation\Conversation;
use wcf\data\DatabaseObjectDecorator;
use wcf\system\request\LinkHandler;
* Notification object for conversations.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.user.notification.object
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\User\Notification\Object
+ *
+ * @method Conversation getDecoratedObject()
+ * @mixin Conversation
*/
class ConversationUserNotificationObject extends DatabaseObjectDecorator implements IUserNotificationObject {
/**
- * @see \wcf\data\DatabaseObjectDecorator::$baseClass
+ * @inheritDoc
*/
- protected static $baseClass = 'wcf\data\conversation\Conversation';
+ protected static $baseClass = Conversation::class;
/**
- * @see \wcf\system\user\notification\object\IUserNotificationObject::getTitle()
+ * @inheritDoc
*/
public function getTitle() {
return $this->subject;
}
/**
- * @see \wcf\system\user\notification\object\IUserNotificationObject::getURL()
+ * @inheritDoc
*/
public function getURL() {
- return LinkHandler::getInstance()->getLink('Conversation', array(
+ return LinkHandler::getInstance()->getLink('Conversation', [
'object' => $this->getDecoratedObject()
- ));
+ ]);
}
/**
- * @see \wcf\system\user\notification\object\IUserNotificationObject::getAuthorID()
+ * @inheritDoc
*/
public function getAuthorID() {
return $this->userID;
<?php
namespace wcf\system\user\notification\object\type;
+use wcf\data\conversation\message\ConversationMessage;
+use wcf\data\conversation\message\ConversationMessageList;
+use wcf\system\user\notification\object\ConversationMessageUserNotificationObject;
/**
* Represents a conversation message notification object type.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.user.notification.object.type
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\User\Notification\Object\Type
*/
class ConversationMessageNotificationObjectType extends AbstractUserNotificationObjectType {
/**
- * @see \wcf\system\user\notification\object\type\AbstractUserNotificationObjectType::$decoratorClassName
+ * @inheritDoc
*/
- protected static $decoratorClassName = 'wcf\system\user\notification\object\ConversationMessageUserNotificationObject';
+ protected static $decoratorClassName = ConversationMessageUserNotificationObject::class;
/**
- * @see \wcf\system\user\notification\object\type\AbstractUserNotificationObjectType::$objectClassName
+ * @inheritDoc
*/
- protected static $objectClassName = 'wcf\data\conversation\message\ConversationMessage';
+ protected static $objectClassName = ConversationMessage::class;
/**
- * @see \wcf\system\user\notification\object\type\AbstractUserNotificationObjectType::$objectListClassName
+ * @inheritDoc
*/
- protected static $objectListClassName = 'wcf\data\conversation\message\ConversationMessageList';
+ protected static $objectListClassName = ConversationMessageList::class;
}
<?php
namespace wcf\system\user\notification\object\type;
use wcf\data\conversation\Conversation;
+use wcf\data\conversation\ConversationList;
+use wcf\system\user\notification\object\ConversationUserNotificationObject;
use wcf\system\WCF;
/**
* Represents a conversation notification object type.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.user.notification.object.type
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\User\Notification\Object\Type
*/
class ConversationNotificationObjectType extends AbstractUserNotificationObjectType {
/**
- * @see \wcf\system\user\notification\object\type\AbstractUserNotificationObjectType::$decoratorClassName
+ * @inheritDoc
*/
- protected static $decoratorClassName = 'wcf\system\user\notification\object\ConversationUserNotificationObject';
+ protected static $decoratorClassName = ConversationUserNotificationObject::class;
/**
- * @see \wcf\system\user\notification\object\type\AbstractUserNotificationObjectType::$objectClassName
+ * @inheritDoc
*/
- protected static $objectClassName = 'wcf\data\conversation\Conversation';
+ protected static $objectClassName = Conversation::class;
/**
- * @see \wcf\system\user\notification\object\type\AbstractUserNotificationObjectType::$objectListClassName
+ * @inheritDoc
*/
- protected static $objectListClassName = 'wcf\data\conversation\ConversationList';
+ protected static $objectListClassName = ConversationList::class;
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\system\user\notification\object\type\IUserNotificationObjectType::getObjectsByIDs()
+ * @inheritDoc
*/
public function getObjectsByIDs(array $objectIDs) {
$objects = Conversation::getUserConversations($objectIDs, WCF::getUser()->userID);
// '__unknownNotificationObject' tells the notification API
// that the object does not exist anymore so that the related
// notification can be deleted automatically
- $objects[$objectID] = new static::$decoratorClassName(new static::$objectClassName(null, array(
+ $objects[$objectID] = new static::$decoratorClassName(new static::$objectClassName(null, [
'__unknownNotificationObject' => true,
'conversationID' => $objectID
- )));
+ ]));
}
}
+++ /dev/null
-<?php
-namespace wcf\system\user\online\location;
-use wcf\data\conversation\Conversation;
-use wcf\data\user\online\UserOnline;
-use wcf\system\database\util\PreparedStatementConditionBuilder;
-use wcf\system\WCF;
-
-/**
- * Implementation of IUserOnlineLocation for the conversation page location.
- *
- * @author Marcel Werk
- * @copyright 2001-2016 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf.conversation
- * @subpackage system.user.online.location
- * @category Community Framework
- */
-class ConversationLocation implements IUserOnlineLocation {
- /**
- * conversation ids
- * @var array<integer>
- */
- protected $conversationIDs = array();
-
- /**
- * list of conversations
- * @var array<\wcf\data\conversation\Conversation>
- */
- protected $conversations = null;
-
- /**
- * @see \wcf\system\user\online\location\IUserOnlineLocation::cache()
- */
- public function cache(UserOnline $user) {
- if ($user->objectID) $this->conversationIDs[] = $user->objectID;
- }
-
- /**
- * @see \wcf\system\user\online\location\IUserOnlineLocation::get()
- */
- public function get(UserOnline $user, $languageVariable = '') {
- if ($this->conversations === null) {
- $this->readConversations();
- }
-
- if (!isset($this->conversations[$user->objectID])) {
- return '';
- }
-
- return WCF::getLanguage()->getDynamicVariable($languageVariable, array('conversation' => $this->conversations[$user->objectID]));
- }
-
- /**
- * Loads the conversations.
- */
- protected function readConversations() {
- $this->conversations = array();
-
- if (!WCF::getUser()->userID) return;
- if (empty($this->conversationIDs)) return;
- $this->conversationIDs = array_unique($this->conversationIDs);
-
- $conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('conversation_to_user.participantID = ?', array(WCF::getUser()->userID));
- $conditionBuilder->add('conversation_to_user.conversationID IN (?)', array($this->conversationIDs));
- $conditionBuilder->add('conversation_to_user.hideConversation <> ?', array(Conversation::STATE_LEFT));
-
- $sql = "SELECT conversation.*
- FROM wcf".WCF_N."_conversation_to_user conversation_to_user
- LEFT JOIN wcf".WCF_N."_conversation conversation
- ON (conversation.conversationID = conversation_to_user.conversationID)
- ".$conditionBuilder;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditionBuilder->getParameters());
- while ($conversation = $statement->fetchObject('\wcf\data\conversation\Conversation')) {
- $this->conversations[$conversation->conversationID] = $conversation;
- }
- }
-}
use wcf\data\conversation\message\ConversationMessageEditor;
use wcf\data\conversation\message\ConversationMessageList;
use wcf\data\object\type\ObjectTypeCache;
+use wcf\system\html\input\HtmlInputProcessor;
use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
use wcf\system\search\SearchIndexManager;
use wcf\system\WCF;
* Worker implementation for updating conversation messages.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf
- * @subpackage system.worker
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\Worker
+ *
+ * @method ConversationMessageList getObjectList()
*/
class ConversationMessageRebuildDataWorker extends AbstractRebuildDataWorker {
/**
- * @see \wcf\system\worker\AbstractWorker::$limit
+ * @inheritDoc
*/
protected $limit = 500;
/**
- * @see \wcf\system\worker\IWorker::countObjects()
+ * @var HtmlInputProcessor
+ */
+ protected $htmlInputProcessor;
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+ /**
+ * @inheritDoc
*/
public function countObjects() {
if ($this->count === null) {
}
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\system\worker\AbstractRebuildDataWorker::initObjectList
+ * @inheritDoc
*/
protected function initObjectList() {
$this->objectList = new ConversationMessageList();
}
/**
- * @see \wcf\system\worker\IWorker::execute()
+ * @inheritDoc
*/
public function execute() {
- $this->objectList->getConditionBuilder()->add('conversation_message.messageID BETWEEN ? AND ?', array($this->limit * $this->loopCount + 1, $this->limit * $this->loopCount + $this->limit));
+ $this->objectList->getConditionBuilder()->add('conversation_message.messageID BETWEEN ? AND ?', [$this->limit * $this->loopCount + 1, $this->limit * $this->loopCount + $this->limit]);
parent::execute();
$attachmentStatement = WCF::getDB()->prepareStatement($sql);
foreach ($this->objectList as $message) {
- SearchIndexManager::getInstance()->add('com.woltlab.wcf.conversation.message', $message->messageID, $message->message, ($message->subject ?: ''), $message->time, $message->userID, $message->username);
+ SearchIndexManager::getInstance()->set(
+ 'com.woltlab.wcf.conversation.message',
+ $message->messageID,
+ $message->message,
+ $message->subject ?: '',
+ $message->time,
+ $message->userID,
+ $message->username
+ );
$editor = new ConversationMessageEditor($message);
- $data = array();
+ $data = [];
// count attachments
- $attachmentStatement->execute(array($attachmentObjectType->objectTypeID, $message->messageID));
+ $attachmentStatement->execute([$attachmentObjectType->objectTypeID, $message->messageID]);
$row = $attachmentStatement->fetchSingleRow();
$data['attachments'] = $row['attachments'];
- // update embedded objects
- $data['hasEmbeddedObjects'] = (MessageEmbeddedObjectManager::getInstance()->registerObjects('com.woltlab.wcf.conversation.message', $message->messageID, $message->message) ? 1 : 0);
+ // update message
+ if (!$message->enableHtml) {
+ $this->getHtmlInputProcessor()->process($message->message, 'com.woltlab.wcf.conversation.message', $message->messageID, true);
+ $data['message'] = $this->getHtmlInputProcessor()->getHtml();
+ $data['enableHtml'] = 1;
+ }
+ else {
+ $this->getHtmlInputProcessor()->processEmbeddedContent($message->message, 'com.woltlab.wcf.conversation.message', $message->messageID);
+ }
+
+ if (MessageEmbeddedObjectManager::getInstance()->registerObjects($this->getHtmlInputProcessor())) {
+ $data['hasEmbeddedObjects'] = 1;
+ }
+ else {
+ $data['hasEmbeddedObjects'] = 0;
+ }
$editor->update($data);
}
}
+
+ /**
+ * @return HtmlInputProcessor
+ */
+ protected function getHtmlInputProcessor() {
+ if ($this->htmlInputProcessor === null) {
+ $this->htmlInputProcessor = new HtmlInputProcessor();
+ }
+
+ return $this->htmlInputProcessor;
+ }
}
* Worker implementation for updating conversations.
*
* @author Marcel Werk
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package com.woltlab.wcf
- * @subpackage system.worker
- * @category Community Framework
+ * @package WoltLabSuite\Core\System\Worker
+ *
+ * @method ConversationList getObjectList()
*/
class ConversationRebuildDataWorker extends AbstractRebuildDataWorker {
/**
- * @see \wcf\system\worker\AbstractWorker::$limit
+ * @inheritDoc
*/
protected $limit = 100;
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\system\worker\IWorker::countObjects()
+ * @inheritDoc
*/
public function countObjects() {
if ($this->count === null) {
}
}
+ /** @noinspection PhpMissingParentCallCommonInspection */
/**
- * @see \wcf\system\worker\AbstractRebuildDataWorker::initObjectList
+ * @inheritDoc
*/
protected function initObjectList() {
$this->objectList = new ConversationList();
}
/**
- * @see \wcf\system\worker\IWorker::execute()
+ * @inheritDoc
*/
public function execute() {
- $this->objectList->getConditionBuilder()->add('conversation.conversationID BETWEEN ? AND ?', array($this->limit * $this->loopCount + 1, $this->limit * $this->loopCount + $this->limit));
+ $this->objectList->getConditionBuilder()->add('conversation.conversationID BETWEEN ? AND ?', [$this->limit * $this->loopCount + 1, $this->limit * $this->loopCount + $this->limit]);
parent::execute();
AND participantID IS NOT NULL";
$existingParticipantStatement = WCF::getDB()->prepareStatement($sql, 5);
- $obsoleteConversations = array();
+ $obsoleteConversations = [];
foreach ($this->objectList as $conversation) {
$editor = new ConversationEditor($conversation);
if (!$conversation->userID) $obsolete = true;
}
else {
- $existingParticipantStatement->execute(array($conversation->conversationID));
+ $existingParticipantStatement->execute([$conversation->conversationID]);
$row = $existingParticipantStatement->fetchSingleRow();
if (!$row['participants']) $obsolete = true;
}
}
// update data
- $data = array();
+ $data = [];
// get first post
- $firstMessageStatement->execute(array($conversation->conversationID));
+ $firstMessageStatement->execute([$conversation->conversationID]);
if (($row = $firstMessageStatement->fetchSingleRow()) !== false) {
$data['firstMessageID'] = $row['messageID'];
$data['lastPostTime'] = $data['time'] = $row['time'];
}
// get last post
- $lastMessageStatement->execute(array($conversation->conversationID));
+ $lastMessageStatement->execute([$conversation->conversationID]);
if (($row = $lastMessageStatement->fetchSingleRow()) !== false) {
$data['lastPostTime'] = $row['time'];
$data['lastPosterID'] = $row['userID'];
}
// get stats
- $statsStatement->execute(array($conversation->conversationID));
+ $statsStatement->execute([$conversation->conversationID]);
$row = $statsStatement->fetchSingleRow();
$data['replies'] = ($row['messages'] ? $row['messages'] - 1 : 0);
$data['attachments'] = ($row['attachments'] ?: 0);
// get number of participants
- $participantCounterStatement->execute(array($conversation->conversationID, Conversation::STATE_LEFT, $conversation->userID, 0));
+ $participantCounterStatement->execute([$conversation->conversationID, Conversation::STATE_LEFT, $conversation->userID, 0]);
$row = $participantCounterStatement->fetchSingleRow();
$data['participants'] = $row['participants'];
// get participant summary
- $participantStatement->execute(array($conversation->conversationID, $conversation->userID, 0));
- $users = array();
+ $participantStatement->execute([$conversation->conversationID, $conversation->userID, 0]);
+ $users = [];
while ($row = $participantStatement->fetchArray()) {
$users[] = $row;
}
+++ /dev/null
-#conversationLabelFilter {
- margin-bottom: @wcfGapMedium;
-}
-
-.conversationLabelList {
- margin-bottom: @wcfGapMedium;
-
- li:not(:last-child) {
- margin-bottom: @wcfGapTiny;
- }
-
- &~small {
- display: block;
- }
-}
-
-#unreadConversations .dropdownMenu > li {
- h3 {
- max-width: 250px;
- overflow: hidden;
- text-overflow: ellipsis;
- }
-}
-
-.conversationParticipantList {
- > li {
- .inlineDataList {
- font-size: @wcfSmallFontSize;
- }
-
- &.conversationLeft > div {
- > a > img,
- > span > img {
- .grayscale;
- }
- }
- }
-}
-
-.conversationLeft .userLink,
-.conversationLeft.userLink,
-.conversationLeft p > span {
- text-decoration: line-through;
-}
-
-.sidebar fieldset.conversationQuota {
- > div {
- text-align: center;
- }
-}
-
-.conversationUsageBar {
- background-color: @wcfColor;
- border-radius: 5px;
- height: 20px;
- padding: 4px;
-
- .boxShadowNative(~"inset 0 1px 5px rgba(0, 0, 0, .5), 0 1px 0 rgba(255, 255, 255, .5)");
-
- > span {
- border-radius: 3px;
- color: transparent;
- display: block;
- height: 100%;
-
- .boxShadowNative(~"inset 0 1px 0 rgba(255, 255, 255, .5)");
- .linearGradient(rgba(165, 223, 65, 1), rgba(165, 223, 65, 1), rgba(76, 169, 22, 1));
- }
-
- &.yellow > span {
- .linearGradient(rgba(254, 207, 35, 1), rgba(254, 207, 35, 1), rgba(253, 146, 21, 1));
- }
-
- &.red > span {
- .linearGradient(rgba(240, 163, 163, 1), rgba(240, 163, 163, 1), rgba(244, 35, 35, 1));
- }
-}
-
-.conversationFolderList > li > a > span {
- float: right;
-}
-
-@media only screen and (max-width: 800px) {
- .conversationList {
- thead {
- display: none;
- }
-
- tbody {
- .columnMark,
- .columnReplies,
- .columnParticipants,
- .columnLastPost,
- .conversationParticipantSummary,
- .columnSubject .statusDisplay {
- display: none;
- }
- }
- }
-}
-
-@media only screen and (max-width: 1239px) {
- .conversationList {
- thead .columnParticipants,
- tbody .columnParticipants {
- display: none;
- }
- }
-}
\ No newline at end of file
--- /dev/null
+/* list of participants */
+.conversationParticipantList {
+ > li {
+ &.conversationLeft > div {
+ > a > img,
+ > span > img {
+ @extend .grayscale;
+ }
+ }
+ }
+}
+
+/* participant left status */
+.conversationLeft .userLink,
+.conversationLeft.userLink,
+.conversationLeft p > span {
+ text-decoration: line-through;
+}
+
+/* quota usage display */
+.sidebar .box.conversationQuota .boxContent {
+ text-align: center;
+}
+.conversationUsageBar {
+ background-color: rgba(165, 223, 65, 1);
+ height: 5px;
+
+ > span {
+ background-color: rgba(76, 169, 22, 1);
+ color: transparent;
+ display: block;
+ height: 100%;
+ }
+
+ &.yellow {
+ background-color: rgba(254, 207, 35, 1);
+
+ > span {
+ background-color: rgba(253, 146, 21, 1);
+ }
+ }
+
+ &.red {
+ background-color: rgba(255, 205, 210, 1);
+
+ > span {
+ background-color: rgba(244, 67, 54, 1);
+ }
+ }
+}
+
+.conversationItem {
+ .conversationInfo {
+ display: flex;
+ }
+
+ .conversationParticipant {
+ flex: 1 1 auto;
+ }
+ .conversationLastPostTime {
+ flex: 0 0 auto;
+ margin-left: 10px;
+ }
+}
message MEDIUMTEXT NOT NULL,
time INT(10) NOT NULL DEFAULT 0,
attachments SMALLINT(5) NOT NULL DEFAULT 0,
- enableSmilies TINYINT(1) NOT NULL DEFAULT 1,
enableHtml TINYINT(1) NOT NULL DEFAULT 0,
- enableBBCodes TINYINT(1) NOT NULL DEFAULT 1,
- showSignature TINYINT(1) NOT NULL DEFAULT 1,
ipAddress VARCHAR(39) NOT NULL DEFAULT '',
lastEditTime INT(10) NOT NULL DEFAULT 0,
editCount MEDIUMINT(7) NOT NULL DEFAULT 0,
<item name="wcf.clipboard.item.com.woltlab.wcf.conversation.conversation.leave"><![CDATA[Ausblenden ({#$count})]]></item>
<item name="wcf.clipboard.item.com.woltlab.wcf.conversation.conversation.leavePermanently"><![CDATA[Verlassen ({#$count})]]></item>
<item name="wcf.clipboard.item.com.woltlab.wcf.conversation.conversation.markAsRead"><![CDATA[Als gelesen markieren ({#$count})]]></item>
- <item name="wcf.clipboard.item.com.woltlab.wcf.conversation.conversation.markAsRead.confirmMessage"><![CDATA[Wollen Sie die {if $count == 1}markierte Konversation{else}markierten Konversationen{/if} wirklich als gelesen markieren?]]></item>
+ <item name="wcf.clipboard.item.com.woltlab.wcf.conversation.conversation.markAsRead.confirmMessage"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Willst du{else}Wollen Sie{/if} die {if $count == 1}markierte Konversation{else}markierten Konversationen{/if} wirklich als gelesen markieren?]]></item>
<item name="wcf.clipboard.item.com.woltlab.wcf.conversation.conversation.open"><![CDATA[Öffnen ({#$count})]]></item>
<item name="wcf.clipboard.item.com.woltlab.wcf.conversation.conversation.restore"><![CDATA[Als aktiv markieren ({#$count})]]></item>
- <item name="wcf.clipboard.label.com.woltlab.wcf.conversation.conversation.marked"><![CDATA[{if $count == 1}Eine Konversation{else}{#$count} Konversationen{/if} markiert]]></item>
+ <item name="wcf.clipboard.label.com.woltlab.wcf.conversation.conversation.marked"><![CDATA[{if $count == 1}Eine Konversation{else}{#$count} Konversationen{/if}]]></item>
</category>
<category name="wcf.conversation">
<item name="wcf.conversation.button.add"><![CDATA[Konversation starten]]></item>
<item name="wcf.conversation.button.saveAsDraft"><![CDATA[Entwurf speichern]]></item>
<item name="wcf.conversation.conversations"><![CDATA[Konversationen]]></item>
+ <item name="wcf.conversation.filter.participants"><![CDATA[Filter nach Teilnehmern]]></item>
<item name="wcf.conversation.folders"><![CDATA[Ordner]]></item>
<item name="wcf.conversation.folder.draft"><![CDATA[Entwürfe]]></item>
<item name="wcf.conversation.folder.hidden"><![CDATA[Ausgeblendet]]></item>
<item name="wcf.conversation.hideConversation.leave"><![CDATA[Ausblenden]]></item>
<item name="wcf.conversation.hideConversation.leave.description"><![CDATA[Die Konversation wird bis zu einer neuen Antwort nicht mehr als aktive Konversation gelistet.]]></item>
<item name="wcf.conversation.hideConversation.leavePermanently"><![CDATA[Verlassen]]></item>
- <item name="wcf.conversation.hideConversation.leavePermanently.description"><![CDATA[Die Konversation wird verlassen und Sie werden nicht länger als aktiver Teilnehmer gelistet.]]></item>
+ <item name="wcf.conversation.hideConversation.leavePermanently.description"><![CDATA[Die Konversation wird verlassen und {if LANGUAGE_USE_INFORMAL_VARIANT}di wirst{else}Sie werden{/if} nicht länger als aktiver Teilnehmer gelistet.]]></item>
<item name="wcf.conversation.hideConversation.restore"><![CDATA[Als aktiv markieren]]></item>
<item name="wcf.conversation.information"><![CDATA[Informationen]]></item>
<item name="wcf.conversation.invisible"><![CDATA[unsichtbar]]></item>
<item name="wcf.conversation.invisibleParticipants"><![CDATA[Unsichtbare Teilnehmer]]></item>
- <item name="wcf.conversation.invisibleParticipants.description"><![CDATA[Unsichtbare Teilnehmer sind für andere Teilnehmer nicht sichtbar. Mehrere Teilnehmer können mit Komma getrennt angegeben werden.]]></item>
+ <item name="wcf.conversation.invisibleParticipants.description"><![CDATA[Unsichtbare Teilnehmer sind für andere Teilnehmer nicht sichtbar.]]></item>
<item name="wcf.conversation.lastPostTime"><![CDATA[Letzte Antwort]]></item>
- <item name="wcf.conversation.lastVisitTime"><![CDATA[Letzter Aufruf]]></item>
+ <item name="wcf.conversation.lastVisitTime"><![CDATA[Konversation gelesen]]></item>
<item name="wcf.conversation.leave.title"><![CDATA[Teilnahme verwalten]]></item>
- <item name="wcf.conversation.markAllAsRead.confirmMessage"><![CDATA[Wollen Sie wirklich alle Konversationen als gelesen markieren?]]></item>
+ <item name="wcf.conversation.markAllAsRead.confirmMessage"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Willst du{else}Wollen Sie{/if} wirklich alle Konversationen als gelesen markieren?]]></item>
<item name="wcf.conversation.message"><![CDATA[Nachricht]]></item>
- <item name="wcf.conversation.message.add"><![CDATA[Neue Antwort erstellen]]></item>
- <item name="wcf.conversation.message.add.previousPosts"><![CDATA[{if $items == 1}Vorherige Nachricht{else}Vorherige Nachrichten{/if}]]></item>
<item name="wcf.conversation.message.button.add"><![CDATA[Antworten]]></item>
<item name="wcf.conversation.message.edit"><![CDATA[Nachricht bearbeiten]]></item>
<item name="wcf.conversation.noConversations"><![CDATA[Es wurden keine Konversationen gefunden.]]></item>
<item name="wcf.conversation.noMoreItems"><![CDATA[Keine aktuellen Konversationen]]></item>
<item name="wcf.conversation.participantCanInvite"><![CDATA[Teilnehmer können weitere Teilnehmer hinzufügen]]></item>
<item name="wcf.conversation.participants"><![CDATA[Teilnehmer]]></item>
- <item name="wcf.conversation.participants.description"><![CDATA[Mehrere Teilnehmer können mit Komma getrennt angegeben werden.]]></item>
+ <item name="wcf.conversation.participants.description"><![CDATA[]]></item>
<item name="wcf.conversation.participants.error.mailboxIsFull"><![CDATA[{$errorData[username]} hat das zulässige Limit für Konversationen bereits erreicht und kann an keinen neuen Konversationen teilnehmen.]]></item>
<item name="wcf.conversation.participants.error.notFound"><![CDATA[Der Benutzername {$errorData[username]} konnte nicht gefunden werden.]]></item>
- <item name="wcf.conversation.participants.error.isAuthor"><![CDATA[Sie sind bereits Teilnehmer dieser Konversation.]]></item>
+ <item name="wcf.conversation.participants.error.isAuthor"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du bist{else}Sie sind{/if} bereits Teilnehmer dieser Konversation.]]></item>
<item name="wcf.conversation.participants.error.duplicate"><![CDATA[{$errorData[username]} ist bereits Teilnehmer dieser Konversation.]]></item>
<item name="wcf.conversation.participants.error.canNotUseConversation"><![CDATA[{$errorData[username]} besitzt nicht die notwendigen Berechtigungen, um an einer Konversation teilnehmen zu dürfen.]]></item>
<item name="wcf.conversation.participants.error.doesNotAcceptConversation"><![CDATA[{$errorData[username]} möchte nicht an Konversationen teilnehmen.]]></item>
- <item name="wcf.conversation.participants.error.ignoresYou"><![CDATA[{$errorData[username]} hat Sie blockiert.]]></item>
- <item name="wcf.conversation.participants.error.tooManyParticipants"><![CDATA[Sie haben zu viele Teilnehmer angegeben. Das Maximum liegt bei {#$__wcf->getSession()->getPermission('user.conversation.maxParticipants')} Teilnehmern.]]></item>
- <item name="wcf.conversation.participants.error.invisibleParticipantsNoPermission"><![CDATA[Sie haben keine Berechtigung, unsichtbare Teilnehmer hinzuzufügen.]]></item>
- <item name="wcf.conversation.participants.error.participantCanInviteNoPermission"><![CDATA[Sie haben keine Berechtigung, Teilnehmern das Hinzufügen weiterer Teilnehmer zu erlauben.]]></item>
+ <item name="wcf.conversation.participants.error.ignoresYou"><![CDATA[{$errorData[username]} hat {if LANGUAGE_USE_INFORMAL_VARIANT}dich{else}Sie{/if} blockiert.]]></item>
+ <item name="wcf.conversation.participants.error.tooManyParticipants"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du hast{else}Sie haben{/if} zu viele Teilnehmer angegeben. Das Maximum liegt bei {#$__wcf->getSession()->getPermission('user.conversation.maxParticipants')} Teilnehmern.]]></item>
+ <item name="wcf.conversation.participants.error.invisibleParticipantsNoPermission"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du hast{else}Sie haben{/if} keine Berechtigung, unsichtbare Teilnehmer hinzuzufügen.]]></item>
+ <item name="wcf.conversation.participants.error.participantCanInviteNoPermission"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du hast{else}Sie haben{/if} keine Berechtigung, Teilnehmern das Hinzufügen weiterer Teilnehmer zu erlauben.]]></item>
<item name="wcf.conversation.participants.removeParticipant"><![CDATA[Teilnehmer entfernen]]></item>
- <item name="wcf.conversation.participants.removeParticipant.confirmMessage"><![CDATA[Wollen Sie {$participant->username} wirklich aus dieser Konversation entfernen?]]></item>
+ <item name="wcf.conversation.participants.removeParticipant.confirmMessage"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Willst du{else}Wollen Sie{/if} <span class="confirmationObject">{$participant->username}</span> wirklich aus dieser Konversation entfernen?]]></item>
<item name="wcf.conversation.quota"><![CDATA[Speicherplatz]]></item>
<item name="wcf.conversation.quota.description"><![CDATA[{#$conversationCount/$maxConversationCount*100}% belegt ({#$conversationCount} von {#$maxConversationCount})]]></item>
<item name="wcf.conversation.replies"><![CDATA[Antworten]]></item>
+ <item name="wcf.conversation.reply"><![CDATA[Auf diese Konversation antworten…]]></item>
<item name="wcf.conversation.showAll"><![CDATA[Alle Konversationen anzeigen]]></item>
- <item name="wcf.conversation.ownPosts"><![CDATA[Diese Konversation enthält Nachrichten von Ihnen.]]></item>
+ <item name="wcf.conversation.ownPosts"><![CDATA[Diese Konversation enthält Nachrichten von {if LANGUAGE_USE_INFORMAL_VARIANT}dir{else}Ihnen{/if}.]]></item>
<item name="wcf.conversation.gotoLastPost"><![CDATA[Zur letzten Nachricht springen]]></item>
<item name="wcf.conversation.searchConversations"><![CDATA[Konversationen durchsuchen]]></item>
+ <item name="wcf.conversation.searchConversation"><![CDATA[Aktuelle Konversation durchsuchen]]></item>
+ <item name="wcf.conversation.searchedConversation"><![CDATA[Nur Konversation <a href="{link controller='Conversation' object=$searchedConversation}{/link}">{$searchedConversation->getTitle()}</a> durchsuchen]]></item>
<item name="wcf.conversation.participants.other"><![CDATA[und {if $conversation->participants - $participantSummaryCount == 1}ein weiterer{else}{#$conversation->participants-$participantSummaryCount} weitere{/if}]]></item>
<item name="wcf.conversation.attachments"><![CDATA[Diese Konversation enthält {if $conversation->attachments == 1}einen Dateianhang{else}{#$conversation->attachments} Dateianhänge{/if}.]]></item>
- <item name="wcf.conversation.error.mailboxIsFull"><![CDATA[Sie haben das zulässige Limit für Konversationen bereits erreicht und können keine neuen Konversationen starten.]]></item>
+ <item name="wcf.conversation.error.mailboxIsFull"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du hast{else}Sie haben{/if} das zulässige Limit für Konversationen bereits erreicht und können keine neuen Konversationen starten.]]></item>
<item name="wcf.conversation.markAllAsRead"><![CDATA[Alle Konversationen als gelesen markieren]]></item>
<item name="wcf.conversation.message.editNote"><![CDATA[{$message->username} hat diese Nachricht {#$message->editCount} mal editiert, zuletzt: {@$message->lastEditTime|time}.]]></item>
- <item name="wcf.conversation.noParticipantsWarning"><![CDATA[Sie sind dabei, auf eine Konversation ohne weitere Teilnehmer zu antworten. Alle anderen Teilnehmer haben diese Konversation verlassen. Niemand wird Ihre Nachricht lesen!]]></item>
+ <item name="wcf.conversation.noParticipantsWarning"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du bist{else}Sie sind{/if} dabei, auf eine Konversation ohne weitere Teilnehmer zu antworten. Alle anderen Teilnehmer haben diese Konversation verlassen. Niemand wird {if LANGUAGE_USE_INFORMAL_VARIANT}deine{else}Ihre{/if} Nachricht lesen!]]></item>
<item name="wcf.conversation.message.permalink"><![CDATA[Permalink zur {#$startIndex}. Nachricht]]></item>
<item name="wcf.conversation.markAsRead.doubleClick"><![CDATA[Konversation durch Doppelklick als gelesen markieren]]></item>
</category>
<item name="wcf.conversation.label.management.addLabel"><![CDATA[Label hinzufügen]]></item>
<item name="wcf.conversation.label.management.addLabel.success"><![CDATA[Label wurde hinzugefügt]]></item>
<item name="wcf.conversation.label.management.deleteLabel"><![CDATA[Label löschen]]></item>
- <item name="wcf.conversation.label.management.deleteLabel.confirmMessage"><![CDATA[Wollen Sie das Label „#labelName#“ wirklich löschen?]]></item>
- <item name="wcf.conversation.label.management.edit.description"><![CDATA[Klicken Sie ein Label an, um dieses zu bearbeiten oder zu löschen.]]></item>
+ <item name="wcf.conversation.label.management.deleteLabel.confirmMessage"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Willst du{else}Wollen Sie{/if} das Label <span class="confirmationObject">#labelName#</span> wirklich löschen?]]></item>
+ <item name="wcf.conversation.label.management.edit.description"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Klicke{else}Klicken Sie{/if} ein Label an, um dieses zu bearbeiten oder zu löschen.]]></item>
<item name="wcf.conversation.label.management.editLabel"><![CDATA[Label „#labelName#“ bearbeiten]]></item>
<item name="wcf.conversation.label.management.existingLabels"><![CDATA[Vorhandene Labels]]></item>
<item name="wcf.conversation.label.placeholder"><![CDATA[Label]]></item>
</category>
<category name="wcf.page">
- <item name="wcf.page.category.com.woltlab.wcf.conversation"><![CDATA[Konversationen]]></item>
- <item name="wcf.page.com.woltlab.wcf.conversation.ConversationAddForm"><![CDATA[Neue Konversation starten]]></item>
- <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageAddForm"><![CDATA[Neue Konversationsantwort erstellen]]></item>
- <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageEditForm"><![CDATA[Konversationsnachricht bearbeiten]]></item>
- <item name="wcf.page.com.woltlab.wcf.conversation.ConversationListPage"><![CDATA[Konversationen]]></item>
- <item name="wcf.page.com.woltlab.wcf.conversation.ConversationPage"><![CDATA[Konversation]]></item>
+ <item name="wcf.page.onlineLocation.com.woltlab.wcf.conversation.Conversation"><![CDATA[Konversation <a href="{link controller='Conversation' object=$conversation}{/link}" class="conversationLink" data-conversation-id="{@$conversation->conversationID}">{$conversation->subject}</a>]]></item>
</category>
<category name="wcf.search">
+ <item name="wcf.search.type.com.woltlab.wcf.conversation"><![CDATA[Diese Konversation]]></item>
<item name="wcf.search.type.com.woltlab.wcf.conversation.message"><![CDATA[Konversationen]]></item>
<item name="wcf.search.object.com.woltlab.wcf.conversation.message"><![CDATA[Konversation]]></item>
</category>
<item name="wcf.user.notification.conversation.message.message.stacked"><![CDATA[{if $count < 4}{@$authors[0]->getAnchorTag()}{if $count == 2} und {else}, {/if}{@$authors[1]->getAnchorTag()}{if $count == 3} und {@$authors[2]->getAnchorTag()}{/if}{else}{@$authors[0]->getAnchorTag()} und {#$count} weitere{/if} haben auf die Konversation <a href="{link controller='Conversation' object=$message->getConversation()}{/link}">{$message->getConversation()->getTitle()}</a> geantwortet.]]></item>
<item name="wcf.user.notification.conversation.message.title"><![CDATA[Neue Antwort auf Konversation]]></item>
<item name="wcf.user.notification.conversation.message.title.stacked"><![CDATA[{#$count} Teilnehmer haben auf eine Konversation geantwortet]]></item>
- <item name="wcf.user.notification.conversation.message.mail"><![CDATA[{@$author->username} hat auf die Konversation "{@$message->getTitle()}" geantwortet:
-{if $notificationType == 'instant'}
----------------------------------
-{@$message->getMailText()}
----------------------------------
-{/if}{link controller='Conversation' object=$message->getConversation() isEmail=true}messageID={@$message->messageID}{/link}#message{@$message->messageID}]]></item>
+ <item name="wcf.user.notification.conversation.message.mail.plaintext"><![CDATA[{@$authorList} {if $count == 1 && !$guestTimesTriggered}hat{else}haben{/if} auf die Konversation „{$event->getUserNotificationObject()->getConversation()->subject}“ [URL:{link controller='Conversation' object=$event->getUserNotificationObject()->getConversation() isEmail=true}{/link}] geantwortet{if $count == 1 && !$guestTimesTriggered}:{else}.{/if}]]></item>
+ <item name="wcf.user.notification.conversation.message.mail.html"><![CDATA[<p>{@$authorList} {if $count == 1 && !$guestTimesTriggered}hat{else}haben{/if} auf die Konversation <a href="{link controller='Conversation' object=$event->getUserNotificationObject()->getConversation() isEmail=true}{/link}">{$event->getUserNotificationObject()->getConversation()->subject}</a> geantwortet:</p>]]></item>
<item name="wcf.user.notification.conversation.message"><![CDATA[{@$author->getAnchorTag()} hat die Konversation <a href="{link controller='Conversation' object=$conversation}{/link}">{$conversation->subject}</a> gestartet.]]></item>
<item name="wcf.user.notification.conversation.title"><![CDATA[Neue Konversation]]></item>
- <item name="wcf.user.notification.conversation.mail"><![CDATA[{@$author->username} hat die Konversation "{@$conversation->subject}" gestartet:
-{if $notificationType == 'instant'}
----------------------------------
-{@$conversation->getFirstMessage()->getMailText()}
----------------------------------
-{/if}{link controller='Conversation' object=$conversation isEmail=true}{/link}]]></item>
+ <item name="wcf.user.notification.conversation.mail.plaintext"><![CDATA[{@$event->getAuthor()->username} [URL:{link controller='User' object=$event->getAuthor() isEmail=true}{/link}] hat die Konversation „{@$event->getUserNotificationObject()->subject}“ [URL:{link controller='Conversation' object=$event->getUserNotificationObject() isEmail=true}{/link}] gestartet:]]></item>
+ <item name="wcf.user.notification.conversation.mail.html"><![CDATA[<p><a href="{link controller='User' object=$event->getAuthor() isEmail=true}{/link}">{$event->getAuthor()->username}</a> hat die Konversation <a href="{link controller='Conversation' object=$event->getUserNotificationObject() isEmail=true}{/link}">{$event->getUserNotificationObject()->subject}</a> gestartet:</p>]]></item>
<item name="wcf.user.notification.com.woltlab.wcf.conversation"><![CDATA[Konversationen]]></item>
<item name="wcf.user.notification.com.woltlab.wcf.conversation.notification.conversation"><![CDATA[Neue Konversation]]></item>
<item name="wcf.user.notification.com.woltlab.wcf.conversation.message.notification.conversationMessage"><![CDATA[Antwort auf bestehende Konversation]]></item>
<item name="wcf.user.option.conversationsPerPage"><![CDATA[Konversationen pro Seite]]></item>
<item name="wcf.user.option.canSendConversation"><![CDATA[Kann Konversationen schreiben]]></item>
</category>
-
- <category name="wcf.user.usersOnline">
- <item name="wcf.user.usersOnline.location.ConversationAddForm"><![CDATA[Erstellt eine neue Konversation]]></item>
- <item name="wcf.user.usersOnline.location.ConversationListPage"><![CDATA[Betrachtet die Liste seiner Konversationen]]></item>
- <item name="wcf.user.usersOnline.location.ConversationMessageAddForm"><![CDATA[Schreibt eine Antwort auf die Konversation <a href="{link controller='Conversation' object=$conversation}{/link}" class="conversationLink" data-conversation-id="{@$conversation->conversationID}">{$conversation->subject}</a>]]></item>
- <item name="wcf.user.usersOnline.location.ConversationMessageEditForm"><![CDATA[Bearbeitet eine Nachricht in der Konversation <a href="{link controller='Conversation' object=$conversation}{/link}" class="conversationLink" data-conversation-id="{@$conversation->conversationID}">{$conversation->subject}</a>]]></item>
- <item name="wcf.user.usersOnline.location.ConversationPage"><![CDATA[Liest die Konversation <a href="{link controller='Conversation' object=$conversation}{/link}" class="conversationLink" data-conversation-id="{@$conversation->conversationID}">{$conversation->subject}</a>]]></item>
- </category>
</language>
<item name="wcf.clipboard.item.com.woltlab.wcf.conversation.conversation.markAsRead.confirmMessage"><![CDATA[Do you really want to mark the marked conversation{if $count != 1}s{/if} as read?]]></item>
<item name="wcf.clipboard.item.com.woltlab.wcf.conversation.conversation.open"><![CDATA[Open ({#$count})]]></item>
<item name="wcf.clipboard.item.com.woltlab.wcf.conversation.conversation.restore"><![CDATA[Mark as Active ({#$count})]]></item>
- <item name="wcf.clipboard.label.com.woltlab.wcf.conversation.conversation.marked"><![CDATA[{if $count == 1}One Conversation{else}{#$count} Conversations{/if} Marked]]></item>
+ <item name="wcf.clipboard.label.com.woltlab.wcf.conversation.conversation.marked"><![CDATA[{if $count == 1}One Conversation{else}{#$count} Conversations{/if}]]></item>
</category>
<category name="wcf.conversation">
<item name="wcf.conversation.button.add"><![CDATA[New Conversation]]></item>
<item name="wcf.conversation.button.saveAsDraft"><![CDATA[Save Draft]]></item>
<item name="wcf.conversation.conversations"><![CDATA[Conversations]]></item>
+ <item name="wcf.conversation.filter.participants"><![CDATA[Filter by Participants]]></item>
<item name="wcf.conversation.folders"><![CDATA[Folders]]></item>
<item name="wcf.conversation.folder.draft"><![CDATA[Drafts]]></item>
<item name="wcf.conversation.folder.hidden"><![CDATA[Hidden]]></item>
<item name="wcf.conversation.information"><![CDATA[Details]]></item>
<item name="wcf.conversation.invisible"><![CDATA[invisible]]></item>
<item name="wcf.conversation.invisibleParticipants"><![CDATA[Invisible Participants]]></item>
- <item name="wcf.conversation.invisibleParticipants.description"><![CDATA[Invisible participants remain invisible to other participants until they write a message. Separate multiple participants with a comma.]]></item>
+ <item name="wcf.conversation.invisibleParticipants.description"><![CDATA[Invisible participants remain invisible to other participants until they write a message.]]></item>
<item name="wcf.conversation.lastPostTime"><![CDATA[Last Reply]]></item>
- <item name="wcf.conversation.lastVisitTime"><![CDATA[Last Visited]]></item>
+ <item name="wcf.conversation.lastVisitTime"><![CDATA[Conversation Read]]></item>
<item name="wcf.conversation.leave.title"><![CDATA[Manage Participation]]></item>
<item name="wcf.conversation.markAllAsRead.confirmMessage"><![CDATA[Do you really want to mark all conversations as read?]]></item>
<item name="wcf.conversation.message"><![CDATA[Message]]></item>
- <item name="wcf.conversation.message.add"><![CDATA[Reply]]></item>
- <item name="wcf.conversation.message.add.previousPosts"><![CDATA[Previous message{if $items != 1}s{/if}]]></item>
<item name="wcf.conversation.message.button.add"><![CDATA[Reply]]></item>
<item name="wcf.conversation.message.edit"><![CDATA[Edit Message]]></item>
<item name="wcf.conversation.noConversations"><![CDATA[There are not any conversations at the moment.]]></item>
<item name="wcf.conversation.noMoreItems"><![CDATA[You have no recent conversations.]]></item>
<item name="wcf.conversation.participantCanInvite"><![CDATA[Participants can add new participants]]></item>
<item name="wcf.conversation.participants"><![CDATA[Participants]]></item>
- <item name="wcf.conversation.participants.description"><![CDATA[Separate multiple participants with a comma.]]></item>
+ <item name="wcf.conversation.participants.description"><![CDATA[]]></item>
<item name="wcf.conversation.participants.error.mailboxIsFull"><![CDATA[{$errorData[username]} is already participating in too many conversations and cannot be added.]]></item>
<item name="wcf.conversation.participants.error.notFound"><![CDATA[The username “{$errorData[username]}” does not exist.]]></item>
<item name="wcf.conversation.participants.error.isAuthor"><![CDATA[You are already a participant of this conversation.]]></item>
<item name="wcf.conversation.participants.error.invisibleParticipantsNoPermission"><![CDATA[You do not have the permission to add invisible participants.]]></item>
<item name="wcf.conversation.participants.error.participantCanInviteNoPermission"><![CDATA[You do not have the permission to allow participants to add new participants.]]></item>
<item name="wcf.conversation.participants.removeParticipant"><![CDATA[Remove Participant]]></item>
- <item name="wcf.conversation.participants.removeParticipant.confirmMessage"><![CDATA[Do you really want to remove “{$participant->username}” from this conversation?]]></item>
+ <item name="wcf.conversation.participants.removeParticipant.confirmMessage"><![CDATA[Do you really want to remove <span class="confirmationObject">{$participant->username}</span> from this conversation?]]></item>
<item name="wcf.conversation.quota"><![CDATA[Quota]]></item>
<item name="wcf.conversation.quota.description"><![CDATA[{#$conversationCount/$maxConversationCount*100}% used ({#$conversationCount} of {#$maxConversationCount})]]></item>
<item name="wcf.conversation.replies"><![CDATA[Replies]]></item>
+ <item name="wcf.conversation.reply"><![CDATA[Reply to this conversation…]]></item>
<item name="wcf.conversation.showAll"><![CDATA[Display All Conversations]]></item>
<item name="wcf.conversation.ownPosts"><![CDATA[Conversation contains your own messages]]></item>
- <item name="wcf.conversation.gotoLastPost"><![CDATA[Jump to Last Message]]></item>
+ <item name="wcf.conversation.gotoLastPost"><![CDATA[Go to Last Message]]></item>
<item name="wcf.conversation.searchConversations"><![CDATA[Search Conversations]]></item>
+ <item name="wcf.conversation.searchConversation"><![CDATA[Search This Conversation Only]]></item>
+ <item name="wcf.conversation.searchedConversation"><![CDATA[Only search conversation <a href="{link controller='Conversation' object=$searchedConversation}{/link}">{$searchedConversation->getTitle()}</a>]]></item>
<item name="wcf.conversation.participants.other"><![CDATA[and {if $conversation->participants - $participantSummaryCount == 1}one other{else}{#$conversation->participants-$participantSummaryCount} others{/if}]]></item>
<item name="wcf.conversation.attachments"><![CDATA[Conversation contains {#$conversation->attachments} attachment{if $conversation->attachments != 1}s{/if}]]></item>
<item name="wcf.conversation.error.mailboxIsFull"><![CDATA[You have reached your maximum conversations limit and cannot start new conversations.]]></item>
<item name="wcf.conversation.label.management.addLabel"><![CDATA[Add Label]]></item>
<item name="wcf.conversation.label.management.addLabel.success"><![CDATA[Label was added]]></item>
<item name="wcf.conversation.label.management.deleteLabel"><![CDATA[Delete Label]]></item>
- <item name="wcf.conversation.label.management.deleteLabel.confirmMessage"><![CDATA[Do you really want to delete the label “#labelName#”?]]></item>
+ <item name="wcf.conversation.label.management.deleteLabel.confirmMessage"><![CDATA[Do you really want to delete the label <span class="confirmationObject">#labelName#</span>?]]></item>
<item name="wcf.conversation.label.management.edit.description"><![CDATA[Click on a label to edit or delete it.]]></item>
<item name="wcf.conversation.label.management.editLabel"><![CDATA[Edit Label “#labelName#”]]></item>
<item name="wcf.conversation.label.management.existingLabels"><![CDATA[Existing Labels]]></item>
</category>
<category name="wcf.page">
- <item name="wcf.page.category.com.woltlab.wcf.conversation"><![CDATA[Conversations]]></item>
- <item name="wcf.page.com.woltlab.wcf.conversation.ConversationAddForm"><![CDATA[New Conversation]]></item>
- <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageAddForm"><![CDATA[Reply to Conversation]]></item>
- <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageEditForm"><![CDATA[Edit Conversation Message]]></item>
- <item name="wcf.page.com.woltlab.wcf.conversation.ConversationListPage"><![CDATA[Conversations]]></item>
- <item name="wcf.page.com.woltlab.wcf.conversation.ConversationPage"><![CDATA[Conversation]]></item>
+ <item name="wcf.page.onlineLocation.com.woltlab.wcf.conversation.Conversation"><![CDATA[Conversation <a href="{link controller='Conversation' object=$conversation}{/link}" class="conversationLink" data-conversation-id="{@$conversation->conversationID}">{$conversation->subject}</a>]]></item>
</category>
<category name="wcf.search">
+ <item name="wcf.search.type.com.woltlab.wcf.conversation"><![CDATA[This Conversation]]></item>
<item name="wcf.search.type.com.woltlab.wcf.conversation.message"><![CDATA[Conversations]]></item>
<item name="wcf.search.object.com.woltlab.wcf.conversation.message"><![CDATA[Conversation]]></item>
</category>
{@$message->getMailText()}
---------------------------------
{/if}{link controller='Conversation' object=$message->getConversation() isEmail=true}messageID={@$message->messageID}{/link}#message{@$message->messageID}]]></item>
+ <item name="wcf.user.notification.conversation.message.mail.plaintext"><![CDATA[{@$authorList} replied to the conversation “{$event->getUserNotificationObject()->getConversation()->subject}” [URL:{link controller='Conversation' object=$event->getUserNotificationObject()->getConversation() isEmail=true}{/link}]{if $count == 1 && !$guestTimesTriggered}:{else}.{/if}]]></item>
+ <item name="wcf.user.notification.conversation.message.mail.html"><![CDATA[<p>{@$authorList} replied to the conversation <a href="{link controller='Conversation' object=$event->getUserNotificationObject()->getConversation() isEmail=true}{/link}">{$event->getUserNotificationObject()->getConversation()->subject}</a>:</p>]]></item>
<item name="wcf.user.notification.conversation.message"><![CDATA[{@$author->getAnchorTag()} started the conversation <a href="{link controller='Conversation' object=$conversation}{/link}">{$conversation->subject}</a>.]]></item>
<item name="wcf.user.notification.conversation.title"><![CDATA[New Conversation]]></item>
- <item name="wcf.user.notification.conversation.mail"><![CDATA[{@$author->username} started the conversation "{@$conversation->subject}":
-{if $notificationType == 'instant'}
----------------------------------
-{@$conversation->getFirstMessage()->getMailText()}
----------------------------------
-{/if}{link controller='Conversation' object=$conversation isEmail=true}{/link}]]></item>
+ <item name="wcf.user.notification.conversation.mail.plaintext"><![CDATA[{@$event->getAuthor()->username} [URL:{link controller='User' object=$event->getAuthor() isEmail=true}{/link}] started the conversation “{@$event->getUserNotificationObject()->subject}” [URL:{link controller='Conversation' object=$event->getUserNotificationObject() isEmail=true}{/link}]:]]></item>
+ <item name="wcf.user.notification.conversation.mail.html"><![CDATA[<p><a href="{link controller='User' object=$event->getAuthor() isEmail=true}{/link}">{$event->getAuthor()->username}</a> started the conversation <a href="{link controller='Conversation' object=$event->getUserNotificationObject() isEmail=true}{/link}">{$event->getUserNotificationObject()->subject}</a>:</p>]]></item>
<item name="wcf.user.notification.com.woltlab.wcf.conversation"><![CDATA[Conversations]]></item>
<item name="wcf.user.notification.com.woltlab.wcf.conversation.notification.conversation"><![CDATA[Notify me of new conversations]]></item>
<item name="wcf.user.notification.com.woltlab.wcf.conversation.message.notification.conversationMessage"><![CDATA[Notify me of new replies in conversations]]></item>
<item name="wcf.user.option.conversationsPerPage"><![CDATA[Conversations per Page]]></item>
<item name="wcf.user.option.canSendConversation"><![CDATA[Can Add Me to Conversations]]></item>
</category>
-
- <category name="wcf.user.usersOnline">
- <item name="wcf.user.usersOnline.location.ConversationAddForm"><![CDATA[Creating a conversation]]></item>
- <item name="wcf.user.usersOnline.location.ConversationListPage"><![CDATA[Viewing list of conversations]]></item>
- <item name="wcf.user.usersOnline.location.ConversationMessageAddForm"><![CDATA[Writing a reply to conversation <a href="{link controller='Conversation' object=$conversation}{/link}" class="conversationLink" data-conversation-id="{@$conversation->conversationID}">{$conversation->subject}</a>]]></item>
- <item name="wcf.user.usersOnline.location.ConversationMessageEditForm"><![CDATA[Editing message in conversation <a href="{link controller='Conversation' object=$conversation}{/link}" class="conversationLink" data-conversation-id="{@$conversation->conversationID}">{$conversation->subject}</a>]]></item>
- <item name="wcf.user.usersOnline.location.ConversationPage"><![CDATA[Reading conversation <a href="{link controller='Conversation' object=$conversation}{/link}" class="conversationLink" data-conversation-id="{@$conversation->conversationID}">{$conversation->subject}</a>]]></item>
- </category>
</language>
</type>
<!-- /Modification Log -->
- <!-- user online locations -->
- <type>
- <name>com.woltlab.wcf.conversation.ConversationListPage</name>
- <definitionname>com.woltlab.wcf.user.online.location</definitionname>
- <controller>wcf\page\ConversationListPage</controller>
- <languagevariable>wcf.user.usersOnline.location.ConversationListPage</languagevariable>
- </type>
- <type>
- <name>com.woltlab.wcf.conversation.ConversationAddForm</name>
- <definitionname>com.woltlab.wcf.user.online.location</definitionname>
- <controller>wcf\form\ConversationAddForm</controller>
- <languagevariable>wcf.user.usersOnline.location.ConversationAddForm</languagevariable>
- </type>
- <type>
- <name>com.woltlab.wcf.conversation.ConversationPage</name>
- <definitionname>com.woltlab.wcf.user.online.location</definitionname>
- <classname>wcf\system\user\online\location\ConversationLocation</classname>
- <controller>wcf\page\ConversationPage</controller>
- <languagevariable>wcf.user.usersOnline.location.ConversationPage</languagevariable>
- </type>
- <type>
- <name>com.woltlab.wcf.conversation.ConversationMessageAddForm</name>
- <definitionname>com.woltlab.wcf.user.online.location</definitionname>
- <classname>wcf\system\user\online\location\ConversationLocation</classname>
- <controller>wcf\form\ConversationMessageAddForm</controller>
- <languagevariable>wcf.user.usersOnline.location.ConversationMessageAddForm</languagevariable>
- </type>
- <type>
- <name>com.woltlab.wcf.conversation.ConversationMessageEditForm</name>
- <definitionname>com.woltlab.wcf.user.online.location</definitionname>
- <classname>wcf\system\user\online\location\ConversationLocation</classname>
- <controller>wcf\form\ConversationMessageEditForm</controller>
- <languagevariable>wcf.user.usersOnline.location.ConversationMessageEditForm</languagevariable>
- </type>
- <!-- /user online locations -->
-
<!-- importers -->
<type>
<name>com.woltlab.wcf.conversation</name>
<definitionname>com.woltlab.wcf.importer</definitionname>
- <classname><![CDATA[wcf\system\importer\ConversationImporter]]></classname>
+ <classname>wcf\system\importer\ConversationImporter</classname>
</type>
<type>
<name>com.woltlab.wcf.conversation.label</name>
<definitionname>com.woltlab.wcf.importer</definitionname>
- <classname><![CDATA[wcf\system\importer\ConversationLabelImporter]]></classname>
+ <classname>wcf\system\importer\ConversationLabelImporter</classname>
</type>
<type>
<name>com.woltlab.wcf.conversation.message</name>
<definitionname>com.woltlab.wcf.importer</definitionname>
- <classname><![CDATA[wcf\system\importer\ConversationMessageImporter]]></classname>
+ <classname>wcf\system\importer\ConversationMessageImporter</classname>
</type>
<type>
<name>com.woltlab.wcf.conversation.user</name>
<definitionname>com.woltlab.wcf.importer</definitionname>
- <classname><![CDATA[wcf\system\importer\ConversationUserImporter]]></classname>
+ <classname>wcf\system\importer\ConversationUserImporter</classname>
</type>
<type>
<name>com.woltlab.wcf.conversation.attachment</name>
<definitionname>com.woltlab.wcf.importer</definitionname>
- <classname><![CDATA[wcf\system\importer\ConversationAttachmentImporter]]></classname>
+ <classname>wcf\system\importer\ConversationAttachmentImporter</classname>
</type>
<!-- /importers -->
<type>
<name>com.woltlab.wcf.conversation</name>
<definitionname>com.woltlab.wcf.rebuildData</definitionname>
- <classname><![CDATA[wcf\system\worker\ConversationRebuildDataWorker]]></classname>
+ <classname>wcf\system\worker\ConversationRebuildDataWorker</classname>
</type>
<type>
<name>com.woltlab.wcf.conversation.message</name>
<definitionname>com.woltlab.wcf.rebuildData</definitionname>
- <classname><![CDATA[wcf\system\worker\ConversationMessageRebuildDataWorker]]></classname>
+ <classname>wcf\system\worker\ConversationMessageRebuildDataWorker</classname>
<nicevalue>-5</nicevalue>
</type>
<!-- /rebuild data workers -->
- <!-- pages -->
- <type>
- <name>com.woltlab.wcf.conversation.ConversationAddForm</name>
- <definitionname>com.woltlab.wcf.page</definitionname>
- <classname><![CDATA[wcf\form\ConversationAddForm]]></classname>
- <options>module_conversation</options>
- <categoryname>com.woltlab.wcf.conversation</categoryname>
- </type>
- <type>
- <name>com.woltlab.wcf.conversation.ConversationMessageAddForm</name>
- <definitionname>com.woltlab.wcf.page</definitionname>
- <classname><![CDATA[wcf\form\ConversationMessageAddForm]]></classname>
- <options>module_conversation</options>
- <categoryname>com.woltlab.wcf.conversation</categoryname>
- </type>
- <type>
- <name>com.woltlab.wcf.conversation.ConversationMessageEditForm</name>
- <definitionname>com.woltlab.wcf.page</definitionname>
- <classname><![CDATA[wcf\form\ConversationMessageEditForm]]></classname>
- <options>module_conversation</options>
- <categoryname>com.woltlab.wcf.conversation</categoryname>
- </type>
- <type>
- <name>com.woltlab.wcf.conversation.ConversationListPage</name>
- <definitionname>com.woltlab.wcf.page</definitionname>
- <classname><![CDATA[wcf\page\ConversationListPage]]></classname>
- <options>module_conversation</options>
- <categoryname>com.woltlab.wcf.conversation</categoryname>
- </type>
- <type>
- <name>com.woltlab.wcf.conversation.ConversationPage</name>
- <definitionname>com.woltlab.wcf.page</definitionname>
- <classname><![CDATA[wcf\page\ConversationPage]]></classname>
- <options>module_conversation</options>
- <categoryname>com.woltlab.wcf.conversation</categoryname>
- </type>
- <!-- /pages -->
-
<!-- stat handlers -->
<type>
<name>com.woltlab.wcf.conversation</name>
<definitionname>com.woltlab.wcf.statDailyHandler</definitionname>
- <classname><![CDATA[wcf\system\stat\ConversationStatDailyHandler]]></classname>
+ <classname>wcf\system\stat\ConversationStatDailyHandler</classname>
<categoryname>com.woltlab.wcf.conversation</categoryname>
</type>
<type>
<name>com.woltlab.wcf.conversation.message</name>
<definitionname>com.woltlab.wcf.statDailyHandler</definitionname>
- <classname><![CDATA[wcf\system\stat\ConversationMessageStatDailyHandler]]></classname>
+ <classname>wcf\system\stat\ConversationMessageStatDailyHandler</classname>
<categoryname>com.woltlab.wcf.conversation</categoryname>
</type>
<!-- /stat handlers -->
<categoryname>message.conversation</categoryname>
<optiontype>select</optiontype>
<defaultvalue>lastPostTime</defaultvalue>
- <selectoptions><![CDATA[subject:wcf.global.subject
-lastPostTime:wcf.conversation.lastPostTime]]></selectoptions>
+ <selectoptions>subject:wcf.global.subject
+lastPostTime:wcf.conversation.lastPostTime</selectoptions>
</option>
<option name="conversation_list_default_sort_order">
<categoryname>message.conversation</categoryname>
<optiontype>select</optiontype>
<defaultvalue>DESC</defaultvalue>
- <selectoptions><![CDATA[ASC:wcf.global.sortOrder.ascending
-DESC:wcf.global.sortOrder.descending]]></selectoptions>
+ <selectoptions>ASC:wcf.global.sortOrder.ascending
+DESC:wcf.global.sortOrder.descending</selectoptions>
</option>
</options>
</import>
<?xml version="1.0" encoding="UTF-8"?>
<package name="com.woltlab.wcf.conversation" xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/package.xsd">
<packageinformation>
- <packagename>User Conversation System</packagename>
- <packagedescription>Private conversations between multiple users.</packagedescription>
- <version>2.1.6</version>
- <date>2016-06-01</date>
+ <packagename>WoltLab Suite Core: Conversations</packagename>
+ <packagedescription>Private conversations between multiple users</packagedescription>
+ <version>3.0.0 Beta 2</version>
+ <date>2016-10-03</date>
</packageinformation>
<authorinformation>
</authorinformation>
<requiredpackages>
- <requiredpackage minversion="2.1.11">com.woltlab.wcf</requiredpackage>
+ <requiredpackage minversion="3.0.0 Beta 2">com.woltlab.wcf</requiredpackage>
</requiredpackages>
<excludedpackages>
- <excludedpackage version="2.2.0 Alpha 1">com.woltlab.wcf</excludedpackage>
+ <excludedpackage version="3.1.0 Alpha 1">com.woltlab.wcf</excludedpackage>
</excludedpackages>
<instructions type="install">
- <instruction type="file">files.tar</instruction>
- <instruction type="userGroupOption">userGroupOption.xml</instruction>
- <instruction type="sql">install.sql</instruction>
- <instruction type="template">templates.tar</instruction>
- <instruction type="option">option.xml</instruction>
- <instruction type="templateListener">templateListener.xml</instruction>
- <instruction type="language">language/*.xml</instruction>
- <instruction type="objectType">objectType.xml</instruction>
- <instruction type="clipboardAction">clipboardAction.xml</instruction>
- <instruction type="coreObject">coreObject.xml</instruction>
- <instruction type="userNotificationEvent">userNotificationEvent.xml</instruction>
- <instruction type="userOption">userOption.xml</instruction>
- <instruction type="eventListener">eventListener.xml</instruction>
- <instruction type="script">acp/install_com.woltlab.wcf.conversation_2.0.0.php</instruction>
+ <instruction type="file" />
+ <instruction type="userGroupOption" />
+ <instruction type="sql" />
+ <instruction type="template" />
+ <instruction type="option" />
+ <instruction type="templateListener" />
+ <instruction type="language" />
+ <instruction type="objectType" />
+ <instruction type="clipboardAction" />
+ <instruction type="coreObject" />
+ <instruction type="userNotificationEvent" />
+ <instruction type="userOption" />
+ <instruction type="eventListener" />
+ <instruction type="script">acp/install_com.woltlab.wcf.conversation.php</instruction>
+ <instruction type="page" />
</instructions>
- <instructions type="update" fromversion="2.0.10">
- <instruction type="file" run="standalone">files.tar</instruction>
- <instruction type="template" run="standalone">templates.tar</instruction>
-
- <instruction type="language" run="standalone">language/*.xml</instruction>
-
- <instruction type="sql" run="standalone">update1_210.sql</instruction>
- <instruction type="sql" run="standalone">update2_210.sql</instruction>
- <instruction type="sql" run="standalone">update3_210.sql</instruction>
-
- <instruction type="clipboardAction">clipboardAction.xml</instruction>
- <instruction type="eventListener">eventListener_update210.xml</instruction>
- <instruction type="objectType">objectType.xml</instruction>
- <instruction type="option">option.xml</instruction>
- <instruction type="userGroupOption">userGroupOption.xml</instruction>
- <instruction type="userOption">userOption.xml</instruction>
- </instructions>
-
- <instructions type="update" fromversion="2.1.5">
+ <instructions type="update" fromversion="3.0.0 Beta 1">
<instruction type="file">files_update.tar</instruction>
<instruction type="template">templates_update.tar</instruction>
- <instruction type="language">language/*.xml</instruction>
+ <instruction type="language" />
</instructions>
</package>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/maelstrom/page.xsd">
+ <import>
+ <page identifier="com.woltlab.wcf.conversation.ConversationList">
+ <controller>wcf\page\ConversationListPage</controller>
+ <handler>wcf\system\page\handler\ConversationListPageHandler</handler>
+ <name language="de">Konversationenliste</name>
+ <name language="en">Conversation List</name>
+ <pageType>system</pageType>
+
+ <content language="en">
+ <title>Conversations</title>
+ </content>
+ <content language="de">
+ <title>Konversationen</title>
+ </content>
+ </page>
+ <page identifier="com.woltlab.wcf.conversation.Conversation">
+ <controller>wcf\page\ConversationPage</controller>
+ <handler>wcf\system\page\handler\DefaultConversationRelatedPageHandler</handler>
+ <name language="de">Konversation</name>
+ <name language="en">Conversation</name>
+ <pageType>system</pageType>
+ <requireObjectID>1</requireObjectID>
+ <hasFixedParent>1</hasFixedParent>
+ <parent>com.woltlab.wcf.conversation.ConversationList</parent>
+ </page>
+ <page identifier="com.woltlab.wcf.conversation.ConversationAdd">
+ <controller>wcf\form\ConversationAddForm</controller>
+ <name language="de">Konversation starten</name>
+ <name language="en">New Conversation</name>
+ <pageType>system</pageType>
+ <hasFixedParent>1</hasFixedParent>
+ <parent>com.woltlab.wcf.conversation.ConversationList</parent>
+
+ <content language="en">
+ <title>New Conversation</title>
+ </content>
+ <content language="de">
+ <title>Konversation starten</title>
+ </content>
+ </page>
+ </import>
+</data>
<import>
<templatelistener name="userPanel">
<environment>user</environment>
- <templatename>userPanel</templatename>
+ <templatename>pageHeaderUser</templatename>
<eventname>menuItems</eventname>
<templatecode><![CDATA[{include file='__userPanelConversationDropdown'}]]></templatecode>
</templatelistener>
<templatelistener name="searchAreaConversationSettings">
<environment>user</environment>
- <templatename>searchArea</templatename>
+ <templatename>pageHeaderSearch</templatename>
<eventname>settings</eventname>
<templatecode><![CDATA[{include file='__searchAreaConversationSettings'}]]></templatecode>
</templatelistener>
+
+ <templatelistener name="userProfileStartConversation">
+ <environment>user</environment>
+ <templatename>user</templatename>
+ <eventname>menuInteraction</eventname>
+ <templatecode><![CDATA[{include file='__userProfileStartConversation'}]]></templatecode>
+ </templatelistener>
+
+ <templatelistener name="mobileMenuConversation">
+ <environment>user</environment>
+ <templatename>pageMenuMobile</templatename>
+ <eventname>userMenuItems</eventname>
+ <templatecode><![CDATA[{include file='__mobileMenuConversation'}]]></templatecode>
+ </templatelistener>
</import>
-</data>
\ No newline at end of file
+
+ <delete>
+ <templatelistener name="searchAreaConversationSettings">
+ <environment>user</environment>
+ <templatename>searchArea</templatename>
+ <eventname>settings</eventname>
+ <templatecode><![CDATA[{include file='__searchAreaConversationSettings'}]]></templatecode>
+ </templatelistener>
+ </delete>
+</data>
--- /dev/null
+<li class="menuOverlayItem" data-more="com.woltlab.wcf.conversation">
+ <a href="{link controller='ConversationList'}{/link}" class="menuOverlayItemLink menuOverlayItemBadge box24" data-badge-identifier="unreadConversations">
+ <span class="icon icon24 fa-comments"></span>
+ <span class="menuOverlayItemTitle">{lang}wcf.conversation.conversations{/lang}</span>
+ {if $__wcf->getConversationHandler()->getUnreadConversationCount()}<span class="badge badgeUpdate">{#$__wcf->getConversationHandler()->getUnreadConversationCount()}</span>{/if}
+ </a>
+</li>
{if $__searchAreaInitialized|empty && $templateName|substr:0:12 == 'conversation'}
- {capture assign='__searchInputPlaceholder'}{lang}wcf.conversation.searchConversations{/lang}{/capture}
- {capture assign='__searchHiddenInputFields'}<input type="hidden" name="types[]" value="com.woltlab.wcf.conversation.message" />{/capture}
- {assign var='__searchAreaInitialized' value=true}
-{/if}
\ No newline at end of file
+ {assign var='__searchObjectTypeName' value='com.woltlab.wcf.conversation.message'}
+
+ {if $__wcf->getActivePage()->identifier == 'com.woltlab.wcf.conversation.Conversation'}
+ {capture assign='__searchTypeLabel'}{lang}wcf.search.type.com.woltlab.wcf.conversation{/lang}{/capture}
+ {capture assign='__searchTypesScoped'}<li><a href="#" data-extended-link="{link controller='Search'}types[]=com.woltlab.wcf.conversation.message{/link}" data-object-type="com.woltlab.wcf.conversation.message" data-parameters='{ "conversationID": {@$conversation->conversationID} }'>{lang}wcf.search.type.com.woltlab.wcf.conversation{/lang}</a></li>{/capture}
+ {/if}
+{/if}
{if MODULE_CONVERSATION && $__wcf->user->userID && $__wcf->session->getPermission('user.conversation.canUseConversation') && $user->userID != $__wcf->user->userID}
- <li><a class="jsTooltip" href="{link controller='ConversationAdd'}userID={@$user->userID}{/link}" title="{lang}wcf.conversation.button.add{/lang}"><span class="icon icon16 icon-comments"></span> <span class="invisible">{lang}wcf.conversation.button.add{/lang}</span></a></li>
+ <li><a class="jsTooltip" href="{link controller='ConversationAdd'}userID={@$user->userID}{/link}" title="{lang}wcf.conversation.button.add{/lang}"><span class="icon icon16 fa-comments"></span> <span class="invisible">{lang}wcf.conversation.button.add{/lang}</span></a></li>
{/if}
\ No newline at end of file
{if MODULE_CONVERSATION && $__wcf->user->userID && $__wcf->session->getPermission('user.conversation.canUseConversation')}
<li id="unreadConversations" data-count="{#$__wcf->getConversationHandler()->getUnreadConversationCount()}">
- <a href="{link controller='ConversationList'}{/link}"><span class="icon icon16 icon-comments"></span> <span>{lang}wcf.conversation.conversations{/lang}</span> {if $__wcf->getConversationHandler()->getUnreadConversationCount()}<span class="badge badgeInverse">{#$__wcf->getConversationHandler()->getUnreadConversationCount()}</span>{/if}</a>
+ <a class="jsTooltip" href="{link controller='ConversationList'}{/link}" title="{lang}wcf.conversation.conversations{/lang}"><span class="icon icon32 fa-comments"></span> <span>{lang}wcf.conversation.conversations{/lang}</span> {if $__wcf->getConversationHandler()->getUnreadConversationCount()}<span class="badge badgeUpdate">{#$__wcf->getConversationHandler()->getUnreadConversationCount()}</span>{/if}</a>
{if !OFFLINE || $__wcf->session->getPermission('admin.general.canViewPageDuringOfflineMode')}
<script data-relocate="true" src="{@$__wcf->getPath()}js/WCF.Conversation{if !ENABLE_DEBUG_MODE}.min{/if}.js?v={@LAST_UPDATE_TIME}"></script>
<script data-relocate="true">
- //<![CDATA[
$(function() {
new WCF.User.Panel.Conversation({
markAllAsReadConfirmMessage: '{lang}wcf.conversation.markAllAsRead.confirmMessage{/lang}',
title: '{lang}wcf.conversation.conversations{/lang}'
});
});
- //]]>
</script>
{/if}
</li>
--- /dev/null
+{if MODULE_CONVERSATION && $__wcf->user->userID && $__wcf->session->getPermission('user.conversation.canUseConversation') && $user->userID != $__wcf->user->userID}<li><a href="{link controller='ConversationAdd'}userID={@$user->userID}{/link}">{lang}wcf.conversation.button.add{/lang}</a></li>{/if}
-{if MODULE_CONVERSATION && $__wcf->user->userID && $__wcf->session->getPermission('user.conversation.canUseConversation') && $user->userID != $__wcf->user->userID}<li><a class="button jsTooltip" href="{link controller='ConversationAdd'}userID={@$user->userID}{/link}" title="{lang}wcf.conversation.button.add{/lang}"><span class="icon icon16 icon-comments"></span> <span class="invisible">{lang}wcf.conversation.button.add{/lang}</span></a></li>{/if}
\ No newline at end of file
+{if MODULE_CONVERSATION && $__wcf->user->userID && $__wcf->session->getPermission('user.conversation.canUseConversation') && $user->userID != $__wcf->user->userID}<li><a class="button jsTooltip" href="{link controller='ConversationAdd'}userID={@$user->userID}{/link}" title="{lang}wcf.conversation.button.add{/lang}"><span class="icon icon16 fa-comments"></span> <span class="invisible">{lang}wcf.conversation.button.add{/lang}</span></a></li>{/if}
\ No newline at end of file
-{include file='documentHeader'}
+{capture assign='pageTitle'}{$conversation->subject} {if $pageNo > 1} - {lang}wcf.page.pageNo{/lang}{/if}{/capture}
-<head>
- <title>{$conversation->subject} {if $pageNo > 1}- {lang}wcf.page.pageNo{/lang} {/if} - {PAGE_TITLE|language}</title>
-
- {include file='headInclude'}
-
- <script data-relocate="true" src="{@$__wcf->getPath()}js/WCF.Conversation{if !ENABLE_DEBUG_MODE}.min{/if}.js?v={@LAST_UPDATE_TIME}"></script>
- <script data-relocate="true">
- //<![CDATA[
- $(function() {
- WCF.Language.addObject({
- 'wcf.conversation.edit.addParticipants': '{lang}wcf.conversation.edit.addParticipants{/lang}',
- 'wcf.conversation.edit.assignLabel': '{lang}wcf.conversation.edit.assignLabel{/lang}',
- 'wcf.conversation.edit.close': '{lang}wcf.conversation.edit.close{/lang}',
- 'wcf.conversation.edit.leave': '{lang}wcf.conversation.edit.leave{/lang}',
- 'wcf.conversation.edit.open': '{lang}wcf.conversation.edit.open{/lang}',
- 'wcf.conversation.leave.title': '{lang}wcf.conversation.leave.title{/lang}',
- 'wcf.global.state.closed': '{lang}wcf.global.state.closed{/lang}',
- 'wcf.message.bbcode.code.copy': '{lang}wcf.message.bbcode.code.copy{/lang}',
- 'wcf.message.error.editorAlreadyInUse': '{lang}wcf.message.error.editorAlreadyInUse{/lang}',
- 'wcf.moderation.report.reportContent': '{lang}wcf.moderation.report.reportContent{/lang}',
- 'wcf.moderation.report.success': '{lang}wcf.moderation.report.success{/lang}',
- 'wcf.conversation.label.assignLabels': '{lang}wcf.conversation.label.assignLabels{/lang}'
- });
+{capture assign='contentHeader'}
+ <header class="contentHeader">
+ <div class="contentHeaderIcon">
+ {@$conversation->getUserProfile()->getAvatar()->getImageTag(64)}
+ </div>
+
+ <div class="contentHeaderTitle">
+ <h1 class="contentTitle">{$conversation->subject}</h1>
- var $availableLabels = [ {implode from=$labelList item=label}{ cssClassName: '{if $label->cssClassName}{@$label->cssClassName}{/if}', labelID: {@$label->labelID}, label: '{$label->label}' }{/implode} ];
- var $editorHandler = new WCF.Conversation.EditorHandlerConversation($availableLabels);
- var $inlineEditor = new WCF.Conversation.InlineEditor('.conversation');
- $inlineEditor.setEditorHandler($editorHandler);
-
- {assign var=__supportPaste value=true}
- {if $conversation->isClosed}{assign var=__supportPaste value=false}{/if}
- {include file='__messageQuoteManager' wysiwygSelector='text' supportPaste=$__supportPaste}
-
- new WCF.Conversation.Message.InlineEditor({@$conversation->conversationID}, $quoteManager);
- new WCF.Conversation.Message.QuoteHandler($quoteManager);
- {if !$conversation->isClosed}new WCF.Conversation.QuickReply($quoteManager);{/if}
-
- {if $__wcf->session->getPermission('user.profile.canReportContent')}
- new WCF.Moderation.Report.Content('com.woltlab.wcf.conversation.message', '.jsReportConversationMessage');
- {/if}
- new WCF.Conversation.RemoveParticipant({@$conversation->conversationID});
- new WCF.Message.BBCode.CodeViewer();
- });
- //]]>
- </script>
-</head>
-
-<body id="tpl{$templateName|ucfirst}" data-template="{$templateName}" data-application="{$templateNameApplication}">
+ <ul class="inlineList contentHeaderMetaData">
+ {hascontent}
+ <li>
+ <span class="icon icon16 fa-tags"></span>
+ <ul class="labelList">
+ {content}
+ {foreach from=$conversation->getAssignedLabels() item=label}
+ <li><span class="label badge{if $label->cssClassName} {$label->cssClassName}{/if}">{lang}{$label->label}{/lang}</span></li>
+ {/foreach}
+ {/content}
+ </ul>
+ </li>
+ {/hascontent}
+
+ <li>
+ <span class="icon icon16 fa-user"></span>
+ {if $conversation->userID}
+ <a href="{link controller='User' object=$conversation->getUserProfile()->getDecoratedObject()}{/link}" class="userLink" data-user-id="{@$conversation->userID}">{$conversation->username}</a>
+ {else}
+ {$conversation->username}
+ {/if}
+ </li>
+
+ <li>
+ <span class="icon icon16 fa-clock-o"></span>
+ {@$conversation->time|time}
+ </li>
+
+ {if $conversation->isClosed}
+ <li>
+ <span class="icon icon16 fa-lock jsIconLock"></span>
+ {lang}wcf.global.state.closed{/lang}
+ </li>
+ {/if}
+ </ul>
+ </div>
+
+ <nav class="contentHeaderNavigation">
+ <ul class="conversation jsConversationInlineEditorContainer" data-conversation-id="{@$conversation->conversationID}" data-label-ids="[ {implode from=$conversation->getAssignedLabels() item=label}{@$label->labelID}{/implode} ]" data-is-closed="{@$conversation->isClosed}" data-can-close-conversation="{if $conversation->userID == $__wcf->getUser()->userID}1{else}0{/if}" data-can-add-participants="{if $conversation->canAddParticipants()}1{else}0{/if}">
+ <li class="jsOnly"><a href="#" class="button jsConversationInlineEditor"><span class="icon icon16 fa-pencil"></span> <span>{lang}wcf.global.button.edit{/lang}</span></a></li>
+ {if !$conversation->isClosed}<li class="jsOnly"><a href="#" title="{lang}wcf.conversation.message.add{/lang}" class="button buttonPrimary jsQuickReply"><span class="icon icon16 fa-plus"></span> <span>{lang}wcf.conversation.message.button.add{/lang}</span></a></li>{/if}
+ {event name='contentHeaderNavigation'}
+ </ul>
+ </nav>
+ </header>
+{/capture}
{include file='header'}
-<header class="boxHeadline marginTop conversationHeadline labeledHeadline">
- <h1><a href="{link controller='Conversation' object=$conversation}{/link}">{$conversation->subject}</a>{if $conversation->isClosed} <span class="icon icon16 icon-lock jsTooltip jsIconLock" title="{lang}wcf.global.state.closed{/lang}"></span>{/if}</h1>
-
- {hascontent}
- <ul class="labelList">
- {content}
- {foreach from=$conversation->getAssignedLabels() item=label}
- <li><span class="label badge{if $label->cssClassName} {$label->cssClassName}{/if}">{lang}{$label->label}{/lang}</span></li>
- {/foreach}
- {/content}
- </ul>
- {/hascontent}
-
- {event name='headlineData'}
-</header>
-
-{include file='userNotice'}
-
{if !$conversation->isDraft}
- <div class="container containerPadding marginTop">
- <fieldset>
- <legend>{lang}wcf.conversation.participants{/lang}</legend>
-
- <ul class="containerBoxList tripleColumned conversationParticipantList">
- {foreach from=$participants item=participant}
- <li class="jsParticipant{if !$participant->userID || $participant->hideConversation == 2} conversationLeft{/if}">
- <div class="box24">
- {if $participant->userID}<a href="{link controller='User' object=$participant}{/link}" class="framed">{@$participant->getAvatar()->getImageTag(24)}</a>{else}<span class="framed">{@$participant->getAvatar()->getImageTag(24)}</span>{/if}
- <div>
- <p>
- {if $participant->userID}<a href="{link controller='User' object=$participant}{/link}" class="userLink" data-user-id="{@$participant->userID}">{$participant->username}</a>{else}<span>{$participant->username}</span>{/if}
- {if $participant->isInvisible}<small>({lang}wcf.conversation.invisible{/lang})</small>{/if}
- {if $participant->userID && ($conversation->userID == $__wcf->getUser()->userID) && ($participant->userID != $__wcf->getUser()->userID) && $participant->hideConversation != 2}
- <a href="#" class="jsDeleteButton jsTooltip jsOnly" title="{lang}wcf.conversation.participants.removeParticipant{/lang}" data-confirm-message="{lang}wcf.conversation.participants.removeParticipant.confirmMessage{/lang}" data-object-id="{@$participant->userID}"><span class="icon icon16 icon-remove"></span></a>
- {/if}
- </p>
- <dl class="plain inlineDataList">
- <dt>{lang}wcf.conversation.lastVisitTime{/lang}</dt>
- <dd>{if $participant->lastVisitTime}{@$participant->lastVisitTime|time}{else}-{/if}</dd>
- </dl>
- </div>
+ <section class="section">
+ <h2 class="sectionTitle">{lang}wcf.conversation.participants{/lang}</h2>
+
+ <ul class="containerBoxList tripleColumned conversationParticipantList">
+ {foreach from=$participants item=participant}
+ <li class="jsParticipant{if !$participant->userID || $participant->hideConversation == 2} conversationLeft{/if}">
+ <div class="box24">
+ {if $participant->userID}<a href="{link controller='User' object=$participant}{/link}">{@$participant->getAvatar()->getImageTag(24)}</a>{else}<span>{@$participant->getAvatar()->getImageTag(24)}</span>{/if}
+ <div>
+ <p>
+ {if $participant->userID}<a href="{link controller='User' object=$participant}{/link}" class="userLink" data-user-id="{@$participant->userID}">{$participant->username}</a>{else}<span>{$participant->username}</span>{/if}
+ {if $participant->isInvisible}<small>({lang}wcf.conversation.invisible{/lang})</small>{/if}
+ {if $participant->userID && ($conversation->userID == $__wcf->getUser()->userID) && ($participant->userID != $__wcf->getUser()->userID) && $participant->hideConversation != 2}
+ <a href="#" class="jsDeleteButton jsTooltip jsOnly" title="{lang}wcf.conversation.participants.removeParticipant{/lang}" data-confirm-message-html="{lang __encode=true}wcf.conversation.participants.removeParticipant.confirmMessage{/lang}" data-object-id="{@$participant->userID}"><span class="icon icon16 fa-times"></span></a>
+ {/if}
+ </p>
+ <dl class="plain inlineDataList small">
+ <dt>{lang}wcf.conversation.lastVisitTime{/lang}</dt>
+ <dd>{if $participant->lastVisitTime}{@$participant->lastVisitTime|time}{else}-{/if}</dd>
+ </dl>
</div>
- </li>
- {/foreach}
- </ul>
- </fieldset>
- </div>
+ </div>
+ </li>
+ {/foreach}
+ </ul>
+ </section>
{/if}
-<div class="contentNavigation">
- {pages print=true assign=pagesLinks controller='Conversation' object=$conversation link="pageNo=%d"}
-
- <nav>
- <ul class="conversation jsConversationInlineEditorContainer" data-conversation-id="{@$conversation->conversationID}" data-label-ids="[ {implode from=$conversation->getAssignedLabels() item=label}{@$label->labelID}{/implode} ]" data-is-closed="{@$conversation->isClosed}" data-can-close-conversation="{if $conversation->userID == $__wcf->getUser()->userID}1{else}0{/if}" data-can-add-participants="{if $conversation->canAddParticipants()}1{else}0{/if}">
- <li class="jsOnly"><a href="#" class="button jsConversationInlineEditor"><span class="icon icon16 icon-pencil"></span> <span>{lang}wcf.global.button.edit{/lang}</span></a></li>
- {if !$conversation->isClosed}<li><a href="{link controller='ConversationMessageAdd' id=$conversationID}{/link}" title="{lang}wcf.conversation.message.add{/lang}" class="button buttonPrimary jsQuickReply"><span class="icon icon16 icon-plus"></span> <span>{lang}wcf.conversation.message.button.add{/lang}</span></a></li>{/if}
- {event name='contentNavigationButtonsTop'}
- </ul>
- </nav>
-</div>
+{hascontent}
+ <div class="paginationTop">
+ {content}{pages print=true assign=pagesLinks controller='Conversation' object=$conversation link="pageNo=%d"}{/content}
+ </div>
+{/hascontent}
-<div class="marginTop">
+<div class="section">
<ul class="messageList">
{include file='conversationMessageList'}
+ {hascontent}
+ <li class="messageListPagination">
+ {content}{@$pagesLinks}{/content}
+ </li>
+ {/hascontent}
{if !$conversation->isClosed}{include file='conversationQuickReply'}{/if}
</ul>
</div>
-<div class="contentNavigation">
- {@$pagesLinks}
-
- {hascontent}
- <nav>
- <ul>
- {content}
- {if !$conversation->isClosed}<li><a href="{link controller='ConversationMessageAdd' id=$conversationID}{/link}" title="{lang}wcf.conversation.message.add{/lang}" class="button buttonPrimary jsQuickReply"><span class="icon icon16 icon-plus"></span> <span>{lang}wcf.conversation.message.button.add{/lang}</span></a></li>{/if}
- {event name='contentNavigationButtonsBottom'}
- {/content}
- </ul>
- </nav>
- {/hascontent}
-</div>
+{if !ENABLE_DEBUG_MODE}<script src="{@$__wcf->getPath()}js/WoltLabSuite.Core.Conversation.min.js?v={@LAST_UPDATE_TIME}"></script>{/if}
+<script data-relocate="true" src="{@$__wcf->getPath()}js/WCF.Conversation{if !ENABLE_DEBUG_MODE}.min{/if}.js?v={@LAST_UPDATE_TIME}"></script>
+<script data-relocate="true">
+ $(function() {
+ WCF.Language.addObject({
+ 'wcf.conversation.edit.addParticipants': '{lang}wcf.conversation.edit.addParticipants{/lang}',
+ 'wcf.conversation.edit.assignLabel': '{lang}wcf.conversation.edit.assignLabel{/lang}',
+ 'wcf.conversation.edit.close': '{lang}wcf.conversation.edit.close{/lang}',
+ 'wcf.conversation.edit.leave': '{lang}wcf.conversation.edit.leave{/lang}',
+ 'wcf.conversation.edit.open': '{lang}wcf.conversation.edit.open{/lang}',
+ 'wcf.conversation.leave.title': '{lang}wcf.conversation.leave.title{/lang}',
+ 'wcf.global.state.closed': '{lang}wcf.global.state.closed{/lang}',
+ 'wcf.message.bbcode.code.copy': '{lang}wcf.message.bbcode.code.copy{/lang}',
+ 'wcf.message.error.editorAlreadyInUse': '{lang}wcf.message.error.editorAlreadyInUse{/lang}',
+ 'wcf.moderation.report.reportContent': '{lang}wcf.moderation.report.reportContent{/lang}',
+ 'wcf.moderation.report.success': '{lang}wcf.moderation.report.success{/lang}',
+ 'wcf.conversation.label.assignLabels': '{lang}wcf.conversation.label.assignLabels{/lang}'
+ });
+
+ var $availableLabels = [ {implode from=$labelList item=label}{ cssClassName: '{if $label->cssClassName}{@$label->cssClassName}{/if}', labelID: {@$label->labelID}, label: '{$label->label}' }{/implode} ];
+ var $editorHandler = new WCF.Conversation.EditorHandlerConversation($availableLabels);
+ var $inlineEditor = new WCF.Conversation.InlineEditor('.conversation');
+ $inlineEditor.setEditorHandler($editorHandler);
+
+ {assign var=__supportPaste value=true}
+ {if $conversation->isClosed}{assign var=__supportPaste value=false}{/if}
+ {include file='__messageQuoteManager' wysiwygSelector='text' supportPaste=$__supportPaste}
+
+ new WCF.Conversation.Message.InlineEditor({@$conversation->conversationID}, $quoteManager);
+ new WCF.Conversation.Message.QuoteHandler($quoteManager);
+ {* if !$conversation->isClosed}new WCF.Conversation.QuickReply($quoteManager);{/if *}
+
+ {if $__wcf->session->getPermission('user.profile.canReportContent')}
+ new WCF.Moderation.Report.Content('com.woltlab.wcf.conversation.message', '.jsReportConversationMessage');
+ {/if}
+ new WCF.Conversation.RemoveParticipant({@$conversation->conversationID});
+ new WCF.Message.BBCode.CodeViewer();
+ });
+</script>
{include file='footer'}
-
-</body>
-</html>
-{include file='documentHeader'}
-
-<head>
- <title>{lang}wcf.conversation.add{/lang} - {PAGE_TITLE|language}</title>
-
- {include file='headInclude'}
-
- <script data-relocate="true">
- //<![CDATA[
- $(function() {
- new WCF.Search.User('#participants', null, false, [ ], true);
- new WCF.Search.User('#invisibleParticipants', null, false, [ ], true);
-
- WCF.Message.Submit.registerButton('text', $('#messageContainer > .formSubmit > input[type=submit]'));
- new WCF.Message.FormGuard();
-
- WCF.System.Dependency.Manager.register('Redactor_text', function() { new WCF.Message.UserMention('text'); });
-
- {include file='__messageQuoteManager' wysiwygSelector='text' supportPaste=true}
- });
- //]]>
- </script>
-</head>
-
-<body id="tpl{$templateName|ucfirst}" data-template="{$templateName}" data-application="{$templateNameApplication}">
{include file='header'}
-<header class="boxHeadline">
- <h1>{lang}wcf.conversation.add{/lang}</h1>
-</header>
-
-{include file='userNotice'}
-
{include file='formError'}
<form id="messageContainer" class="jsFormGuard" method="post" action="{link controller='ConversationAdd'}{/link}">
- <div class="container containerPadding marginTop">
- <fieldset>
- <legend>{lang}wcf.conversation.information{/lang}</legend>
-
- <dl{if $errorField == 'subject'} class="formError"{/if}>
- <dt><label for="subject">{lang}wcf.global.subject{/lang}</label></dt>
- <dd>
- <input type="text" id="subject" name="subject" value="{$subject}" required="required" maxlength="255" class="long" />
- {if $errorField == 'subject'}
- <small class="innerError">
- {if $errorType == 'empty'}
- {lang}wcf.global.form.error.empty{/lang}
- {elseif $errorType == 'censoredWordsFound'}
- {lang}wcf.message.error.censoredWordsFound{/lang}
- {else}
- {lang}wcf.conversation.subject.error.{@$errorType}{/lang}
- {/if}
- </small>
- {/if}
- </dd>
- </dl>
-
- {event name='informationFields'}
- </fieldset>
+ <section class="section">
+ <h2 class="sectionTitle">{lang}wcf.conversation.information{/lang}</h2>
- <fieldset>
- <legend>{lang}wcf.conversation.participants{/lang}</legend>
-
- <dl{if $errorField == 'participants'} class="formError"{/if}>
- <dt><label for="participants">{lang}wcf.conversation.participants{/lang}</label></dt>
- <dd>
- <textarea id="participants" name="participants" class="long" cols="40" rows="2">{$participants}</textarea>
- {if $errorField == 'participants'}
- <small class="innerError">
- {if $errorType == 'empty'}
- {lang}wcf.global.form.error.empty{/lang}
- {elseif $errorType|is_array}
- {foreach from=$errorType item='errorData'}
- {lang}wcf.conversation.participants.error.{@$errorData.type}{/lang}
- {/foreach}
- {else}
- {lang}wcf.conversation.participants.error.{@$errorType}{/lang}
- {/if}
- </small>
- {/if}
- <small>{lang}wcf.conversation.participants.description{/lang}</small>
- </dd>
- </dl>
-
- {if $__wcf->session->getPermission('user.conversation.canAddInvisibleParticipants')}
+ <dl{if $errorField == 'subject'} class="formError"{/if}>
+ <dt><label for="subject">{lang}wcf.global.subject{/lang}</label></dt>
+ <dd>
+ <input type="text" id="subject" name="subject" value="{$subject}" required maxlength="255" class="long">
+ {if $errorField == 'subject'}
+ <small class="innerError">
+ {if $errorType == 'empty'}
+ {lang}wcf.global.form.error.empty{/lang}
+ {elseif $errorType == 'censoredWordsFound'}
+ {lang}wcf.message.error.censoredWordsFound{/lang}
+ {else}
+ {lang}wcf.conversation.subject.error.{@$errorType}{/lang}
+ {/if}
+ </small>
+ {/if}
+ </dd>
+ </dl>
+
+ {event name='informationFields'}
+ </section>
+
+ <section class="section">
+ <h2 class="sectionTitle">{lang}wcf.conversation.participants{/lang}</h2>
+
+ <dl{if $errorField == 'participants'} class="formError"{/if}>
+ <dt><label for="participants">{lang}wcf.conversation.participants{/lang}</label></dt>
+ <dd>
+ <input type="text" id="participants" name="participants" class="long" value="{$participants}">
+ {if $errorField == 'participants'}
+ <small class="innerError">
+ {if $errorType == 'empty'}
+ {lang}wcf.global.form.error.empty{/lang}
+ {elseif $errorType|is_array}
+ {foreach from=$errorType item='errorData'}
+ {lang}wcf.conversation.participants.error.{@$errorData.type}{/lang}
+ {/foreach}
+ {else}
+ {lang}wcf.conversation.participants.error.{@$errorType}{/lang}
+ {/if}
+ </small>
+ {/if}
+ <small>{lang}wcf.conversation.participants.description{/lang}</small>
+ </dd>
+ </dl>
+
+ {if $__wcf->session->getPermission('user.conversation.canAddInvisibleParticipants')}
<dl{if $errorField == 'invisibleParticipants'} class="formError"{/if}>
<dt><label for="invisibleParticipants">{lang}wcf.conversation.invisibleParticipants{/lang}</label></dt>
<dd>
- <textarea id="invisibleParticipants" name="invisibleParticipants" class="long" cols="40" rows="2">{$invisibleParticipants}</textarea>
+ <input type="text" id="invisibleParticipants" name="invisibleParticipants" class="long" value="{$invisibleParticipants}">
{if $errorField == 'invisibleParticipants'}
<small class="innerError">
{if $errorType == 'empty'}
<small>{lang}wcf.conversation.invisibleParticipants.description{/lang}</small>
</dd>
</dl>
- {/if}
-
- {if $__wcf->session->getPermission('user.conversation.canSetCanInvite')}
+ {/if}
+
+ {if $__wcf->session->getPermission('user.conversation.canSetCanInvite')}
<dl>
<dt></dt>
<dd>
- <label><input type="checkbox" name="participantCanInvite" id="participantCanInvite" value="1"{if $participantCanInvite} checked="checked"{/if} /> {lang}wcf.conversation.participantCanInvite{/lang}</label>
- </dd>
- </dl>
- {/if}
-
- {event name='participantFields'}
- </fieldset>
-
- <fieldset>
- <legend>{lang}wcf.conversation.message{/lang}</legend>
-
- <dl class="wide{if $errorField == 'text'} formError{/if}">
- <dt><label for="text">{lang}wcf.conversation.message{/lang}</label></dt>
- <dd>
- <textarea id="text" name="text" rows="20" cols="40" data-autosave="com.woltlab.wcf.conversation.conversationAdd" data-autosave-prompt="true">{$text}</textarea>
- {if $errorField == 'text'}
- <small class="innerError">
- {if $errorType == 'empty'}
- {lang}wcf.global.form.error.empty{/lang}
- {elseif $errorType == 'tooLong'}
- {lang}wcf.message.error.tooLong{/lang}
- {elseif $errorType == 'censoredWordsFound'}
- {lang}wcf.message.error.censoredWordsFound{/lang}
- {elseif $errorType == 'disallowedBBCodes'}
- {lang}wcf.message.error.disallowedBBCodes{/lang}
- {else}
- {lang}wcf.conversation.message.error.{@$errorType}{/lang}
- {/if}
- </small>
- {/if}
+ <label><input type="checkbox" name="participantCanInvite" id="participantCanInvite" value="1"{if $participantCanInvite} checked{/if}> {lang}wcf.conversation.participantCanInvite{/lang}</label>
</dd>
</dl>
-
- {event name='messageFields'}
- </fieldset>
+ {/if}
- {include file='messageFormTabs' wysiwygContainerID='text'}
+ {event name='participantFields'}
+ </section>
- {event name='fieldsets'}
- </div>
+ <section class="section">
+ <h2 class="sectionTitle">{lang}wcf.conversation.message{/lang}</h2>
+
+ <dl class="wide{if $errorField == 'text'} formError{/if}">
+ <dt><label for="text">{lang}wcf.conversation.message{/lang}</label></dt>
+ <dd>
+ <textarea id="text" name="text" class="wysiwygTextarea"
+ data-autosave="com.woltlab.wcf.conversation.conversationAdd"
+ data-autosave-prompt="true"
+ data-support-mention="true"
+ >{$text}</textarea>
+ {if $errorField == 'text'}
+ <small class="innerError">
+ {if $errorType == 'empty'}
+ {lang}wcf.global.form.error.empty{/lang}
+ {elseif $errorType == 'tooLong'}
+ {lang}wcf.message.error.tooLong{/lang}
+ {elseif $errorType == 'censoredWordsFound'}
+ {lang}wcf.message.error.censoredWordsFound{/lang}
+ {elseif $errorType == 'disallowedBBCodes'}
+ {lang}wcf.message.error.disallowedBBCodes{/lang}
+ {else}
+ {lang}wcf.conversation.message.error.{@$errorType}{/lang}
+ {/if}
+ </small>
+ {/if}
+ </dd>
+ </dl>
+
+ {event name='messageFields'}
+ </section>
+
+ {include file='messageFormTabs' wysiwygContainerID='text'}
+
+ {event name='sections'}
<div class="formSubmit">
- <input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s" />
+ <input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
<button name="draft" accesskey="d" value="1">{lang}wcf.conversation.button.saveAsDraft{/lang}</button>
- {include file='messageFormPreviewButton'}
+ {include file='messageFormPreviewButton' previewMessageObjectType='com.woltlab.wcf.conversation.message' previewMessageObjectID=0}
{@SECURITY_TOKEN_INPUT_TAG}
</div>
</form>
-{include file='footer'}
-{include file='wysiwyg'}
+<script data-relocate="true">
+ require(['WoltLabSuite/Core/Ui/ItemList/User'], function(UiItemListUser) {
+ UiItemListUser.init('participants', {
+ maxItems: {@$__wcf->getSession()->getPermission('user.conversation.maxParticipants')}
+ });
+
+ UiItemListUser.init('invisibleParticipants', {
+ maxItems: {@$__wcf->getSession()->getPermission('user.conversation.maxParticipants')}
+ });
+ });
+
+ $(function() {
+ WCF.Message.Submit.registerButton('text', $('#messageContainer > .formSubmit > input[type=submit]'));
+ new WCF.Message.FormGuard();
+
+ {include file='__messageQuoteManager' wysiwygSelector='text' supportPaste=true}
+ });
+</script>
-</body>
-</html>
\ No newline at end of file
+{include file='wysiwyg'}
+{include file='footer'}
-<fieldset>
- <legend>{lang}wcf.conversation.edit.addParticipants{/lang}</legend>
-
- <dl class="jsAddParticipants">
- <dt><label for="participantsInput">{lang}wcf.conversation.participants{/lang}</label></dt>
- <dd>
- <textarea id="participantsInput" name="participants" class="long" cols="40" rows="2"></textarea>
- <small>{lang}wcf.conversation.participants.description{/lang}</small>
- </dd>
- </dl>
-</fieldset>
+<dl class="jsAddParticipants">
+ <dt><label for="participantsInput">{lang}wcf.conversation.participants{/lang}</label></dt>
+ <dd>
+ <textarea id="participantsInput" name="participants" class="long" cols="40" rows="2"></textarea>
+ <small>{lang}wcf.conversation.participants.description{/lang}</small>
+ </dd>
+</dl>
<div class="formSubmit">
<button id="addParticipants" class="buttonPrimary">{lang}wcf.global.button.submit{/lang}</button>
-<fieldset>
- <legend>{lang}wcf.conversation.label.assignLabels{/lang}</legend>
+<section class="section">
+ <h2 class="sectionTitle">{lang}wcf.conversation.label.assignLabels{/lang}</h2>
<ul>
{foreach from=$labelList item=label}
<li>
<label>
- <input type="checkbox"{if $label->labelID|in_array:$assignedLabels} checked="checked"{/if} data-label-id="{@$label->labelID}" />
+ <input type="checkbox"{if $label->labelID|in_array:$assignedLabels} checked{/if} data-label-id="{@$label->labelID}">
<span class="badge label{if $label->cssClassName} {@$label->cssClassName}{/if}">{$label->label}</span>
</label>
</li>
{/foreach}
</ul>
-</fieldset>
+</section>
<div class="formSubmit">
<button class="buttonPrimary" id="assignLabels">{lang}wcf.global.button.save{/lang}</button>
{hascontent}
- <fieldset>
- <legend>{lang}wcf.conversation.label.management.existingLabels{/lang}</legend>
- </fieldset>
-
- <ul class="conversationLabelList">
- {content}
- {foreach from=$labelList item=label}
- <li><a class="badge label{if $label->cssClassName} {@$label->cssClassName}{/if}" data-label-id="{@$label->labelID}" data-css-class-name="{if $label->cssClassName}{@$label->cssClassName}{else}none{/if}">{$label->label}</a></li>
- {/foreach}
- {/content}
- </ul>
-
- <small>{lang}wcf.conversation.label.management.edit.description{/lang}</small>
+ <section class="section">
+ <header class="sectionHeader">
+ <h2 class="sectionTitle">{lang}wcf.conversation.label.management.existingLabels{/lang}</h2>
+ <p class="sectionDescription">{lang}wcf.conversation.label.management.edit.description{/lang}</p>
+ </header>
+ <ul class="conversationLabelList">
+ {content}
+ {foreach from=$labelList item=label}
+ <li><a class="badge label{if $label->cssClassName} {@$label->cssClassName}{/if}" data-label-id="{@$label->labelID}" data-css-class-name="{if $label->cssClassName}{@$label->cssClassName}{else}none{/if}">{$label->label}</a></li>
+ {/foreach}
+ {/content}
+ </ul>
+ </section>
{/hascontent}
-<fieldset id="conversationLabelManagementForm">
- <legend>{lang}wcf.conversation.label.management.addLabel{/lang}</legend>
+<section class="section" id="conversationLabelManagementForm">
+ <h2 class="sectionTitle">{lang}wcf.conversation.label.management.addLabel{/lang}</h2>
<dl>
<dt><label for="labelName">{lang}wcf.conversation.label.labelName{/lang}</label></dt>
- <dd><input type="text" id="labelName" class="long" /></dd>
+ <dd><input type="text" id="labelName" class="long"></dd>
</dl>
<dl>
<dt>{lang}wcf.conversation.label.cssClassName{/lang}</dt>
<ul id="labelManagementList">
{foreach from=$cssClassNames item=cssClassName}
<li><label>
- <input type="radio" name="cssClassName" value="{@$cssClassName}"{if $cssClassName == 'none'} checked="checked"{/if} />
+ <input type="radio" name="cssClassName" value="{@$cssClassName}"{if $cssClassName == 'none'} checked{/if}>
<span class="badge label{if $cssClassName != 'none'} {@$cssClassName}{/if}">{lang}wcf.conversation.label.placeholder{/lang}</span>
</label></li>
{/foreach}
<button id="editLabel" style="display: none;" class="buttonPrimary">{lang}wcf.global.button.save{/lang}</button>
<button id="deleteLabel" style="display: none;">{lang}wcf.conversation.label.management.deleteLabel{/lang}</button>
</div>
-</fieldset>
\ No newline at end of file
+</section>
\ No newline at end of file
-<fieldset>
- <legend>{lang}wcf.conversation.hideConversation{/lang}</legend>
+<section class="section">
+ <h2 class="sectionTitle">{lang}wcf.conversation.hideConversation{/lang}</h2>
<dl class="wide">
{if $hideConversation == 1}
<dd>
- <label><input type="radio" name="hideConversation" value="0" /> {lang}wcf.conversation.hideConversation.restore{/lang}</label>
+ <label><input type="radio" name="hideConversation" value="0"> {lang}wcf.conversation.hideConversation.restore{/lang}</label>
</dd>
{/if}
{if $hideConversation != 1}
<dd>
- <label><input type="radio" name="hideConversation" value="1" /> {lang}wcf.conversation.hideConversation.leave{/lang}</label>
+ <label><input type="radio" name="hideConversation" value="1"> {lang}wcf.conversation.hideConversation.leave{/lang}</label>
<small>{lang}wcf.conversation.hideConversation.leave.description{/lang}</small>
</dd>
{/if}
<dd>
- <label><input type="radio" name="hideConversation" value="2" /> {lang}wcf.conversation.hideConversation.leavePermanently{/lang}</label>
+ <label><input type="radio" name="hideConversation" value="2"> {lang}wcf.conversation.hideConversation.leavePermanently{/lang}</label>
<small>{lang}wcf.conversation.hideConversation.leavePermanently.description{/lang}</small>
</dd>
</dl>
-</fieldset>
+</section>
<div class="formSubmit">
<button id="hideConversation" class="buttonPrimary">{lang}wcf.global.button.submit{/lang}</button>
-{include file='documentHeader'}
+{capture assign='pageTitle'}{if $filter}{lang}wcf.conversation.folder.{$filter}{/lang}{else}{$__wcf->getActivePage()->getTitle()}{/if}{if $pageNo > 1} - {lang}wcf.page.pageNo{/lang}{/if}{/capture}
-<head>
- <title>{lang}wcf.conversation.conversations{/lang} {if $pageNo > 1}- {lang}wcf.page.pageNo{/lang} {/if}- {PAGE_TITLE|language}</title>
-
- {include file='headInclude'}
-
- <link rel="alternate" type="application/rss+xml" title="{lang}wcf.global.button.rss{/lang}" href="{link controller='ConversationFeed' appendSession=false}at={@$__wcf->getUser()->userID}-{@$__wcf->getUser()->accessToken}{/link}" />
- <script data-relocate="true" src="{@$__wcf->getPath()}js/WCF.Conversation{if !ENABLE_DEBUG_MODE}.min{/if}.js?v={@LAST_UPDATE_TIME}"></script>
- <script data-relocate="true">
- //<![CDATA[
- $(function() {
- WCF.Language.addObject({
- 'wcf.conversation.edit.addParticipants': '{lang}wcf.conversation.edit.addParticipants{/lang}',
- 'wcf.conversation.edit.assignLabel': '{lang}wcf.conversation.edit.assignLabel{/lang}',
- 'wcf.conversation.edit.close': '{lang}wcf.conversation.edit.close{/lang}',
- 'wcf.conversation.edit.leave': '{lang}wcf.conversation.edit.leave{/lang}',
- 'wcf.conversation.edit.open': '{lang}wcf.conversation.edit.open{/lang}',
- 'wcf.conversation.label.management': '{lang}wcf.conversation.label.management{/lang}',
- 'wcf.conversation.label.management.addLabel.success': '{lang}wcf.conversation.label.management.addLabel.success{/lang}',
- 'wcf.conversation.label.management.deleteLabel.confirmMessage': '{lang}wcf.conversation.label.management.deleteLabel.confirmMessage{/lang}',
- 'wcf.conversation.label.management.editLabel': '{lang}wcf.conversation.label.management.editLabel{/lang}',
- 'wcf.conversation.label.placeholder': '{lang}wcf.conversation.label.placeholder{/lang}',
- 'wcf.conversation.leave.title': '{lang}wcf.conversation.leave.title{/lang}',
- 'wcf.global.state.closed': '{lang}wcf.global.state.closed{/lang}',
- 'wcf.conversation.label.assignLabels': '{lang}wcf.conversation.label.assignLabels{/lang}'
- });
-
- WCF.Clipboard.init('wcf\\page\\ConversationListPage', {@$hasMarkedItems}, { });
-
- var $editorHandler = new WCF.Conversation.EditorHandler();
- var $inlineEditor = new WCF.Conversation.InlineEditor('.conversation');
- $inlineEditor.setEditorHandler($editorHandler, 'list');
-
- new WCF.Conversation.Clipboard($editorHandler);
- new WCF.Conversation.Label.Manager('{link controller='ConversationList' encode=false}{if $filter}filter={@$filter}{/if}&sortField={$sortField}&sortOrder={$sortOrder}&pageNo={@$pageNo}{/link}');
- new WCF.Conversation.Preview();
- new WCF.Conversation.MarkAsRead();
- new WCF.Conversation.MarkAllAsRead();
-
- // mobile safari hover workaround
- if ($(window).width() <= 800) {
- $('.sidebar').addClass('mobileSidebar').hover(function() { });
- }
- });
- //]]>
- </script>
-</head>
-
-<body id="tpl{$templateName|ucfirst}" data-template="{$templateName}" data-application="{$templateNameApplication}">
-
-{capture assign='sidebar'}
- <fieldset>
- <legend>{lang}wcf.conversation.folders{/lang}</legend>
+{capture assign='contentHeader'}
+ <header class="contentHeader">
+ <div class="contentHeaderTitle">
+ <h1 class="contentTitle">{if $filter}{lang}wcf.conversation.folder.{$filter}{/lang}{else}{$__wcf->getActivePage()->getTitle()}{/if}</h1>
+ </div>
- <nav>
- <ul class="conversationFolderList">
- <li{if $filter == ''} class="active"{/if}><a href="{link controller='ConversationList'}{/link}">{lang}wcf.conversation.conversations{/lang}{if $conversationCount} <span class="badge">{#$conversationCount}</span>{/if}</a></li>
- <li{if $filter == 'draft'} class="active"{/if}><a href="{link controller='ConversationList'}filter=draft{/link}">{lang}wcf.conversation.folder.draft{/lang}{if $draftCount} <span class="badge">{#$draftCount}</span>{/if}</a></li>
- <li{if $filter == 'outbox'} class="active"{/if}><a href="{link controller='ConversationList'}filter=outbox{/link}">{lang}wcf.conversation.folder.outbox{/lang}{if $outboxCount} <span class="badge">{#$outboxCount}</span>{/if}</a></li>
- <li{if $filter == 'hidden'} class="active"{/if}><a href="{link controller='ConversationList'}filter=hidden{/link}">{lang}wcf.conversation.folder.hidden{/lang}{if $hiddenCount} <span class="badge">{#$hiddenCount}</span>{/if}</a></li>
+ <nav class="contentHeaderNavigation">
+ <ul>
+ <li><a href="{link controller='ConversationAdd'}{/link}" title="{lang}wcf.conversation.add{/lang}" class="button"><span class="icon icon16 fa-plus"></span> <span>{lang}wcf.conversation.button.add{/lang}</span></a></li>
+ {event name='contentHeaderNavigation'}
</ul>
</nav>
- </fieldset>
+ </header>
+{/capture}
+
+{capture assign='headContent'}
+ <link rel="alternate" type="application/rss+xml" title="{lang}wcf.global.button.rss{/lang}" href="{link controller='ConversationFeed'}at={@$__wcf->getUser()->userID}-{@$__wcf->getUser()->accessToken}{/link}">
+{/capture}
+
+{capture assign='sidebarRight'}
+ <section class="box">
+ <h2 class="boxTitle">{lang}wcf.conversation.folders{/lang}</h2>
+
+ <div class="boxContent">
+ <nav>
+ <ol class="boxMenu">
+ <li{if $filter == ''} class="active"{/if}>
+ <a class="boxMenuLink" href="{link controller='ConversationList'}{/link}"><span class="boxMenuLinkTitle">{lang}wcf.conversation.conversations{/lang}</span>{if $conversationCount} <span class="badge">{#$conversationCount}</span>{/if}</a>
+ </li>
+ <li{if $filter == 'draft'} class="active"{/if}>
+ <a class="boxMenuLink" href="{link controller='ConversationList'}filter=draft{/link}"><span class="boxMenuLinkTitle">{lang}wcf.conversation.folder.draft{/lang}</span>{if $draftCount} <span class="badge">{#$draftCount}</span>{/if}</a>
+ </li>
+ <li{if $filter == 'outbox'} class="active"{/if}>
+ <a class="boxMenuLink" href="{link controller='ConversationList'}filter=outbox{/link}"><span class="boxMenuLinkTitle">{lang}wcf.conversation.folder.outbox{/lang}</span>{if $outboxCount} <span class="badge">{#$outboxCount}</span>{/if}</a>
+ </li>
+ <li{if $filter == 'hidden'} class="active"{/if}>
+ <a class="boxMenuLink" href="{link controller='ConversationList'}filter=hidden{/link}"><span class="boxMenuLinkTitle">{lang}wcf.conversation.folder.hidden{/lang}</span>{if $hiddenCount} <span class="badge">{#$hiddenCount}</span>{/if}</a>
+ </li>
+ </ol>
+ </nav>
+ </div>
+ </section>
- <fieldset class="jsOnly">
- <legend>{lang}wcf.conversation.label{/lang}</legend>
+ <section class="box">
+ <h2 class="boxTitle">{lang}wcf.conversation.filter.participants{/lang}</h2>
- <div id="conversationLabelFilter" class="dropdown">
- <div class="dropdownToggle" data-toggle="conversationLabelFilter">
- {if $labelID}
- {foreach from=$labelList item=label}
- {if $label->labelID == $labelID}
- <span class="badge label{if $label->cssClassName} {@$label->cssClassName}{/if}">{$label->label}</span>
- {/if}
- {/foreach}
- {else}
- <span class="badge">{lang}wcf.conversation.label.filter{/lang}</span>
- {/if}
- </div>
-
- <div class="dropdownMenu">
- <ul class="scrollableDropdownMenu">
- {foreach from=$labelList item=label}
- <li><a href="{link controller='ConversationList'}{if $filter}filter={@$filter}{/if}&sortField={$sortField}&sortOrder={$sortOrder}&pageNo={@$pageNo}&labelID={@$label->labelID}{/link}"><span class="badge label{if $label->cssClassName} {@$label->cssClassName}{/if}" data-css-class-name="{if $label->cssClassName}{@$label->cssClassName}{/if}" data-label-id="{@$label->labelID}">{$label->label}</span></a></li>
- {/foreach}
- </ul>
- <ul>
- <li class="dropdownDivider"{if !$labelList|count} style="display: none;"{/if}></li>
- <li><a href="{link controller='ConversationList'}{if $filter}filter={@$filter}{/if}&sortField={$sortField}&sortOrder={$sortOrder}&pageNo={@$pageNo}{/link}"><span class="badge label">{lang}wcf.conversation.label.disableFilter{/lang}</span></a></li>
- </ul>
+ <div class="boxContent">
+ <form action="{link controller='ConversationList'}{if $filter}filter={@$filter}&{/if}sortField={$sortField}&sortOrder={$sortOrder}&pageNo={@$pageNo}{/link}" method="post">
+ <dl>
+ <dt></dt>
+ <dd><label><textarea id="participants" name="participants" class="long">{implode from=$participants item=participant glue=','}{$participant}{/implode}</textarea></label></dd>
+ </dl>
+
+ <div class="formSubmit">
+ <input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
+ {@SECURITY_TOKEN_INPUT_TAG}
+ </div>
+ </form>
+ </div>
+ </section>
+
+ <section class="box jsOnly">
+ <h2 class="boxTitle">{lang}wcf.conversation.label{/lang}</h2>
+
+ <div class="boxContent">
+ <div id="conversationLabelFilter" class="dropdown">
+ <div class="dropdownToggle" data-toggle="conversationLabelFilter">
+ {if $labelID}
+ {foreach from=$labelList item=label}
+ {if $label->labelID == $labelID}
+ <span class="badge label{if $label->cssClassName} {@$label->cssClassName}{/if}">{$label->label}</span>
+ {/if}
+ {/foreach}
+ {else}
+ <span class="badge">{lang}wcf.conversation.label.filter{/lang}</span>
+ {/if}
+ </div>
+
+ <div class="dropdownMenu">
+ <ul class="scrollableDropdownMenu">
+ {foreach from=$labelList item=label}
+ <li><a href="{link controller='ConversationList'}{if $filter}filter={@$filter}&{/if}{if !$participants|empty}participants={implode from=$participants item=participant}{$participant|rawurlencode}{/implode}&{/if}sortField={$sortField}&sortOrder={$sortOrder}&pageNo={@$pageNo}&labelID={@$label->labelID}{/link}"><span class="badge label{if $label->cssClassName} {@$label->cssClassName}{/if}" data-css-class-name="{if $label->cssClassName}{@$label->cssClassName}{/if}" data-label-id="{@$label->labelID}">{$label->label}</span></a></li>
+ {/foreach}
+ </ul>
+ <ul>
+ <li class="dropdownDivider"{if !$labelList|count} style="display: none;"{/if}></li>
+ <li><a href="{link controller='ConversationList'}{if $filter}filter={@$filter}&{/if}{if !$participants|empty}participants={implode from=$participants item=participant}{$participant|rawurlencode}{/implode}&{/if}sortField={$sortField}&sortOrder={$sortOrder}&pageNo={@$pageNo}{/link}"><span class="badge label">{lang}wcf.conversation.label.disableFilter{/lang}</span></a></li>
+ </ul>
+ </div>
</div>
</div>
- <button id="manageLabel">{lang}wcf.conversation.label.management{/lang}</button>
- </fieldset>
+ <div class="boxContent">
+ <button id="manageLabel">{lang}wcf.conversation.label.management{/lang}</button>
+ </div>
+ </section>
{event name='beforeQuotaBox'}
- <fieldset class="conversationQuota">
- <legend>{lang}wcf.conversation.quota{/lang}</legend>
+ <section class="box conversationQuota">
+ <h2 class="boxTitle">{lang}wcf.conversation.quota{/lang}</h2>
- <div>
+ <div class="boxContent">
{assign var='conversationCount' value=$__wcf->getConversationHandler()->getConversationCount()}
{assign var='maxConversationCount' value=$__wcf->session->getPermission('user.conversation.maxConversations')}
<p class="conversationUsageBar{if $conversationCount/$maxConversationCount >= 1.0} red{elseif $conversationCount/$maxConversationCount > 0.9} yellow{/if}">
</p>
<p><small>{lang}wcf.conversation.quota.description{/lang}</small></p>
</div>
- </fieldset>
+ </section>
{event name='boxes'}
{/capture}
{capture assign='headerNavigation'}
- <li><a rel="alternate" href="{link controller='ConversationFeed' appendSession=false}at={@$__wcf->getUser()->userID}-{@$__wcf->getUser()->accessToken}{/link}" title="{lang}wcf.global.button.rss{/lang}" class="jsTooltip"><span class="icon icon16 icon-rss"></span> <span class="invisible">{lang}wcf.global.button.rss{/lang}</span></a></li>
- <li class="jsOnly"><a href="#" title="{lang}wcf.conversation.markAllAsRead{/lang}" class="markAllAsReadButton jsTooltip"><span class="icon icon16 icon-ok"></span> <span class="invisible">{lang}wcf.conversation.markAllAsRead{/lang}</span></a></li>
+ <li><a rel="alternate" href="{link controller='ConversationFeed'}at={@$__wcf->getUser()->userID}-{@$__wcf->getUser()->accessToken}{/link}" title="{lang}wcf.global.button.rss{/lang}" class="jsTooltip"><span class="icon icon16 fa-rss"></span> <span class="invisible">{lang}wcf.global.button.rss{/lang}</span></a></li>
+ <li class="jsOnly"><a href="#" title="{lang}wcf.conversation.markAllAsRead{/lang}" class="markAllAsReadButton jsTooltip"><span class="icon icon16 fa-check"></span> <span class="invisible">{lang}wcf.conversation.markAllAsRead{/lang}</span></a></li>
{/capture}
-{include file='header' sidebarOrientation='left'}
+{include file='header'}
-<header class="boxHeadline">
- <h1>{if $filter}{lang}wcf.conversation.folder.{$filter}{/lang}{else}{lang}wcf.conversation.conversations{/lang}{/if}</h1>
-</header>
-
-{include file='userNotice'}
-
-<div class="contentNavigation">
- {assign var='labelIDParameter' value=''}
- {if $labelID}{assign var='labelIDParameter' value="&labelID=$labelID"}{/if}
- {pages print=true assign=pagesLinks controller='ConversationList' link="filter=$filter&pageNo=%d&sortField=$sortField&sortOrder=$sortOrder$labelIDParameter"}
-
- <nav>
- <ul>
- <li><a href="{link controller='ConversationAdd'}{/link}" title="{lang}wcf.conversation.add{/lang}" class="button"><span class="icon icon16 icon-asterisk"></span> <span>{lang}wcf.conversation.button.add{/lang}</span></a></li>
- {event name='contentNavigationButtonsTop'}
- </ul>
- </nav>
-</div>
+{hascontent}
+ <div class="paginationTop">
+ {content}
+ {assign var='participantsParameter' value=''}
+ {if $participants}{capture assign='participantsParameter'}&participants={implode from=$participants item=participant}{$participant|rawurlencode}{/implode}{/capture}{/if}
+ {assign var='labelIDParameter' value=''}
+ {if $labelID}{assign var='labelIDParameter' value="&labelID=$labelID"}{/if}
+ {pages print=true assign=pagesLinks controller='ConversationList' link="filter=$filter$participantsParameter&pageNo=%d&sortField=$sortField&sortOrder=$sortOrder$labelIDParameter"}
+ {/content}
+ </div>
+{/hascontent}
{if !$items}
<p class="info">{lang}wcf.conversation.noConversations{/lang}</p>
{else}
- <div class="marginTop tabularBox tabularBoxTitle messageGroupList conversationList jsClipboardContainer" data-type="com.woltlab.wcf.conversation.conversation">
- <header>
- <h2>{lang}wcf.conversation.conversations{/lang} <span class="badge badgeInverse">{#$items}</span></h2>
- </header>
-
- <table class="table">
- <thead>
- <tr>
- <th class="columnMark jsOnly"><label><input type="checkbox" class="jsClipboardMarkAll" /></label></th>
- <th colspan="2" class="columnTitle columnSubject{if $sortField == 'subject'} active {@$sortOrder}{/if}"><a href="{link controller='ConversationList'}{if $filter}filter={@$filter}&{/if}pageNo={@$pageNo}&sortField=subject&sortOrder={if $sortField == 'subject' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{if $labelID}&labelID={@$labelID}{/if}{/link}">{lang}wcf.global.subject{/lang}</a></th>
- <th class="columnDigits columnReplies{if $sortField == 'replies'} active {@$sortOrder}{/if}"><a href="{link controller='ConversationList'}{if $filter}filter={@$filter}&{/if}pageNo={@$pageNo}&sortField=replies&sortOrder={if $sortField == 'replies' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{if $labelID}&labelID={@$labelID}{/if}{/link}">{lang}wcf.conversation.replies{/lang}</a></th>
- <th class="columnDigits columnParticipants{if $sortField == 'participants'} active {@$sortOrder}{/if}"><a href="{link controller='ConversationList'}{if $filter}filter={@$filter}&{/if}pageNo={@$pageNo}&sortField=participants&sortOrder={if $sortField == 'participants' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{if $labelID}&labelID={@$labelID}{/if}{/link}">{lang}wcf.conversation.participants{/lang}</a></th>
- <th class="columnText columnLastPost{if $sortField == 'lastPostTime'} active {@$sortOrder}{/if}"><a href="{link controller='ConversationList'}{if $filter}filter={@$filter}&{/if}pageNo={@$pageNo}&sortField=lastPostTime&sortOrder={if $sortField == 'lastPostTime' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{if $labelID}&labelID={@$labelID}{/if}{/link}">{lang}wcf.conversation.lastPostTime{/lang}</a></th>
+ <div class="section tabularBox messageGroupList conversationList jsClipboardContainer" data-type="com.woltlab.wcf.conversation.conversation">
+ <ol class="tabularList">
+ <li class="tabularListRow tabularListRowHead">
+ <ol class="tabularListColumns">
+ <li class="columnMark jsOnly"><label><input type="checkbox" class="jsClipboardMarkAll"></label></li>
+ <li class="columnSubject{if $sortField === 'subject'} active {@$sortOrder}{/if}"><a href="{link controller='ConversationList'}{if $filter}filter={@$filter}&{/if}{if !$participants|empty}participants={implode from=$participants item=participant}{$participant|rawurlencode}{/implode}&{/if}pageNo={@$pageNo}&sortField=subject&sortOrder={if $sortField == 'subject' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{if $labelID}&labelID={@$labelID}{/if}{/link}">{lang}wcf.global.subject{/lang}</a></li>
+ <li class="columnStats{if $sortField == 'replies'} active {@$sortOrder}{/if}"><a href="{link controller='ConversationList'}{if $filter}filter={@$filter}&{/if}{if !$participants|empty}participants={implode from=$participants item=participant}{$participant|rawurlencode}{/implode}&{/if}pageNo={@$pageNo}&sortField=replies&sortOrder={if $sortField == 'replies' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{if $labelID}&labelID={@$labelID}{/if}{/link}">{lang}wcf.conversation.replies{/lang}</a></li>
+ <li class="columnLastPost{if $sortField === 'lastPostTime'} active {@$sortOrder}{/if}"><a href="{link controller='ConversationList'}{if $filter}filter={@$filter}&{/if}{if !$participants|empty}participants={implode from=$participants item=participant}{$participant|rawurlencode}{/implode}&{/if}pageNo={@$pageNo}&sortField=lastPostTime&sortOrder={if $sortField == 'lastPostTime' && $sortOrder == 'ASC'}DESC{else}ASC{/if}{if $labelID}&labelID={@$labelID}{/if}{/link}">{lang}wcf.conversation.lastPostTime{/lang}</a></li>
{event name='columnHeads'}
- </tr>
- </thead>
+ </ol>
+ </li>
- <tbody>
- {foreach from=$objects item=conversation}
- <tr class="conversation jsClipboardObject{if $conversation->isNew()} new{/if}" data-conversation-id="{@$conversation->conversationID}" data-label-ids="[ {implode from=$conversation->getAssignedLabels() item=label}{@$label->labelID}{/implode} ]" data-is-closed="{@$conversation->isClosed}" data-can-close-conversation="{if $conversation->userID == $__wcf->getUser()->userID}1{else}0{/if}" data-can-add-participants="{if $conversation->canAddParticipants()}1{else}0{/if}">
- <td class="columnMark jsOnly">
- <label><input type="checkbox" class="jsClipboardItem" data-object-id="{@$conversation->conversationID}" /></label>
- </td>
- <td class="columnIcon columnAvatar">
+ {foreach from=$objects item=conversation}
+ <li class="tabularListRow">
+ <ol class="tabularListColumns messageGroup conversation jsClipboardObject{if $conversation->isNew()} new{/if}" data-conversation-id="{@$conversation->conversationID}" data-label-ids="[ {implode from=$conversation->getAssignedLabels() item=label}{@$label->labelID}{/implode} ]" data-is-closed="{@$conversation->isClosed}" data-can-close-conversation="{if $conversation->userID == $__wcf->getUser()->userID}1{else}0{/if}" data-can-add-participants="{if $conversation->canAddParticipants()}1{else}0{/if}">
+ <li class="columnMark jsOnly">
+ <label><input type="checkbox" class="jsClipboardItem" data-object-id="{@$conversation->conversationID}"></label>
+ </li>
+ <li class="columnIcon columnAvatar">
{if $conversation->getUserProfile()->getAvatar()}
<div>
- <p class="framed"{if $conversation->isNew()} title="{lang}wcf.conversation.markAsRead.doubleClick{/lang}"{/if}>{@$conversation->getUserProfile()->getAvatar()->getImageTag(32)}</p>
+ <p{if $conversation->isNew()} title="{lang}wcf.conversation.markAsRead.doubleClick{/lang}"{/if}>{@$conversation->getUserProfile()->getAvatar()->getImageTag(48)}</p>
{if $conversation->ownPosts && $conversation->userID != $__wcf->user->userID}
{if $__wcf->getUserProfileHandler()->getAvatar()}
- <small class="framed myAvatar" title="{lang}wcf.conversation.ownPosts{/lang}">{@$__wcf->getUserProfileHandler()->getAvatar()->getImageTag(16)}</small>
+ <small class="myAvatar jsTooltip" title="{lang}wcf.conversation.ownPosts{/lang}">{@$__wcf->getUserProfileHandler()->getAvatar()->getImageTag(24)}</small>
{/if}
{/if}
</div>
{/if}
- </td>
- <td class="columnText columnSubject">
+ </li>
+ <li class="columnSubject">
{hascontent}
<ul class="labelList">
{content}
{foreach from=$conversation->getAssignedLabels() item=label}
- <li><a href="{link controller='ConversationList'}{if $filter}filter={@$filter}{/if}&sortField={$sortField}&sortOrder={$sortOrder}&pageNo={@$pageNo}&labelID={@$label->labelID}{/link}" class="badge label{if $label->cssClassName} {@$label->cssClassName}{/if}">{$label->label}</a></li>
+ <li><a href="{link controller='ConversationList'}{if $filter}filter={@$filter}&{/if}{if !$participants|empty}participants={implode from=$participants item=participant}{$participant|rawurlencode}{/implode}&{/if}sortField={$sortField}&sortOrder={$sortOrder}&pageNo={@$pageNo}&labelID={@$label->labelID}{/link}" class="badge label{if $label->cssClassName} {@$label->cssClassName}{/if}">{$label->label}</a></li>
{/foreach}
{/content}
</ul>
{/hascontent}
<h3>
- <a href="{if $conversation->isNew()}{link controller='Conversation' object=$conversation}action=firstNew{/link}{else}{link controller='Conversation' object=$conversation}{/link}{/if}" class="conversationLink messageGroupLink" data-conversation-id="{@$conversation->conversationID}">{$conversation->subject|tableWordwrap}</a>
+ <a href="{if $conversation->isNew()}{link controller='Conversation' object=$conversation}action=firstNew{/link}{else}{link controller='Conversation' object=$conversation}{/link}{/if}" class="conversationLink messageGroupLink" data-conversation-id="{@$conversation->conversationID}">{$conversation->subject}</a>
+ {if $conversation->replies}
+ <span class="badge messageGroupCounterMobile">{@$conversation->replies|shortUnit}</span>
+ {/if}
</h3>
<aside class="statusDisplay">
{smallpages pages=$conversation->getPages() controller='Conversation' object=$conversation link='pageNo=%d'}
<ul class="statusIcons">
- {if $conversation->isClosed}<li><span class="icon icon16 icon-lock jsIconLock jsTooltip" title="{lang}wcf.global.state.closed{/lang}"></span></li>{/if}
- {if $conversation->attachments}<li><span class="icon icon16 icon-paper-clip jsIconAttachment jsTooltip" title="{lang}wcf.conversation.attachments{/lang}"></span></li>{/if}
+ {if $conversation->isClosed}<li><span class="icon icon16 fa-lock jsIconLock jsTooltip" title="{lang}wcf.global.state.closed{/lang}"></span></li>{/if}
+ {if $conversation->attachments}<li><span class="icon icon16 fa-paperclip jsIconAttachment jsTooltip" title="{lang}wcf.conversation.attachments{/lang}"></span></li>{/if}
</ul>
</aside>
- <ul class="messageGroupInfo mobileOptimization">
+ <ul class="inlineList dotSeparated small messageGroupInfo">
<li class="messageGroupAuthor">{if $conversation->userID}<a href="{link controller='User' object=$conversation->getUserProfile()->getDecoratedObject()}{/link}" class="userLink" data-user-id="{@$conversation->userID}">{$conversation->username}</a>{else}{$conversation->username}{/if}</li>
<li class="messageGroupTime">{@$conversation->time|time}</li>
- <li class="messageGroupLastPoster">{if $conversation->lastPosterID}<a href="{link controller='User' object=$conversation->getLastPosterProfile()->getDecoratedObject()}{/link}" class="userLink" data-user-id="{@$conversation->getLastPosterProfile()->userID}">{$conversation->lastPoster}</a>{else}{$conversation->lastPoster}{/if}</li>
- <li class="messageGroupLastPostTime">{@$conversation->lastPostTime|time}</li>
<li class="messageGroupEditLink jsOnly"><a class="jsConversationInlineEditor">{lang}wcf.global.button.edit{/lang}</a></li>
{event name='messageGroupInfo'}
</ul>
+ <ul class="messageGroupInfoMobile">
+ <li class="messageGroupAuthorMobile">{$conversation->username}</li>
+ <li class="messageGroupLastPostTimeMobile">{@$conversation->lastPostTime|time}</li>
+ </ul>
+
{if $conversation->getParticipantSummary()|count}
<small class="conversationParticipantSummary">
{assign var='participantSummaryCount' value=$conversation->getParticipantSummary()|count}
{/if}
{event name='conversationData'}
- </td>
- <td class="columnDigits columnReplies">{#$conversation->replies}</td>
- <td class="columnDigits columnParticipants">{#$conversation->participants}</td>
- <td class="columnText columnLastPost">
+ </li>
+ <li class="columnStats">
+ <dl class="plain statsDataList">
+ <dt>{lang}wcf.conversation.replies{/lang}</dt>
+ <dd>{@$conversation->replies|shortUnit}</dd>
+ </dl>
+ <dl class="plain statsDataList">
+ <dt>{lang}wcf.conversation.participants{/lang}</dt>
+ <dd>{@$conversation->participants|shortUnit}</dd>
+ </dl>
+
+ <div class="messageGroupListStatsSimple">{@$conversation->replies|shortUnit}</div>
+ </li>
+ <li class="columnLastPost">
{if $conversation->replies != 0}
- <div class="box24">
- <a href="{link controller='Conversation' object=$conversation}action=lastPost{/link}" class="framed jsTooltip" title="{lang}wcf.conversation.gotoLastPost{/lang}">{@$conversation->getLastPosterProfile()->getAvatar()->getImageTag(24)}</a>
+ <div class="box32">
+ <a href="{link controller='Conversation' object=$conversation}action=lastPost{/link}" class="jsTooltip" title="{lang}wcf.conversation.gotoLastPost{/lang}">{@$conversation->getLastPosterProfile()->getAvatar()->getImageTag(32)}</a>
<div>
<p>
</div>
</div>
{/if}
- </td>
+ </li>
{event name='columns'}
- </tr>
- {/foreach}
- </tbody>
- </table>
+ </ol>
+ </li>
+ {/foreach}
+ </ol>
</div>
{/if}
-<div class="contentNavigation">
- {@$pagesLinks}
+<footer class="contentFooter">
+ {hascontent}
+ <div class="paginationBottom">
+ {content}{@$pagesLinks}{/content}
+ </div>
+ {/hascontent}
- <nav>
+ <nav class="contentFooterNavigation">
<ul>
- <li><a href="{link controller='ConversationAdd'}{/link}" title="{lang}wcf.conversation.add{/lang}" class="button"><span class="icon icon16 icon-asterisk"></span> <span>{lang}wcf.conversation.button.add{/lang}</span></a></li>
- {event name='contentNavigationButtonsTop'}
+ <li><a href="{link controller='ConversationAdd'}{/link}" title="{lang}wcf.conversation.add{/lang}" class="button"><span class="icon icon16 fa-plus"></span> <span>{lang}wcf.conversation.button.add{/lang}</span></a></li>
+ {event name='contentFooterNavigation'}
</ul>
</nav>
-
- <nav class="jsClipboardEditor" data-types="[ 'com.woltlab.wcf.conversation.conversation' ]"></nav>
-</div>
+</footer>
-{include file='footer'}
+<script data-relocate="true" src="{@$__wcf->getPath()}js/WCF.Conversation{if !ENABLE_DEBUG_MODE}.min{/if}.js?v={@LAST_UPDATE_TIME}"></script>
+<script data-relocate="true">
+ require(['Language', 'WoltLabSuite/Core/Ui/ItemList/User'], function(Language, UiItemListUser) {
+ Language.addObject({
+ 'wcf.conversation.edit.addParticipants': '{lang}wcf.conversation.edit.addParticipants{/lang}',
+ 'wcf.conversation.edit.assignLabel': '{lang}wcf.conversation.edit.assignLabel{/lang}',
+ 'wcf.conversation.edit.close': '{lang}wcf.conversation.edit.close{/lang}',
+ 'wcf.conversation.edit.leave': '{lang}wcf.conversation.edit.leave{/lang}',
+ 'wcf.conversation.edit.open': '{lang}wcf.conversation.edit.open{/lang}',
+ 'wcf.conversation.label.management': '{lang}wcf.conversation.label.management{/lang}',
+ 'wcf.conversation.label.management.addLabel.success': '{lang}wcf.conversation.label.management.addLabel.success{/lang}',
+ 'wcf.conversation.label.management.deleteLabel.confirmMessage': '{lang}wcf.conversation.label.management.deleteLabel.confirmMessage{/lang}',
+ 'wcf.conversation.label.management.editLabel': '{lang}wcf.conversation.label.management.editLabel{/lang}',
+ 'wcf.conversation.label.placeholder': '{lang}wcf.conversation.label.placeholder{/lang}',
+ 'wcf.conversation.leave.title': '{lang}wcf.conversation.leave.title{/lang}',
+ 'wcf.global.state.closed': '{lang}wcf.global.state.closed{/lang}',
+ 'wcf.conversation.label.assignLabels': '{lang}wcf.conversation.label.assignLabels{/lang}'
+ });
+
+ WCF.Clipboard.init('wcf\\page\\ConversationListPage', {@$hasMarkedItems}, { });
+
+ var $editorHandler = new WCF.Conversation.EditorHandler();
+ var $inlineEditor = new WCF.Conversation.InlineEditor('.conversation');
+ $inlineEditor.setEditorHandler($editorHandler, 'list');
+
+ new WCF.Conversation.Clipboard($editorHandler);
+ new WCF.Conversation.Label.Manager('{link controller='ConversationList' encode=false}{if $filter}filter={@$filter}&{/if}{if !$participants|empty}participants={implode from=$participants item=participant}{$participant|rawurlencode}{/implode}&{/if}sortField={$sortField}&sortOrder={$sortOrder}&pageNo={@$pageNo}{/link}');
+ new WCF.Conversation.Preview();
+ new WCF.Conversation.MarkAsRead();
+ new WCF.Conversation.MarkAllAsRead();
+
+ // mobile safari hover workaround
+ if ($(window).width() <= 800) {
+ $('.sidebar').addClass('mobileSidebar').hover(function() { });
+ }
+
+ UiItemListUser.init('participants', {
+ excludedSearchValues: ['{$__wcf->user->username|encodeJS}']
+ });
+ });
+</script>
-</body>
-</html>
+{include file='footer'}
{foreach from=$conversations item=conversation}
<li class="conversationItem{if $conversation->lastVisitTime < $conversation->lastPostTime} conversationItemUnread interactiveDropdownItemOutstanding{/if}" data-link="{link controller='Conversation' object=$conversation}action=firstNew{/link}" data-object-id="{@$conversation->conversationID}" data-is-read="{if $conversation->lastVisitTime < $conversation->lastPostTime}false{else}true{/if}">
- <div class="box32">
- <div class="framed">
- {if $conversation->lastPosterID}
- {@$conversation->getLastPosterProfile()->getAvatar()->getImageTag(32)}
+ <div class="box48">
+ <div>
+ {if $conversation->userID == $__wcf->user->userID}
+ {if $conversation->participants > 1}
+ <span class="icon icon48 fa-users"></span>
+ {else}
+ {@$conversation->getOtherParticipantProfile()->getAvatar()->getImageTag(48)}
+ {/if}
{else}
- {@$conversation->getUserProfile()->getAvatar()->getImageTag(32)}
+ {@$conversation->getUserProfile()->getAvatar()->getImageTag(48)}
{/if}
</div>
<div>
<h3><a href="{link controller='Conversation' object=$conversation}action=firstNew{/link}">{$conversation->subject}</a></h3>
- <small>{if $conversation->lastPosterID}<a href="{link controller='User' id=$conversation->lastPosterID title=$conversation->lastPoster}{/link}">{$conversation->lastPoster}</a>{else}{$conversation->username}{/if} - {@$conversation->lastPostTime|time}</small>
+ <small class="conversationInfo">
+ <span class="conversationParticipant">
+ {if $conversation->userID == $__wcf->user->userID}
+ {if $conversation->participants > 1}
+ {assign var='participantSummaryCount' value=$conversation->getParticipantSummary()|count}
+ {implode from=$conversation->getParticipantSummary() item=participant}<a href="{link controller='User' object=$participant}{/link}" class="userLink{if $participant->hideConversation == 2} conversationLeft{/if}" data-user-id="{@$participant->userID}">{$participant->username}</a>{/implode}
+ {if $participantSummaryCount < $conversation->participants}{lang}wcf.conversation.participants.other{/lang}{/if}
+ {else}
+ {if $conversation->getOtherParticipantProfile()->userID}<a href="{link controller='User' id=$conversation->getOtherParticipantProfile()->userID title=$conversation->getOtherParticipantProfile()->username}{/link}">{$conversation->getOtherParticipantProfile()->username}</a>{else}{$conversation->getOtherParticipantProfile()->username}{/if}
+ {/if}
+ {else}
+ {if $conversation->userID}<a href="{link controller='User' id=$conversation->userID title=$conversation->username}{/link}">{$conversation->username}</a>{else}{$conversation->username}{/if}
+ {/if}
+ </span>
+
+ <span class="conversationLastPostTime">{@$conversation->lastPostTime|time}</span>
+ </small>
</div>
</div>
</li>
-{/foreach}
\ No newline at end of file
+{/foreach}
+++ /dev/null
-{include file='documentHeader'}
-
-<head>
- <title>{lang}wcf.conversation.message.add{/lang} - {$conversation->subject} - {PAGE_TITLE|language}</title>
-
- {include file='headInclude'}
-
- <script data-relocate="true" src="{@$__wcf->getPath()}js/WCF.Conversation{if !ENABLE_DEBUG_MODE}.min{/if}.js?v={@LAST_UPDATE_TIME}"></script>
- <script data-relocate="true">
- //<![CDATA[
- $(function() {
- WCF.Language.addObject({
- 'wcf.message.bbcode.code.copy': '{lang}wcf.message.bbcode.code.copy{/lang}'
- });
-
- {include file='__messageQuoteManager' wysiwygSelector='text' supportPaste=true}
- new WCF.Conversation.Message.QuoteHandler($quoteManager);
-
- WCF.Message.Submit.registerButton('text', $('#messageContainer > .formSubmit > input[type=submit]'));
- new WCF.Message.FormGuard();
- new WCF.Message.BBCode.CodeViewer();
-
- WCF.System.Dependency.Manager.register('CKEditor', function() { new WCF.Message.UserMention('text'); });
- });
- //]]>
- </script>
-</head>
-
-<body id="tpl{$templateName|ucfirst}" data-template="{$templateName}" data-application="{$templateNameApplication}">
-{include file='header'}
-
-<header class="boxHeadline">
- <h1>{lang}wcf.conversation.message.add{/lang}</h1>
-</header>
-
-{include file='userNotice'}
-
-{if !$conversation->isDraft && !$conversation->hasOtherParticipants()}
- <p class="warning">{lang}wcf.conversation.noParticipantsWarning{/lang}</p>
-{/if}
-
-{include file='formError'}
-
-<form id="messageContainer" class="jsFormGuard" method="post" action="{link controller='ConversationMessageAdd' id=$conversationID}{/link}">
- <div class="container containerPadding marginTop">
- <fieldset>
- <legend>{lang}wcf.conversation.message{/lang}</legend>
-
- <dl class="wide{if $errorField == 'text'} formError{/if}">
- <dt><label for="text">{lang}wcf.conversation.message{/lang}</label></dt>
- <dd>
- <textarea id="text" name="text" rows="20" cols="40" data-autosave="com.woltlab.wcf.conversation.messageAdd-{@$conversation->conversationID}">{$text}</textarea>
- {if $errorField == 'text'}
- <small class="innerError">
- {if $errorType == 'empty'}
- {lang}wcf.global.form.error.empty{/lang}
- {elseif $errorType == 'tooLong'}
- {lang}wcf.message.error.tooLong{/lang}
- {elseif $errorType == 'censoredWordsFound'}
- {lang}wcf.message.error.censoredWordsFound{/lang}
- {elseif $errorType == 'disallowedBBCodes'}
- {lang}wcf.message.error.disallowedBBCodes{/lang}
- {else}
- {lang}wcf.conversation.message.error.{@$errorType}{/lang}
- {/if}
- </small>
- {/if}
- </dd>
- </dl>
-
- {event name='messageFields'}
- </fieldset>
-
- {include file='messageFormTabs' wysiwygContainerID='text'}
-
- {event name='fieldsets'}
- </div>
-
- <div class="formSubmit">
- <input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s" />
- {include file='messageFormPreviewButton'}
- {@SECURITY_TOKEN_INPUT_TAG}
- </div>
-</form>
-
-<header class="boxHeadline boxSubHeadline">
- <h2>{lang}wcf.conversation.message.add.previousPosts{/lang}{if $items != 1} <span class="badge">{#$items}</span>{/if}</h2>
-</header>
-
-<div>
- <ul class="messageList">
- {foreach from=$messages item=message}
- {assign var='objectID' value=$message->messageID}
-
- <li class="marginTop">
- <article class="message messageReduced{if $message->getUserProfile()->userOnlineGroupID} userOnlineGroupMarking{@$message->getUserProfile()->userOnlineGroupID}{/if}" data-object-id="{@$message->messageID}">
- <div>
- <section class="messageContent">
- <div>
- <header class="messageHeader">
- <div class="box32">
- <a href="{link controller='User' object=$message->getUserProfile()}{/link}" class="framed">{@$message->getUserProfile()->getAvatar()->getImageTag(32)}</a>
-
- <div class="messageHeadline">
- <p>
- <span class="username"><a href="{link controller='User' object=$message->getUserProfile()}{/link}" class="userLink" data-user-id="{@$message->userID}">{$message->username}</a></span>
- <a href="{link controller='Conversation' object=$conversation}messageID={@$message->messageID}{/link}#message{@$message->messageID}" class="permalink">{@$message->time|time}</a>
- </p>
- </div>
- </div>
- </header>
-
- <div class="messageBody">
- <div>
- <div class="messageText">
- {@$message->getFormattedMessage()}
- </div>
- </div>
-
- {include file='attachments'}
-
- <footer class="messageOptions">
- <nav class="jsMobileNavigation buttonGroupNavigation">
- <ul class="smallButtons buttonGroup"><li class="toTopLink"><a href="{$__wcf->getAnchor('top')}" title="{lang}wcf.global.scrollUp{/lang}" class="button jsTooltip"><span class="icon icon16 icon-arrow-up"></span> <span class="invisible">{lang}wcf.global.scrollUp{/lang}</span></a></li></ul>
- </nav>
- </footer>
- </div>
- </div>
- </section>
- </div>
- </article>
- </li>
- {/foreach}
- </ul>
-</div>
-
-{include file='footer'}
-{include file='wysiwyg'}
-
-</body>
-</html>
\ No newline at end of file
+++ /dev/null
-{include file='documentHeader'}
-
-<head>
- <title>{lang}wcf.conversation.message.edit{/lang} - {$conversation->subject} - {PAGE_TITLE|language}</title>
-
- {include file='headInclude'}
-
- <script data-relocate="true">
- //<![CDATA[
- $(function() {
- WCF.Language.addObject({
- 'wcf.message.bbcode.code.copy': '{lang}wcf.message.bbcode.code.copy{/lang}'
- });
-
- {if $isFirstMessage && $conversation->isDraft}
- new WCF.Search.User('#participants', null, false, [ ], true);
- new WCF.Search.User('#invisibleParticipants', null, false, [ ], true);
- {/if}
-
- WCF.Message.Submit.registerButton('text', $('#messageContainer > .formSubmit > input[type=submit]'));
- new WCF.Message.FormGuard();
- new WCF.Message.BBCode.CodeViewer();
-
- WCF.System.Dependency.Manager.register('CKEditor', function() { new WCF.Message.UserMention('text'); });
- });
- //]]>
- </script>
-</head>
-
-<body id="tpl{$templateName|ucfirst}" data-template="{$templateName}" data-application="{$templateNameApplication}">
-{include file='header'}
-
-<header class="boxHeadline">
- <h1>{lang}wcf.conversation.message.edit{/lang}</h1>
-</header>
-
-{include file='userNotice'}
-
-{include file='formError'}
-
-<form id="messageContainer" class="jsFormGuard" method="post" action="{link controller='ConversationMessageEdit' id=$messageID}{/link}">
- <div class="container containerPadding marginTop">
- {if $isFirstMessage}
- <fieldset>
- <legend>{lang}wcf.conversation.information{/lang}</legend>
-
- <dl{if $errorField == 'subject'} class="formError"{/if}>
- <dt><label for="subject">{lang}wcf.global.subject{/lang}</label></dt>
- <dd>
- <input type="text" id="subject" name="subject" value="{$subject}" required="required" maxlength="255" class="long" />
- {if $errorField == 'subject'}
- <small class="innerError">
- {if $errorType == 'empty'}
- {lang}wcf.global.form.error.empty{/lang}
- {else}
- {lang}wcf.conversation.subject.error.{@$errorType}{/lang}
- {/if}
- </small>
- {/if}
- </dd>
- </dl>
-
- {event name='informationFields'}
- </fieldset>
-
- <fieldset>
- <legend>{lang}wcf.conversation.participants{/lang}</legend>
-
- {if $conversation->isDraft}
- <dl{if $errorField == 'participants'} class="formError"{/if}>
- <dt><label for="participants">{lang}wcf.conversation.participants{/lang}</label></dt>
- <dd>
- <textarea id="participants" name="participants" class="long" cols="40" rows="2">{$participants}</textarea>
- {if $errorField == 'participants'}
- <small class="innerError">
- {if $errorType == 'empty'}
- {lang}wcf.global.form.error.empty{/lang}
- {elseif $errorType|is_array}
- {foreach from=$errorType item='errorData'}
- {lang}wcf.conversation.participants.error.{@$errorData.type}{/lang}
- {/foreach}
- {else}
- {lang}wcf.conversation.participants.error.{@$errorType}{/lang}
- {/if}
- </small>
- {/if}
- <small>{lang}wcf.conversation.participants.description{/lang}</small>
- </dd>
- </dl>
-
- <dl{if $errorField == 'invisibleParticipants'} class="formError"{/if}>
- <dt><label for="invisibleParticipants">{lang}wcf.conversation.invisibleParticipants{/lang}</label></dt>
- <dd>
- <textarea id="invisibleParticipants" name="invisibleParticipants" class="long" cols="40" rows="2">{$invisibleParticipants}</textarea>
- {if $errorField == 'invisibleParticipants'}
- <small class="innerError">
- {if $errorType == 'empty'}
- {lang}wcf.global.form.error.empty{/lang}
- {elseif $errorType|is_array}
- {foreach from=$errorType item='errorData'}
- {lang}wcf.conversation.participants.error.{@$errorData.type}{/lang}
- {/foreach}
- {else}
- {lang}wcf.conversation.participants.error.{@$errorType}{/lang}
- {/if}
- </small>
- {/if}
- <small>{lang}wcf.conversation.invisibleParticipants.description{/lang}</small>
- </dd>
- </dl>
- {/if}
-
- <dl>
- <dt></dt>
- <dd>
- <label><input type="checkbox" name="participantCanInvite" id="participantCanInvite" value="1"{if $participantCanInvite} checked="checked"{/if} /> {lang}wcf.conversation.participantCanInvite{/lang}</label>
- </dd>
- </dl>
-
- {event name='participantFields'}
- </fieldset>
- {/if}
-
- <fieldset>
- <legend>{lang}wcf.conversation.message{/lang}</legend>
-
- <dl class="wide{if $errorField == 'text'} formError{/if}">
- <dt><label for="text">{lang}wcf.conversation.message{/lang}</label></dt>
- <dd>
- <textarea id="text" name="text" rows="20" cols="40" data-autosave="com.woltlab.wcf.conversation.messageEdit-{@$message->messageID}">{$text}</textarea>
- {if $errorField == 'text'}
- <small class="innerError">
- {if $errorType == 'empty'}
- {lang}wcf.global.form.error.empty{/lang}
- {elseif $errorType == 'tooLong'}
- {lang}wcf.message.error.tooLong{/lang}
- {elseif $errorType == 'censoredWordsFound'}
- {lang}wcf.message.error.censoredWordsFound{/lang}
- {elseif $errorType == 'disallowedBBCodes'}
- {lang}wcf.message.error.disallowedBBCodes{/lang}
- {else}
- {lang}wcf.conversation.message.error.{@$errorType}{/lang}
- {/if}
- </small>
- {/if}
- </dd>
- </dl>
-
- {event name='messageFields'}
- </fieldset>
-
- {include file='messageFormTabs' wysiwygContainerID='text'}
-
- {event name='fieldsets'}
- </div>
-
- <div class="formSubmit">
- <input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s" />
- {if $isFirstMessage && $conversation->isDraft}<button name="draft" accesskey="d" value="1">{lang}wcf.conversation.button.saveAsDraft{/lang}</button>{/if}
- {include file='messageFormPreviewButton'}
- {@SECURITY_TOKEN_INPUT_TAG}
- </div>
-</form>
-
-{if $messages|count}
- <header class="boxHeadline boxSubHeadline">
- <h2>{lang}wcf.conversation.message.add.previousPosts{/lang}</h2>
- </header>
-
- <div>
- <ul class="messageList">
- {foreach from=$messages item=message}
- {assign var='objectID' value=$message->messageID}
-
- <li class="marginTop">
- <article class="message messageReduced{if $message->getUserProfile()->userOnlineGroupID} userOnlineGroupMarking{@$message->getUserProfile()->userOnlineGroupID}{/if}">
- <div>
- <section class="messageContent">
- <div>
- <header class="messageHeader">
- <div class="box32">
- <a href="{link controller='User' object=$message->getUserProfile()}{/link}" class="framed">{@$message->getUserProfile()->getAvatar()->getImageTag(32)}</a>
-
- <div class="messageHeadline">
- <p>
- <span class="username"><a href="{link controller='User' object=$message->getUserProfile()}{/link}" class="userLink" data-user-id="{@$message->userID}">{$message->username}</a></span>
- <a href="{link controller='Conversation' object=$conversation}messageID={@$message->messageID}{/link}#message{@$message->messageID}" class="permalink">{@$message->time|time}</a>
- </p>
- </div>
- </div>
- </header>
-
- <div class="messageBody">
- <div>
- <div class="messageText">
- {@$message->getFormattedMessage()}
- </div>
- </div>
-
- {include file='attachments'}
-
- <footer class="messageOptions">
- <nav class="jsMobileNavigation buttonGroupNavigation">
- <ul class="smallButtons buttonGroup"><li class="toTopLink"><a href="{$__wcf->getAnchor('top')}" title="{lang}wcf.global.scrollUp{/lang}" class="button jsTooltip"><span class="icon icon16 icon-arrow-up"></span> <span class="invisible">{lang}wcf.global.scrollUp{/lang}</span></a></li></ul>
- </nav>
- </footer>
- </div>
- </div>
- </section>
- </div>
- </article>
- </li>
- {/foreach}
- </ul>
- </div>
-{/if}
-
-{include file='footer'}
-{include file='wysiwyg'}
-
-</body>
-</html>
+{capture assign='wysiwygSelector'}messageEditor{@$message->messageID}{/capture}
<div class="messageInlineEditor">
- <textarea id="messageEditor{@$message->messageID}" rows="20" cols="40" data-autosave="com.woltlab.wcf.conversation.messageEdit-{@$message->messageID}">{$message->message}</textarea>
+ <textarea id="{$wysiwygSelector}" class="wysiwygTextarea"
+ data-autosave="com.woltlab.wcf.conversation.messageEdit-{@$message->messageID}"
+ data-support-mention="true"
+ >{$message->message}</textarea>
{capture assign=wysiwygContainerID}messageEditor{@$message->messageID}{/capture}
{include file='messageFormTabsInline' inConversationInlineEdit=true wysiwygContainerID=$wysiwygContainerID}
<div class="formSubmit">
<button class="buttonPrimary" data-type="save">{lang}wcf.global.button.submit{/lang}</button>
- <button data-type="extended">{lang}wcf.message.button.extendedEdit{/lang}</button>
+
+ {include file='messageFormPreviewButton' previewMessageFieldID=$wysiwygSelector previewButtonID=$wysiwygSelector|concat:'_PreviewButton' previewMessageObjectType='com.woltlab.wcf.conversation.message' previewMessageObjectID=$message->messageID}
+
<button data-type="cancel">{lang}wcf.global.button.cancel{/lang}</button>
</div>
{include file='wysiwyg' wysiwygEnableUpload=true}
<script data-relocate="true">
- //<![CDATA[
$(function() {
WCF.System.Dependency.Manager.register('Redactor_messageEditor{@$message->messageID}', function() { new WCF.Message.UserMention('messageEditor{@$message->messageID}'); });
});
- //]]>
</script>
</div>
{assign var='objectID' value=$message->messageID}
{assign var='userProfile' value=$message->getUserProfile()}
- <li id="message{@$message->messageID}" class="marginTop{if MESSAGE_SIDEBAR_ENABLE_MESSAGE_GROUP_STARTER_ICON && $conversation->userID == $message->userID} messageGroupStarter{/if}">
- <article class="message messageSidebarOrientation{@$__wcf->getStyleHandler()->getStyle()->getVariable('messageSidebarOrientation')|ucfirst} dividers jsMessage{if $userProfile->userOnlineGroupID} userOnlineGroupMarking{@$userProfile->userOnlineGroupID}{/if}" data-can-edit="{if $message->canEdit()}1{else}0{/if}" data-object-id="{@$message->messageID}">
- <div>
- {include file='messageSidebar'}
-
- <section class="messageContent">
- <div>
- <header class="messageHeader">
- <ul class="messageQuickOptions">
- <li><a href="{link controller='Conversation' object=$conversation}messageID={@$message->messageID}{/link}#message{@$message->messageID}" class="badge jsTooltip" title="{lang}wcf.conversation.message.permalink{/lang}">{#$startIndex}</a></li>
- </ul>
-
- <div class="messageHeadline">
- <p><a href="{link controller='Conversation' object=$conversation}messageID={@$message->messageID}{/link}#message{@$message->messageID}" class="permalink">{@$message->time|time}</a></p>
- </div>
+ <li id="message{@$message->messageID}" class="anchorFixedHeader{if $conversation->userID == $message->userID} messageGroupStarter{/if}">
+ <article class="message messageSidebarOrientation{@$__wcf->getStyleHandler()->getStyle()->getVariable('messageSidebarOrientation')|ucfirst} jsMessage{if $userProfile->userOnlineGroupID} userOnlineGroupMarking{@$userProfile->userOnlineGroupID}{/if}" data-can-edit="{if $message->canEdit()}1{else}0{/if}" data-object-id="{@$message->messageID}">
+ {include file='messageSidebar'}
+
+ <div class="messageContent">
+ <header class="messageHeader">
+ <div class="messageHeaderBox">
+ <ul class="messageHeaderMetaData">
+ <li><a href="{link controller='Conversation' object=$conversation}messageID={@$message->messageID}{/link}#message{@$message->messageID}" class="permalink messagePublicationTime">{@$message->time|time}</a></li>
+ {event name='messageHeaderMetaData'}
+ </ul>
+
+ <ul class="messageStatus">
{if $conversation->isNewMessage($message->getDecoratedObject())}
- <p class="newMessageBadge">{lang}wcf.message.new{/lang}</p>
+ <li><span class="badge label newMessageBadge">{lang}wcf.message.new{/lang}</span></li>
{/if}
- {event name='messageHeader'}
- </header>
+ {event name='messageStatus'}
+ </ul>
+ </div>
+
+ <ul class="messageQuickOptions">
+ <li><a href="{link controller='Conversation' object=$conversation}messageID={@$message->messageID}{/link}#message{@$message->messageID}" class="jsTooltip" title="{lang}wcf.conversation.message.permalink{/lang}">#{#$startIndex}</a></li>
- <div class="messageBody">
- <div>
- <div class="messageText">
- {@$message->getFormattedMessage()}
-
- {event name='messageText'}
- </div>
- </div>
-
- {include file='attachments'}
-
- {if $message->showSignature && $message->getUserProfile()->showSignature()}
- <div class="messageSignature">
- <div>{@$message->getUserProfile()->getSignature()}</div>
- </div>
- {/if}
-
- {event name='messageBody'}
-
- <div class="messageFooter">
- {if $message->editCount}
- <p class="messageFooterNote">{lang}wcf.conversation.message.editNote{/lang}</p>
- {/if}
-
- {event name='messageFooterNotes'}
- </div>
-
- <footer class="messageOptions">
- <nav class="jsMobileNavigation buttonGroupNavigation">
- <ul class="smallButtons buttonGroup">
- {if $message->canEdit()}<li><a href="{link controller='ConversationMessageEdit' id=$message->messageID}{/link}" title="{lang}wcf.conversation.message.edit{/lang}" class="button{if !$conversation->isDraft || $message->messageID != $conversation->firstMessageID} jsMessageEditButton{/if}"><span class="icon icon16 icon-pencil"></span> <span>{lang}wcf.global.button.edit{/lang}</span></a></li>{/if}
- <li class="jsQuoteMessage" data-object-id="{@$message->messageID}" data-is-quoted="{if $__quoteFullQuote|isset && $message->messageID|in_array:$__quoteFullQuote}1{else}0{/if}"><a rel="nofollow" href="{link controller='ConversationMessageAdd' id=$conversation->conversationID quoteMessageID=$message->messageID}{/link}" title="{lang}wcf.message.quote.quoteMessage{/lang}" class="button jsTooltip{if $__quoteFullQuote|isset && $message->messageID|in_array:$__quoteFullQuote} active{/if}"><span class="icon icon16 icon-quote-left"></span> <span class="invisible">{lang}wcf.message.quote.quoteMessage{/lang}</span></a></li>
- {if $message->userID != $__wcf->getUser()->userID && $__wcf->session->getPermission('user.profile.canReportContent')}<li class="jsReportConversationMessage jsOnly" data-object-id="{@$message->messageID}"><a href="#" title="{lang}wcf.moderation.report.reportContent{/lang}" class="button jsTooltip"><span class="icon icon16 icon-warning-sign"></span> <span class="invisible">{lang}wcf.moderation.report.reportContent{/lang}</span></a></li>{/if}
- {event name='messageOptions'}
- <li class="toTopLink"><a href="{$__wcf->getAnchor('top')}" title="{lang}wcf.global.scrollUp{/lang}" class="button jsTooltip"><span class="icon icon16 icon-arrow-up"></span> <span class="invisible">{lang}wcf.global.scrollUp{/lang}</span></a></li>
- </ul>
- </nav>
- </footer>
+ {event name='messageQuickOptions'}
+ </ul>
+
+ {event name='messageHeader'}
+ </header>
+
+ <div class="messageBody">
+ {event name='beforeMessageText'}
+
+ <div class="messageText">
+ {@$message->getFormattedMessage()}
+ </div>
+
+ {event name='afterMessageText'}
+ </div>
+
+ <footer class="messageFooter">
+ {include file='attachments'}
+
+ {if $message->showSignature && $message->getUserProfile()->showSignature()}
+ <div class="messageSignature">
+ <div>{@$message->getUserProfile()->getSignature()}</div>
</div>
+ {/if}
+
+ {event name='messageFooter'}
+
+ <div class="messageFooterNotes">
+ {if $message->editCount}
+ <p class="messageFooterNote">{lang}wcf.conversation.message.editNote{/lang}</p>
+ {/if}
+
+ {event name='messageFooterNotes'}
+ </div>
+
+ <div class="messageFooterGroup">
+ <ul class="messageFooterButtons buttonList smallButtons jsMobileNavigation">
+ {if $message->canEdit()}<li class="jsOnly"><a href="#" title="{lang}wcf.conversation.message.edit{/lang}" class="button{if !$conversation->isDraft || $message->messageID != $conversation->firstMessageID} jsMessageEditButton{/if}"><span class="icon icon16 fa-pencil"></span> <span>{lang}wcf.global.button.edit{/lang}</span></a></li>{/if}
+ <li class="jsQuoteMessage" data-object-id="{@$message->messageID}" data-is-quoted="{if $__quoteFullQuote|isset && $message->messageID|in_array:$__quoteFullQuote}1{else}0{/if}"><a rel="nofollow" href="{link controller='ConversationMessageAdd' id=$conversation->conversationID quoteMessageID=$message->messageID}{/link}" title="{lang}wcf.message.quote.quoteMessage{/lang}" class="button jsTooltip{if $__quoteFullQuote|isset && $message->messageID|in_array:$__quoteFullQuote} active{/if}"><span class="icon icon16 fa-quote-left"></span> <span class="invisible">{lang}wcf.message.quote.quoteMessage{/lang}</span></a></li>
+ {if $message->userID != $__wcf->getUser()->userID && $__wcf->session->getPermission('user.profile.canReportContent')}<li class="jsReportConversationMessage jsOnly" data-object-id="{@$message->messageID}"><a href="#" title="{lang}wcf.moderation.report.reportContent{/lang}" class="button jsTooltip"><span class="icon icon16 fa-exclamation-triangle"></span> <span class="invisible">{lang}wcf.moderation.report.reportContent{/lang}</span></a></li>{/if}
+ {event name='messageFooterButtons'}
+ </ul>
</div>
- </section>
+ </footer>
</div>
</article>
</li>
{if $modificationLogList|isset}
{assign var=__modificationLogEntries value=$modificationLogList->getEntriesUntil($__modificationLogTime)}
{foreach from=$__modificationLogEntries item=modificationLogEntry}
- <li class="marginTop jsModificationLogEntry">
- <article class="message messageCollapsed">
- <div class="messageHeader">
- <div class="box24">
- <a href="{link controller='User' object=$modificationLogEntry->getUserProfile()}{/link}" class="framed">{@$modificationLogEntry->getUserProfile()->getAvatar()->getImageTag(24)}</a>
-
- <div>
- <h1><a href="{link controller='User' object=$modificationLogEntry->getUserProfile()}{/link}" class="userLink" data-user-id="{@$modificationLogEntry->userID}">{$modificationLogEntry->username}</a>
- -
- {@$modificationLogEntry->time|time}</h1>
- <small>{@$modificationLogEntry}</small>
+ <li class="jsModificationLogEntry">
+ <article class="message messageReduced">
+ <div class="messageContent">
+ <div class="messageHeader">
+ <div class="box32 messageHeaderWrapper">
+ <a href="{link controller='User' object=$modificationLogEntry->getUserProfile()}{/link}">{@$modificationLogEntry->getUserProfile()->getAvatar()->getImageTag(32)}</a>
+
+ <div class="messageHeaderBox">
+ <h2 class="messageTitle">
+ <a href="{link controller='User' object=$modificationLogEntry->getUserProfile()}{/link}" class="userLink username" data-user-id="{@$modificationLogEntry->userID}">{$modificationLogEntry->username}</a>
+ <small class="separatorLeft">{@$modificationLogEntry->time|time}</small>
+ </h2>
+ <div>{@$modificationLogEntry}</div>
+ </div>
</div>
</div>
</div>
</article>
</li>
{/foreach}
-{/if}
\ No newline at end of file
+{/if}
<div class="box48">
{if $message->getUserProfile()->getAvatar()}
- <a href="{link controller='User' object=$message->getUserProfile()->getDecoratedObject()}{/link}" class="framed">{@$message->getUserProfile()->getAvatar()->getImageTag(48)}</a>
+ <a href="{link controller='User' object=$message->getUserProfile()->getDecoratedObject()}{/link}">{@$message->getUserProfile()->getAvatar()->getImageTag(48)}</a>
{/if}
<div>
<div class="containerHeadline">
- <h3><a href="{link controller='User' object=$message->getUserProfile()->getDecoratedObject()}{/link}">{$message->username}</a> <small>- {@$message->time|time}</small></h3>
+ <h3><a href="{link controller='User' object=$message->getUserProfile()->getDecoratedObject()}{/link}">{$message->username}</a> <small class="separatorLeft">{@$message->time|time}</small></h3>
</div>
- <div>{@$message->getExcerpt()|nl2br}</div>
+ <div>{@$message->getExcerpt()|nl2br:false}</div>
{event name='previewData'}
</div>
-<li id="messageQuickReply" class="marginTop jsOnly{if $conversation->userID == $__wcf->getUser()->userID} messageGroupStarter{/if}" style="display: none;" data-conversation-id="{@$conversation->conversationID}" data-last-post-time="{@$conversation->lastPostTime}" data-page-no="{@$pageNo}">
- <article class="message messageSidebarOrientation{@$__wcf->getStyleHandler()->getStyle()->getVariable('messageSidebarOrientation')|ucfirst} dividers{if $__wcf->getUserProfileHandler()->userOnlineGroupID} userOnlineGroupMarking{@$__wcf->getUserProfileHandler()->userOnlineGroupID}{/if}">
- <div>
- {include file='messageSidebar' userProfile=$__wcf->getUserProfileHandler()}
+<li id="messageQuickReply" class="jsOnly{if $conversation->userID == $__wcf->getUser()->userID} messageGroupStarter{/if}{if $pageNo < $pages} messageQuickReplyCollapsed{/if}" data-object-id="{@$conversation->conversationID}" data-last-post-time="{@$conversation->lastPostTime}" data-page-no="{@$pageNo}">
+ <article class="message messageSidebarOrientation{@$__wcf->getStyleHandler()->getStyle()->getVariable('messageSidebarOrientation')|ucfirst}{if $__wcf->getUserProfileHandler()->userOnlineGroupID} userOnlineGroupMarking{@$__wcf->getUserProfileHandler()->userOnlineGroupID}{/if}">
+ {include file='messageSidebar' userProfile=$__wcf->getUserProfileHandler()->getUserProfile()}
+
+ <div class="messageContent messageQuickReplyContent"{if $pageNo < $pages} data-placeholder="{lang}wcf.conversation.reply{/lang}"{/if}>
+ <div class="messageBody">
+ {if !$conversation->isDraft && !$conversation->hasOtherParticipants()}
+ <p class="warning" style="margin-bottom: 14px">{lang}wcf.conversation.noParticipantsWarning{/lang}</p>
+ {/if}
+
+ <textarea id="text" name="text" class="wysiwygTextarea"
+ data-autosave="com.woltlab.wcf.conversation.messageAdd-{@$conversation->conversationID}"
+ data-support-mention="true"
+ ></textarea>
+ {include file='messageFormTabsInline' inConversationQuickReply=true}
+ </div>
- <section class="messageContent messageQuickReplyContent">
- <div>
- <header class="messageHeader">
- </header>
-
- <div class="messageBody">
- {if !$conversation->isDraft && !$conversation->hasOtherParticipants()}
- <p class="warning" style="margin-bottom: 14px">{lang}wcf.conversation.noParticipantsWarning{/lang}</p>
- {/if}
-
- <textarea id="text" name="text" rows="20" cols="40" data-autosave="com.woltlab.wcf.conversation.messageAdd-{@$conversation->conversationID}" style="width: 100%"></textarea>
- {include file='messageFormTabsInline' inConversationQuickReply=true}
- </div>
-
- <div class="formSubmit">
- <button class="buttonPrimary" data-type="save" accesskey="s">{lang}wcf.global.button.submit{/lang}</button>
- <button data-type="extended">{lang}wcf.message.button.extendedReply{/lang}</button>
- <button data-type="cancel">{lang}wcf.global.button.cancel{/lang}</button>
- </div>
+ <footer class="messageFooter">
+ <div class="formSubmit">
+ <button class="buttonPrimary" data-type="save" accesskey="s">{lang}wcf.global.button.submit{/lang}</button>
+ {include file='messageFormPreviewButton' previewMessageObjectType='com.woltlab.wcf.conversation.message' previewMessageObjectID=0}
</div>
- </section>
+ </footer>
</div>
</article>
<script data-relocate="true">
- //<![CDATA[
- $(function() {
- WCF.System.Dependency.Manager.register('Redactor_text', function() { new WCF.Message.UserMention('text'); });
+ require(['WoltLabSuite/Core/Ui/Message/Reply'], function(UiMessageReply) {
+ new UiMessageReply({
+ ajax: {
+ className: 'wcf\\data\\conversation\\message\\ConversationMessageAction'
+ }
+ });
});
- //]]>
</script>
{include file='wysiwyg'}
</li>
\ No newline at end of file
--- /dev/null
+{if $mimeType === 'text/plain'}
+{lang}wcf.user.notification.conversation.mail.plaintext{/lang}
+
+{@$event->getUserNotificationObject()->getFirstMessage()->getMailText($mimeType)} {* this line ends with a space *}
+{else}
+ {lang}wcf.user.notification.conversation.mail.html{/lang}
+ {assign var='user' value=$event->getAuthor()}
+ {assign var='conversation' value=$event->getUserNotificationObject()}
+ {assign var='message' value=$conversation->getFirstMessage()}
+
+ {if $notificationType == 'instant'}{assign var='avatarSize' value=128}
+ {else}{assign var='avatarSize' value=64}{/if}
+ {capture assign='messageContent'}
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td><a href="{link controller='User' object=$user isEmail=true}{/link}" title="{$message->username}">{@$user->getAvatar()->getImageTag($avatarSize)}</a></td>
+ <td class="boxContent">
+ <div class="containerHeadline">
+ <h3>
+ {if $message->userID}
+ <a href="{link controller='User' object=$user isEmail=true}{/link}">{$message->username}</a>
+ {else}
+ {$message->username}
+ {/if}
+ ·
+ <small>{$message->time|plainTime}</small>
+ </h3>
+ </div>
+ <div>
+ {@$message->getMailText($mimeType)}
+ </div>
+ </td>
+ </tr>
+ </table>
+ {/capture}
+ {include file='email_paddingHelper' block=true class='box'|concat:$avatarSize content=$messageContent sandbox=true}
+{/if}
--- /dev/null
+{assign var='count' value=$event->getAuthors()|count}{assign var='guestTimesTriggered' value=$event->getNotification()->guestTimesTriggered}{assign var='authors' value=$event->getAuthors()|array_values}
+{if $mimeType === 'text/plain'}
+{capture assign='authorList'}{lang}wcf.user.notification.mail.authorList.plaintext{/lang}{/capture}
+{lang}wcf.user.notification.conversation.message.mail.plaintext{/lang}{if $count == 1 && !$guestTimesTriggered}
+
+{@$event->getUserNotificationObject()->getMailText($mimeType)}{/if} {* this line ends with a space *}
+{else}
+ {capture assign='authorList'}{lang}wcf.user.notification.mail.authorList.html{/lang}{/capture}
+ {lang}wcf.user.notification.conversation.message.mail.html{/lang}
+ {assign var='user' value=$event->getAuthor()}
+ {assign var='message' value=$event->getUserNotificationObject()}
+ {assign var='conversation' value=$message->getConversation()}
+
+ {if $notificationType == 'instant'}{assign var='avatarSize' value=128}
+ {else}{assign var='avatarSize' value=64}{/if}
+ {capture assign='messageContent'}
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td><a href="{link controller='User' object=$user isEmail=true}{/link}" title="{$message->username}">{@$user->getAvatar()->getImageTag($avatarSize)}</a></td>
+ <td class="boxContent">
+ <div class="containerHeadline">
+ <h3>
+ {if $message->userID}
+ <a href="{link controller='User' object=$user isEmail=true}{/link}">{$message->username}</a>
+ {else}
+ {$message->username}
+ {/if}
+ ·
+ <small>{$message->time|plainTime}</small>
+ </h3>
+ </div>
+ <div>
+ {@$message->getMailText($mimeType)}
+ </div>
+ </td>
+ </tr>
+ </table>
+ {/capture}
+ {include file='email_paddingHelper' block=true class='box'|concat:$avatarSize content=$messageContent sandbox=true}
+{/if}
<article class="message messageReduced">
- <div>
- <section class="messageContent">
- <div>
- <header class="messageHeader">
- <div class="box32">
- {if $message->userID}
- <a href="{link controller='User' object=$message->getUserProfile()->getDecoratedObject()}{/link}" class="framed">{@$message->getUserProfile()->getAvatar()->getImageTag(32)}</a>
- {else}
- <span class="framed">{@$message->getUserProfile()->getAvatar()->getImageTag(32)}</span>
- {/if}
-
- <div class="messageHeadline">
- <h1>{if $message->getConversation()->canRead()}<a href="{@$message->getLink()}">{$message->getTitle()}</a>{else}{$message->getTitle()}{/if}</h1>
- <p>
- <span class="username">{if $message->userID}<a href="{link controller='User' object=$message->getUserProfile()->getDecoratedObject()}{/link}">{$message->getUsername()}</a>{else}{$message->getUsername()}{/if}</span>
- {@$message->getTime()|time}
- </p>
- </div>
- </div>
- </header>
+ <div class="messageContent">
+ <header class="messageHeader">
+ <div class="box32 messageHeaderWrapper">
+ {if $message->userID}
+ <a href="{link controller='User' object=$message->getUserProfile()->getDecoratedObject()}{/link}">{@$message->getUserProfile()->getAvatar()->getImageTag(32)}</a>
+ {else}
+ <span>{@$message->getUserProfile()->getAvatar()->getImageTag(32)}</span>
+ {/if}
- <div class="messageBody">
- <div>
- <div class="messageText">
- {@$message->getFormattedMessage()}
- </div>
- </div>
+ <div class="messageHeaderBox">
+ <h2 class="messageTitle">{if $message->getConversation()->canRead()}<a href="{@$message->getLink()}">{$message->getTitle()}</a>{else}{$message->getTitle()}{/if}</h2>
+
+ <ul class="messageHeaderMetaData">
+ <li>{if $message->userID}<a href="{link controller='User' object=$message->getUserProfile()->getDecoratedObject()}{/link}" class="username">{$message->getUsername()}</a>{else}<span class="username">{$message->getUsername()}</span>{/if}</li>
+ <li><span class="messagePublicationTime">{@$message->getTime()|time}</span></li>
+
+ {event name='messageHeaderMetaData'}
+ </ul>
</div>
</div>
- </section>
+
+ {event name='messageHeader'}
+ </header>
+
+ <div class="messageBody">
+ {event name='beforeMessageText'}
+
+ <div class="messageText">
+ {@$message->getFormattedMessage()}
+ </div>
+
+ {event name='afterMessageText'}
+ </div>
</div>
</article>
\ No newline at end of file
--- /dev/null
+<dl>
+ <dt></dt>
+ <dd><label><input type="checkbox" name="conversationID" value="{@$searchedConversation->conversationID}" checked> {lang}wcf.conversation.searchedConversation{/lang}</label></dd>
+</dl>
+++ /dev/null
-ALTER TABLE wcf1_conversation_message ADD lastEditTime INT(10) NOT NULL DEFAULT 0;
+++ /dev/null
-ALTER TABLE wcf1_conversation_message ADD editCount MEDIUMINT(7) NOT NULL DEFAULT 0;
+++ /dev/null
-ALTER TABLE wcf1_conversation_message ADD hasEmbeddedObjects TINYINT(1) NOT NULL DEFAULT 0;
<option name="user.conversation.allowedAttachmentExtensions">
<categoryname>user.conversation</categoryname>
<optiontype>textarea</optiontype>
- <defaultvalue><![CDATA[gif
+ <defaultvalue>gif
jpg
jpeg
png
bmp
zip
txt
-pdf]]></defaultvalue>
+pdf</defaultvalue>
<options>module_attachment</options>
- <wildcard><![CDATA[*]]></wildcard>
+ <wildcard>*</wildcard>
<usersonly>1</usersonly>
</option>
<option name="user.conversation.maxAttachmentCount">
<categoryname>settings.privacy.messaging</categoryname>
<optiontype>select</optiontype>
<editable>3</editable>
- <selectoptions><![CDATA[0:wcf.user.access.registered
+ <selectoptions>0:wcf.user.access.registered
1:wcf.user.access.following
-2:wcf.user.access.nobody]]></selectoptions>
+2:wcf.user.access.nobody</selectoptions>
<defaultvalue>0</defaultvalue>
<options>module_conversation</options>
</option>
<optiontype>select</optiontype>
<editable>3</editable>
<defaultvalue>0</defaultvalue>
- <selectoptions><![CDATA[0:wcf.global.defaultValue
+ <selectoptions>0:wcf.global.defaultValue
5
10
20
30
-40]]></selectoptions>
+40</selectoptions>
<options>module_conversation</options>
</option>
<option name="conversationMessagesPerPage">
<optiontype>select</optiontype>
<editable>3</editable>
<defaultvalue>0</defaultvalue>
- <selectoptions><![CDATA[0:wcf.global.defaultValue
+ <selectoptions>0:wcf.global.defaultValue
5
10
20
30
-40]]></selectoptions>
+40</selectoptions>
<options>module_conversation</options>
</option>
</options>