<script data-relocate="true" src="{@$__wcf->getPath()}js/WCF.Comment{if !ENABLE_DEBUG_MODE}.min{/if}.js?v={@$__wcfVersion}"></script>
<script data-relocate="true" src="{@$__wcf->getPath()}js/WCF.Moderation{if !ENABLE_DEBUG_MODE}.min{/if}.js?v={@$__wcfVersion}"></script>
+{if !$__wcf->user->userID}
+ <script type="text/javascript" src="http{if $__wcf->secureConnection()}s{/if}://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
+{/if}
<script data-relocate="true">
//<![CDATA[
$(function() {
--- /dev/null
+<div>
+ <fieldset>
+ <dl>
+ <dt><label for="username">{lang}wcf.user.username{/lang}</label></dt>
+ <dd>
+ <input type="text" id="username" name="username" value="{$username}" required="required" class="long" autofocus="true" />
+ </dd>
+ </dl>
+ </fieldset>
+
+ {if MODULE_SYSTEM_RECAPTCHA}
+ {include file='recaptcha'}
+ {/if}
+</div>
+
+<div class="formSubmit">
+ <input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s" />
+</div>
<legend><label for="recaptcha_response_field">{lang}wcf.recaptcha.title{/lang}</label></legend>
<small>{lang}wcf.recaptcha.description{/lang}</small>
- <dl class="wide reCaptcha{if $errorField == 'recaptchaString'} formError{/if}">
- <script data-relocate="true">
- //<![CDATA[
- var RecaptchaOptions = {
- lang: '{@$recaptchaLanguageCode}',
- theme : 'custom'
- }
- //]]>
- </script>
+ <dl class="wide reCaptcha{if $errorField|isset && $errorField == 'recaptchaString'} formError{/if}">
+ {if !$ajaxRecaptcha|isset || !$ajaxRecaptcha}
+ <script data-relocate="true">
+ //<![CDATA[
+ var RecaptchaOptions = {
+ lang: '{@$recaptchaLanguageCode}',
+ theme : 'custom'
+ }
+ //]]>
+ </script>
+ {/if}
<dt class="jsOnly">
<label for="recaptcha_response_field">reCAPTCHA</label>
</dt>
<dd class="jsOnly">
<div id="recaptcha_image" class="framed"></div>
<input type="text" id="recaptcha_response_field" name="recaptcha_response_field" class="medium marginTop" />
- {if $errorField == 'recaptchaString'}
+ {if $errorField|isset && $errorField == 'recaptchaString'}
<small class="innerError">
{if $errorType == 'empty'}{lang}wcf.global.form.error.empty{/lang}{/if}
{if $errorType == 'false'}{lang}wcf.recaptcha.error.recaptchaString.false{/lang}{/if}
</ul>
</dd>
- <script data-relocate="true" src="http{if $recaptchaUseSSL}s{/if}://www.google.com/recaptcha/api/challenge?k={$recaptchaPublicKey}"></script>
- <noscript>
- <dd>
- <iframe src="http{if $recaptchaUseSSL}s{/if}://www.google.com/recaptcha/api/noscript?k={$recaptchaPublicKey}" height="300" width="500" seamless="seamless"></iframe><br />
- <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
- <input type="hidden" name="recaptcha_response_field" value="manual_challenge" />
- </dd>
- {if $errorField == 'recaptchaString'}
- <small class="innerError">
- {if $errorType == 'empty'}{lang}wcf.global.form.error.empty{/lang}{/if}
- {if $errorType == 'false'}{lang}wcf.recaptcha.error.recaptchaString.false{/lang}{/if}
- </small>
- {/if}
- </noscript>
+ {if !$ajaxRecaptcha|isset || !$ajaxRecaptcha}
+ <script data-relocate="true" src="http{if $recaptchaUseSSL}s{/if}://www.google.com/recaptcha/api/challenge?k={$recaptchaPublicKey}"></script>
+ <noscript>
+ <dd>
+ <iframe src="http{if $recaptchaUseSSL}s{/if}://www.google.com/recaptcha/api/noscript?k={$recaptchaPublicKey}" height="300" width="500" seamless="seamless"></iframe><br />
+ <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
+ <input type="hidden" name="recaptcha_response_field" value="manual_challenge" />
+ </dd>
+ {if $errorField == 'recaptchaString'}
+ <small class="innerError">
+ {if $errorType == 'empty'}{lang}wcf.global.form.error.empty{/lang}{/if}
+ {if $errorType == 'false'}{lang}wcf.recaptcha.error.recaptchaString.false{/lang}{/if}
+ </small>
+ {/if}
+ </noscript>
+ {else}
+ <script data-relocate="true">
+ //<![CDATA[
+ Recaptcha.create("{$recaptchaPublicKey}", "recaptcha_image", {
+ lang: '{@$recaptchaLanguageCode}',
+ theme : 'custom'
+ });
+ //]]>
+ </script>
+ {/if}
</dl>
</fieldset>
<categoryname>settings.privacy.messaging</categoryname>
<optiontype>select</optiontype>
<editable>3</editable>
- <selectoptions><![CDATA[1:wcf.user.access.registered
+ <selectoptions><![CDATA[0:wcf.user.access.everyone
+1:wcf.user.access.registered
2:wcf.user.access.following
3:wcf.user.access.nobody]]></selectoptions>
<defaultvalue>1</defaultvalue>
/**
* Namespace for comments
*/
-WCF.Comment = {};
+WCF.Comment = { };
/**
* Comment support for WCF
*/
_userAvatar: '',
+ /**
+ * data of the comment the active guest user is about to create
+ * @var object
+ */
+ _commentData: { },
+
+ /**
+ * guest dialog with username input field and recaptcha
+ * @var jQuery
+ */
+ _guestDialog: null,
+
+ /**
+ * true if the guest has to solve a recaptcha challenge to save the comment
+ * @var boolean
+ */
+ _useRecaptcha: true,
+
/**
* Initializes the WCF.Comment.Handler class.
*
}
this._proxy = new WCF.Action.Proxy({
+ failure: $.proxy(this._failure, this),
success: $.proxy(this._success, this)
});
$data.commentID = $input.data('commentID');
}
- this._proxy.setOption('data', {
- actionName: $actionName,
- className: 'wcf\\data\\comment\\CommentAction',
- parameters: {
- data: $data
+ if (!WCF.User.userID) {
+ this._commentData = $data;
+
+ // check if guest dialog has already been loaded
+ if (this._guestDialog === null) {
+ 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();
}
- });
- this._proxy.sendRequest();
-
- // reset input
- //$input.val('').blur();
+ else {
+ // request a new recaptcha
+ if (this._useRecaptcha) {
+ Recaptcha.reload();
+ }
+
+ this._guestDialog.find('input[type="submit"]').enable();
+
+ this._guestDialog.wcfDialog('open');
+ }
+ }
+ else {
+ this._proxy.setOption('data', {
+ actionName: $actionName,
+ className: 'wcf\\data\\comment\\CommentAction',
+ parameters: {
+ data: $data
+ }
+ });
+ this._proxy.sendRequest();
+ }
},
/**
}, 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 'addComment':
- this._commentAdd.find('input').val('').blur();
- $(data.returnValues.template).insertAfter(this._commentAdd).wcfFadeIn();
+ if (data.returnValues.errors) {
+ this._handleGuestDialogErrors(data.returnValues.errors);
+ }
+ else {
+ this._commentAdd.find('input').val('').blur();
+ $(data.returnValues.template).insertAfter(this._commentAdd).wcfFadeIn();
+
+ if (!WCF.User.userID) {
+ this._guestDialog.wcfDialog('close');
+ }
+ }
break;
case 'addResponse':
- var $comment = this._comments[data.returnValues.commentID];
- $comment.find('.jsCommentResponseAdd input').val('').blur();
+ if (data.returnValues.errors) {
+ this._handleGuestDialogErrors(data.returnValues.errors);
+ }
+ else {
+ var $comment = this._comments[data.returnValues.commentID];
+ $comment.find('.jsCommentResponseAdd input').val('').blur();
+
+ var $responseList = $comment.find('ul.commentResponseList');
+ if (!$responseList.length) $responseList = $('<ul class="commentResponseList" />').insertBefore($comment.find('.commentOptionContainer'));
+ $(data.returnValues.template).appendTo($responseList).wcfFadeIn();
+ }
- var $responseList = $comment.find('ul.commentResponseList');
- if (!$responseList.length) $responseList = $('<ul class="commentResponseList" />').insertBefore($comment.find('.commentOptionContainer'));
- $(data.returnValues.template).appendTo($responseList).wcfFadeIn();
+ if (!WCF.User.userID) {
+ this._guestDialog.wcfDialog('close');
+ }
break;
case 'edit':
case 'remove':
this._remove(data);
break;
+
+ case 'getGuestDialog':
+ this._createGuestDialog(data);
+ break;
}
WCF.DOMNodeInsertedHandler.execute();
this._cancelEdit($input);
},
+ /**
+ * Creates the guest dialog based on the given return data from the AJAX
+ * request.
+ *
+ * @param object data
+ */
+ _createGuestDialog: function(data) {
+ this._guestDialog = $('<div id="commentAddGuestDialog" />').append(data.returnValues.template).hide().appendTo(document.body);
+
+ // 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));
+
+ // check if recaptcha is used
+ this._useRecaptcha = this._guestDialog.find('dl.reCaptcha').length > 0;
+
+ 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 errors during creation of a comment or response due to the input
+ * in the guest dialog.
+ *
+ * @param object errors
+ */
+ _handleGuestDialogErrors: function(errors) {
+ if (errors.username) {
+ var $usernameInput = this._guestDialog.find('input[name="username"]');
+ var $errorMessage = $usernameInput.next('.innerError');
+ if (!$errorMessage.length) {
+ $errorMessage = $('<small class="innerError" />').text(errors.username).insertAfter($usernameInput);
+ }
+ else {
+ $errorMessage.text(errors.username).show();
+ }
+ }
+
+ if (errors.recaptcha) {
+ Recaptcha.reload();
+
+ var $recaptchaInput = this._guestDialog.find('input[name="recaptcha_response_field"]');
+ var $errorMessage = $recaptchaInput.next('.innerError');
+ if (!$errorMessage.length) {
+ $errorMessage = $('<small class="innerError" />').text(errors.recaptcha).insertAfter($recaptchaInput);
+ }
+ else {
+ $errorMessage.text(errors.recaptcha).show();
+ }
+ }
+
+ this._guestDialog.find('input[type="submit"]').enable();
+ },
+
+ /**
+ * Handles submitting the guest dialog.
+ *
+ * @param Event event
+ */
+ _submit: function(event) {
+ var $submit = true;
+
+ this._guestDialog.find('input[type="submit"]').enable();
+
+ // validate username
+ var $usernameInput = this._guestDialog.find('input[name="username"]');
+ var $username = $usernameInput.val();
+ var $usernameErrorMessage = $usernameInput.next('.innerError');
+ if (!$username) {
+ $submit = false;
+ if (!$usernameErrorMessage.length) {
+ $usernameErrorMessage = $('<small class="innerError" />').text(WCF.Language.get('wcf.global.form.error.empty')).insertAfter($usernameInput);
+ }
+ else {
+ $usernameErrorMessage.text(WCF.Language.get('wcf.global.form.error.empty')).show();
+ }
+ }
+
+ // validate recaptcha
+ if (this._useRecaptcha) {
+ var $recaptchaInput = this._guestDialog.find('input[name="recaptcha_response_field"]');
+ var $recaptchaResponse = $recaptchaInput.val();
+ var $recaptchaErrorMessage = $recaptchaInput.next('.innerError');
+ if (!$recaptchaResponse) {
+ $submit = false;
+ if (!$recaptchaErrorMessage.length) {
+ $recaptchaErrorMessage = $('<small class="innerError" />').text(WCF.Language.get('wcf.global.form.error.empty')).insertAfter($recaptchaInput);
+ }
+ else {
+ $recaptchaErrorMessage.text(WCF.Language.get('wcf.global.form.error.empty')).show();
+ }
+ }
+ }
+
+ if ($submit) {
+ if ($usernameErrorMessage.length) {
+ $usernameErrorMessage.hide();
+ }
+
+ if (this._useRecaptcha && $recaptchaErrorMessage.length) {
+ $recaptchaErrorMessage.hide();
+ }
+
+ var $data = this._commentData;
+ $data.username = $username;
+
+ var $parameters = {
+ data: $data
+ };
+
+ if (this._useRecaptcha) {
+ $parameters.recaptchaChallenge = Recaptcha.get_challenge();
+ $parameters.recaptchaResponse = Recaptcha.get_response();
+ }
+
+ this._proxy.setOption('data', {
+ actionName: this._commentData.commentID ? 'addResponse' : 'addComment',
+ className: 'wcf\\data\\comment\\CommentAction',
+ parameters: $parameters
+ });
+ this._proxy.sendRequest();
+
+ this._guestDialog.find('input[type="submit"]').disable();
+ }
+ },
+
/**
* Saves editing of a comment or response.
*
* @see WCF.Like._getWidgetContainer()
*/
_getWidgetContainer: function(containerID) { }
-});
\ No newline at end of file
+});
use wcf\system\exception\PermissionDeniedException;
use wcf\system\exception\UserInputException;
use wcf\system\like\LikeHandler;
+use wcf\system\recaptcha\RecaptchaHandler;
use wcf\system\user\activity\event\UserActivityEventHandler;
use wcf\system\user\notification\object\CommentResponseUserNotificationObject;
use wcf\system\user\notification\object\CommentUserNotificationObject;
use wcf\system\user\notification\UserNotificationHandler;
use wcf\system\WCF;
use wcf\util\MessageUtil;
+use wcf\util\UserUtil;
/**
* Executes comment-related actions.
/**
* @see \wcf\data\AbstractDatabaseObjectAction::$allowGuestAccess
*/
- protected $allowGuestAccess = array('loadComments');
+ protected $allowGuestAccess = array('addComment', 'addResponse', 'loadComments', 'getGuestDialog');
/**
* @see \wcf\data\AbstractDatabaseObjectAction::$className
* @var \wcf\data\comment\response\CommentResponse
*/
public $createdResponse = null;
+
+ /**
+ * errors occuring durch the validation of addComment or addResponse
+ * @var array
+ */
+ public $validationErrors = array();
/**
* @see \wcf\data\AbstractDatabaseObjectAction::delete()
CommentHandler::enforceFloodControl();
$this->readInteger('objectID', false, 'data');
+
+ $this->validateUsername();
+ $this->validateRecaptcha();
+
$this->validateMessage();
$objectType = $this->validateObjectType();
* @return array
*/
public function addComment() {
+ if (!empty($this->validationErrors)) {
+ return array(
+ 'errors' => $this->validationErrors
+ );
+ }
+
// create comment
$this->createdComment = CommentEditor::create(array(
'objectTypeID' => $this->parameters['data']['objectTypeID'],
'objectID' => $this->parameters['data']['objectID'],
'time' => TIME_NOW,
- 'userID' => WCF::getUser()->userID,
- 'username' => WCF::getUser()->username,
+ 'userID' => WCF::getUser()->userID ?: null,
+ 'username' => WCF::getUser()->userID ? WCF::getUser()->username : $this->parameters['data']['username'],
'message' => $this->parameters['data']['message'],
'responses' => 0,
'responseIDs' => serialize(array())
// fire activity event
$objectType = ObjectTypeCache::getInstance()->getObjectType($this->parameters['data']['objectTypeID']);
- if (UserActivityEventHandler::getInstance()->getObjectTypeID($objectType->objectType.'.recentActivityEvent')) {
+ if ($this->createdComment->userID && UserActivityEventHandler::getInstance()->getObjectTypeID($objectType->objectType.'.recentActivityEvent')) {
UserActivityEventHandler::getInstance()->fireEvent($objectType->objectType.'.recentActivityEvent', $this->createdComment->commentID);
}
}
}
+ if (!$this->createdComment->userID) {
+ // save user name is session
+ WCF::getSession()->register('username', $this->createdComment->username);
+
+ // save last comment time for flood control
+ WCF::getSession()->register('lastCommentTime', $this->createdComment->time);
+
+ // unmark recaptcha as done for furture requests
+ WCF::getSession()->unregister('recaptchaDone');
+ }
+
return array(
'template' => $this->renderComment($this->createdComment)
);
$this->readInteger('objectID', false, 'data');
$this->validateMessage();
+ $this->validateUsername();
+ $this->validateRecaptcha();
+
// validate comment id
$this->validateCommentID();
- // validate object type id
$objectType = $this->validateObjectType();
// validate object id and permissions
* @return array
*/
public function addResponse() {
+ if (!empty($this->validationErrors)) {
+ return array(
+ 'errors' => $this->validationErrors
+ );
+ }
+
// create response
$this->createdResponse = CommentResponseEditor::create(array(
'commentID' => $this->comment->commentID,
'time' => TIME_NOW,
- 'userID' => WCF::getUser()->userID,
- 'username' => WCF::getUser()->username,
+ 'userID' => WCF::getUser()->userID ?: null,
+ 'username' => WCF::getUser()->userID ? WCF::getUser()->username : $this->parameters['data']['username'],
'message' => $this->parameters['data']['message']
));
// fire activity event
$objectType = ObjectTypeCache::getInstance()->getObjectType($this->comment->objectTypeID);
- if (UserActivityEventHandler::getInstance()->getObjectTypeID($objectType->objectType.'.response.recentActivityEvent')) {
+ if ($this->createdResponse->userID && UserActivityEventHandler::getInstance()->getObjectTypeID($objectType->objectType.'.response.recentActivityEvent')) {
UserActivityEventHandler::getInstance()->fireEvent($objectType->objectType.'.response.recentActivityEvent', $this->createdResponse->responseID);
}
}
}
+ if (!$this->createdResponse->userID) {
+ // save user name is session
+ WCF::getSession()->register('username', $this->createdResponse->username);
+
+ // save last comment time for flood control
+ WCF::getSession()->register('lastCommentTime', $this->createdResponse->time);
+
+ // unmark recaptcha as done for furture requests
+ WCF::getSession()->unregister('recaptchaDone');
+ }
+
return array(
'commentID' => $this->comment->commentID,
'template' => $this->renderResponse($this->createdResponse),
}
}
+ /**
+ * Validates the 'getGuestDialog' action.
+ */
+ public function validateGetGuestDialog() {
+ if (WCF::getUser()->userID) {
+ throw new PermissionDeniedException();
+ }
+
+ CommentHandler::enforceFloodControl();
+
+ $this->readInteger('objectID', false, 'data');
+ $objectType = $this->validateObjectType();
+
+ // validate object id and permissions
+ $this->commentProcessor = $objectType->getProcessor();
+ if (!$this->commentProcessor->canAdd($this->parameters['data']['objectID'])) {
+ throw new PermissionDeniedException();
+ }
+
+ // validate message already at this point to make sure that the
+ // message is valid when submitting the dialog to avoid having to
+ // go back to the message to fix it
+ $this->validateMessage();
+ }
+
+ /**
+ * Returns the dialog for guests when they try to write a comment letting
+ * them enter a username and solving a captcha.
+ *
+ * @return array
+ */
+ public function getGuestDialog() {
+ RecaptchaHandler::getInstance()->assignVariables();
+
+ return array(
+ 'template' => WCF::getTPL()->fetch('commentAddGuestDialog', 'wcf', array(
+ 'ajaxRecaptcha' => true,
+ 'username' => WCF::getSession()->getVar('username')
+ ))
+ );
+ }
+
/**
* Renders a comment.
*
$comment->setIsEditable($this->commentProcessor->canEditComment($comment->getDecoratedObject()));
// set user profile
- $userProfile = UserProfile::getUserProfile($comment->userID);
- $comment->setUserProfile($userProfile);
+ if ($comment->userID) {
+ $userProfile = UserProfile::getUserProfile($comment->userID);
+ $comment->setUserProfile($userProfile);
+ }
WCF::getTPL()->assign(array(
'commentList' => array($comment)
$response->setIsEditable($this->commentProcessor->canEditResponse($response->getDecoratedObject()));
// set user profile
- $userProfile = UserProfile::getUserProfile($response->userID);
- $response->setUserProfile($userProfile);
+ if ($response->userID) {
+ $userProfile = UserProfile::getUserProfile($response->userID);
+ $response->setUserProfile($userProfile);
+ }
// render response
WCF::getTPL()->assign(array(
}
}
+ /**
+ * Validates the username parameter.
+ */
+ protected function validateUsername() {
+ if (WCF::getUser()->userID) return;
+
+ try {
+ $this->readString('username', false, 'data');
+
+ if (!UserUtil::isValidUsername($this->parameters['data']['username'])) {
+ throw new UserInputException('username', 'notValid');
+ }
+ if (!UserUtil::isAvailableUsername($this->parameters['data']['username'])) {
+ throw new UserInputException('username', 'notUnique');
+ }
+ }
+ catch (UserInputException $e) {
+ if ($e->getType() == 'empty') {
+ $this->validationErrors['username'] = WCF::getLanguage()->get('wcf.global.form.error.empty');
+ }
+ else {
+ $this->validationErrors['username'] = WCF::getLanguage()->get('wcf.user.username.error.'.$e->getType());
+ }
+ }
+ }
+
+ /**
+ * Validates the recaptcha challenge.
+ */
+ protected function validateRecaptcha() {
+ if (WCF::getUser()->userID || !MODULE_SYSTEM_RECAPTCHA || WCF::getSession()->getVar('recaptchaDone')) return;
+
+ $this->readString('recaptchaChallenge');
+ $this->readString('recaptchaResponse');
+
+ try {
+ RecaptchaHandler::getInstance()->validate($this->parameters['recaptchaChallenge'], $this->parameters['recaptchaResponse']);
+ }
+ catch (UserInputException $e) {
+ $this->validationErrors['recaptcha'] = WCF::getLanguage()->get('wcf.recaptcha.error.recaptchaString.false');
+ }
+ }
+
/**
* Returns the comment object.
*
$this->responseIDs[] = $responseID;
$responseIDs[$responseID] = $comment->commentID;
}
- $userIDs[] = $comment->userID;
+
+ if ($comment->userID) {
+ $userIDs[] = $comment->userID;
+ }
$comment = new StructuredComment($comment);
$comment->setIsDeletable($this->commentManager->canDeleteComment($comment->getDecoratedObject()));
$commentID = $responseIDs[$response->responseID];
$this->objects[$commentID]->addResponse($response);
- $userIDs[] = $response->userID;
+ if ($response->userID) {
+ $userIDs[] = $response->userID;
+ }
}
}
$users = UserProfile::getUserProfiles($userIDs);
foreach ($this->objects as $comment) {
- if (isset($users[$comment->userID])) {
+ if ($comment->userID && isset($users[$comment->userID])) {
$comment->setUserProfile($users[$comment->userID]);
}
foreach ($comment as $response) {
- if (isset($users[$response->userID])) {
+ if ($response->userID && isset($users[$response->userID])) {
$response->setUserProfile($users[$response->userID]);
}
}
return $data['updates'];
}
+ /**
+ * @see \wcf\system\request\RouteHandler::secureConnection()
+ */
+ public function secureConnection() {
+ return RouteHandler::secureConnection();
+ }
+
/**
* Initialises the cronjobs.
*/
return;
}
+ // flood control for guests is session based
+ if (!WCF::getUser()->userID) {
+ $lastCommentTime = WCF::getSession()->getVar('lastCommentTime');
+
+ if ($lastCommentTime && $lastCommentTime + WCF::getSession()->getPermission('user.comment.floodControlTime') > TIME_NOW) {
+ throw new NamedUserException(WCF::getLanguage()->getDynamicVariable('wcf.comment.error.floodControl', array(
+ 'lastCommentTime' => $lastCommentTime
+ )));
+ }
+
+ return;
+ }
+
// check for comments
$sql = "SELECT time
FROM wcf".WCF_N."_comment
public function getMessage() {
// @todo: use cache or a single query to retrieve required data
$comment = new Comment($this->userNotificationObject->commentID);
- $commentAuthor = new User($comment->userID);
+ if ($comment->userID) {
+ $commentAuthor = new User($comment->userID);
+ }
+ else {
+ $commentAuthor = new User(null, array(
+ 'username' => $comment->username
+ ));
+ }
return $this->getLanguage()->getDynamicVariable('wcf.user.notification.commentResponseOwner.message', array(
'author' => $this->author,
*/
public function getEmailMessage($notificationType = 'instant') {
$comment = new Comment($this->userNotificationObject->commentID);
- $commentAuthor = new User($comment->userID);
$owner = new User($comment->objectID);
+ if ($comment->userID) {
+ $commentAuthor = new User($comment->userID);
+ }
+ else {
+ $commentAuthor = new User(null, array(
+ 'username' => $comment->username
+ ));
+ }
return $this->getLanguage()->getDynamicVariable('wcf.user.notification.commentResponseOwner.mail', array(
'response' => $this->userNotificationObject,
public function getMessage() {
// @todo: use cache or a single query to retrieve required data
$comment = new Comment($this->userNotificationObject->commentID);
- $user = new User($comment->objectID);
+ if ($comment->userID) {
+ $commentAuthor = new User($comment->userID);
+ }
+ else {
+ $commentAuthor = new User(null, array(
+ 'username' => $comment->username
+ ));
+ }
return $this->getLanguage()->getDynamicVariable('wcf.user.notification.commentResponse.message', array(
'author' => $this->author,
<item name="wcf.comment.response.add"><![CDATA[Antworten …]]></item>
<item name="wcf.comment.response.more"><![CDATA[{literal}{if $count == 1}Eine weitere Antwort{else}{#$count} weitere Antworten{/if}{/literal}]]></item>
<item name="wcf.comment.button.response.add"><![CDATA[Antworten]]></item>
+ <item name="wcf.comment.guestDialog.title"><![CDATA[TODO]]></item>
</category>
<category name="wcf.dashboard">
<item name="wcf.comment.response.add"><![CDATA[Reply …]]></item>
<item name="wcf.comment.response.more"><![CDATA[{literal}{if $count == 1}One more reply{else}{#$count} more replies{/if}{/literal}]]></item>
<item name="wcf.comment.button.response.add"><![CDATA[Reply]]></item>
+ <item name="wcf.comment.guestDialog.title"><![CDATA[TODO]]></item>
</category>
<category name="wcf.dashboard">