runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- - name: phpcs
- uses: chekalsky/phpcs-action@e269c2f264f400adcda7c6b24c8550302350d495
- name: Setup PHP with tools
uses: shivammathur/setup-php@v2
with:
- php-version: '8.0'
+ php-version: '8.1'
extensions: ctype, dom, exif, gd, gmp, hash, intl, json, libxml, mbstring, opcache, pcre, pdo, pdo_mysql, zlib
- tools: php-cs-fixer
+ tools: cs2pr, phpcs, php-cs-fixer
+ - name: phpcs
+ run: phpcs -n -q --report=checkstyle | cs2pr
- name: php-cs-fixer
run: php-cs-fixer fix --dry-run --diff
ts:
- "5.4"
- "5.5"
- master
+ paths:
+ - '*.php'
pull_request:
+ paths:
+ - '*.php'
jobs:
syntax:
fail-fast: false
matrix:
php:
- - '7.2'
- - '7.3'
- - '7.4'
- - '8.0'
- '8.1'
+ - '8.2'
steps:
- name: Set up PHP
uses: shivammathur/setup-php@v2
->setRules([
'@PSR1' => true,
'@PSR2' => true,
+ '@PSR12' => true,
+ '@PER' => true,
'array_push' => true,
'backtick_to_shell_exec' => true,
'non_printable_character' => ['use_escape_sequences_in_strings' => true],
- 'lowercase_static_reference' => true,
'magic_constant_casing' => true,
'magic_method_casing' => true,
'native_function_casing' => true,
'native_function_type_declaration_casing' => true,
'cast_spaces' => ['space' => 'none'],
- 'lowercase_cast' => true,
'no_unset_cast' => true,
- 'short_scalar_cast' => true,
'class_attributes_separation' => true,
- 'no_blank_lines_after_class_opening' => true,
'no_null_property_initialization' => true,
'self_accessor' => true,
'single_class_element_per_statement' => true,
- 'single_trait_insert_per_statement' => true,
'no_empty_comment' => true,
'single_line_comment_style' => ['comment_types' => ['hash']],
'native_function_invocation' => ['include' => ['@internal']],
'no_unreachable_default_argument_value' => true,
'nullable_type_declaration_for_default_null_value' => true,
- 'return_type_declaration' => true,
'static_lambda' => true,
'fully_qualified_strict_types' => true,
- 'no_leading_import_slash' => true,
'no_unused_imports' => true,
'ordered_imports' => true,
- 'declare_equal_normalize' => true,
'dir_constant' => true,
'explicit_indirect_variable' => true,
'function_to_constant' => true,
'clean_namespace' => true,
'no_leading_namespace_whitespace' => true,
- 'single_blank_line_before_namespace' => true,
'no_homoglyph_names' => true,
'operator_linebreak' => true,
'standardize_increment' => true,
'standardize_not_equals' => true,
- 'ternary_operator_spaces' => true,
'ternary_to_elvis_operator' => true,
'ternary_to_null_coalescing' => true,
'unary_operator_spaces' => true,
'array_indentation' => true,
'blank_line_before_statement' => ['statements' => ['return', 'exit']],
- 'compact_nullable_typehint' => true,
'method_chaining_indentation' => true,
'no_extra_blank_lines' => ['tokens' => ['case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'square_brace_block', 'switch', 'throw', 'use']],
'no_spaces_around_offset' => true,
+++ /dev/null
-<?php
-
-/**
- * @author Tim Duesterhus
- * @copyright 2001-2020 WoltLab GmbH
- * @license WoltLab License <http://www.woltlab.com/license-agreement.html>
- */
-
-// Reuse the install script to create the indices with the correct names.
-
-return require(__DIR__ . '/install_com.woltlab.wcf.conversation.php');
+++ /dev/null
-<?php
-
-/**
- * @author Tim Duesterhus
- * @copyright 2001-2021 WoltLab GmbH
- * @license WoltLab License <http://www.woltlab.com/license-agreement.html>
- */
-
-use wcf\system\database\table\index\DatabaseTableIndex;
-use wcf\system\database\table\index\DatabaseTablePrimaryIndex;
-use wcf\system\database\table\PartialDatabaseTable;
-
-// 1) Generate a blueprint to fill in the generated index names.
-
-$blueprint = [
- PartialDatabaseTable::create('wcf1_conversation')
- ->indices([
- // DatabaseTablePrimaryIndex::create()
- // ->columns(['conversationID']),
- DatabaseTableIndex::create()
- ->columns(['userID', 'isDraft']),
- ]),
- PartialDatabaseTable::create('wcf1_conversation_to_user')
- ->indices([
- DatabaseTableIndex::create()
- ->columns(['participantID', 'conversationID'])
- ->type(DatabaseTableIndex::UNIQUE_TYPE),
- // DatabaseTableIndex::create()
- // ->columns(['participantID', 'hideConversation']),
- ]),
- PartialDatabaseTable::create('wcf1_conversation_message')
- ->indices([
- // DatabaseTablePrimaryIndex::create()
- // ->columns(['messageID']),
- DatabaseTableIndex::create()
- ->columns(['conversationID', 'userID']),
- DatabaseTableIndex::create()
- ->columns(['ipAddress']),
- ]),
- PartialDatabaseTable::create('wcf1_conversation_label')
- ->indices([
- // DatabaseTablePrimaryIndex::create()
- // ->columns(['labelID']),
- ]),
- PartialDatabaseTable::create('wcf1_conversation_label_to_object')
- ->indices([
- DatabaseTableIndex::create()
- ->columns(['labelID', 'conversationID'])
- ->type(DatabaseTableIndex::UNIQUE_TYPE),
- ]),
-];
-
-// 2) Use this blueprint to recreate the index objects with ->generatedName() set to false.
-// Simply dropping the indices with ->generatedName() set to true does not work, because it will
-// also remove named indices as the fact that a name was generated does not persist to the database.
-
-$data = [];
-foreach ($blueprint as $blueprintTable) {
- $data[] = PartialDatabaseTable::create($blueprintTable->getName())
- ->indices(\array_map(static function ($index) {
- \assert($index instanceof DatabaseTableIndex);
-
- return DatabaseTableIndex::create($index->getName())
- ->columns($index->getColumns())
- ->type($index->getType())
- ->drop();
- }, $blueprintTable->getIndices()));
-}
-
-return $data;
+++ /dev/null
-<?php
-
-/**
- * Deletes orphaned attachments.
- *
- * @author Tim Duesterhus
- * @copyright 2001-2022 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core
- */
-
-use wcf\data\attachment\AttachmentAction;
-use wcf\data\object\type\ObjectTypeCache;
-use wcf\system\package\SplitNodeException;
-use wcf\system\WCF;
-
-$objectType = ObjectTypeCache::getInstance()
- ->getObjectTypeByName('com.woltlab.wcf.attachment.objectType', 'com.woltlab.wcf.conversation.message');
-
-$sql = "SELECT attachmentID
- FROM wcf1_attachment
- WHERE objectTypeID = ?
- AND objectID NOT IN (
- SELECT messageID
- FROM wcf1_conversation_message
- )";
-$statement = WCF::getDB()->prepare($sql, 100);
-$statement->execute([$objectType->objectTypeID]);
-$attachmentIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
-
-if (empty($attachmentIDs)) {
- return;
-}
-
-(new AttachmentAction($attachmentIDs, 'delete'))->executeAction();
-
-// If we reached this location we processed at least one attachment.
-// If this was the final attachment the next iteration will abort this
-// script early, thus not splitting the node.
-throw new SplitNodeException();
switch (key) {
case 'close':
- $('<li><span class="icon icon16 fa-lock jsTooltip jsIconLock" title="' + WCF.Language.get('wcf.global.state.closed') + '" /></li>').prependTo($conversation.find('.statusIcons'));
+ $(`<li>
+ <span class="jsTooltip jsIconLock" title="${WCF.Language.get('wcf.global.state.closed')}">
+ <fa-icon size="16" name="lock"></fa-icon>
+ </span>
+ </li>`).prependTo($conversation.find('.statusIcons'));
this._attributes[conversationID].isClosed = 1;
break;
switch (key) {
case 'close':
- $('<li><span class="icon icon16 fa-lock jsIconLock" /> ' + WCF.Language.get('wcf.global.state.closed') + '</li>').appendTo(container);
+ $(`<li>
+ <fa-icon size="16" name="lock"></fa-icon>
+ ${WCF.Language.get('wcf.global.state.closed')}
+ </li>`).appendTo(container);
this._attributes[conversationID].isClosed = 1;
break;
var availableLabels = this.getAvailableLabels();
if (!labelList.length) {
- labelList = $('<li><span class="icon icon16 fa-tags"></span> <ul class="labelList"></ul></li>').prependTo(container);
+ labelList = $(`<li>
+ <fa-icon size="16" name="tags"></fa-icon>
+ <ul class="labelList"></ul>
+ </li>`).prependTo(container);
labelList = labelList.children('ul');
}
}
});
-/**
- * Provides methods to remove participants from conversations.
- *
- * @see WCF.Action.Delete
- * @deprecated 5.4 Handled via `WoltLabSuite/Core/Ui/Object/Action`.
- */
-WCF.Conversation.RemoveParticipant = WCF.Action.Delete.extend({
- /**
- * conversation id
- * @var integer
- */
- _conversationID: 0,
-
- /**
- * @see WCF.Action.Delete.init()
- */
- init: function(conversationID) {
- this._conversationID = conversationID;
- this._super('wcf\\data\\conversation\\ConversationAction', '.jsParticipant');
- },
-
- /**
- * @see WCF.Action.Delete._sendRequest()
- */
- _sendRequest: function(object) {
- this.proxy.setOption('data', {
- actionName: 'removeParticipant',
- className: this._className,
- objectIDs: [ this._conversationID ],
- parameters: {
- userID: $(object).data('objectID')
- }
- });
-
- this.proxy.sendRequest();
- },
-
- /**
- * @see WCF.Action.Delete._success()
- */
- _success: function(data, textStatus, jqXHR) {
- var $userID = data.returnValues.userID;
-
- for (var $index in this._containers) {
- var $container = $('#' + this._containers[$index]);
- if ($container.find('.jsDeleteButton').data('objectID') == $userID) {
- $container.find('.userLink').addClass('conversationLeft');
- $container.find('.jsDeleteButton').remove();
- }
- }
- }
-});
-
/**
* Namespace for label-related classes.
*/
}
});
-/**
- * Provides a flexible conversation preview.
- *
- * @see WCF.Popover
- * @deprecated 5.3 handled via `WoltLabSuite/Core/Controller/Popover`
- */
-WCF.Conversation.Preview = WCF.Popover.extend({
- /**
- * action proxy
- * @var WCF.Action.Proxy
- */
- _proxy: null,
-
- /**
- * @see WCF.Popover.init()
- */
- init: function() {
- this._super('.conversationLink');
-
- // init proxy
- this._proxy = new WCF.Action.Proxy({
- showLoadingOverlay: false
- });
-
- WCF.DOMNodeInsertedHandler.addCallback('WCF.Conversation.Preview', $.proxy(this._initContainers, this));
- },
-
- /**
- * @see WCF.Popover._loadContent()
- */
- _loadContent: function() {
- var $link = $('#' + this._activeElementID);
-
- this._proxy.setOption('data', {
- actionName: 'getMessagePreview',
- className: 'wcf\\data\\conversation\\ConversationAction',
- objectIDs: [ $link.data('conversationID') ]
- });
-
- var $elementID = this._activeElementID;
- var self = this;
- this._proxy.setOption('success', function(data, textStatus, jqXHR) {
- self._insertContent($elementID, data.returnValues.template, true);
- });
- this._proxy.sendRequest();
- }
-});
-
-/**
- * Marks one conversation as read.
- */
-WCF.Conversation.MarkAsRead = Class.extend({
- /**
- * action proxy
- * @var WCF.Action.Proxy
- */
- _proxy: null,
-
- /**
- * Initializes the mark as read for conversations.
- */
- init: function() {
- this._proxy = new WCF.Action.Proxy({
- success: $.proxy(this._success, this)
- });
-
- $(document).on('dblclick', '.conversationList .new .columnAvatar', $.proxy(this._dblclick, this));
- },
-
- /**
- * Handles double clicks on avatar.
- *
- * @param object event
- */
- _dblclick: function(event) {
- this._proxy.setOption('data', {
- actionName: 'markAsRead',
- className: 'wcf\\data\\conversation\\ConversationAction',
- objectIDs: [ $(event.currentTarget).parents('ol:eq(0)').data('conversationID') ]
- });
- this._proxy.sendRequest();
- },
-
- /**
- * Handles successful AJAX requests.
- *
- * @param object data
- * @param string textStatus
- * @param jQuery jqXHR
- */
- _success: function(data, textStatus, jqXHR) {
- $('.conversationList .new').each(function(index, element) {
- var $element = $(element);
- if (WCF.inArray($element.data('conversationID'), data.objectIDs)) {
- // remove new class
- $element.removeClass('new');
-
- // hide arrows
- $element.find('.firstNewPost').parent().remove();
-
- // remove event
- $element.find('.columnAvatar').off('dblclick');
- }
- });
- }
-});
-
-/**
- * Marks all conversations as read.
- */
-WCF.Conversation.MarkAllAsRead = Class.extend({
- /**
- * action proxy
- * @var WCF.Action.Proxy
- */
- _proxy: null,
-
- /**
- * Initializes the WCF.Conversation.MarkAllAsRead class.
- */
- init: function() {
- this._proxy = new WCF.Action.Proxy({
- success: $.proxy(this._success, this)
- });
-
- $('.markAllAsReadButton').click($.proxy(this._click, this));
- },
-
- /**
- * Handles clicks.
- *
- * @param object event
- */
- _click: function(event) {
- event.preventDefault();
-
- this._proxy.setOption('data', {
- actionName: 'markAllAsRead',
- className: 'wcf\\data\\conversation\\ConversationAction'
- });
- this._proxy.sendRequest();
- },
-
- /**
- * Marks all conversations as read.
- *
- * @param object data
- * @param string textStatus
- * @param jQuery jqXHR
- */
- _success: function(data, textStatus, jqXHR) {
- // fix dropdown
- WCF.System.Event.fireEvent('com.woltlab.wcf.conversation.userPanel', 'reset');
-
- // fix conversation list
- var $conversationList = $('.conversationList');
- $conversationList.find('.new').removeClass('new');
- $conversationList.find('.columnAvatar').off('dblclick');
-
- new WCF.System.Notification().show();
- }
-});
-
/**
* Namespace for conversation messages.
*/
return 'wcf\\data\\conversation\\message\\ConversationMessageAction';
}
});
-
-/**
- * @deprecated 5.5, use `WoltLabSuite/Core/Conversation/Ui/Message/Quote` instead
- */
-WCF.Conversation.Message.QuoteHandler = WCF.Message.Quote.Handler.extend({
- /**
- * @see WCF.Message.QuoteManager.init()
- */
- init: function(quoteManager) {
- require(["WoltLabSuite/Core/Conversation/Ui/Message/Quote"], ({ UiConversationMessageQuote }) => {
- new UiConversationMessageQuote(quoteManager);
- });
- }
-});
--- /dev/null
+/**
+ * Marks all conversations as read.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2022 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.0
+ */
+define(["require", "exports", "tslib", "WoltLabSuite/Core/Ajax", "WoltLabSuite/Core/Ui/Notification"], function (require, exports, tslib_1, Ajax_1, UiNotification) {
+ "use strict";
+ Object.defineProperty(exports, "__esModule", { value: true });
+ exports.setup = void 0;
+ UiNotification = tslib_1.__importStar(UiNotification);
+ async function markAllAsRead() {
+ await (0, Ajax_1.dboAction)("markAllAsRead", "wcf\\data\\conversation\\ConversationAction").dispatch();
+ document.querySelectorAll(".conversationList .new").forEach((el) => {
+ el.classList.remove("new");
+ });
+ document.querySelector("#unreadConversations .badgeUpdate")?.remove();
+ UiNotification.show();
+ }
+ function setup() {
+ document.querySelectorAll(".markAllAsReadButton").forEach((el) => {
+ el.addEventListener("click", (event) => {
+ event.preventDefault();
+ void markAllAsRead();
+ });
+ });
+ }
+ exports.setup = setup;
+});
--- /dev/null
+/**
+ * Handles the mark as read button for single conversations.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2022 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.0
+ */
+define(["require", "exports", "WoltLabSuite/Core/Ajax"], function (require, exports, Ajax_1) {
+ "use strict";
+ Object.defineProperty(exports, "__esModule", { value: true });
+ exports.setup = void 0;
+ const unreadConversations = new WeakSet();
+ async function markAsRead(conversation) {
+ const conversationId = parseInt(conversation.dataset.conversationId, 10);
+ await (0, Ajax_1.dboAction)("markAsRead", "wcf\\data\\conversation\\ConversationAction").objectIds([conversationId]).dispatch();
+ conversation.classList.remove("new");
+ conversation.querySelector(".columnAvatar p")?.removeAttribute("title");
+ }
+ function setup() {
+ document.querySelectorAll(".conversationList .new .columnAvatar").forEach((el) => {
+ if (!unreadConversations.has(el)) {
+ unreadConversations.add(el);
+ el.addEventListener("dblclick", (event) => {
+ event.preventDefault();
+ const conversation = el.closest(".conversation");
+ if (!conversation.classList.contains("new")) {
+ return;
+ }
+ void markAsRead(conversation);
+ }, { once: true });
+ }
+ });
+ }
+ exports.setup = setup;
+});
* @author Matthias Schmidt
* @copyright 2001-2021 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module WoltLabSuite/Core/Conversation/Ui/Message/Quote
* @woltlabExcludeBundle tiny
*/
define(["require", "exports", "WoltLabSuite/Core/Ui/Message/Quote"], function (require, exports, Quote_1) {
* @author Matthias Schmidt
* @copyright 2001-2021 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module WoltLabSuite/Core/Conversation/Ui/Object/Action/RemoveParticipant
*/
define(["require", "exports", "tslib", "WoltLabSuite/Core/Ui/Object/Action/Handler"], function (require, exports, tslib_1, Handler_1) {
"use strict";
* @author Alexander Ebert
* @copyright 2001-2021 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module WoltLabSuite/Core/Conversation/Ui/Participant/Add
*/
define(["require", "exports", "tslib", "WoltLabSuite/Core/Ajax", "WoltLabSuite/Core/Dom/Util", "WoltLabSuite/Core/Ui/Dialog", "WoltLabSuite/Core/Ui/Notification", "WoltLabSuite/Core/Ui/ItemList/User", "WoltLabSuite/Core/Language"], function (require, exports, tslib_1, Ajax, Util_1, Dialog_1, UiNotification, UiItemListUser, Language) {
"use strict";
UiItemListUser = tslib_1.__importStar(UiItemListUser);
Language = tslib_1.__importStar(Language);
class UiParticipantAdd {
+ conversationId;
constructor(conversationId) {
this.conversationId = conversationId;
Ajax.api(this, {
Language = tslib_1.__importStar(Language);
UiNotification = tslib_1.__importStar(UiNotification);
class UiSubjectEditor {
+ objectId;
+ subject;
constructor(objectId) {
this.objectId = objectId;
}
</dd>
</dl>
<div class="formSubmit">
- <button class="buttonPrimary jsButtonSave">${Language.get("wcf.global.button.save")}</button>
+ <button type="button" class="button buttonPrimary jsButtonSave">${Language.get("wcf.global.button.save")}</button>
</div>
`,
};
* @author Alexander Ebert
* @copyright 2001-2021 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module WoltLabSuite/Core/Ui/User/Menu/Data/Notification
* @woltlabExcludeBundle tiny
*/
define(["require", "exports", "tslib", "WoltLabSuite/Core/Ajax", "WoltLabSuite/Core/Ui/User/Menu/View", "WoltLabSuite/Core/Ui/User/Menu/Manager"], function (require, exports, tslib_1, Ajax_1, View_1, Manager_1) {
exports.setup = void 0;
View_1 = tslib_1.__importDefault(View_1);
class UserMenuDataConversation {
+ button;
+ counter = 0;
+ options;
+ stale = true;
+ view = undefined;
constructor(button, options) {
- this.counter = 0;
- this.stale = true;
- this.view = undefined;
this.button = button;
this.options = options;
const badge = button.querySelector(".badge");
const buttons = [];
if (this.options.canStartConversation) {
buttons.push({
- icon: '<span class="icon icon24 fa-plus"></span>',
+ icon: '<fa-icon size="24" name="plus"></fa-icon>',
link: this.options.newConversationLink,
name: "newConversation",
title: this.options.newConversationTitle,
--- /dev/null
+<?php
+
+use wcf\system\event\EventHandler;
+use wcf\system\worker\event\RebuildWorkerCollecting;
+
+return static function (): void {
+ $eventHandler = EventHandler::getInstance();
+
+ $eventHandler->register(RebuildWorkerCollecting::class, static function (RebuildWorkerCollecting $event) {
+ $event->register(\wcf\system\worker\ConversationMessageRebuildDataWorker::class, -5);
+ $event->register(\wcf\system\worker\ConversationRebuildDataWorker::class, 0);
+ $event->register(\wcf\system\worker\ConversationMessageSearchIndexRebuildDataWorker::class, 300);
+ });
+};
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
*
* @property-read int $conversationID unique id of the conversation
* @property-read string $subject subject of the conversation
* default participation state
* @var int
*/
- const STATE_DEFAULT = 0;
+ public const STATE_DEFAULT = 0;
/**
* conversation is hidden but returns visible upon new message
* @var int
*/
- const STATE_HIDDEN = 1;
+ public const STATE_HIDDEN = 1;
/**
* conversation was left permanently
* @var int
*/
- const STATE_LEFT/*4DEAD*/ = 2;
+ public const STATE_LEFT/*4DEAD*/ = 2;
/**
* true if the current user can add users without limitations
/**
* @inheritDoc
*/
- public function getTitle()
+ public function getTitle(): string
{
return $this->subject;
}
/**
* @inheritDoc
*/
- public function getLink()
+ public function getLink(): string
{
return LinkHandler::getInstance()->getLink('Conversation', [
'object' => $this,
/**
* Returns true if this conversation is new for the active user.
- *
- * @return bool
*/
- public function isNew()
+ public function isNew(): bool
{
if (!$this->isDraft && $this->lastPostTime > $this->lastVisitTime) {
return true;
/**
* Returns true if the active user doesn't have read the given message.
- *
- * @param ConversationMessage $message
- * @return bool
*/
- public function isNewMessage(ConversationMessage $message)
+ public function isNewMessage(ConversationMessage $message): bool
{
if (!$this->isDraft && $message->time > $this->lastVisitTime) {
return true;
/**
* Returns true if the conversation is not closed or the user was not removed.
- *
- * @return bool
*/
- public function canReply()
+ public function canReply(): bool
{
if (!$this->canRead()) {
return false;
/**
* Returns true if the active user has the permission to read this conversation.
- *
- * @return bool
*/
- public function canRead()
+ public function canRead(): bool
{
if (!WCF::getUser()->userID) {
return false;
/**
* Returns true if the current user can add new participants to this conversation.
- *
- * @return bool
*/
- public function canAddParticipants()
+ public function canAddParticipants(): bool
{
if ($this->isDraft) {
return false;
/**
* Returns true if the current user can add participants without limitations.
- *
- * @return bool
*/
- public function canAddParticipantsUnrestricted()
+ public function canAddParticipantsUnrestricted(): bool
{
if ($this->canAddUnrestricted === null) {
$this->canAddUnrestricted = false;
/**
* Returns false if the active user is the last participant of this conversation.
- *
- * @return bool
*/
- public function hasOtherParticipants()
+ public function hasOtherParticipants(): bool
{
if ($this->userID == WCF::getUser()->userID) {
// author
/**
* Returns true if the current user is an active participant of this conversation.
- *
- * @return bool
*/
- public function isActiveParticipant()
+ public function isActiveParticipant(): bool
{
if ($this->isActiveParticipant === null) {
$sql = "SELECT leftAt
/**
* @inheritDoc
*/
- public function getPopoverLinkClass()
+ public function getPopoverLinkClass(): string
{
return 'conversationLink';
}
*
* @param int[] $conversationIDs
* @param int $userID
- * @return bool
*/
- public static function isParticipant(array $conversationIDs, $userID = null)
+ public static function isParticipant(array $conversationIDs, $userID = null): bool
{
if ($userID === null) {
$userID = WCF::getUser()->userID;
use wcf\system\log\modification\ConversationModificationLogHandler;
use wcf\system\request\LinkHandler;
use wcf\system\search\SearchIndexManager;
+use wcf\system\style\FontAwesomeIcon;
use wcf\system\user\notification\object\ConversationUserNotificationObject;
use wcf\system\user\notification\UserNotificationHandler;
use wcf\system\user\storage\UserStorageHandler;
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
*
* @method ConversationEditor[] getObjects()
* @method ConversationEditor getSingleObject()
];
}
- /**
- * Validates parameters to return the mixed conversation list.
- *
- * @deprecated 5.5
- */
- public function validateGetMixedConversationList()
- {
- // does nothing
- }
-
- /**
- * Returns a mixed conversation list with up to 10 unread conversations.
- *
- * @return mixed[][]
- * @deprecated 5.5 This method provided the data for the legacy user panel implementation.
- */
- 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 < lastPostTime');
- $unreadConversationList->sqlLimit = 10;
- $unreadConversationList->sqlOrderBy = 'lastPostTime DESC';
- $unreadConversationList->readObjects();
-
- $conversations = [];
- $count = 0;
- foreach ($unreadConversationList as $conversation) {
- $conversations[] = $conversation;
- $count++;
- }
-
- if ($count < 10) {
- $conversationList = new UserConversationList(WCF::getUser()->userID);
- $conversationList->sqlSelects .= $sqlSelect;
- $conversationList->getConditionBuilder()->add('conversation_to_user.lastVisitTime >= lastPostTime');
- $conversationList->sqlLimit = (10 - $count);
- $conversationList->sqlOrderBy = 'lastPostTime DESC';
- $conversationList->readObjects();
-
- foreach ($conversationList as $conversation) {
- $conversations[] = $conversation;
- }
- }
-
- WCF::getTPL()->assign([
- 'conversations' => $conversations,
- ]);
-
- $totalCount = ConversationHandler::getInstance()->getUnreadConversationCount();
- if ($count < 10 && $count < $totalCount) {
- UserStorageHandler::getInstance()->reset([WCF::getUser()->userID], 'unreadConversationCount');
- }
-
- return [
- 'template' => WCF::getTPL()->fetch('conversationListUserPanel'),
- 'totalCount' => $totalCount,
- ];
- }
-
/**
* @since 5.5
*/
$conversations = \array_map(static function (ViewableConversation $conversation) {
if ($conversation->userID === WCF::getUser()->userID) {
if ($conversation->participants > 1) {
- $image = '<span class="icon icon48 fa-users"></span>';
+ $image = FontAwesomeIcon::fromValues('users')->toHtml(48);
$usernames = \array_column($conversation->getParticipantSummary(), 'username');
} else {
$image = $conversation->getOtherParticipantProfile()->getAvatar()->getImageTag(48);
}
} else {
if ($conversation->participants > 1) {
- $image = '<span class="icon icon48 fa-users"></span>';
+ $image = FontAwesomeIcon::fromValues('users')->toHtml(48);
$usernames = \array_filter($conversation->getParticipantNames(), static function ($username) use ($conversation) {
return $username !== $conversation->getUserProfile()->username;
});
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
*
* @method static Conversation create(array $parameters = [])
* @method Conversation getDecoratedObject()
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
*
* @method Conversation current()
* @method Conversation[] getObjects()
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
*/
class ConversationParticipantList extends UserProfileList
{
* @author Alexander Ebert
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
*
* @method Conversation getDecoratedObject()
* @mixin Conversation
/**
* @inheritDoc
*/
- public function getLink()
+ public function getLink(): string
{
return LinkHandler::getInstance()->getLink('Conversation', [
'object' => $this->getDecoratedObject(),
/**
* @inheritDoc
*/
- public function getTitle()
+ public function getTitle(): string
{
return $this->getDecoratedObject()->getTitle();
}
/**
* @inheritDoc
*/
- public function getFormattedMessage()
+ public function getFormattedMessage(): string
{
return '';
}
/**
* @inheritDoc
*/
- public function getMessage()
+ public function getMessage(): string
{
return '';
}
/**
* @inheritDoc
*/
- public function getExcerpt($maxLength = 255)
+ public function getExcerpt($maxLength = 255): string
{
return '';
}
/**
* @inheritDoc
*/
- public function getUsername()
+ public function getUsername(): string
{
return $this->getDecoratedObject()->lastPoster;
}
/**
* @inheritDoc
*/
- public function __toString()
+ public function __toString(): string
{
return $this->getFormattedMessage();
}
* @author Alexander Ebert
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
*
* @method FeedConversation current()
* @method FeedConversation[] getObjects()
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
*
* @method ViewableConversation current()
* @method ViewableConversation[] getObjects()
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
*
* @method Conversation getDecoratedObject()
* @mixin Conversation
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Label
*
* @property-read int $labelID unique id of the conversation label
* @property-read int $userID id of the user who created the conversation label
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Label
*
* @method ConversationLabel create()
* @method ConversationLabelEditor[] getObjects()
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Label
*
* @method static ConversationLabel create(array $parameters = [])
* @method ConversationLabel getDecoratedObject()
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Label
*
* @method ConversationLabel current()
* @method ConversationLabel[] getObjects()
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
*
* @property-read int $messageID unique id of the conversation message
* @property-read int $conversationID id of the conversation the conversation message belongs to
/**
* @inheritDoc
*/
- public function getFormattedMessage()
+ public function getFormattedMessage(): string
{
$processor = new HtmlOutputProcessor();
$processor->process($this->message, 'com.woltlab.wcf.conversation.message', $this->messageID);
/**
* Returns a simplified version of the formatted message.
- *
- * @return string
*/
- public function getSimplifiedFormattedMessage()
+ public function getSimplifiedFormattedMessage(): string
{
$processor = new HtmlOutputProcessor();
$processor->setOutputType('text/simplified-html');
/**
* @inheritDoc
*/
- public function getExcerpt($maxLength = 255)
+ public function getExcerpt($maxLength = 255): string
{
return StringUtil::truncateHTML($this->getSimplifiedFormattedMessage(), $maxLength);
}
* 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($mimeType = 'text/plain')
+ public function getMailText($mimeType = 'text/plain'): string
{
switch ($mimeType) {
case 'text/plain':
/**
* Returns true if current user may edit this message.
- *
- * @return bool
*/
- public function canEdit()
+ public function canEdit(): bool
{
return WCF::getUser()->userID == $this->userID
&& (
/**
* @inheritDoc
*/
- public function getMessage()
+ public function getMessage(): string
{
return $this->message;
}
/**
* @inheritDoc
*/
- public function getLink()
+ public function getLink(): string
{
return LinkHandler::getInstance()->getLink('Conversation', [
'object' => $this->getConversation(),
/**
* @inheritDoc
*/
- public function getTitle()
+ public function getTitle(): string
{
if ($this->messageID == $this->getConversation()->firstMessageID) {
return $this->getConversation()->subject;
/**
* @inheritDoc
*/
- public function isVisible()
+ public function isVisible(): bool
{
return true;
}
/**
* @inheritDoc
*/
- public function __toString()
+ public function __toString(): string
{
return $this->getFormattedMessage();
}
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
*
* @method ConversationMessageEditor[] getObjects()
* @method ConversationMessageEditor getSingleObject()
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
*
* @method static ConversationMessage create(array $parameters = [])
* @method ConversationMessage getDecoratedObject()
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
*
* @method ConversationMessage current()
* @method ConversationMessage[] getObjects()
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
*
* @property-read string|null $subject
*/
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
*
* @method SearchResultConversationMessage current()
* @method SearchResultConversationMessage[] getObjects()
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
*/
class SimplifiedViewableConversationMessageList extends ViewableConversationMessageList
{
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
*
* @method ConversationMessage getDecoratedObject()
* @mixin ConversationMessage
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
*
* @method ViewableConversationMessage current()
* @method ViewableConversationMessage[] getObjects()
* @author Alexander Ebert
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Modification\Log
*
* @method ViewableConversationModificationLog current()
* @method ViewableConversationModificationLog[] getObjects()
* @author Alexander Ebert
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Modification\Log
*
* @method ModificationLog getDecoratedObject()
* @mixin ModificationLog
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Form
*/
class ConversationAddForm extends MessageForm
{
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Form
*/
class ConversationDraftEditForm extends ConversationAddForm
{
* @author Alexander Ebert
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Page
*/
class ConversationFeedPage extends AbstractFeedPage
{
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Page
*
* @property UserConversationList $objectList
*/
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Page
*
* @property ViewableConversationMessageList $objectList
*/
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Attachment
*
* @method ConversationMessage getObject($objectID)
*/
* @author Matthias Schmidt
* @copyright 2001-2019 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()
* @author Matthias Schmidt
* @copyright 2001-2019 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()
* @author Alexander Ebert
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Clipboard\Action
*/
class ConversationClipboardAction extends AbstractClipboardAction
{
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Conversation
*/
class ConversationHandler extends SingletonFactory
{
* @author Alexander Ebert
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Event\Listener
* @since 5.2
*/
class ConversationPruneIpAddressesCronjobListener implements IParameterizedEventListener
* @author Alexander Ebert
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Event\Listener
*/
class ConversationUserActionRenameListener extends AbstractUserActionRenameListener
{
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Event\Listener
*/
class ConversationUserMergeListener extends AbstractUserMergeListener
{
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Event\Listener
*/
class UserGroupAddCanBeAddedAsConversationParticipantListener implements IParameterizedEventListener
{
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Importer
*/
class ConversationAttachmentImporter extends AbstractAttachmentImporter
{
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Importer
*/
class ConversationImporter extends AbstractImporter
{
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Importer
*/
class ConversationLabelImporter extends AbstractImporter
{
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Importer
*/
class ConversationMessageImporter extends AbstractImporter
{
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Importer
*/
class ConversationUserImporter extends AbstractImporter
{
}
$data['participantID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.user', $data['participantID']);
- $sql = "INSERT INTO wcf" . WCF_N . "_conversation_to_user
+ $sql = "INSERT INTO wcf1_conversation_to_user
(conversationID, participantID, username, hideConversation, isInvisible, lastVisitTime)
VALUES (?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE hideConversation = IF(hideConversation > 0 AND hideConversation = VALUES(hideConversation),hideConversation,0),
isInvisible = IF(isInvisible AND VALUES(isInvisible),1,0),
lastVisitTime = GREATEST(lastVisitTime,VALUES(lastVisitTime))";
- $statement = WCF::getDB()->prepareStatement($sql);
+ $statement = WCF::getDB()->prepare($sql);
$statement->execute([
$data['conversationID'],
$data['participantID'],
// save labels
if ($data['participantID'] && !empty($additionalData['labelIDs'])) {
- $sql = "INSERT IGNORE INTO wcf" . WCF_N . "_conversation_label_to_object
+ $sql = "INSERT IGNORE INTO wcf1_conversation_label_to_object
(labelID, conversationID)
VALUES (?, ?)";
- $statement = WCF::getDB()->prepareStatement($sql);
+ $statement = WCF::getDB()->prepare($sql);
foreach ($additionalData['labelIDs'] as $labelID) {
$labelID = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.conversation.label', $labelID);
if ($labelID) {
* @author Alexander Ebert
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Log\Modification
*/
class ConversationModificationLogHandler extends VoidExtendedModificationLogHandler
{
* @author Alexander Ebert
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Message\Quote
*/
class ConversationMessageQuoteHandler extends AbstractMessageQuoteHandler
{
* @author Alexander Ebert
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Moderation\Queue
*/
class ConversationMessageModerationQueueReportHandler extends AbstractModerationQueueHandler implements
IModerationQueueReportHandler
* @author Matthias Schmidt
* @copyright 2001-2019 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
* @author Matthias Schmidt
* @copyright 2001-2019 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
* @author Matthias Schmidt
* @copyright 2001-2019 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
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Search
*/
final class ConversationMessageSearch extends AbstractSearchProvider
{
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Stat
*/
class ConversationMessageStatDailyHandler extends AbstractStatDailyHandler
{
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Stat
*/
class ConversationStatDailyHandler extends AbstractStatDailyHandler
{
* @author Joshua Ruesweg
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Content\Provider
* @since 5.2
*/
class ConversationMessageUserContentProvider extends AbstractDatabaseUserContentProvider
* @author Joshua Ruesweg
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Content\Provider
* @since 5.2
*/
class ConversationUserContentProvider extends AbstractDatabaseUserContentProvider
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Event
*
* @method ConversationMessageUserNotificationObject getUserNotificationObject()
*/
/**
* @inheritDoc
*/
- public function getTitle()
+ public function getTitle(): string
{
$count = \count($this->getAuthors());
if ($count > 1) {
/**
* @inheritDoc
*/
- public function getMessage()
+ public function getMessage(): string
{
$authors = \array_values($this->getAuthors());
$count = \count($authors);
* @inheritDoc
* @since 5.2
*/
- public function getEmailTitle()
+ public function getEmailTitle(): string
{
if (\count($this->getAuthors()) > 1) {
return parent::getEmailTitle();
/**
* @inheritDoc
*/
- public function getLink()
+ public function getLink(): string
{
return $this->getUserNotificationObject()->getLink();
}
/**
* @inheritDoc
*/
- public function getEventHash()
+ public function getEventHash(): string
{
return \sha1($this->eventID . '-' . $this->getUserNotificationObject()->conversationID);
}
/**
* @inheritDoc
*/
- public function checkAccess()
+ public function checkAccess(): bool
{
return $this->getUserNotificationObject()->getConversation()->canRead();
}
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Event
*
* @method ConversationUserNotificationObject getUserNotificationObject()
*/
/**
* @inheritDoc
*/
- public function getTitle()
+ public function getTitle(): string
{
return $this->getLanguage()->get('wcf.user.notification.conversation.title');
}
/**
* @inheritDoc
*/
- public function getMessage()
+ public function getMessage(): string
{
return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message', [
'author' => $this->author,
* @inheritDoc
* @since 5.2
*/
- public function getEmailTitle()
+ public function getEmailTitle(): string
{
return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.mail.title', [
'author' => $this->author,
/**
* @inheritDoc
*/
- public function getLink()
+ public function getLink(): string
{
return $this->getUserNotificationObject()->getLink();
}
/**
* @inheritDoc
*/
- public function checkAccess()
+ public function checkAccess(): bool
{
return $this->getUserNotificationObject()->canRead();
}
* @author Matthias Schmidt
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Event
* @since 3.1
*/
trait TTestableConversationRelatedUserNotificationEvent
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Object
*
* @method ConversationMessage getDecoratedObject()
* @mixin ConversationMessage
/**
* @inheritDoc
*/
- public function getTitle()
+ public function getTitle(): string
{
return $this->getConversation()->subject;
}
/**
* @inheritDoc
*/
- public function getURL()
+ public function getURL(): string
{
return $this->getLink();
}
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Object
*
* @method Conversation getDecoratedObject()
* @mixin Conversation
/**
* @inheritDoc
*/
- public function getTitle()
+ public function getTitle(): string
{
return $this->subject;
}
/**
* @inheritDoc
*/
- public function getURL()
+ public function getURL(): string
{
return $this->getLink();
}
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Object\Type
*/
class ConversationMessageNotificationObjectType extends AbstractUserNotificationObjectType
{
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Object\Type
*/
class ConversationNotificationObjectType extends AbstractUserNotificationObjectType
{
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Worker
*
* @method ConversationMessageList getObjectList()
*/
if ($this->count === null) {
$this->count = 0;
$sql = "SELECT MAX(messageID) AS messageID
- FROM wcf" . WCF_N . "_conversation_message";
- $statement = WCF::getDB()->prepareStatement($sql);
+ FROM wcf1_conversation_message";
+ $statement = WCF::getDB()->prepare($sql);
$statement->execute();
$row = $statement->fetchArray();
if ($row !== false) {
$attachmentObjectType = ObjectTypeCache::getInstance()
->getObjectTypeByName('com.woltlab.wcf.attachment.objectType', 'com.woltlab.wcf.conversation.message');
$sql = "SELECT COUNT(*) AS attachments
- FROM wcf" . WCF_N . "_attachment
+ FROM wcf1_attachment
WHERE objectTypeID = ?
AND objectID = ?";
- $attachmentStatement = WCF::getDB()->prepareStatement($sql);
+ $attachmentStatement = WCF::getDB()->prepare($sql);
// retrieve permissions
$userIDs = [];
$updateData[$message->messageID] = $data;
}
- $sql = "UPDATE wcf" . WCF_N . "_conversation_message
+ $sql = "UPDATE wcf1_conversation_message
SET attachments = ?,
message = ?,
enableHtml = ?,
hasEmbeddedObjects = ?
WHERE messageID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
+ $statement = WCF::getDB()->prepare($sql);
WCF::getDB()->beginTransaction();
foreach ($updateData as $messageID => $data) {
* @author Tim Duesterhus
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Worker
*
* @method ConversationMessageList getObjectList()
*/
if ($this->count === null) {
$this->count = 0;
$sql = "SELECT MAX(messageID) AS messageID
- FROM wcf" . WCF_N . "_conversation_message";
- $statement = WCF::getDB()->prepareStatement($sql);
+ FROM wcf1_conversation_message";
+ $statement = WCF::getDB()->prepare($sql);
$statement->execute();
$row = $statement->fetchArray();
if ($row !== false) {
* @author Marcel Werk
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Worker
*
* @method ConversationList getObjectList()
*/
if ($this->count === null) {
$this->count = 0;
$sql = "SELECT MAX(conversationID) AS conversationID
- FROM wcf" . WCF_N . "_conversation";
- $statement = WCF::getDB()->prepareStatement($sql);
+ FROM wcf1_conversation";
+ $statement = WCF::getDB()->prepare($sql);
$statement->execute();
$row = $statement->fetchArray();
if ($row !== false) {
// prepare statements
$sql = "SELECT messageID, time, userID, username
- FROM wcf" . WCF_N . "_conversation_message
+ FROM wcf1_conversation_message
WHERE conversationID = ?
ORDER BY time";
- $firstMessageStatement = WCF::getDB()->prepareStatement($sql, 1);
+ $firstMessageStatement = WCF::getDB()->prepare($sql, 1);
$sql = "SELECT time, userID, username
- FROM wcf" . WCF_N . "_conversation_message
+ FROM wcf1_conversation_message
WHERE conversationID = ?
ORDER BY time DESC";
- $lastMessageStatement = WCF::getDB()->prepareStatement($sql, 1);
+ $lastMessageStatement = WCF::getDB()->prepare($sql, 1);
$sql = "SELECT COUNT(*) AS messages,
SUM(attachments) AS attachments
- FROM wcf" . WCF_N . "_conversation_message
+ FROM wcf1_conversation_message
WHERE conversationID = ?";
- $statsStatement = WCF::getDB()->prepareStatement($sql);
+ $statsStatement = WCF::getDB()->prepare($sql);
$sql = "SELECT COUNT(*) AS participants
- FROM wcf" . WCF_N . "_conversation_to_user conversation_to_user
+ FROM wcf1_conversation_to_user conversation_to_user
WHERE conversation_to_user.conversationID = ?
AND conversation_to_user.hideConversation <> ?
AND conversation_to_user.participantID <> ?
AND conversation_to_user.isInvisible = ?";
- $participantCounterStatement = WCF::getDB()->prepareStatement($sql);
+ $participantCounterStatement = WCF::getDB()->prepare($sql);
$sql = "SELECT conversation_to_user.participantID AS userID, conversation_to_user.hideConversation, user_table.username
- FROM wcf" . WCF_N . "_conversation_to_user conversation_to_user
- LEFT JOIN wcf" . WCF_N . "_user user_table
+ FROM wcf1_conversation_to_user conversation_to_user
+ LEFT JOIN wcf1_user user_table
ON user_table.userID = conversation_to_user.participantID
WHERE conversation_to_user.conversationID = ?
AND conversation_to_user.participantID <> ?
AND conversation_to_user.isInvisible = ?
ORDER BY user_table.username";
- $participantStatement = WCF::getDB()->prepareStatement($sql, 5);
+ $participantStatement = WCF::getDB()->prepare($sql, 5);
$sql = "SELECT COUNT(*) AS participants
- FROM wcf" . WCF_N . "_conversation_to_user
+ FROM wcf1_conversation_to_user
WHERE conversationID = ?
AND hideConversation <> ?
AND participantID IS NOT NULL";
- $existingParticipantStatement = WCF::getDB()->prepareStatement($sql);
+ $existingParticipantStatement = WCF::getDB()->prepare($sql);
$obsoleteConversations = [];
$updateData = [];
$updateData[$conversation->conversationID] = $data;
}
- $sql = "UPDATE wcf" . WCF_N . "_conversation
+ $sql = "UPDATE wcf1_conversation
SET firstMessageID = ?,
lastPostTime = ?,
lastPosterID = ?,
participants = ?,
participantSummary = ?
WHERE conversationID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
+ $statement = WCF::getDB()->prepare($sql);
WCF::getDB()->beginTransaction();
foreach ($updateData as $conversationID => $data) {
<item name="wcf.acp.option.module_conversation"><![CDATA[Konversationen]]></item>
</category>
<category name="wcf.acp.rebuildData">
- <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation"><![CDATA[Konversationen aktualisieren]]></item>
- <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.description"><![CDATA[Aktualisiert Zähler der Konversationen]]></item>
- <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message"><![CDATA[Konversationsnachrichten aktualisieren]]></item>
- <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.description"><![CDATA[Aktualisiert Zähler der Konversationsnachrichten]]></item>
- <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.search.index"><![CDATA[Suchindex für Konversationsnachrichten aktualisieren]]></item>
- <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.search.index.description"><![CDATA[Warnung: Die Ausführung dieser Aktion kann bei größeren Foren sehr lange dauern.]]></item>
+ <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationRebuildDataWorker"><![CDATA[Konversationen aktualisieren]]></item>
+ <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationRebuildDataWorker.description"><![CDATA[Aktualisiert Zähler der Konversationen]]></item>
+ <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationMessageRebuildDataWorker"><![CDATA[Konversationsnachrichten aktualisieren]]></item>
+ <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationMessageRebuildDataWorker.description"><![CDATA[Aktualisiert Zähler der Konversationsnachrichten]]></item>
+ <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationMessageSearchIndexRebuildDataWorker"><![CDATA[Suchindex für Konversationsnachrichten aktualisieren]]></item>
+ <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationMessageSearchIndexRebuildDataWorker.description"><![CDATA[Warnung: Die Ausführung dieser Aktion kann bei größeren Foren sehr lange dauern.]]></item>
</category>
<category name="wcf.acp.stat">
<item name="wcf.acp.stat.com.woltlab.wcf.conversation"><![CDATA[Konversationen]]></item>
<item name="wcf.conversation.log.conversation.open"><![CDATA[Hat die Konversation wieder geöffnet.]]></item>
<item name="wcf.conversation.log.conversation.close"><![CDATA[Hat die Konversation für neue Nachrichten geschlossen.]]></item>
<item name="wcf.conversation.log.conversation.leave"><![CDATA[Hat die Konversation verlassen.]]></item>
- <item name="wcf.conversation.log.conversation.addParticipants"><![CDATA[Hat folgende Teilnehmer hinzugefügt: {implode from=$additionalData[participants] item=participant}<a href="{link controller='User' id=$participant[userID] title=$participant[username]}{/link}" class="userLink" data-object-id="{@$participant[userID]}">{$participant[username]}</a>{/implode}]]></item>
- <item name="wcf.conversation.log.conversation.removeParticipant"><![CDATA[Hat folgenden Teilnehmer entfernt: <a href="{link controller='User' id=$additionalData[userID] title=$additionalData[username]}{/link}" class="userLink" data-object-id="{@$additionalData[userID]}">{$additionalData[username]}</a>]]></item>
+ <item name="wcf.conversation.log.conversation.addParticipants"><![CDATA[Hat folgende Teilnehmer hinzugefügt: {implode from=$additionalData[participants] item=participant}<a href="{link controller='User' id=$participant[userID] title=$participant[username]}{/link}" class="userLink" data-object-id="{$participant[userID]}">{$participant[username]}</a>{/implode}]]></item>
+ <item name="wcf.conversation.log.conversation.removeParticipant"><![CDATA[Hat folgenden Teilnehmer entfernt: <a href="{link controller='User' id=$additionalData[userID] title=$additionalData[username]}{/link}" class="userLink" data-object-id="{$additionalData[userID]}">{$additionalData[username]}</a>]]></item>
</category>
<category name="wcf.acp.dataImport">
<item name="wcf.acp.dataImport.data.com.woltlab.wcf.conversation"><![CDATA[Konversationen]]></item>
</category>
</import>
<delete>
- <item name="wcf.conversation.markAllAsRead" />
+ <item name="wbb.conversation.gotoFirstNewPost"/>
+ <item name="wbb.conversation.gotoLastPost"/>
+ <item name="wcf.acp.group.canBeAddedAsParticipant"/>
+ <item name="wcf.acp.group.option.user.conversation.allowedAttachmentExtensions.description"/>
+ <item name="wcf.acp.option.conversation_reply_show_messages_max"/>
+ <item name="wcf.acp.option.conversation_reply_show_messages_max.description"/>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation"/>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.description"/>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message"/>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.description"/>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.search.index"/>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.search.index.description"/>
+ <item name="wcf.clipboard.item.conversation.assignLabel"/>
+ <item name="wcf.clipboard.item.conversation.close"/>
+ <item name="wcf.clipboard.item.conversation.leave"/>
+ <item name="wcf.clipboard.item.conversation.leavePermanently"/>
+ <item name="wcf.clipboard.item.conversation.open"/>
+ <item name="wcf.clipboard.item.conversation.restore"/>
+ <item name="wcf.clipboard.label.conversation.marked"/>
+ <item name="wcf.conversation.gotoFirstNewPost"/>
+ <item name="wcf.conversation.log"/>
+ <item name="wcf.conversation.log.action"/>
+ <item name="wcf.conversation.log.noEntries"/>
+ <item name="wcf.conversation.log.time"/>
+ <item name="wcf.conversation.log.title"/>
+ <item name="wcf.conversation.markAllAsRead"/>
+ <item name="wcf.conversation.markAllAsRead.confirmMessage"/>
+ <item name="wcf.conversation.message.add"/>
+ <item name="wcf.conversation.message.add.previousPosts"/>
+ <item name="wcf.conversation.message.new"/>
+ <item name="wcf.conversation.subject"/>
+ <item name="wcf.page.category.com.woltlab.wcf.conversation"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.Conversation"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.ConversationAdd"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.ConversationAddForm"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.ConversationList"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.ConversationListPage"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageAdd"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageAddForm"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageEdit"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageEditForm"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.ConversationPage"/>
+ <item name="wcf.page.onlineLocation.com.woltlab.wcf.conversation.ConversationAdd"/>
+ <item name="wcf.page.onlineLocation.com.woltlab.wcf.conversation.ConversationList"/>
+ <item name="wcf.page.onlineLocation.com.woltlab.wcf.conversation.ConversationMessageAdd"/>
+ <item name="wcf.page.onlineLocation.com.woltlab.wcf.conversation.ConversationMessageEdit"/>
+ <item name="wcf.user.notification.com.woltlab.wcf.conversation.conversation"/>
+ <item name="wcf.user.notification.com.woltlab.wcf.conversation.conversationMessage"/>
+ <item name="wcf.user.notification.conversation.mail"/>
+ <item name="wcf.user.notification.conversation.message.mail"/>
+ <item name="wcf.user.notification.conversation.message.output"/>
+ <item name="wcf.user.notification.conversation.message.shortOutput"/>
+ <item name="wcf.user.notification.conversation.output"/>
+ <item name="wcf.user.notification.conversation.shortOutput"/>
+ <item name="wcf.user.usersOnline.location.ConversationAddForm"/>
+ <item name="wcf.user.usersOnline.location.ConversationListPage"/>
+ <item name="wcf.user.usersOnline.location.ConversationMessageAddForm"/>
+ <item name="wcf.user.usersOnline.location.ConversationMessageEditForm"/>
+ <item name="wcf.user.usersOnline.location.ConversationPage"/>
</delete>
</language>
<item name="wcf.acp.option.module_conversation"><![CDATA[Conversations]]></item>
</category>
<category name="wcf.acp.rebuildData">
- <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation"><![CDATA[Rebuild Conversations]]></item>
- <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.description"><![CDATA[Rebuilds the conversation counters.]]></item>
- <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message"><![CDATA[Rebuild Conversation Messages]]></item>
- <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.description"><![CDATA[Rebuilds the conversation message counters.]]></item>
- <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.search.index"><![CDATA[Rebuild Conversation Message Search Index]]></item>
- <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.search.index.description"><![CDATA[Warning: This action can take a while to complete on large forums.]]></item>
+ <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationRebuildDataWorker"><![CDATA[Rebuild Conversations]]></item>
+ <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationRebuildDataWorker.description"><![CDATA[Rebuilds the conversation counters.]]></item>
+ <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationMessageRebuildDataWorker"><![CDATA[Rebuild Conversation Messages]]></item>
+ <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationMessageRebuildDataWorker.description"><![CDATA[Rebuilds the conversation message counters.]]></item>
+ <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationMessageSearchIndexRebuildDataWorker"><![CDATA[Rebuild Conversation Message Search Index]]></item>
+ <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationMessageSearchIndexRebuildDataWorker.description"><![CDATA[Warning: This action can take a while to complete on large forums.]]></item>
</category>
<category name="wcf.acp.stat">
<item name="wcf.acp.stat.com.woltlab.wcf.conversation"><![CDATA[Conversations]]></item>
<item name="wcf.conversation.log.conversation.open"><![CDATA[Opened the conversation again.]]></item>
<item name="wcf.conversation.log.conversation.close"><![CDATA[Closed the conversation for new replies.]]></item>
<item name="wcf.conversation.log.conversation.leave"><![CDATA[Left the conversation.]]></item>
- <item name="wcf.conversation.log.conversation.addParticipants"><![CDATA[Added the following participants: {implode from=$additionalData[participants] item=participant}<a href="{link controller='User' id=$participant[userID] title=$participant[username]}{/link}" class="userLink" data-object-id="{@$participant[userID]}">{$participant[username]}</a>{/implode}.]]></item>
- <item name="wcf.conversation.log.conversation.removeParticipant"><![CDATA[Removed a participant: <a href="{link controller='User' id=$additionalData[userID] title=$additionalData[username]}{/link}" class="userLink" data-object-id="{@$additionalData[userID]}">{$additionalData[username]}</a>.]]></item>
+ <item name="wcf.conversation.log.conversation.addParticipants"><![CDATA[Added the following participants: {implode from=$additionalData[participants] item=participant}<a href="{link controller='User' id=$participant[userID] title=$participant[username]}{/link}" class="userLink" data-object-id="{$participant[userID]}">{$participant[username]}</a>{/implode}.]]></item>
+ <item name="wcf.conversation.log.conversation.removeParticipant"><![CDATA[Removed a participant: <a href="{link controller='User' id=$additionalData[userID] title=$additionalData[username]}{/link}" class="userLink" data-object-id="{$additionalData[userID]}">{$additionalData[username]}</a>.]]></item>
</category>
<category name="wcf.acp.dataImport">
<item name="wcf.acp.dataImport.data.com.woltlab.wcf.conversation"><![CDATA[Conversations]]></item>
</category>
</import>
<delete>
- <item name="wcf.conversation.markAllAsRead" />
+ <item name="wcf.acp.group.canBeAddedAsParticipant"/>
+ <item name="wcf.acp.group.option.user.conversation.allowedAttachmentExtensions.description"/>
+ <item name="wcf.acp.option.conversation_reply_show_messages_max"/>
+ <item name="wcf.acp.option.conversation_reply_show_messages_max.description"/>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation"/>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.description"/>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message"/>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.description"/>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.search.index"/>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.search.index.description"/>
+ <item name="wcf.clipboard.item.conversation.assignLabel"/>
+ <item name="wcf.clipboard.item.conversation.close"/>
+ <item name="wcf.clipboard.item.conversation.leave"/>
+ <item name="wcf.clipboard.item.conversation.leavePermanently"/>
+ <item name="wcf.clipboard.item.conversation.open"/>
+ <item name="wcf.clipboard.item.conversation.restore"/>
+ <item name="wcf.clipboard.label.conversation.marked"/>
+ <item name="wcf.conversation.gotoFirstNewPost"/>
+ <item name="wcf.conversation.markAllAsRead"/>
+ <item name="wcf.conversation.markAllAsRead.confirmMessage"/>
+ <item name="wcf.conversation.message.add"/>
+ <item name="wcf.conversation.message.add.previousPosts"/>
+ <item name="wcf.conversation.message.new"/>
+ <item name="wcf.conversation.subject"/>
+ <item name="wcf.page.category.com.woltlab.wcf.conversation"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.Conversation"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.ConversationAdd"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.ConversationAddForm"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.ConversationList"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.ConversationListPage"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageAdd"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageAddForm"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageEdit"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageEditForm"/>
+ <item name="wcf.page.com.woltlab.wcf.conversation.ConversationPage"/>
+ <item name="wcf.page.onlineLocation.com.woltlab.wcf.conversation.ConversationAdd"/>
+ <item name="wcf.page.onlineLocation.com.woltlab.wcf.conversation.ConversationList"/>
+ <item name="wcf.page.onlineLocation.com.woltlab.wcf.conversation.ConversationMessageAdd"/>
+ <item name="wcf.page.onlineLocation.com.woltlab.wcf.conversation.ConversationMessageEdit"/>
+ <item name="wcf.user.notification.conversation.mail"/>
+ <item name="wcf.user.notification.conversation.message.mail"/>
+ <item name="wcf.user.notification.conversation.message.output"/>
+ <item name="wcf.user.notification.conversation.message.shortOutput"/>
+ <item name="wcf.user.notification.conversation.output"/>
+ <item name="wcf.user.notification.conversation.shortOutput"/>
+ <item name="wcf.user.usersOnline.location.ConversationAddForm"/>
+ <item name="wcf.user.usersOnline.location.ConversationListPage"/>
+ <item name="wcf.user.usersOnline.location.ConversationMessageAddForm"/>
+ <item name="wcf.user.usersOnline.location.ConversationMessageEditForm"/>
+ <item name="wcf.user.usersOnline.location.ConversationPage"/>
</delete>
</language>
</type>
<!-- /importers -->
<!-- rebuild data workers -->
- <type>
- <name>com.woltlab.wcf.conversation</name>
- <definitionname>com.woltlab.wcf.rebuildData</definitionname>
- <classname>wcf\system\worker\ConversationRebuildDataWorker</classname>
- </type>
- <type>
- <name>com.woltlab.wcf.conversation.message</name>
- <definitionname>com.woltlab.wcf.rebuildData</definitionname>
- <classname>wcf\system\worker\ConversationMessageRebuildDataWorker</classname>
- <nicevalue>-5</nicevalue>
- </type>
- <type>
- <name>com.woltlab.wcf.conversation.message.search.index</name>
- <definitionname>com.woltlab.wcf.rebuildData</definitionname>
- <classname>wcf\system\worker\ConversationMessageSearchIndexRebuildDataWorker</classname>
- <nicevalue>121</nicevalue>
- </type>
+
<!-- /rebuild data workers -->
<!-- stat handlers -->
<type>
<definitionname>com.woltlab.wcf.floodControl</definitionname>
</type>
</import>
+ <delete>
+ <type name="com.woltlab.wcf.conversation">
+ <definitionname>com.woltlab.wcf.rebuildData</definitionname>
+ <classname>wcf\system\worker\ConversationRebuildDataWorker</classname>
+ </type>
+ <type name="com.woltlab.wcf.conversation.message">
+ <definitionname>com.woltlab.wcf.rebuildData</definitionname>
+ <classname>wcf\system\worker\ConversationMessageRebuildDataWorker</classname>
+ <nicevalue>-5</nicevalue>
+ </type>
+ <type name="com.woltlab.wcf.conversation.message.search.index">
+ <definitionname>com.woltlab.wcf.rebuildData</definitionname>
+ <classname>wcf\system\worker\ConversationMessageSearchIndexRebuildDataWorker</classname>
+ <nicevalue>121</nicevalue>
+ </type>
+ </delete>
</data>
"packages": {
"": {
"dependencies": {
- "@woltlab/wcf": "https://github.com/WoltLab/WCF.git#5ed76b3a3267dfbffdf19405822d22510ad2bc7d"
+ "@woltlab/wcf": "https://github.com/WoltLab/WCF.git#d0139b8637e75c763701d96a722e0835c8986a37"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.51.0",
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/@googlemaps/markerclusterer": {
+ "version": "2.0.15",
+ "resolved": "https://registry.npmjs.org/@googlemaps/markerclusterer/-/markerclusterer-2.0.15.tgz",
+ "integrity": "sha512-/I6Esi5FtyeVHsezN9Kut8zRJoqe7KkTIJXGVqpKFf6BjC7qQ1xRajLMkOz0s8XKgLevbr+KdYjuvmj+LohOGg==",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "supercluster": "^7.1.3"
+ }
+ },
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.8",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
}
},
"node_modules/@woltlab/wcf": {
- "version": "5.4.0",
- "resolved": "git+ssh://git@github.com/WoltLab/WCF.git#5ed76b3a3267dfbffdf19405822d22510ad2bc7d",
- "integrity": "sha512-RFdoxbASRY4VpBSZkGhI6Vovf49YR4D9bjdxweJgobf+rPAcJAXmE5idzwk3osKrUS+yH2STewzsxZ6Bpak5cQ==",
+ "version": "6.0.0",
+ "resolved": "git+ssh://git@github.com/WoltLab/WCF.git#d0139b8637e75c763701d96a722e0835c8986a37",
+ "integrity": "sha512-pdZOdlN0pJKk8m4JwPgB+/9su/OzRVP2K53vnwuXKdxWv0igLZxphYwSUq4uicBOyzcd0qF4T8OLFxqPocfaFA==",
"dependencies": {
+ "@googlemaps/markerclusterer": "^2.0.15",
"@types/facebook-js-sdk": "^3.3.6",
"@types/google.maps": "^3.51.1",
"@types/jquery": "^3.5.14",
"@types/perfect-scrollbar": "^0.7.0",
"@types/pica": "^5.1.3",
- "@types/prismjs": "^1.16.6",
+ "@types/prismjs": "^1.26.0",
"@types/twitter-for-web": "0.0.2",
- "focus-trap": "^6.9.4",
+ "focus-trap": "^7.2.0",
+ "html-parsed-element": "^0.4.1",
"qr-creator": "^1.0.0",
- "tabbable": "^5.3.3",
+ "reflect-metadata": "^0.1.13",
+ "tabbable": "^6.0.1",
"tslib": "^2.5.0"
}
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"node_modules/fast-glob": {
"version": "3.2.12",
"dev": true
},
"node_modules/focus-trap": {
- "version": "6.9.4",
- "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-6.9.4.tgz",
- "integrity": "sha512-v2NTsZe2FF59Y+sDykKY+XjqZ0cPfhq/hikWVL88BqLivnNiEffAsac6rP6H45ff9wG9LL5ToiDqrLEP9GX9mw==",
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.2.0.tgz",
+ "integrity": "sha512-v4wY6HDDYvzkBy4735kW5BUEuw6Yz9ABqMYLuTNbzAFPcBOGiGHwwcNVMvUz4G0kgSYh13wa/7TG3XwTeT4O/A==",
"dependencies": {
- "tabbable": "^5.3.3"
+ "tabbable": "^6.0.1"
}
},
"node_modules/fs.realpath": {
"node": ">=8"
}
},
+ "node_modules/html-parsed-element": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/html-parsed-element/-/html-parsed-element-0.4.1.tgz",
+ "integrity": "sha512-uRNt6oVAFAQ/PBS9JZiURMpR2Me0KR11mOG6sbamJl1PIX7qMX1h/ck2EhY11RPU4m39o9x9XvOs5KaLneaxGA=="
+ },
"node_modules/ignore": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
"dev": true
},
+ "node_modules/kdbush": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-3.0.0.tgz",
+ "integrity": "sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew=="
+ },
"node_modules/levn": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
}
]
},
+ "node_modules/reflect-metadata": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
+ "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg=="
+ },
"node_modules/regexpp": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/supercluster": {
+ "version": "7.1.5",
+ "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-7.1.5.tgz",
+ "integrity": "sha512-EulshI3pGUM66o6ZdH3ReiFcvHpM3vAigyK+vcxdjpJyEbIIrtbmBdY23mGgnI24uXiGFvrGq9Gkum/8U7vJWg==",
+ "dependencies": {
+ "kdbush": "^3.0.0"
+ }
+ },
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
}
},
"node_modules/tabbable": {
- "version": "5.3.3",
- "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz",
- "integrity": "sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA=="
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.0.1.tgz",
+ "integrity": "sha512-SYJSIgeyXW7EuX1ytdneO5e8jip42oHWg9xl/o3oTYhmXusZVgiA+VlPvjIN+kHii9v90AmzTZEBcsEvuAY+TA=="
},
"node_modules/text-table": {
"version": "0.2.0",
"strip-json-comments": "^3.1.1"
}
},
+ "@googlemaps/markerclusterer": {
+ "version": "2.0.15",
+ "resolved": "https://registry.npmjs.org/@googlemaps/markerclusterer/-/markerclusterer-2.0.15.tgz",
+ "integrity": "sha512-/I6Esi5FtyeVHsezN9Kut8zRJoqe7KkTIJXGVqpKFf6BjC7qQ1xRajLMkOz0s8XKgLevbr+KdYjuvmj+LohOGg==",
+ "requires": {
+ "fast-deep-equal": "^3.1.3",
+ "supercluster": "^7.1.3"
+ }
+ },
"@humanwhocodes/config-array": {
"version": "0.11.8",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
}
},
"@woltlab/wcf": {
- "version": "git+ssh://git@github.com/WoltLab/WCF.git#5ed76b3a3267dfbffdf19405822d22510ad2bc7d",
- "integrity": "sha512-RFdoxbASRY4VpBSZkGhI6Vovf49YR4D9bjdxweJgobf+rPAcJAXmE5idzwk3osKrUS+yH2STewzsxZ6Bpak5cQ==",
- "from": "@woltlab/wcf@https://github.com/WoltLab/WCF.git#5ed76b3a3267dfbffdf19405822d22510ad2bc7d",
+ "version": "git+ssh://git@github.com/WoltLab/WCF.git#d0139b8637e75c763701d96a722e0835c8986a37",
+ "integrity": "sha512-pdZOdlN0pJKk8m4JwPgB+/9su/OzRVP2K53vnwuXKdxWv0igLZxphYwSUq4uicBOyzcd0qF4T8OLFxqPocfaFA==",
+ "from": "@woltlab/wcf@https://github.com/WoltLab/WCF.git#d0139b8637e75c763701d96a722e0835c8986a37",
"requires": {
+ "@googlemaps/markerclusterer": "^2.0.15",
"@types/facebook-js-sdk": "^3.3.6",
"@types/google.maps": "^3.51.1",
"@types/jquery": "^3.5.14",
"@types/perfect-scrollbar": "^0.7.0",
"@types/pica": "^5.1.3",
- "@types/prismjs": "^1.16.6",
+ "@types/prismjs": "^1.26.0",
"@types/twitter-for-web": "0.0.2",
- "focus-trap": "^6.9.4",
+ "focus-trap": "^7.2.0",
+ "html-parsed-element": "^0.4.1",
"qr-creator": "^1.0.0",
- "tabbable": "^5.3.3",
+ "reflect-metadata": "^0.1.13",
+ "tabbable": "^6.0.1",
"tslib": "^2.5.0"
}
},
"fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"fast-glob": {
"version": "3.2.12",
"dev": true
},
"focus-trap": {
- "version": "6.9.4",
- "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-6.9.4.tgz",
- "integrity": "sha512-v2NTsZe2FF59Y+sDykKY+XjqZ0cPfhq/hikWVL88BqLivnNiEffAsac6rP6H45ff9wG9LL5ToiDqrLEP9GX9mw==",
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.2.0.tgz",
+ "integrity": "sha512-v4wY6HDDYvzkBy4735kW5BUEuw6Yz9ABqMYLuTNbzAFPcBOGiGHwwcNVMvUz4G0kgSYh13wa/7TG3XwTeT4O/A==",
"requires": {
- "tabbable": "^5.3.3"
+ "tabbable": "^6.0.1"
}
},
"fs.realpath": {
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
+ "html-parsed-element": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/html-parsed-element/-/html-parsed-element-0.4.1.tgz",
+ "integrity": "sha512-uRNt6oVAFAQ/PBS9JZiURMpR2Me0KR11mOG6sbamJl1PIX7qMX1h/ck2EhY11RPU4m39o9x9XvOs5KaLneaxGA=="
+ },
"ignore": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
"dev": true
},
+ "kdbush": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-3.0.0.tgz",
+ "integrity": "sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew=="
+ },
"levn": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
"dev": true
},
+ "reflect-metadata": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
+ "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg=="
+ },
"regexpp": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true
},
+ "supercluster": {
+ "version": "7.1.5",
+ "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-7.1.5.tgz",
+ "integrity": "sha512-EulshI3pGUM66o6ZdH3ReiFcvHpM3vAigyK+vcxdjpJyEbIIrtbmBdY23mGgnI24uXiGFvrGq9Gkum/8U7vJWg==",
+ "requires": {
+ "kdbush": "^3.0.0"
+ }
+ },
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
}
},
"tabbable": {
- "version": "5.3.3",
- "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz",
- "integrity": "sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA=="
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.0.1.tgz",
+ "integrity": "sha512-SYJSIgeyXW7EuX1ytdneO5e8jip42oHWg9xl/o3oTYhmXusZVgiA+VlPvjIN+kHii9v90AmzTZEBcsEvuAY+TA=="
},
"text-table": {
"version": "0.2.0",
"typescript": "^4.9.5"
},
"dependencies": {
- "@woltlab/wcf": "https://github.com/WoltLab/WCF.git#5ed76b3a3267dfbffdf19405822d22510ad2bc7d"
+ "@woltlab/wcf": "https://github.com/WoltLab/WCF.git#d0139b8637e75c763701d96a722e0835c8986a37"
}
}
<packagename language="de">WoltLab Suite Core: Konversationen</packagename>
<packagedescription>Private conversations between multiple users</packagedescription>
<packagedescription language="de">Private Konversationen zwischen mehreren Benutzern</packagedescription>
- <version>5.5.5</version>
- <date>2022-09-22</date>
+ <version>6.0.0 dev 1</version>
+ <date>2022-08-30</date>
</packageinformation>
<authorinformation>
</authorinformation>
<requiredpackages>
- <requiredpackage minversion="5.5.5">com.woltlab.wcf</requiredpackage>
+ <requiredpackage minversion="6.0.0 dev 1">com.woltlab.wcf</requiredpackage>
</requiredpackages>
<excludedpackages>
- <excludedpackage version="5.6.0 Alpha 1">com.woltlab.wcf</excludedpackage>
+ <excludedpackage version="6.1.0 Alpha 1">com.woltlab.wcf</excludedpackage>
</excludedpackages>
<instructions type="install">
<instruction type="eventListener" />
<instruction type="page" />
</instructions>
-
- <instructions type="update" fromversion="5.4.*">
+
+ <instructions type="update" fromversion="5.5.*">
<instruction type="file" />
<instruction type="template" />
- <instruction type="database">acp/database/update_com.woltlab.wcf.conversation_5.5_step1.php</instruction>
- <instruction type="database">acp/database/update_com.woltlab.wcf.conversation_5.5_step2.php</instruction>
-
- <instruction type="acpTemplateDelete" />
- <instruction type="fileDelete" />
- <instruction type="templateDelete" />
<instruction type="language" />
<instruction type="objectType" />
+ <instruction type="templateListener" />
- <!-- Updates to <moddefaultvalue> only -->
- <instruction type="userGroupOption" />
-
- <instruction type="script">acp/update_com.woltlab.wcf.conversation_5.5_cleanup_orphaned_attachments.php</instruction>
- </instructions>
-
- <instructions type="update" fromversion="5.5.3">
- <instruction type="language"/>
-
- <instruction type="userGroupOption"/>
- </instructions>
-
- <instructions type="update" fromversion="5.5.5 dev 1">
- <void/>
+ <instruction type="templateDelete" />
</instructions>
</package>
<?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/2019/templateDelete.xsd">
<delete>
- <template>__userStartConversation</template>
- <template>conversationListUnread</template>
- <template>conversationLog</template>
- <template>conversationMessageAdd</template>
- <template>conversationMessageEdit</template>
- <template>searchResultConversationMessage</template>
+ <template>conversationListUserPanel</template>
</delete>
</data>
<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>
<templatelistener name="userGroupAddCanBeAddedAsConversationParticipant">
<environment>admin</environment>
<templatename>userGroupAdd</templatename>
<templatecode><![CDATA[{include file='__userGroupAddCanBeAddedAsConversationParticipant'}]]></templatecode>
</templatelistener>
</import>
+ <delete>
+ <templatelistener name="mobileMenuConversation">
+ <environment>user</environment>
+ <templatename>pageMenuMobile</templatename>
+ <eventname>userMenuItems</eventname>
+ <templatecode><![CDATA[{include file='__mobileMenuConversation'}]]></templatecode>
+ </templatelistener>
+ </delete>
</data>
+++ /dev/null
-{if MODULE_CONVERSATION && $__wcf->user->userID && $__wcf->session->getPermission('user.conversation.canUseConversation')}
- <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}
{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'}extended=1&type=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}
+ {capture assign='__searchTypesScoped'}<li><a href="#" data-extended-link="{link controller='Search'}extended=1&type=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') && $__wcf->session->getPermission('user.conversation.canStartConversation') && $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 fa-comments"></span> <span class="invisible">{lang}wcf.conversation.button.add{/lang}</span></a></li>
-{/if}
\ No newline at end of file
+ <li>
+ <a class="jsTooltip" href="{link controller='ConversationAdd'}userID={@$user->userID}{/link}" title="{lang}wcf.conversation.button.add{/lang}">
+ {icon name='comments' type='solid'}
+ <span class="invisible">{lang}wcf.conversation.button.add{/lang}</span>
+ </a>
+ </li>
+{/if}
aria-haspopup="true"
aria-expanded="false"
>
- <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}
+ {icon size=32 name='comments' type='solid'}
+ <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" src="{$__wcf->getPath()}js/WCF.Conversation{if !ENABLE_DEBUG_MODE}.min{/if}.js?v={@LAST_UPDATE_TIME}"></script>
<script data-relocate="true">
require(["WoltLabSuite/Core/Conversation/Ui/User/Menu/Data/Conversation"], ({ setup }) => {
setup({
</div>
<div class="contentHeaderTitle">
- <h1 class="contentTitle jsConversationSubject" data-conversation-id="{@$conversation->conversationID}">{$conversation->subject}</h1>
+ <h1 class="contentTitle jsConversationSubject" data-conversation-id="{$conversation->conversationID}">{$conversation->subject}</h1>
<ul class="inlineList contentHeaderMetaData">
{hascontent}
<li>
- <span class="icon icon16 fa-tags"></span>
+ {icon name='tags'}
<ul class="labelList">
{content}
{foreach from=$conversation->getAssignedLabels() item=label}
{/hascontent}
<li>
- <span class="icon icon16 fa-user"></span>
+ {icon name='user'}
{user object=$conversation->getUserProfile()}
</li>
<li>
- <span class="icon icon16 fa-clock-o"></span>
+ {icon name='clock'}
<a href="{$conversation->getLink()}">{@$conversation->time|time}</a>
</li>
{if $conversation->isClosed}
<li>
- <span class="icon icon16 fa-lock jsIconLock"></span>
+ <span class="jsIconLock">
+ {icon name='lock'}
+ </span>
{lang}wcf.global.state.closed{/lang}
</li>
{/if}
<nav class="contentHeaderNavigation">
<ul>
{content}
- {if $conversation->canReply()}<li class="jsOnly"><a href="#" class="button buttonPrimary jsQuickReply"><span class="icon icon16 fa-reply"></span> <span>{lang}wcf.conversation.message.button.add{/lang}</span></a></li>{/if}
+ {if $conversation->canReply()}
+ <li class="jsOnly">
+ <button type="button" class="button buttonPrimary jsQuickReply">
+ {icon name='reply'}
+ <span>{lang}wcf.conversation.message.button.add{/lang}</span>
+ </button>
+ </li>
+ {/if}
{event name='contentHeaderNavigation'}
{/content}
</ul>
{/capture}
{capture assign='contentInteractionButtons'}
- <div class="conversation jsConversationInlineEditorContainer contentInteractionButton" 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}" data-is-draft="{if $conversation->isDraft}1{else}0{/if}">
- <a href="{if $conversation->isDraft}{link controller='ConversationDraftEdit' id=$conversation->conversationID}{/link}{else}#{/if}" class="button small jsConversationInlineEditor"><span class="icon icon16 fa-pencil"></span> <span>{lang}wcf.global.button.edit{/lang}</span></a>
+ <div class="conversation jsConversationInlineEditorContainer contentInteractionButton" 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}" data-is-draft="{if $conversation->isDraft}1{else}0{/if}">
+ {if $conversation->isDraft}
+ <a href="{link controller='ConversationDraftEdit' id=$conversation->conversationID}{/link}" class="button small jsConversationInlineEditor">
+ {icon name='pencil'}
+ <span>{lang}wcf.global.button.edit{/lang}</span>
+ </a>
+ {else}
+ <button type="button" class="button small jsConversationInlineEditor">
+ {icon name='pencil'}
+ <span>{lang}wcf.global.button.edit{/lang}</span>
+ </button>
+ {/if}
</div>
{/capture}
<ul class="containerBoxList tripleColumned conversationParticipantList jsObjectActionContainer" data-object-action-class-name="wcf\data\conversation\ConversationAction">
{foreach from=$participants item=participant}
- <li class="jsParticipant jsObjectActionObject{if !$participant->userID || $participant->hideConversation == 2 || $participant->leftAt > 0} conversationLeft{/if}" data-object-id="{@$conversation->getObjectID()}">
+ <li class="jsParticipant jsObjectActionObject{if !$participant->userID || $participant->hideConversation == 2 || $participant->leftAt > 0} conversationLeft{/if}" data-object-id="{$conversation->getObjectID()}">
<div class="box24">
{user object=$participant type='avatar24' ariaHidden='true' tabindex='-1'}
<div>
{user object=$participant}
{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 && $participant->leftAt == 0}
- <a href="#" class="jsObjectAction jsTooltip jsOnly" data-object-action="removeParticipant" title="{lang}wcf.conversation.participants.removeParticipant{/lang}" data-confirm-message="{lang __encode=true}wcf.conversation.participants.removeParticipant.confirmMessage{/lang}" data-object-action-parameter-user-id="{@$participant->getObjectID()}"><span class="icon icon16 fa-times"></span></a>
+ <button
+ type="button"
+ class="jsObjectAction jsTooltip jsOnly"
+ data-object-action="removeParticipant"
+ title="{lang}wcf.conversation.participants.removeParticipant{/lang}"
+ data-confirm-message="{lang __encode=true}wcf.conversation.participants.removeParticipant.confirmMessage{/lang}"
+ data-object-action-parameter-user-id="{$participant->getObjectID()}"
+ >
+ {icon name='xmark'}
+ </button>
{/if}
</p>
<dl class="plain inlineDataList small">
</ul>
</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>
+{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.label.assignLabels': '{jslang}wcf.conversation.label.assignLabels{/jslang}'
});
- var $availableLabels = [ {implode from=$labelList item=label}{ cssClassName: '{if $label->cssClassName}{@$label->cssClassName}{/if}', labelID: {@$label->labelID}, label: '{$label->label|encodeJS}' }{/implode} ];
+ var $availableLabels = [ {implode from=$labelList item=label}{ cssClassName: '{if $label->cssClassName}{@$label->cssClassName|encodeJS}{/if}', labelID: {@$label->labelID}, label: '{$label->label|encodeJS}' }{/implode} ];
var $editorHandler = new WCF.Conversation.EditorHandlerConversation($availableLabels);
var $inlineEditor = new WCF.Conversation.InlineEditor('.conversation');
$inlineEditor.setEditorHandler($editorHandler);
<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">
+ <input type="text" id="subject" name="subject" value="{$subject}" required autofocus maxlength="255" class="long">
{if $errorField == 'subject'}
<small class="innerError">
{if $errorType == 'empty'}
<div class="formSubmit">
<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>
+ <button type="submit" class="button" name="draft" accesskey="d" value="1">{lang}wcf.conversation.button.saveAsDraft{/lang}</button>
{include file='messageFormPreviewButton' previewMessageObjectType='com.woltlab.wcf.conversation.message' previewMessageObjectID=0}
{csrfToken}
</div>
{/if}
<div class="formSubmit">
- <button id="addParticipants" class="buttonPrimary">{lang}wcf.global.button.submit{/lang}</button>
+ <button type="button" id="addParticipants" class="button buttonPrimary">{lang}wcf.global.button.submit{/lang}</button>
</div>
\ No newline at end of file
{foreach from=$labelList item=label}
<li>
<label>
- <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>
+ <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>
<div class="formSubmit">
- <button class="buttonPrimary" id="assignLabels">{lang}wcf.global.button.save{/lang}</button>
+ <button type="button" class="button buttonPrimary" id="assignLabels">{lang}wcf.global.button.save{/lang}</button>
</div>
<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>
+ <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>
<ul role="group" aria-label="{lang}wcf.conversation.label.cssClassName{/lang}" id="labelManagementList">
{foreach from=$cssClassNames item=cssClassName}
<li><label>
- <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>
+ <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}
</ul>
</dl>
<div class="formSubmit">
- <button id="addLabel" class="buttonPrimary">{lang}wcf.global.button.save{/lang}</button>
- <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>
+ <button type="button" id="addLabel" class="button buttonPrimary">{lang}wcf.global.button.save{/lang}</button>
+ <button type="button" id="editLabel" class="button" style="display: none;" class="buttonPrimary">{lang}wcf.global.button.save{/lang}</button>
+ <button type="button" id="deleteLabel" class="button" style="display: none;">{lang}wcf.conversation.label.management.deleteLabel{/lang}</button>
</div>
-</section>
\ No newline at end of file
+</section>
</dl>
<div class="formSubmit">
- <button id="hideConversation" class="buttonPrimary">{lang}wcf.global.button.submit{/lang}</button>
+ <button type="button" id="hideConversation" class="button buttonPrimary">{lang}wcf.global.button.submit{/lang}</button>
</div>
<nav class="contentHeaderNavigation">
<ul>
{content}
- {if $__wcf->session->getPermission('user.conversation.canStartConversation')}<li><a href="{link controller='ConversationAdd'}{/link}" title="{lang}wcf.conversation.add{/lang}" class="button buttonPrimary"><span class="icon icon16 fa-plus"></span> <span>{lang}wcf.conversation.button.add{/lang}</span></a></li>{/if}
+ {if $__wcf->session->getPermission('user.conversation.canStartConversation')}
+ <li>
+ <a href="{link controller='ConversationAdd'}{/link}" title="{lang}wcf.conversation.add{/lang}" class="button buttonPrimary">
+ {icon name='plus'}
+ <span>{lang}wcf.conversation.button.add{/lang}</span>
+ </a>
+ </li>
+ {/if}
{event name='contentHeaderNavigation'}
{/content}
</ul>
{if $labelID}
{foreach from=$labelList item=label}
{if $label->labelID == $labelID}
- <span class="badge label{if $label->cssClassName} {@$label->cssClassName}{/if}">{$label->label}</span>
+ <span class="badge label{if $label->cssClassName} {$label->cssClassName}{/if}">{$label->label}</span>
{/if}
{/foreach}
{else}
<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>
+ <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>
</div>
<div class="boxContent">
- <button id="manageLabel">{lang}wcf.conversation.label.management{/lang}</button>
+ <button type="button" id="manageLabel" class="button">{lang}wcf.conversation.label.management{/lang}</button>
</div>
</section>
{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}">
- <span style="width: {if $conversationCount/$maxConversationCount < 1.0}{@$conversationCount/$maxConversationCount*100|round:0}{else}100{/if}%">{#$conversationCount/$maxConversationCount*100}%</span>
+ <span style="width: {if $conversationCount/$maxConversationCount < 1.0}{$conversationCount/$maxConversationCount*100|round:0}{else}100{/if}%">{#$conversationCount/$maxConversationCount*100}%</span>
</p>
<p><small>{lang}wcf.conversation.quota.description{/lang}</small></p>
</div>
{/capture}
{capture assign='contentInteractionButtons'}
- <a href="#" class="markAllAsReadButton contentInteractionButton button small jsOnly"><span class="icon icon16 fa-check"></span> <span>{lang}wcf.global.button.markAllAsRead{/lang}</span></a>
+ <button type="button" class="markAllAsReadButton contentInteractionButton button small jsOnly">
+ {icon name='check'}
+ <span>{lang}wcf.global.button.markAllAsRead{/lang}</span>
+ </button>
{/capture}
{capture assign='contentInteractionDropdownItems'}
<ul class="inlineList">
<li>
<a rel="nofollow" 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={$sortField}&sortOrder={if $sortOrder == 'ASC'}DESC{else}ASC{/if}{if $labelID}&labelID={@$labelID}{/if}{/link}">
- <span class="icon icon16 fa-sort-amount-{$sortOrder|strtolower} jsTooltip" title="{lang}wcf.global.sorting{/lang} ({lang}wcf.global.sortOrder.{if $sortOrder === 'ASC'}ascending{else}descending{/if}{/lang})"></span>
+ {if $sortOrder === 'ASC'}
+ <span class="jsTooltip" title="{lang}wcf.global.sorting{/lang} ({lang}wcf.global.sortOrder.ascending{/lang})">
+ {icon name='arrow-down-wide-short'}
+ </span>
+ {else}
+ <span class="jsTooltip" title="{lang}wcf.global.sorting{/lang} ({lang}wcf.global.sortOrder.descending{/lang})">
+ {icon name='arrow-down-short-wide'}
+ </span>
+ {/if}
</a>
</li>
<li>
{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}">
+ <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>
+ <label><input type="checkbox" class="jsClipboardItem" data-object-id="{$conversation->conversationID}"></label>
</li>
<li class="columnIcon columnAvatar">
{if $conversation->getUserProfile()->getAvatar()}
{/hascontent}
<h3>
- <a href="{if $conversation->isNew()}{link controller='Conversation' object=$conversation}action=firstNew{/link}{else}{$conversation->getLink()}{/if}" class="conversationLink messageGroupLink" data-object-id="{@$conversation->conversationID}">{$conversation->subject}</a>
+ <a href="{if $conversation->isNew()}{link controller='Conversation' object=$conversation}action=firstNew{/link}{else}{$conversation->getLink()}{/if}" class="conversationLink messageGroupLink" data-object-id="{$conversation->conversationID}">{$conversation->subject}</a>
{if $conversation->replies}
<span class="badge messageGroupCounterMobile">{@$conversation->replies|shortUnit}</span>
{/if}
<aside class="statusDisplay" role="presentation">
<ul class="statusIcons">
- {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}
+ {if $conversation->isClosed}
+ <li>
+ <span class="jsIconLock jsTooltip" title="{lang}wcf.global.state.closed{/lang}">
+ {icon name='lock'}
+ </span>
+ </li>
+ {/if}
+ {if $conversation->attachments}
+ <li>
+ <span class="jsIconAttachment jsTooltip" title="{lang}wcf.conversation.attachments{/lang}">
+ {icon name='paperclip'}
+ </span>
+ </li>
+ {/if}
</ul>
</aside>
{if $conversation->getParticipantSummary()|count}
<small class="conversationParticipantSummary">
{assign var='participantSummaryCount' value=$conversation->getParticipantSummary()|count}
- {lang}wcf.conversation.participants{/lang}: {implode from=$conversation->getParticipantSummary() item=participant}<a href="{$participant->getLink()}" class="userLink{if $participant->hideConversation == 2} conversationLeft{/if}" data-object-id="{@$participant->userID}">{$participant->username}</a>{/implode}
+ {lang}wcf.conversation.participants{/lang}: {implode from=$conversation->getParticipantSummary() item=participant}<a href="{$participant->getLink()}" class="userLink{if $participant->hideConversation == 2} conversationLeft{/if}" data-object-id="{$participant->userID}">{$participant->username}</a>{/implode}
{if $participantSummaryCount < $conversation->participants}{lang}wcf.conversation.participants.other{/lang}{/if}
</small>
{/if}
<dd>{@$conversation->participants|shortUnit}</dd>
</dl>
- <div class="messageGroupListStatsSimple">{if $conversation->replies}<span class="icon icon16 fa-comment-o" aria-label="{lang}wcf.conversation.replies{/lang}"></span> {@$conversation->replies|shortUnit}{/if}</div>
+ <div class="messageGroupListStatsSimple">
+ {if $conversation->replies}
+ <span aria-label="{lang}wcf.conversation.replies{/lang}">
+ {icon name='comment'}
+ </span>
+ {@$conversation->replies|shortUnit}
+ {/if}
+ </div>
</li>
<li class="columnLastPost">
{if $conversation->replies != 0 && $conversation->lastPostTime}
<nav class="contentFooterNavigation">
<ul>
{content}
- {if $__wcf->session->getPermission('user.conversation.canStartConversation')}<li><a href="{link controller='ConversationAdd'}{/link}" title="{lang}wcf.conversation.add{/lang}" class="button buttonPrimary"><span class="icon icon16 fa-plus"></span> <span>{lang}wcf.conversation.button.add{/lang}</span></a></li>{/if}
+ {if $__wcf->session->getPermission('user.conversation.canStartConversation')}
+ <li>
+ <a href="{link controller='ConversationAdd'}{/link}" title="{lang}wcf.conversation.add{/lang}" class="button buttonPrimary">
+ {icon name='plus'}
+ <span>{lang}wcf.conversation.button.add{/lang}</span>
+ </a>
+ </li>
+ {/if}
{event name='contentFooterNavigation'}
{/content}
</ul>
{/hascontent}
</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" src="{$__wcf->getPath()}js/WCF.Conversation{if !ENABLE_DEBUG_MODE}.min{/if}.js?v={@LAST_UPDATE_TIME}"></script>
<script data-relocate="true">
require([
'WoltLabSuite/Core/Language',
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.MarkAsRead();
- new WCF.Conversation.MarkAllAsRead();
// mobile safari hover workaround
if ($(window).width() <= 800) {
});
</script>
+<script data-relocate="true">
+ require(['WoltLabSuite/Core/Conversation/Ui/MarkAsRead'], (MarkAsRead) => {
+ MarkAsRead.setup();
+ });
+ require(['WoltLabSuite/Core/Conversation/Ui/MarkAllAsRead'], (MarkAllAsRead) => {
+ MarkAllAsRead.setup();
+ });
+</script>
+
{include file='footer'}
+++ /dev/null
-{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="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(48)}
- {/if}
- </div>
- <div>
- <h3><a href="{link controller='Conversation' object=$conversation}action=firstNew{/link}">{$conversation->subject}</a></h3>
- <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="{$participant->getLink()}" class="userLink{if $participant->hideConversation == 2} conversationLeft{/if}" data-object-id="{@$participant->userID}">{$participant->username}</a>{/implode}
- {if $participantSummaryCount < $conversation->participants}{lang}wcf.conversation.participants.other{/lang}{/if}
- {else}
- {user object=$conversation->getOtherParticipantProfile()}
- {/if}
- {else}
- {user object=$conversation->getUserProfile()}
- {/if}
- </span>
-
- <span class="conversationLastPostTime">{@$conversation->lastPostTime|time}</span>
- </small>
- </div>
- </div>
- </li>
-{/foreach}
{capture assign='wysiwygSelector'}messageEditor{@$message->messageID}{/capture}
<div class="messageInlineEditor">
<textarea id="{$wysiwygSelector}" class="wysiwygTextarea"
- data-autosave="com.woltlab.wcf.conversation.messageEdit-{@$message->messageID}"
+ 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.save{/lang}</button>
+ <button type="button" class="button buttonPrimary" data-type="save">{lang}wcf.global.button.save{/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>
+ <button type="button" class="button" data-type="cancel">{lang}wcf.global.button.cancel{/lang}</button>
</div>
{include file='wysiwyg' wysiwygEnableUpload=true}
{assign var='objectID' value=$message->messageID}
{assign var='userProfile' value=$message->getUserProfile()}
- <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-user-id="{@$message->userID}" data-can-edit="{if $message->canEdit()}1{else}0{/if}" data-object-id="{@$message->messageID}">
+ <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-user-id="{$message->userID}" 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>
+ <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>
</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>
+ <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>
{event name='messageQuickOptions'}
</ul>
<div class="messageFooterGroup">
<ul class="messageFooterButtons buttonList smallButtons jsMobileNavigation">
- {if $message->canEdit()}<li class="jsOnly"><a href="{if $conversation->isDraft && $message->messageID == $conversation->firstMessageID}{link controller='ConversationDraftEdit' id=$conversation->conversationID}{/link}{else}#{/if}" 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}
+ {if $message->canEdit()}
+ <li class="jsOnly">
+ <a
+ href="{if $conversation->isDraft && $message->messageID == $conversation->firstMessageID}{link controller='ConversationDraftEdit' id=$conversation->conversationID}{/link}{else}#{/if}"
+ title="{lang}wcf.conversation.message.edit{/lang}"
+ class="button{if !$conversation->isDraft || $message->messageID != $conversation->firstMessageID} jsMessageEditButton{/if}"
+ >
+ {icon name='pencil'}
+ <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}"
+ >
+ {icon name='quote-left' type='solid'}
+ <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}">
+ <button type="button" title="{lang}wcf.moderation.report.reportContent{/lang}" class="button jsTooltip">
+ {icon name='triangle-exclamation'}
+ <span class="invisible">{lang}wcf.moderation.report.reportContent{/lang}</span>
+ </button>
+ </li>
+ {/if}
{event name='messageFooterButtons'}
</ul>
</div>
-<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}">
+<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() isReply=true enableMicrodata=false}
<div class="messageContent messageQuickReplyContent"{if $pageNo < $pages} data-placeholder="{lang}wcf.conversation.reply{/lang}"{/if}>
{event name='beforeWysiwyg'}
<textarea id="text" name="text" class="wysiwygTextarea"
- data-autosave="com.woltlab.wcf.conversation.messageAdd-{@$conversation->conversationID}"
+ data-autosave="com.woltlab.wcf.conversation.messageAdd-{$conversation->conversationID}"
data-support-mention="true"
></textarea>
{include file='messageFormTabsInline' inConversationQuickReply=true}
<footer class="messageFooter">
<div class="formSubmit">
- <button class="buttonPrimary" data-type="save" accesskey="s">{lang}wcf.global.button.reply{/lang}</button>
+ <button class="button buttonPrimary" data-type="save" accesskey="s">{lang}wcf.global.button.reply{/lang}</button>
{include file='messageFormPreviewButton' previewMessageObjectType='com.woltlab.wcf.conversation.message' previewMessageObjectID=0}
</div>
</footer>
</article>
{include file='wysiwyg'}
-</li>
\ No newline at end of file
+</li>
{user object=$message->getUserProfile() type='avatar32' ariaHidden='true' tabindex='-1'}
<div class="messageHeaderBox">
- <h2 class="messageTitle">{if $message->getConversation()->canRead()}<a href="{@$message->getLink()}">{$message->getTitle()}</a>{else}{$message->getTitle()}{/if}</h2>
+ <h2 class="messageTitle">{if $message->getConversation()->canRead()}<a href="{$message->getLink()}">{$message->getTitle()}</a>{else}{$message->getTitle()}{/if}</h2>
<ul class="messageHeaderMetaData">
<li>{user object=$message->getUserProfile() class='username'}</li>
{event name='afterMessageText'}
</div>
</div>
-</article>
\ No newline at end of file
+</article>
<dl>
<dt></dt>
- <dd><label><input type="checkbox" name="conversationID" value="{@$searchedConversation->conversationID}" checked> {lang}wcf.conversation.searchedConversation{/lang}</label></dd>
+ <dd><label><input type="checkbox" name="conversationID" value="{$searchedConversation->conversationID}" checked> {lang}wcf.conversation.searchedConversation{/lang}</label></dd>
</dl>
--- /dev/null
+/**
+ * Marks all conversations as read.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2022 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.0
+ */
+
+import { dboAction } from "WoltLabSuite/Core/Ajax";
+import * as UiNotification from "WoltLabSuite/Core/Ui/Notification";
+
+async function markAllAsRead(): Promise<void> {
+ await dboAction("markAllAsRead", "wcf\\data\\conversation\\ConversationAction").dispatch();
+
+ document.querySelectorAll(".conversationList .new").forEach((el: HTMLElement) => {
+ el.classList.remove("new");
+ });
+ document.querySelector("#unreadConversations .badgeUpdate")?.remove();
+
+ UiNotification.show();
+}
+
+export function setup(): void {
+ document.querySelectorAll(".markAllAsReadButton").forEach((el: HTMLElement) => {
+ el.addEventListener("click", (event) => {
+ event.preventDefault();
+
+ void markAllAsRead();
+ });
+ });
+}
--- /dev/null
+/**
+ * Handles the mark as read button for single conversations.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2022 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.0
+ */
+
+import { dboAction } from "WoltLabSuite/Core/Ajax";
+
+const unreadConversations = new WeakSet();
+
+async function markAsRead(conversation: HTMLElement): Promise<void> {
+ const conversationId = parseInt(conversation.dataset.conversationId!, 10);
+
+ await dboAction("markAsRead", "wcf\\data\\conversation\\ConversationAction").objectIds([conversationId]).dispatch();
+
+ conversation.classList.remove("new");
+ conversation.querySelector(".columnAvatar p")?.removeAttribute("title");
+}
+
+export function setup(): void {
+ document.querySelectorAll(".conversationList .new .columnAvatar").forEach((el: HTMLElement) => {
+ if (!unreadConversations.has(el)) {
+ unreadConversations.add(el);
+
+ el.addEventListener(
+ "dblclick",
+ (event) => {
+ event.preventDefault();
+
+ const conversation = el.closest(".conversation") as HTMLElement;
+ if (!conversation.classList.contains("new")) {
+ return;
+ }
+ void markAsRead(conversation);
+ },
+ { once: true },
+ );
+ }
+ });
+}
* @author Matthias Schmidt
* @copyright 2001-2021 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module WoltLabSuite/Core/Conversation/Ui/Message/Quote
* @woltlabExcludeBundle tiny
*/
* @author Matthias Schmidt
* @copyright 2001-2021 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module WoltLabSuite/Core/Conversation/Ui/Object/Action/RemoveParticipant
*/
import UiObjectActionHandler from "WoltLabSuite/Core/Ui/Object/Action/Handler";
* @author Alexander Ebert
* @copyright 2001-2021 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module WoltLabSuite/Core/Conversation/Ui/Participant/Add
*/
import * as Ajax from "WoltLabSuite/Core/Ajax";
* @author Alexander Ebert
* @copyright 2001-2021 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module WoltLabSuite/Core/Conversation/Ui/Subject/Editor
*/
import { DialogCallbackObject } from "WoltLabSuite/Core/Ui/Dialog/Data";
import UiDialog from "WoltLabSuite/Core/Ui/Dialog";
</dd>
</dl>
<div class="formSubmit">
- <button class="buttonPrimary jsButtonSave">${Language.get("wcf.global.button.save")}</button>
+ <button type="button" class="button buttonPrimary jsButtonSave">${Language.get(
+ "wcf.global.button.save",
+ )}</button>
</div>
`,
};
* @author Alexander Ebert
* @copyright 2001-2021 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module WoltLabSuite/Core/Ui/User/Menu/Data/Notification
* @woltlabExcludeBundle tiny
*/
const buttons: UserMenuButton[] = [];
if (this.options.canStartConversation) {
buttons.push({
- icon: '<span class="icon icon24 fa-plus"></span>',
+ icon: '<fa-icon size="24" name="plus"></fa-icon>',
link: this.options.newConversationLink,
name: "newConversation",
title: this.options.newConversationTitle,
"ts/**/*"
],
"compilerOptions": {
- "target": "es2017",
+ "target": "ES2022",
"module": "amd",
"rootDir": "ts/",
"outDir": "files/js/",
"lib": [
- "dom",
- "es2017"
+ "DOM",
+ "DOM.Iterable",
+ "ES2022"
],
"strictNullChecks": true,
"moduleResolution": "node",