<name>com.woltlab.wcf.comment</name>
<definitionname>com.woltlab.wcf.message</definitionname>
</type>
+ <type>
+ <name>com.woltlab.wcf.comment.response</name>
+ <definitionname>com.woltlab.wcf.message</definitionname>
+ </type>
<type>
<name>com.woltlab.wcf.paidSubscription</name>
<definitionname>com.woltlab.wcf.message</definitionname>
<classname>wcf\system\worker\CommentRebuildDataWorker</classname>
<nicevalue>120</nicevalue>
</type>
+ <type>
+ <name>com.woltlab.wcf.comment.response</name>
+ <definitionname>com.woltlab.wcf.rebuildData</definitionname>
+ <classname>wcf\system\worker\CommentResponseRebuildDataWorker</classname>
+ <nicevalue>120</nicevalue>
+ </type>
<type>
<name>com.woltlab.wcf.sitemap</name>
<definitionname>com.woltlab.wcf.rebuildData</definitionname>
'wcf.moderation.report.success': '{lang}wcf.moderation.report.success{/lang}'
});
- new {if $commentHandlerClass|isset}{@$commentHandlerClass}{else}WCF.Comment.Handler{/if}('{$commentContainerID}', '{@$__wcf->getUserProfileHandler()->getAvatar()->getImageTag(48)}', '{@$__wcf->getUserProfileHandler()->getAvatar()->getImageTag(32)}');
+ new {if $commentHandlerClass|isset}{@$commentHandlerClass}{else}WCF.Comment.Handler{/if}('{$commentContainerID}');
{if MODULE_LIKE && $commentList->getCommentManager()->supportsLike() && $__wcf->getSession()->getPermission('user.like.canViewLike')}
require(['WoltLabSuite/Core/Ui/Like/Handler'], function(UiLikeHandler) {
var canDislike = {if LIKE_ENABLE_DISLIKE}true{else}false{/if};
<li class="box48 jsCommentAdd jsOnly">
{@$__wcf->getUserProfileHandler()->getAvatar()->getImageTag(48)}
- <div class="commentListAddComment collapsed" data-placeholder="{lang}wcf.comment.add{/lang}">
+ <div class="commentListAddComment collapsed jsOuterEditorContainer" data-placeholder="{lang}wcf.comment.add{/lang}">
<div class="commentListAddCommentEditorContainer">
{if !$commentList->getCommentManager()->canAddWithoutApproval($commentList->objectID)}
<p class="info jsCommentAddRequiresApproval">{lang}wcf.comment.moderation.info{/lang}</p>
</div>
</li>
+{* comment response, editor instance will be re-used *}
+{capture assign=_commentResponseWysiwygSelector}{$wysiwygSelector}Response{/capture}
+<li class="jsCommentResponseAddContainer" style="display: none">
+ <div class="box32 jsCommentResponseAdd jsOnly">
+ {@$__wcf->getUserProfileHandler()->getAvatar()->getImageTag(32)}
+ <div class="commentListAddCommentResponse collapsed jsOuterEditorContainer" data-placeholder="{lang}wcf.comment.response.add{/lang}">
+ <div class="commentListAddCommentResponseEditorContainer">
+ {if !$commentList->getCommentManager()->canAddWithoutApproval($commentList->objectID)}
+ <p class="info jsCommentAddRequiresApproval">{lang}wcf.comment.moderation.info{/lang}</p>
+ {/if}
+
+ <textarea id="{$_commentResponseWysiwygSelector}" name="text" class="wysiwygTextarea"
+ data-disable-attachments="true"
+ data-disable-media="true"
+ ></textarea>
+
+ {* in-template call for full backwards-compatibility *}
+ {$commentList->getCommentManager()->setDisallowedBBCodes()}
+
+ {include file='wysiwyg' wysiwygSelector=$_commentResponseWysiwygSelector}
+
+ <div class="formSubmit">
+ <button class="buttonPrimary" data-type="save" accesskey="s">{lang}wcf.global.button.submit{/lang}</button>
+
+ {include file='messageFormPreviewButton' previewMessageFieldID=$_commentResponseWysiwygSelector previewButtonID=$_commentResponseWysiwygSelector|concat:'_PreviewButton' previewMessageObjectType='com.woltlab.wcf.comment.response' previewMessageObjectID=0}
+ </div>
+ </div>
+ </div>
+ </div>
+</li>
--- /dev/null
+{capture assign='wysiwygSelector'}commentResponseEditor{@$response->responseID}{/capture}
+<textarea id="{$wysiwygSelector}" class="wysiwygTextarea"
+ data-disable-attachments="true"
+ data-disable-media="true"
+>{$response->message}</textarea>
+{*include file='messageFormTabsInline'*}
+
+<div class="formSubmit">
+ <button class="buttonPrimary" data-type="save" accesskey="s">{lang}wcf.global.button.submit{/lang}</button>
+
+ {include file='messageFormPreviewButton' previewMessageFieldID=$wysiwygSelector previewButtonID=$wysiwygSelector|concat:'_PreviewButton' previewMessageObjectType='com.woltlab.wcf.comment.response' previewMessageObjectID=$response->responseID}
+
+ <button data-type="cancel">{lang}wcf.global.button.cancel{/lang}</button>
+</div>
+
+{include file='wysiwyg'}
*/
_responses: { },
- /**
- * user's avatar (48px version)
- * @var string
- */
- _userAvatar: '',
-
- /**
- * user's avatar (32px version)
- * @var string
- */
- _userAvatarSmall: '',
+ _responseCache: {},
/**
* data of the comment the active guest user is about to create
* Initializes the WCF.Comment.Handler class.
*
* @param string containerID
- * @param string userAvatar
- * @param string userAvatarSmall
*/
- init: function(containerID, userAvatar, userAvatarSmall) {
+ init: function(containerID) {
this._commentButtonList = { };
this._comments = { };
this._containerID = containerID;
this._loadNextResponses = { };
this._permalinkComment = null;
this._permalinkResponse = null;
- this._responses = { };
+ this._responseAdd = null;
+ this._responseCache = {};
+ this._responseRevert = null;
+ this._responses = {};
this._scrollTarget = null;
- this._userAvatar = userAvatar;
- this._userAvatarSmall = userAvatarSmall;
this._container = $('#' + $.wcfEscapeID(this._containerID));
if (!this._container.length) {
}
this._proxy = new WCF.Action.Proxy({
- failure: $.proxy(this._failure, this),
success: $.proxy(this._success, this)
});
// add new comment
if (this._container.data('canAdd')) {
if (elBySel('.commentListAddComment .wysiwygTextarea', this._container[0]) === null) {
- console.debug("Missing WYSIWYG implementation, adding comments is not available.");
+ console.error("Missing WYSIWYG implementation, adding comments is not available.");
}
else {
- require(['WoltLabSuite/Core/Ui/Comment/Add'], (function (UiCommentAdd) {
+ require(['WoltLabSuite/Core/Ui/Comment/Add', 'WoltLabSuite/Core/Ui/Comment/Response/Add'], (function (UiCommentAdd, UiCommentResponseAdd) {
new UiCommentAdd(elBySel('.jsCommentAdd', this._container[0]));
+
+ this._responseAdd = new UiCommentResponseAdd(
+ elBySel('.jsCommentResponseAdd', this._container[0]),
+ {
+ callbackInsert: (function () {
+ if (this._responseRevert !== null) {
+ this._responseRevert();
+ this._responseRevert = null;
+ }
+ }).bind(this)
+ });
}).bind(this));
}
}
- require(['WoltLabSuite/Core/Ui/Comment/Edit'], (function (UiCommentEdit) {
+ require(['WoltLabSuite/Core/Ui/Comment/Edit', 'WoltLabSuite/Core/Ui/Comment/Response/Edit'], (function (UiCommentEdit, UiCommentResponseEdit) {
new UiCommentEdit(this._container[0]);
+ new UiCommentResponseEdit(this._container[0]);
}).bind(this));
WCF.DOMNodeInsertedHandler.execute();
*/
_initResponse: function(responseID, response) {
if (response.data('canEdit')) {
- var $editButton = $('<li><a href="#" class="jsTooltip" title="' + WCF.Language.get('wcf.global.button.edit') + '"><span class="icon icon16 fa-pencil" /> <span class="invisible">' + WCF.Language.get('wcf.global.button.edit') + '</span></a></li>');
-
- var self = this;
- $editButton.data('responseID', responseID).appendTo(response.find('ul.buttonList:eq(0)')).click(function(event) { self._prepareEdit(event, true); });
+ var $editButton = $('<li><a href="#" class="jsCommentResponseEditButton jsTooltip" title="' + WCF.Language.get('wcf.global.button.edit') + '"><span class="icon icon16 fa-pencil" /> <span class="invisible">' + WCF.Language.get('wcf.global.button.edit') + '</span></a></li>');
+ $editButton.data('responseID', responseID).appendTo(response.find('ul.buttonList:eq(0)'));
}
if (response.data('canDelete')) {
*/
_initAddResponse: function(commentID, comment) {
var $placeholder = $('<li class="jsCommentShowAddResponse"><a>' + WCF.Language.get('wcf.comment.button.response.add') + '</a></li>').data('commentID', commentID).click($.proxy(this._showAddResponse, this)).appendTo(this._commentButtonList[commentID]);
-
- var $listItem = $('<div class="box32 commentResponseAdd jsCommentResponseAdd">' + this._userAvatarSmall + '<div /></div>').hide();
- $listItem.appendTo(this._commentButtonList[commentID].parent().show());
-
- var $inputContainer = $listItem.children('div');
- var $input = $('<textarea placeholder="' + WCF.Language.get('wcf.comment.response.add') + '" maxlength="65535" class="long" />').data('commentID', commentID).appendTo($inputContainer).flexible();
- $('<button class="small">' + WCF.Language.get('wcf.global.button.submit') + '</button>').click($.proxy(function(event) { this._save(event, true); }, this)).appendTo($inputContainer);
-
- var self = this;
- $input.keyup(function(event) { self._keyUp(event, true); });
-
- comment.data('responsePlaceholder', $placeholder).data('responseInput', $listItem);
-
- // mirror the moderation notice
- var commentRequireApproval = elBySel('.commentListAddCommentEditorContainer .jsCommentAddRequiresApproval', this._container[0]);
- if (commentRequireApproval) {
- $inputContainer[0].insertBefore(commentRequireApproval.cloneNode(true), $inputContainer[0].firstChild);
- }
+ this._commentButtonList[commentID].parent().show();
},
/**
- * Prepares editing of a comment or response.
+ * Displays the UI elements to create a response.
*
* @param object event
- * @param boolean isResponse
*/
- _prepareEdit: function(event, isResponse) {
- if (!isResponse) {
- throw new Error("Editing comments is no longer supported through this method.");
+ _showAddResponse: function(event) {
+ event.preventDefault();
+
+ // API is missing
+ if (this._responseAdd === null) {
+ console.error("Missing response API.");
+ return;
}
- event.preventDefault();
- var $button = $(event.currentTarget);
- var $data = {
- objectID: this._container.data('objectID'),
- objectTypeID: this._container.data('objectTypeID'),
- responseID: $button.data('responseID')
- };
+ var responseContainer = this._responseAdd.getContainer();
+ if (responseContainer === null) {
+ // instance is busy
+ return;
+ }
+
+ if (this._responseRevert !== null) {
+ this._responseRevert();
+ this._responseRevert = null;
+ }
- this._proxy.setOption('data', {
- actionName: 'prepareEdit',
- className: 'wcf\\data\\comment\\CommentAction',
- parameters: {
- data: $data
- }
- });
- this._proxy.sendRequest();
- },
-
- /**
- * Displays the UI elements to create a response.
- *
- * @param object event
- */
- _showAddResponse: function(event) {
var $placeholder = $(event.currentTarget);
var $commentID = $placeholder.data('commentID');
if ($placeholder.prev().hasClass('jsCommentLoadNextResponses')) {
$placeholder.hide();
- var $responseInput = this._comments[$commentID].data('responseInput').show();
- $responseInput.find('textarea').focus();
-
- $responseInput.parents('.commentOptionContainer').addClass('jsAddResponseActive');
- },
-
- /**
- * Handles the keyup event for comments and responses.
- *
- * @param object event
- * @param boolean isResponse
- */
- _keyUp: function(event, isResponse) {
- if (event.which === $.ui.keyCode.ESCAPE) {
- // cancel input
- $(event.currentTarget).val('').trigger('blur', event).trigger('updateHeight');
-
- return;
- }
- else if (event.which === $.ui.keyCode.ENTER && event.ctrlKey) {
- this._save(null, isResponse, $(event.currentTarget));
-
- return false;
- }
- },
-
- /**
- * Saves entered comment/response.
- *
- * @param object event
- * @param boolean isResponse
- * @param jQuery input
- */
- _save: function(event, isResponse, input) {
- if (!isResponse) {
- throw new Error("Adding comments through `_save()` is no longer supported.");
- }
-
- var $input = (event === null) ? input : $(event.currentTarget).parent().children('textarea');
- $input.next('small.innerError').remove();
- var $value = $.trim($input.val());
-
- // ignore empty comments
- if ($value == '') {
- return;
+ if (responseContainer.parentNode && responseContainer.parentNode.classList.contains('jsCommentResponseAddContainer')) {
+ // strip the parent element, it is used as a work-around
+ elRemove(responseContainer.parentNode);
}
- var $data = {
- commentID: $input.data('commentID'),
- message: $value,
- objectID: this._container.data('objectID'),
- objectTypeID: this._container.data('objectTypeID')
- };
+ var commentOptionContainer = this._commentButtonList[$commentID][0].closest('.commentOptionContainer');
+ commentOptionContainer.parentNode.insertBefore(responseContainer, commentOptionContainer.nextSibling);
- if (!WCF.User.userID) {
- this._commentData = $data;
-
- // check if guest dialog has already been loaded
- this._proxy.setOption('data', {
- actionName: 'getGuestDialog',
- className: 'wcf\\data\\comment\\CommentAction',
- parameters: {
- data: {
- message: $value,
- objectID: this._container.data('objectID'),
- objectTypeID: this._container.data('objectTypeID')
- }
- }
- });
- this._proxy.sendRequest();
+ if (typeof this._responseCache[$commentID] === 'string') {
+ this._responseAdd.setContent(this._responseCache[$commentID]);
}
else {
- new WCF.Action.Proxy({
- autoSend: true,
- data: {
- actionName: 'addResponse',
- className: 'wcf\\data\\comment\\CommentAction',
- parameters: {
- data: $data
- }
- },
- success: $.proxy(this._success, this),
- failure: (function(data, jqXHR, textStatus, errorThrown) {
- if (data.returnValues && data.returnValues.fieldName) {
- if (data.returnValues.fieldName === 'text' && data.returnValues.errorType) {
- $('<small class="innerError">' + data.returnValues.errorType + '</small>').insertAfter($input);
-
- return false;
- }
- }
-
- this._failure(data, jqXHR, textStatus, errorThrown);
- }).bind(this)
- });
+ this._responseAdd.setContent('');
}
+
+ this._responseRevert = (function () {
+ this._responseCache[$commentID] = this._responseAdd.getContent();
+
+ elRemove(responseContainer);
+ $placeholder.show();
+ }).bind(this);
},
/**
}, this));
},
- /**
- * Handles a failed AJAX request.
- *
- * @param object data
- * @param object jqXHR
- * @param string textStatus
- * @param string errorThrown
- * @return boolean
- */
- _failure: function(data, jqXHR, textStatus, errorThrown) {
- if (!WCF.User.userID && this._guestDialog) {
- // enable submit button again
- this._guestDialog.find('input[type="submit"]').enable();
- }
-
- return true;
- },
-
/**
* Handles successful AJAX requests.
*
*/
_success: function(data, textStatus, jqXHR) {
switch (data.actionName) {
- case 'addResponse':
- if (data.returnValues.guestDialog) {
- this._createGuestDialog(data.returnValues.guestDialog, data.returnValues.useCaptcha);
- }
- else {
- var $comment = this._comments[data.returnValues.commentID];
- $comment.find('.jsCommentResponseAdd textarea').val('').blur().trigger('updateHeight');
-
- // revert response field
- elBySel('.commentOptionContainer', $comment[0]).classList.remove('jsAddResponseActive');
- elHide(elBySel('.jsCommentResponseAdd', $comment[0]));
- elShow(elBySel('.jsCommentShowAddResponse', $comment[0]));
-
- var $responseList = $comment.find('ul.commentResponseList');
- if (!$responseList.length) $responseList = $('<ul class="containerList commentResponseList" />').insertBefore($comment.find('.commentOptionContainer'));
- $(data.returnValues.template).appendTo($responseList).wcfFadeIn();
-
- if (!WCF.User.userID) {
- this._guestDialog.wcfDialog('close');
- }
- }
- break;
-
- case 'edit':
- this._update(data);
- break;
-
case 'enable':
this._enable(data);
break;
this._insertResponses(data);
break;
- case 'prepareEdit':
- this._edit(data);
- break;
-
case 'remove':
this._remove(data);
break;
-
- case 'getGuestDialog':
- this._createGuestDialog(data.returnValues.template, data.returnValues.useCaptcha);
- break;
}
WCF.DOMNodeInsertedHandler.execute();
var $response = this._responses[data.returnValues.responseID];
var $comment = this._comments[$response.parents('li.comment:eq(0)').data('commentID')];
- // decrease response counter as a correct response count
+ // decrease response counter because a correct response count
// is required in _handleLoadNextResponses()
$comment.data('responses', parseInt($comment.data('responses')) - 1);
}
},
- /**
- * Prepares editing of a comment or response.
- *
- * @param object data
- */
- _edit: function(data) {
- var $content;
- if (data.returnValues.commentID) {
- $content = this._comments[data.returnValues.commentID].find('.commentContent:eq(0) .userMessage:eq(0)');
- }
- else {
- $content = this._responses[data.returnValues.responseID].find('.commentContent:eq(0) .userMessage:eq(0)');
- }
-
- // replace content with input field
- $content.html($.proxy(function(index, oldHTML) {
- var $textarea = $('<textarea class="long" maxlength="65535" />').val(data.returnValues.message);
- $textarea.data('__html', oldHTML).keyup($.proxy(this._keyUpEdit, this));
-
- if (data.returnValues.commentID) {
- $textarea.data('commentID', data.returnValues.commentID);
- }
- else {
- $textarea.data('responseID', data.returnValues.responseID);
- }
-
- return $textarea;
- }, this));
- var $textarea = $content.children('textarea');
- $('<button class="small">' + WCF.Language.get('wcf.global.button.submit') + '</button>').insertAfter($textarea).click($.proxy(this._saveEdit, this));
- $textarea.focus().flexible();
-
- // hide elements
- $content.parent().find('.containerHeadline:eq(0)').hide();
- $content.parent().find('.buttonGroupNavigation:eq(0)').hide();
- },
-
- /**
- * Updates a comment or response.
- *
- * @param object data
- */
- _update: function(data) {
- var $input;
- if (data.returnValues.commentID) {
- $input = this._comments[data.returnValues.commentID].find('.commentContent:eq(0) .userMessage:eq(0) > textarea');
- }
- else {
- $input = this._responses[data.returnValues.responseID].find('.commentContent:eq(0) .userMessage:eq(0) > textarea');
- }
-
- $input.data('__html', data.returnValues.message);
-
- this._cancelEdit($input);
- },
-
- /**
- * Creates the guest dialog using the given template.
- *
- * @param string template
- * @param boolean useCaptcha
- */
- _createGuestDialog: function(template, useCaptcha) {
- var $refreshGuestDialog = !!this._guestDialog;
- if (!this._guestDialog) {
- this._guestDialog = $('<div id="commentAddGuestDialog" />').hide().appendTo(document.body);
- }
-
- this._guestDialog.html(template);
- this._guestDialog.data('useCaptcha', useCaptcha);
-
- // bind submit event listeners
- this._guestDialog.find('input[type="submit"]').click($.proxy(this._submit, this));
- this._guestDialog.find('input[type="text"]').keydown($.proxy(this._keyDown, this));
-
- this._guestDialog.wcfDialog({
- 'title': WCF.Language.get('wcf.comment.guestDialog.title')
- });
- },
-
- /**
- * Handles clicking enter in the input fields of the guest dialog by
- * submitting it.
- *
- * @param Event event
- */
- _keyDown: function(event) {
- if (event.which === $.ui.keyCode.ENTER) {
- this._submit();
- }
- },
-
- /**
- * Handles submitting the guest dialog.
- *
- * @param Event event
- */
- _submit: function(event) {
- var $requestData = {
- actionName: 'addResponse',
- className: 'wcf\\data\\comment\\CommentAction'
- };
-
- var $data = this._commentData;
- $data.username = this._guestDialog.find('input[name="username"]').val();
-
- $requestData.parameters = {
- data: $data
- };
-
- var $captchaData = WCF.System.Captcha.getData('commentAdd');
- if ($captchaData instanceof Promise) {
- $captchaData.then($.proxy(function ($captchaData) {
- $requestData = $.extend($captchaData, $requestData);
- this._proxy.setOption('data', $requestData);
- this._proxy.sendRequest();
- }, this))
- }
- else {
- $requestData = $.extend($captchaData, $requestData);
- this._proxy.setOption('data', $requestData);
- this._proxy.sendRequest();
- }
- },
-
- /**
- * Handles the keyup event for comments and responses during edit.
- *
- * @param object event
- */
- _keyUpEdit: function(event) {
- if (event.which === $.ui.keyCode.ESCAPE) {
- // cancel input
- this._cancelEdit($(event.currentTarget));
- return;
- }
- else if (event.which === $.ui.keyCode.ENTER && event.ctrlKey) {
- this._saveEdit(event);
- return false;
- }
- },
-
- /**
- * Saves editing of a comment or response.
- *
- * @param object event
- */
- _saveEdit: function(event) {
- var $input = $(event.currentTarget);
- if ($input.is('button')) {
- $input.parent().children('small.innerError').remove();
- $input = $input.parent().children('textarea');
- }
- var $message = $.trim($input.val());
-
- // ignore empty message
- if ($message === '') {
- return;
- }
-
- var $data = {
- message: $message,
- objectID: this._container.data('objectID'),
- objectTypeID: this._container.data('objectTypeID')
- };
- if ($input.data('commentID')) {
- $data.commentID = $input.data('commentID');
- }
- else {
- $data.responseID = $input.data('responseID');
- }
-
- new WCF.Action.Proxy({
- autoSend: true,
- data: {
- actionName: 'edit',
- className: 'wcf\\data\\comment\\CommentAction',
- parameters: {
- data: $data
- }
- },
- success: $.proxy(this._success, this),
- failure: (function(data, jqXHR, textStatus, errorThrown) {
- if (data.returnValues && data.returnValues.fieldName) {
- if (data.returnValues.fieldName === 'text' && data.returnValues.errorType) {
- $('<small class="innerError">' + data.returnValues.errorType + '</small>').insertAfter($input);
-
- return false;
- }
- }
-
- this._failure(data, jqXHR, textStatus, errorThrown);
- }).bind(this)
- });
- },
-
- /**
- * Cancels editing of a comment or response.
- *
- * @param jQuery input
- */
- _cancelEdit: function(input) {
- // restore elements
- input.parent().prev('.containerHeadline:eq(0)').show();
- input.parent().next('.buttonGroupNavigation:eq(0)').show();
-
- // restore HTML
- input.parent().html(input.data('__html'));
- }
+ _prepareEdit: function() { console.warn("This method is no longer supported."); },
+ _keyUp: function() { console.warn("This method is no longer supported."); },
+ _save: function() { console.warn("This method is no longer supported."); },
+ _failure: function() { console.warn("This method is no longer supported."); },
+ _edit: function() { console.warn("This method is no longer supported."); },
+ _update: function() { console.warn("This method is no longer supported."); },
+ _createGuestDialog: function() { console.warn("This method is no longer supported."); },
+ _keyDown: function() { console.warn("This method is no longer supported."); },
+ _submit: function() { console.warn("This method is no longer supported."); },
+ _keyUpEdit: function() { console.warn("This method is no longer supported."); },
+ _saveEdit: function() { console.warn("This method is no longer supported."); },
+ _cancelEdit: function() { console.warn("This method is no longer supported."); }
});
/**
/**
* Handles the comment add feature.
*
+ * Warning: This implementation is also used for responses, but in a slightly
+ * modified version. Changes made to this class need to be verified
+ * against the response implementation.
+ *
* @author Alexander Ebert
* @copyright 2001-2017 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @module WoltLabSuite/Core/Ui/Comment/Add
*/
-define(['Ajax', 'Core', 'EventHandler', 'Language', 'Dom/ChangeListener', 'Dom/Util', 'Dom/Traverse', 'Ui/Dialog', 'Ui/Notification', 'WoltLabSuite/Core/Ui/Scroll', 'EventKey', 'User', 'WoltLabSuite/Core/Controller/Captcha'],
- function(Ajax, Core, EventHandler, Language, DomChangeListener, DomUtil, DomTraverse, UiDialog, UiNotification, UiScroll, EventKey, User, ControllerCaptcha) {
+define([
+ 'Ajax', 'Core', 'EventHandler', 'Language', 'Dom/ChangeListener', 'Dom/Util', 'Dom/Traverse', 'Ui/Dialog', 'Ui/Notification', 'WoltLabSuite/Core/Ui/Scroll', 'EventKey', 'User', 'WoltLabSuite/Core/Controller/Captcha'
+],
+function(
+ Ajax, Core, EventHandler, Language, DomChangeListener, DomUtil, DomTraverse, UiDialog, UiNotification, UiScroll, EventKey, User, ControllerCaptcha
+) {
"use strict";
if (!COMPILER_TARGET_DEFAULT) {
init: function() {},
_submitGuestDialog: function() {},
_submit: function() {},
+ _getParameters: function () {},
_validate: function() {},
throwError: function() {},
_showLoadingOverlay: function() {},
*/
init: function(container) {
this._container = container;
- this._content = elBySel('.commentListAddComment', this._container);
+ this._content = elBySel('.jsOuterEditorContainer', this._container);
this._textarea = elBySel('.wysiwygTextarea', this._container);
this._editor = null;
this._loadingOverlay = null;
this._content.classList.remove('collapsed');
- UiScroll.element(this._container, (function() {
+ UiScroll.element(this._container, (function () {
window.jQuery(this._textarea).redactor('WoltLabCaret.endOfEditor');
}).bind(this));
}
this._showLoadingOverlay();
// build parameters
- var commentList = this._container.closest('.commentList');
- var parameters = {
- data: {
- message: this._getEditor().code.get(),
- objectID: elData(commentList, 'object-id'),
- objectTypeID: elData(commentList, 'object-type-id')
- }
- };
+ var parameters = this._getParameters();
EventHandler.fire('com.woltlab.wcf.redactor2', 'submit_text', parameters.data);
}, additionalParameters));
},
+ /**
+ * Returns the request parameters to add a comment.
+ *
+ * @return {{data: {message: string, objectID: number, objectTypeID: number}}}
+ * @protected
+ */
+ _getParameters: function () {
+ var commentList = this._container.closest('.commentList');
+
+ return {
+ data: {
+ message: this._getEditor().code.get(),
+ objectID: ~~elData(commentList, 'object-id'),
+ objectTypeID: ~~elData(commentList, 'object-type-id')
+ }
+ };
+ },
+
/**
* Validates the message and invokes listeners to perform additional validation.
*
},
/**
- * Inserts the rendered message into the post list, unless the post is on the next
- * page in which case a redirect will be performed instead.
+ * Inserts the rendered message.
*
* @param {Object} data response data
+ * @return {Element} scroll target
* @protected
*/
_insertMessage: function(data) {
UiNotification.show(Language.get('wcf.global.success.add'));
DomChangeListener.trigger();
+
+ return this._container.nextElementSibling;
},
/**
elBySel('input[type=text]', dialog.content).addEventListener('keypress', this._submitGuestDialog.bind(this));
}
else {
- this._insertMessage(data);
+ var scrollTarget = this._insertMessage(data);
if (!User.userId) {
UiDialog.close('jsDialogGuestComment');
this._hideLoadingOverlay();
window.setTimeout((function () {
- UiScroll.element(this._container.nextElementSibling);
+ UiScroll.element(scrollTarget);
}).bind(this), 100);
}
},
--- /dev/null
+/**
+ * Handles the comment response add feature.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2017 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module WoltLabSuite/Core/Ui/Comment/Add
+ */
+define([
+ 'Core', 'Language', 'Dom/ChangeListener', 'Dom/Util', 'Dom/Traverse', 'Ui/Notification', 'WoltLabSuite/Core/Ui/Comment/Add'
+],
+function(
+ Core, Language, DomChangeListener, DomUtil, DomTraverse, UiNotification, UiCommentAdd
+) {
+ "use strict";
+
+ if (!COMPILER_TARGET_DEFAULT) {
+ var Fake = function() {};
+ Fake.prototype = {
+ init: function() {},
+ getContainer: function() {},
+ getContent: function() {},
+ setContent: function() {},
+ _submitGuestDialog: function() {},
+ _submit: function() {},
+ _getParameters: function () {},
+ _validate: function() {},
+ throwError: function() {},
+ _showLoadingOverlay: function() {},
+ _hideLoadingOverlay: function() {},
+ _reset: function() {},
+ _handleError: function() {},
+ _getEditor: function() {},
+ _insertMessage: function() {},
+ _ajaxSuccess: function() {},
+ _ajaxFailure: function() {},
+ _ajaxSetup: function() {}
+ };
+ return Fake;
+ }
+
+ /**
+ * @constructor
+ */
+ function UiCommentResponseAdd(container, options) { this.init(container, options); }
+ Core.inherit(UiCommentResponseAdd, UiCommentAdd, {
+ init: function (container, options) {
+ UiCommentResponseAdd._super.prototype.init.call(this, container);
+
+ this._options = Core.extend({
+ callbackInsert: null
+ }, options);
+ },
+
+ /**
+ * Returns the editor container for placement or `null` if the editor is busy.
+ *
+ * @return {(Element|null)}
+ */
+ getContainer: function() {
+ return (this._isBusy) ? null : this._container;
+ },
+
+ /**
+ * Retrieves the current content from the editor.
+ *
+ * @return {string}
+ */
+ getContent: function () {
+ return window.jQuery(this._textarea).redactor('code.get');
+ },
+
+ /**
+ * Sets the content and places the caret at the end of the editor.
+ *
+ * @param {string} html
+ */
+ setContent: function (html) {
+ window.jQuery(this._textarea).redactor('code.set', html);
+ window.jQuery(this._textarea).redactor('WoltLabCaret.endOfEditor');
+
+ var innerError = elBySel('.innerError', this._textarea.parentNode);
+ if (innerError !== null) elRemove(innerError);
+ },
+
+ _getParameters: function () {
+ var parameters = UiCommentResponseAdd._super.prototype._getParameters.call(this);
+ parameters.data.commentID = ~~elData(this._container.closest('.comment'), 'object-id');
+
+ return parameters;
+ },
+
+ _insertMessage: function(data) {
+ var commentContent = DomTraverse.childByClass(this._container.parentNode, 'commentContent');
+ var responseList = commentContent.nextElementSibling;
+ if (responseList === null || !responseList.classList.contains('commentResponseList')) {
+ responseList = elCreate('ul');
+ responseList.className = 'containerList commentResponseList';
+ elData(responseList, 'responses', 0);
+
+ commentContent.parentNode.insertBefore(responseList, commentContent.nextSibling);
+ }
+
+ // insert HTML
+ //noinspection JSCheckFunctionSignatures
+ DomUtil.insertHtml(data.returnValues.template, responseList, 'append');
+
+ UiNotification.show(Language.get('wcf.global.success.add'));
+
+ DomChangeListener.trigger();
+
+ // reset editor
+ window.jQuery(this._textarea).redactor('code.set', '');
+
+ if (this._options.callbackInsert !== null) this._options.callbackInsert();
+
+ // update counter
+ elData(responseList, 'responses', responseList.children.length);
+
+ return responseList.lastElementChild;
+ },
+
+ _ajaxSetup: function() {
+ var data = UiCommentResponseAdd._super.prototype._ajaxSetup.call(this);
+ data.data.actionName = 'addResponse';
+
+ return data;
+ }
+ });
+
+ return UiCommentResponseAdd;
+});
--- /dev/null
+/**
+ * Provides editing support for comment responses.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2017 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module WoltLabSuite/Core/Ui/Comment/Response/Edit
+ */
+define(
+ [
+ 'Ajax', 'Core', 'Dictionary', 'Environment',
+ 'EventHandler', 'Language', 'List', 'Dom/ChangeListener', 'Dom/Traverse',
+ 'Dom/Util', 'Ui/Notification', 'Ui/ReusableDropdown', 'WoltLabSuite/Core/Ui/Scroll', 'WoltLabSuite/Core/Ui/Comment/Edit'
+ ],
+ function(
+ Ajax, Core, Dictionary, Environment,
+ EventHandler, Language, List, DomChangeListener, DomTraverse,
+ DomUtil, UiNotification, UiReusableDropdown, UiScroll, UiCommentEdit
+ )
+{
+ "use strict";
+
+ if (!COMPILER_TARGET_DEFAULT) {
+ var Fake = function() {};
+ Fake.prototype = {
+ init: function() {},
+ rebuild: function() {},
+ _click: function() {},
+ _prepare: function() {},
+ _showEditor: function() {},
+ _restoreMessage: function() {},
+ _save: function() {},
+ _validate: function() {},
+ throwError: function() {},
+ _showMessage: function() {},
+ _hideEditor: function() {},
+ _restoreEditor: function() {},
+ _destroyEditor: function() {},
+ _getEditorId: function() {},
+ _getObjectId: function() {},
+ _ajaxFailure: function() {},
+ _ajaxSuccess: function() {},
+ _ajaxSetup: function() {}
+ };
+ return Fake;
+ }
+
+ /**
+ * @constructor
+ */
+ function UiCommentResponseEdit(container) { this.init(container); }
+ Core.inherit(UiCommentResponseEdit, UiCommentEdit, {
+ /**
+ * Initializes the comment edit manager.
+ *
+ * @param {Element} container container element
+ */
+ init: function(container) {
+ this._activeElement = null;
+ this._callbackClick = null;
+ this._container = container;
+ this._editorContainer = null;
+ this._responses = new List();
+
+ this.rebuild();
+
+ DomChangeListener.add('Ui/Comment/Response/Edit_' + DomUtil.identify(this._container), this.rebuild.bind(this));
+ },
+
+ /**
+ * Initializes each applicable message, should be called whenever new
+ * messages are being displayed.
+ */
+ rebuild: function() {
+ elBySelAll('.commentResponse', this._container, (function (response) {
+ if (this._responses.has(response)) {
+ return;
+ }
+
+ if (elDataBool(response, 'can-edit')) {
+ var button = elBySel('.jsCommentResponseEditButton', response);
+ if (button !== null) {
+ if (this._callbackClick === null) {
+ this._callbackClick = this._click.bind(this);
+ }
+
+ button.addEventListener(WCF_CLICK_EVENT, this._callbackClick);
+ }
+ }
+
+ this._responses.add(response);
+ }).bind(this));
+ },
+
+ /**
+ * Handles clicks on the edit button.
+ *
+ * @param {?Event} event event object
+ * @protected
+ */
+ _click: function(event) {
+ event.preventDefault();
+
+ if (this._activeElement === null) {
+ this._activeElement = event.currentTarget.closest('.commentResponse');
+
+ this._prepare();
+
+ Ajax.api(this, {
+ actionName: 'beginEdit',
+ objectIDs: [this._getObjectId(this._activeElement)]
+ });
+ }
+ else {
+ UiNotification.show('wcf.message.error.editorAlreadyInUse', null, 'warning');
+ }
+ },
+
+ /**
+ * Prepares the message for editor display.
+ *
+ * @protected
+ */
+ _prepare: function() {
+ this._editorContainer = elCreate('div');
+ this._editorContainer.className = 'commentEditorContainer';
+ this._editorContainer.innerHTML = '<span class="icon icon48 fa-spinner"></span>';
+
+ var content = elBySel('.commentResponseContent', this._activeElement);
+ content.insertBefore(this._editorContainer, content.firstChild);
+ },
+
+ /**
+ * Shows the update message.
+ *
+ * @param {Object} data ajax response data
+ * @protected
+ */
+ _showMessage: function(data) {
+ // set new content
+ //noinspection JSCheckFunctionSignatures
+ DomUtil.setInnerHtml(elBySel('.commentResponseContent .userMessage', this._editorContainer.parentNode), data.returnValues.message);
+
+ this._restoreMessage();
+
+ UiNotification.show();
+ },
+
+ /**
+ * Returns the unique editor id.
+ *
+ * @return {string} editor id
+ * @protected
+ */
+ _getEditorId: function() {
+ return 'commentResponseEditor' + this._getObjectId(this._activeElement);
+ },
+
+ _ajaxSetup: function() {
+ var objectTypeId = ~~elData(this._container, 'object-type-id');
+
+ return {
+ data: {
+ className: 'wcf\\data\\comment\\response\\CommentResponseAction',
+ parameters: {
+ data: {
+ objectTypeID: objectTypeId
+ }
+ }
+ },
+ silent: true
+ };
+ }
+ });
+
+ return UiCommentResponseEdit;
+});
* captcha object type used for comments
* @var ObjectType
*/
- public $captchaObjectType = null;
+ public $captchaObjectType;
/**
* @inheritDoc
* comment object
* @var Comment
*/
- protected $comment = null;
+ protected $comment;
/**
* comment processor
* @var ICommentManager
*/
- protected $commentProcessor = null;
+ protected $commentProcessor;
/**
* @var HtmlInputProcessor
* response object
* @var CommentResponse
*/
- protected $response = null;
+ protected $response;
/**
* comment object created by addComment()
* @var Comment
*/
- public $createdComment = null;
+ public $createdComment;
/**
* response object created by addResponse()
* @var CommentResponse
*/
- public $createdResponse = null;
+ public $createdResponse;
/**
* errors occurring through the validation of addComment or addResponse
'userID' => WCF::getUser()->userID ?: null,
'username' => WCF::getUser()->userID ? WCF::getUser()->username : $this->parameters['data']['username'],
'message' => $this->parameters['data']['message'],
+ 'enableHtml' => 1,
'isDisabled' => $this->commentProcessor->canAddWithoutApproval($this->parameters['data']['objectID']) ? 0 : 1
]);
$this->createdResponse->setComment($this->comment);
use wcf\system\bbcode\SimpleMessageParser;
use wcf\system\comment\manager\ICommentManager;
use wcf\system\comment\CommentHandler;
+use wcf\system\html\output\HtmlOutputProcessor;
use wcf\util\StringUtil;
/**
* @property-read integer|null $userID id of the user who wrote the comment response or `null` if the user does not exist anymore or if the comment response has been written by a guest
* @property-read string $username name of the user or guest who wrote the comment response
* @property-read string $message comment response message
+ * @property-read integer $enableHtml is 1 if HTML will rendered in the comment response, otherwise 0
* @property-read integer $isDisabled is 1 if the comment response is disabled, otherwise 0
*/
class CommentResponse extends DatabaseObject implements IMessage {
* @inheritDoc
*/
public function getFormattedMessage() {
- return SimpleMessageParser::getInstance()->parse($this->message);
+ $processor = new HtmlOutputProcessor();
+ $processor->process($this->message, 'com.woltlab.wcf.comment.response', $this->responseID);
+
+ return $processor->getHtml();
}
/**
- * Returns comment object related to this response.
+ * Returns a simplified version of the formatted message.
*
- * @return Comment
+ * @return string
*/
- public function getComment() {
- if ($this->comment === null) {
- $this->comment = new Comment($this->commentID);
- }
+ public function getSimplifiedFormattedMessage() {
+ $processor = new HtmlOutputProcessor();
+ $processor->setOutputType('text/simplified-html');
+ $processor->process($this->message, 'com.woltlab.wcf.comment.response', $this->responseID);
- return $this->comment;
+ return $processor->getHtml();
}
/**
- * Sets related comment object.
+ * Returns a version of this message optimized for use in emails.
*
- * @param Comment $comment
+ * @param string $mimeType Either 'text/plain' or 'text/html'
+ * @return string
*/
- public function setComment(Comment $comment) {
- if ($this->commentID == $comment->commentID) {
- $this->comment = $comment;
+ public function getMailText($mimeType = 'text/plain') {
+ switch ($mimeType) {
+ case 'text/plain':
+ $processor = new HtmlOutputProcessor();
+ $processor->setOutputType('text/plain');
+ $processor->process($this->message, 'com.woltlab.wcf.comment.response', $this->responseID);
+
+ return $processor->getHtml();
+ case 'text/html':
+ return $this->getSimplifiedFormattedMessage();
}
+
+ throw new \LogicException('Unreachable');
}
/**
* @inheritDoc
*/
public function getExcerpt($maxLength = 255) {
- return StringUtil::truncateHTML($this->getFormattedMessage(), $maxLength);
+ return StringUtil::truncateHTML($this->getSimplifiedFormattedMessage(), $maxLength);
}
/**
return $this->message;
}
+ /**
+ * Returns comment object related to this response.
+ *
+ * @return Comment
+ */
+ public function getComment() {
+ if ($this->comment === null) {
+ $this->comment = new Comment($this->commentID);
+ }
+
+ return $this->comment;
+ }
+
+ /**
+ * Sets related comment object.
+ *
+ * @param Comment $comment
+ */
+ public function setComment(Comment $comment) {
+ if ($this->commentID == $comment->commentID) {
+ $this->comment = $comment;
+ }
+ }
+
/**
* @inheritDoc
*/
use wcf\data\comment\Comment;
use wcf\data\comment\CommentEditor;
use wcf\data\comment\CommentList;
+use wcf\data\object\type\ObjectType;
use wcf\data\object\type\ObjectTypeCache;
use wcf\data\AbstractDatabaseObjectAction;
+use wcf\system\bbcode\BBCodeHandler;
+use wcf\system\comment\CommentHandler;
+use wcf\system\comment\manager\ICommentManager;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\exception\UserInputException;
+use wcf\system\html\input\HtmlInputProcessor;
use wcf\system\like\LikeHandler;
use wcf\system\user\activity\event\UserActivityEventHandler;
use wcf\system\user\notification\UserNotificationHandler;
use wcf\system\WCF;
+use wcf\util\MessageUtil;
/**
* Executes comment response-related actions.
* comment object
* @var Comment
*/
- public $comment = null;
+ public $comment;
/**
* comment manager object
- * @var \wcf\system\comment\manager\ICommentManager
+ * @var ICommentManager
*/
- public $commentManager = null;
+ public $commentManager;
+
+ /**
+ * comment processor
+ * @var ICommentManager
+ */
+ protected $commentProcessor;
+
+ /**
+ * @var HtmlInputProcessor
+ */
+ protected $htmlInputProcessor;
+
+ /**
+ * response object
+ * @var CommentResponse
+ */
+ protected $response;
/**
* @inheritDoc
'template' => WCF::getTPL()->fetch('commentResponseList')
];
}
+
+
+ /**
+ * @inheritDoc
+ */
+ public function validateBeginEdit() {
+ $this->response = $this->getSingleObject();
+
+ // validate object type id
+ $objectType = $this->validateObjectType();
+
+ // validate object id and permissions
+ $this->commentProcessor = $objectType->getProcessor();
+ if (!$this->commentProcessor->canEditResponse($this->response->getDecoratedObject())) {
+ throw new PermissionDeniedException();
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function beginEdit() {
+ WCF::getTPL()->assign([
+ 'response' => $this->response,
+ 'wysiwygSelector' => 'commentResponseEditor'.$this->response->responseID
+ ]);
+
+ return [
+ 'actionName' => 'beginEdit',
+ 'template' => WCF::getTPL()->fetch('commentResponseEditor', 'wcf')
+ ];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validateSave() {
+ $this->validateBeginEdit();
+
+ $this->validateMessage();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function save() {
+ /** @var HtmlInputProcessor $htmlInputProcessor */
+ $htmlInputProcessor = $this->parameters['htmlInputProcessor'];
+
+ $action = new CommentResponseAction([$this->response], 'update', [
+ 'data' => [
+ 'message' => $htmlInputProcessor->getHtml()
+ ]
+ ]);
+ $action->executeAction();
+
+ return [
+ 'actionName' => 'save',
+ 'message' => (new CommentResponse($this->response->responseID))->getFormattedMessage()
+ ];
+ }
+
+ /**
+ * Validates message parameter.
+ *
+ * @throws UserInputException
+ */
+ protected function validateMessage() {
+ $this->readString('message', false, 'data');
+ $this->parameters['data']['message'] = MessageUtil::stripCrap($this->parameters['data']['message']);
+
+ if (empty($this->parameters['data']['message'])) {
+ throw new UserInputException('message');
+ }
+
+ CommentHandler::enforceCensorship($this->parameters['data']['message']);
+
+ $this->setDisallowedBBCodes();
+ $htmlInputProcessor = $this->getHtmlInputProcessor($this->parameters['data']['message'], ($this->comment !== null ? $this->comment->commentID : 0));
+
+ // search for disallowed bbcodes
+ $disallowedBBCodes = $htmlInputProcessor->validate();
+ if (!empty($disallowedBBCodes)) {
+ throw new UserInputException('text', WCF::getLanguage()->getDynamicVariable('wcf.message.error.disallowedBBCodes', ['disallowedBBCodes' => $disallowedBBCodes]));
+ }
+
+ if ($htmlInputProcessor->appearsToBeEmpty()) {
+ throw new UserInputException('message');
+ }
+
+ $this->parameters['htmlInputProcessor'] = $htmlInputProcessor;
+ }
+
+ /**
+ * Validates object type id parameter.
+ *
+ * @param integer $objectTypeID
+ * @return ObjectType
+ * @throws UserInputException
+ */
+ protected function validateObjectType($objectTypeID = null) {
+ if ($objectTypeID === null) {
+ $this->readInteger('objectTypeID', false, 'data');
+ $objectTypeID = $this->parameters['data']['objectTypeID'];
+ }
+
+ $objectType = ObjectTypeCache::getInstance()->getObjectType($objectTypeID);
+ if ($objectType === null) {
+ throw new UserInputException('objectTypeID');
+ }
+
+ return $objectType;
+ }
+
+ /**
+ * Sets the list of disallowed bbcodes for comments.
+ */
+ protected function setDisallowedBBCodes() {
+ BBCodeHandler::getInstance()->setDisallowedBBCodes(explode(',', WCF::getSession()->getPermission('user.comment.disallowedBBCodes')));
+ }
+
+ /**
+ * Returns the current html input processor or a new one if `$message` is not null.
+ *
+ * @param string|null $message source message
+ * @param integer $objectID object id
+ * @return HtmlInputProcessor
+ */
+ public function getHtmlInputProcessor($message = null, $objectID = 0) {
+ if ($message === null) {
+ return $this->htmlInputProcessor;
+ }
+
+ $this->htmlInputProcessor = new HtmlInputProcessor();
+ $this->htmlInputProcessor->process($message, 'com.woltlab.wcf.comment', $objectID);
+
+ return $this->htmlInputProcessor;
+ }
}
--- /dev/null
+<?php
+namespace wcf\system\worker;
+use wcf\data\comment\response\CommentResponse;
+use wcf\data\comment\response\CommentResponseEditor;
+use wcf\data\comment\response\CommentResponseList;
+use wcf\system\html\input\HtmlInputProcessor;
+use wcf\system\WCF;
+
+/**
+ * Worker implementation for updating comment responses.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2017 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Worker
+ */
+class CommentResponseRebuildDataWorker extends AbstractRebuildDataWorker {
+ /**
+ * @inheritDoc
+ */
+ protected $limit = 500;
+
+ /**
+ * @var HtmlInputProcessor
+ */
+ protected $htmlInputProcessor;
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+ /**
+ * @inheritDoc
+ */
+ public function countObjects() {
+ if ($this->count === null) {
+ $this->count = 0;
+ $sql = "SELECT MAX(responseID) AS responseID
+ FROM wcf".WCF_N."_comment_response";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute();
+ $row = $statement->fetchArray();
+ if ($row !== false) $this->count = $row['responseID'];
+ }
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+ /**
+ * @inheritDoc
+ */
+ protected function initObjectList() {
+ $this->objectList = new CommentResponseList();
+ $this->objectList->sqlOrderBy = 'comment_response.responseID';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function execute() {
+ $this->objectList->getConditionBuilder()->add('comment_response.responseID BETWEEN ? AND ?', [$this->limit * $this->loopCount + 1, $this->limit * $this->loopCount + $this->limit]);
+
+ parent::execute();
+
+ if (!count($this->objectList)) {
+ return;
+ }
+
+ WCF::getDB()->beginTransaction();
+ /** @var CommentResponse $response */
+ foreach ($this->objectList as $response) {
+ $responseEditor = new CommentResponseEditor($response);
+
+ // update message
+ if (!$response->enableHtml) {
+ $this->getHtmlInputProcessor()->process($response->message, 'com.woltlab.wcf.comment.response', $response->responseID, true);
+
+ $responseEditor->update([
+ 'message' => $this->getHtmlInputProcessor()->getHtml(),
+ 'enableHtml' => 1
+ ]);
+ }
+ else {
+ $this->getHtmlInputProcessor()->reprocess($response->message, 'com.woltlab.wcf.comment.response', $response->responseID);
+ $responseEditor->update(['message' => $this->getHtmlInputProcessor()->getHtml()]);
+ }
+ }
+ WCF::getDB()->commitTransaction();
+ }
+
+ /**
+ * @return HtmlInputProcessor
+ */
+ protected function getHtmlInputProcessor() {
+ if ($this->htmlInputProcessor === null) {
+ $this->htmlInputProcessor = new HtmlInputProcessor();
+ }
+
+ return $this->htmlInputProcessor;
+ }
+}
}
}
+.commentResponse .commentEditorContainer {
+ ~ .containerHeadline,
+ ~ .userMessage,
+ ~ .buttonGroupNavigation {
+ display: none;
+ }
+}
+
.commentListAddComment,
.commentEditorContainer {
.formSubmit {
<item name="wcf.acp.rebuildData.com.woltlab.wcf.databaseConvertEncoding.description"><![CDATA[Warnung: Die Ausführung dieser Aktion kann bei umfangreichen Datenbanken sehr lange dauern.]]></item>
<item name="wcf.acp.rebuildData.com.woltlab.wcf.comment"><![CDATA[Kommentare aktualisieren]]></item>
<item name="wcf.acp.rebuildData.com.woltlab.wcf.comment.description"><![CDATA[Aktualisiert die Kommentare]]></item>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.comment.response"><![CDATA[Antworten auf Kommentare aktualisieren]]></item>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.comment.response.description"><![CDATA[Aktualisiert die Antworten auf Kommentare]]></item>
<item name="wcf.acp.rebuildData.com.woltlab.wcf.page"><![CDATA[Seiten aktualisieren]]></item>
<item name="wcf.acp.rebuildData.com.woltlab.wcf.page.description"><![CDATA[Aktualisiert den Suchindex für CMS-Seiten]]></item>
<item name="wcf.acp.rebuildData.com.woltlab.wcf.sitemap"><![CDATA[Sitemap aktualisieren]]></item>
<item name="wcf.acp.rebuildData.com.woltlab.wcf.databaseConvertEncoding.description"><![CDATA[Warning: This action may take a while to complete on large databases.]]></item>
<item name="wcf.acp.rebuildData.com.woltlab.wcf.comment"><![CDATA[Rebuild Comments]]></item>
<item name="wcf.acp.rebuildData.com.woltlab.wcf.comment.description"><![CDATA[Rebuilds the comments.]]></item>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.comment.response"><![CDATA[Rebuild Comment Responses]]></item>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.comment.response.description"><![CDATA[Rebuilds the comment responses.]]></item>
<item name="wcf.acp.rebuildData.com.woltlab.wcf.page"><![CDATA[Rebuild Pages]]></item>
<item name="wcf.acp.rebuildData.com.woltlab.wcf.page.description"><![CDATA[Rebuilds the page search index.]]></item>
<item name="wcf.acp.rebuildData.com.woltlab.wcf.sitemap"><![CDATA[Rebuild Sitemap]]></item>
userID INT(10),
username VARCHAR(255) NOT NULL,
message TEXT NOT NULL,
+ enableHtml TINYINT(1) NOT NULL DEFAULT 0,
isDisabled TINYINT(1) NOT NULL DEFAULT 0,
KEY (commentID, isDisabled, time),