Add notifications for comments in moderation
authorMatthias Schmidt <gravatronics@live.com>
Sun, 20 Mar 2016 12:11:23 +0000 (13:11 +0100)
committerMatthias Schmidt <gravatronics@live.com>
Sun, 20 Mar 2016 12:11:23 +0000 (13:11 +0100)
15 files changed:
CHANGELOG.md
com.woltlab.wcf/objectType.xml
com.woltlab.wcf/userNotificationEvent.xml
wcfsetup/install/files/lib/data/comment/CommentAction.class.php
wcfsetup/install/files/lib/data/moderation/queue/ViewableModerationQueue.class.php
wcfsetup/install/files/lib/system/moderation/queue/AbstractModerationQueueHandler.class.php
wcfsetup/install/files/lib/system/moderation/queue/IModerationQueueHandler.class.php
wcfsetup/install/files/lib/system/user/notification/event/ModerationQueueCommentResponseUserNotificationEvent.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/user/notification/event/ModerationQueueCommentUserNotificationEvent.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/user/notification/object/type/IMultiRecipientCommentUserNotificationObjectType.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/user/notification/object/type/ModerationQueueCommentResponseUserNotificationObjectType.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/user/notification/object/type/ModerationQueueCommentUserNotificationObjectType.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/user/notification/object/type/TMultiRecipientModerationQueueCommentUserNotificationObjectType.class.php [new file with mode: 0644]
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index 5a6dc9ca0a69af74fe9f30d20b3e529e8acecfd2..265ac40172bc7085d4dd40e145e3de4a2adb6149 100644 (file)
@@ -27,6 +27,7 @@
 * `wcf\system\event\listener\AbstractUserActionRenameListener` added.
 * `wcf\system\event\listener\AbstractUserMergeListener` added.
 * Notice texts support `{$username}` and `{$email}` placeholders.
+* Notifications for comments in moderation.
 
 #### New Traits
 
index cc5987a5347f6433d0a6f6e134fc9e2371ee7694..a3b7f39fe45da5713b53b223a036637178043dab 100644 (file)
                        <definitionname>com.woltlab.wcf.comment.commentableContent</definitionname>
                        <classname><![CDATA[wcf\system\comment\manager\ModerationQueueCommentManager]]></classname>
                </type>
+               <type>
+                       <name>com.woltlab.wcf.moderation.queue.notification</name>
+                       <definitionname>com.woltlab.wcf.notification.objectType</definitionname>
+                       <classname><![CDATA[wcf\system\user\notification\object\type\ModerationQueueCommentUserNotificationObjectType]]></classname>
+                       <category>com.woltlab.wcf.moderation</category>
+               </type>
+               <type>
+                       <name>com.woltlab.wcf.moderation.queue.response.notification</name>
+                       <definitionname>com.woltlab.wcf.notification.objectType</definitionname>
+                       <classname><![CDATA[wcf\system\user\notification\object\type\ModerationQueueCommentResponseUserNotificationObjectType]]></classname>
+                       <category>com.woltlab.wcf.moderation</category>
+               </type>
                <!-- /comments -->
                
                <!-- moderation -->
index 843dadd7163d2b6eac04fbd665305e346182f765..d795fdaef8bd879d2a0c87faf6601e5b79358156 100644 (file)
                        <preset>1</preset>
                        <options>module_like</options>
                </event>
+               
+               <event>
+                       <name>comment</name>
+                       <objecttype>com.woltlab.wcf.moderation.queue.notification</objecttype>
+                       <classname><![CDATA[wcf\system\user\notification\event\ModerationQueueCommentUserNotificationEvent]]></classname>
+                       <preset>1</preset>
+                       <permissions>mod.general.canUseModeration</permissions>
+               </event>
+               <event>
+                       <name>commentResponse</name>
+                       <objecttype>com.woltlab.wcf.moderation.queue.response.notification</objecttype>
+                       <classname><![CDATA[wcf\system\user\notification\event\ModerationQueueCommentResponseUserNotificationEvent]]></classname>
+                       <preset>1</preset>
+                       <permissions>mod.general.canUseModeration</permissions>
+               </event>
        </import>
 </data>
index 9be651011f72c6882819427e3ccfdd57b7924160..2e5d1fc120f51611bada74b92bd5a82f11d019ed 100644 (file)
@@ -5,11 +5,12 @@ use wcf\data\comment\response\CommentResponseAction;
 use wcf\data\comment\response\CommentResponseEditor;
 use wcf\data\comment\response\CommentResponseList;
 use wcf\data\comment\response\StructuredCommentResponse;
+use wcf\data\object\type\ObjectType;
 use wcf\data\object\type\ObjectTypeCache;
-use wcf\data\user\UserProfile;
 use wcf\data\AbstractDatabaseObjectAction;
 use wcf\system\captcha\CaptchaHandler;
 use wcf\system\comment\CommentHandler;
+use wcf\system\comment\manager\ICommentManager;
 use wcf\system\exception\PermissionDeniedException;
 use wcf\system\exception\SystemException;
 use wcf\system\exception\UserInputException;
@@ -17,6 +18,7 @@ use wcf\system\like\LikeHandler;
 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\object\type\IMultiRecipientCommentUserNotificationObjectType;
 use wcf\system\user\notification\UserNotificationHandler;
 use wcf\system\WCF;
 use wcf\util\MessageUtil;
@@ -36,46 +38,46 @@ class CommentAction extends AbstractDatabaseObjectAction {
        /**
         * @see \wcf\data\AbstractDatabaseObjectAction::$allowGuestAccess
         */
-       protected $allowGuestAccess = array('addComment', 'addResponse', 'loadComments', 'getGuestDialog');
+       protected $allowGuestAccess = ['addComment', 'addResponse', 'loadComments', 'getGuestDialog'];
        
        /**
         * captcha object type used for comments
-        * @var \wcf\data\object\type\ObjectType
+        * @var ObjectType
         */
        public $captchaObjectType = null;
        
        /**
-        * @see \wcf\data\AbstractDatabaseObjectAction::$className
+        * @inheritDoc
         */
-       protected $className = 'wcf\data\comment\CommentEditor';
+       protected $className = CommentEditor::class;
        
        /**
         * comment object
-        * @var \wcf\data\comment\Comment
+        * @var Comment
         */
        protected $comment = null;
        
        /**
         * comment processor
-        * @var \wcf\system\comment\manager\ICommentManager
+        * @var ICommentManager
         */
        protected $commentProcessor = null;
        
        /**
         * response object
-        * @var \wcf\data\comment\response\CommentResponse
+        * @var CommentResponse
         */
        protected $response = null;
        
        /**
         * comment object created by addComment()
-        * @var \wcf\data\comment\Comment
+        * @var Comment
         */
        public $createdComment = null;
        
        /**
         * response object created by addResponse()
-        * @var \wcf\data\comment\response\CommentResponse
+        * @var CommentResponse
         */
        public $createdResponse = null;
        
@@ -83,10 +85,10 @@ class CommentAction extends AbstractDatabaseObjectAction {
         * errors occuring durch the validation of addComment or addResponse
         * @var array
         */
-       public $validationErrors = array();
+       public $validationErrors = [];
        
        /**
-        * @see \wcf\data\AbstractDatabaseObjectAction::delete()
+        * @inheritDoc
         */
        public function delete() {
                if (empty($this->objects)) {
@@ -94,14 +96,14 @@ class CommentAction extends AbstractDatabaseObjectAction {
                }
                
                // update counters
-               $processors = array();
-               $groupCommentIDs = $commentIDs = array();
+               $processors = [];
+               $groupCommentIDs = $commentIDs = [];
                foreach ($this->objects as $comment) {
                        if (!isset($processors[$comment->objectTypeID])) {
                                $objectType = ObjectTypeCache::getInstance()->getObjectType($comment->objectTypeID);
                                $processors[$comment->objectTypeID] = $objectType->getProcessor();
                                
-                               $groupCommentIDs[$comment->objectTypeID] = array();
+                               $groupCommentIDs[$comment->objectTypeID] = [];
                        }
                        
                        $processors[$comment->objectTypeID]->updateCounter($comment->objectID, -1 * ($comment->responses + 1));
@@ -110,8 +112,8 @@ class CommentAction extends AbstractDatabaseObjectAction {
                }
                
                if (!empty($groupCommentIDs)) {
-                       $likeObjectIDs = array();
-                       $notificationObjectTypes = array();
+                       $likeObjectIDs = [];
+                       $notificationObjectTypes = [];
                        foreach ($groupCommentIDs as $objectTypeID => $objectIDs) {
                                // remove activity events
                                $objectType = ObjectTypeCache::getInstance()->getObjectType($objectTypeID);
@@ -139,12 +141,12 @@ class CommentAction extends AbstractDatabaseObjectAction {
                // delete responses
                if (!empty($commentIDs)) {
                        $commentResponseList = new CommentResponseList();
-                       $commentResponseList->getConditionBuilder()->add('comment_response.commentID IN (?)', array($commentIDs));
+                       $commentResponseList->getConditionBuilder()->add('comment_response.commentID IN (?)', [$commentIDs]);
                        $commentResponseList->readObjectIDs();
                        if (count($commentResponseList->getObjectIDs())) {
-                               $action = new CommentResponseAction($commentResponseList->getObjectIDs(), 'delete', array(
+                               $action = new CommentResponseAction($commentResponseList->getObjectIDs(), 'delete', [
                                        'ignoreCounters' => true
-                               ));
+                               ]);
                                $action->executeAction();
                        }
                }
@@ -173,18 +175,18 @@ class CommentAction extends AbstractDatabaseObjectAction {
         */
        public function loadComments() {
                $commentList = CommentHandler::getInstance()->getCommentList($this->commentProcessor, $this->parameters['data']['objectTypeID'], $this->parameters['data']['objectID'], false);
-               $commentList->getConditionBuilder()->add("comment.time < ?", array($this->parameters['data']['lastCommentTime']));
+               $commentList->getConditionBuilder()->add("comment.time < ?", [$this->parameters['data']['lastCommentTime']]);
                $commentList->readObjects();
                
-               WCF::getTPL()->assign(array(
+               WCF::getTPL()->assign([
                        'commentList' => $commentList,
-                       'likeData' => (MODULE_LIKE ? $commentList->getLikeData() : array())
-               ));
+                       'likeData' => (MODULE_LIKE ? $commentList->getLikeData() : [])
+               ]);
                
-               return array(
+               return [
                        'lastCommentTime' => $commentList->getMinCommentTime(),
                        'template' => WCF::getTPL()->fetch('commentList')
-               );
+               ];
        }
        
        /**
@@ -211,7 +213,7 @@ class CommentAction extends AbstractDatabaseObjectAction {
        /**
         * Adds a comment.
         * 
-        * @return      array
+        * @return      string[]
         */
        public function addComment() {
                if (!empty($this->validationErrors)) {
@@ -221,14 +223,14 @@ class CommentAction extends AbstractDatabaseObjectAction {
                        WCF::getTPL()->assign('errorType', $this->validationErrors);
                        
                        $guestDialog = $this->getGuestDialog();
-                       return array(
+                       return [
                                'useCaptcha' => $guestDialog['useCaptcha'],
                                'guestDialog' => $guestDialog['template']
-                       );
+                       ];
                }
                
                // create comment
-               $this->createdComment = CommentEditor::create(array(
+               $this->createdComment = CommentEditor::create([
                        'objectTypeID' => $this->parameters['data']['objectTypeID'],
                        'objectID' => $this->parameters['data']['objectID'],
                        'time' => TIME_NOW,
@@ -236,8 +238,8 @@ class CommentAction extends AbstractDatabaseObjectAction {
                        'username' => WCF::getUser()->userID ? WCF::getUser()->username : $this->parameters['data']['username'],
                        'message' => $this->parameters['data']['message'],
                        'responses' => 0,
-                       'responseIDs' => serialize(array())
-               ));
+                       'responseIDs' => serialize([])
+               ]);
                
                // update counter
                $this->commentProcessor->updateCounter($this->parameters['data']['objectID'], 1);
@@ -250,14 +252,26 @@ class CommentAction extends AbstractDatabaseObjectAction {
                
                // fire notification event
                if (UserNotificationHandler::getInstance()->getObjectTypeID($objectType->objectType.'.notification')) {
+                       $notificationObject = new CommentUserNotificationObject($this->createdComment);
                        $notificationObjectType = UserNotificationHandler::getInstance()->getObjectTypeProcessor($objectType->objectType.'.notification');
-                       $userID = $notificationObjectType->getOwnerID($this->createdComment->commentID);
-                       if ($userID != WCF::getUser()->userID) {
-                               $notificationObject = new CommentUserNotificationObject($this->createdComment);
+                       
+                       if ($notificationObjectType instanceof IMultiRecipientCommentUserNotificationObjectType) {
+                               $recipientIDs = $notificationObjectType->getRecipientIDs($this->createdComment);
+                               
+                               // make sure that the active user gets no notification
+                               $recipientIDs = array_diff($recipientIDs, [WCF::getUser()->userID]);
                                
-                               UserNotificationHandler::getInstance()->fireEvent('comment', $objectType->objectType.'.notification', $notificationObject, array($userID), array(
-                                       'objectUserID' => $userID
-                               ));
+                               if (!empty($recipientIDs)) {
+                                       UserNotificationHandler::getInstance()->fireEvent('comment', $objectType->objectType . '.notification', $notificationObject, $recipientIDs);
+                               }
+                       }
+                       else {
+                               $userID = $notificationObjectType->getOwnerID($this->createdComment->commentID);
+                               if ($userID != WCF::getUser()->userID) {
+                                       UserNotificationHandler::getInstance()->fireEvent('comment', $objectType->objectType . '.notification', $notificationObject, [$userID], [
+                                               'objectUserID' => $userID
+                                       ]);
+                               }
                        }
                }
                
@@ -274,9 +288,9 @@ class CommentAction extends AbstractDatabaseObjectAction {
                        }
                }
                
-               return array(
+               return [
                        'template' => $this->renderComment($this->createdComment)
-               );
+               ];
        }
        
        /**
@@ -316,20 +330,20 @@ class CommentAction extends AbstractDatabaseObjectAction {
                        WCF::getTPL()->assign('errorType', $this->validationErrors);
                        
                        $guestDialog = $this->getGuestDialog();
-                       return array(
+                       return [
                                'useCaptcha' => $guestDialog['useCaptcha'],
                                'guestDialog' => $guestDialog['template']
-                       );
+                       ];
                }
                
                // create response
-               $this->createdResponse = CommentResponseEditor::create(array(
+               $this->createdResponse = CommentResponseEditor::create([
                        'commentID' => $this->comment->commentID,
                        'time' => TIME_NOW,
                        'userID' => WCF::getUser()->userID ?: null,
                        'username' => WCF::getUser()->userID ? WCF::getUser()->username : $this->parameters['data']['username'],
                        'message' => $this->parameters['data']['message']
-               ));
+               ]);
                
                // update response data
                $responseIDs = $this->comment->getResponseIDs();
@@ -340,10 +354,10 @@ class CommentAction extends AbstractDatabaseObjectAction {
                
                // update comment
                $commentEditor = new CommentEditor($this->comment);
-               $commentEditor->update(array(
+               $commentEditor->update([
                        'responseIDs' => serialize($responseIDs),
                        'responses' => $responses
-               ));
+               ]);
                
                // update counter
                $this->commentProcessor->updateCounter($this->parameters['data']['objectID'], 1);
@@ -357,27 +371,44 @@ class CommentAction extends AbstractDatabaseObjectAction {
                // fire notification event
                if (UserNotificationHandler::getInstance()->getObjectTypeID($objectType->objectType.'.response.notification')) {
                        $notificationObjectType = UserNotificationHandler::getInstance()->getObjectTypeProcessor($objectType->objectType.'.notification');
-                       $userID = $notificationObjectType->getOwnerID($this->comment->commentID);
-                       
                        $notificationObject = new CommentResponseUserNotificationObject($this->createdResponse);
-                       if ($this->comment->userID != WCF::getUser()->userID) {
-                               UserNotificationHandler::getInstance()->fireEvent('commentResponse', $objectType->objectType.'.response.notification', $notificationObject, array($this->comment->userID), array(
-                                       'commentID' => $this->comment->commentID,
-                                       'objectID' => $this->comment->objectID,
-                                       'objectUserID' => $userID,
-                                       'userID' => $this->comment->userID
-                               ));
-                       }
                        
-                       // notify the container owner
-                       if (UserNotificationHandler::getInstance()->getObjectTypeID($objectType->objectType.'.notification')) {
-                               if ($userID != $this->comment->userID && $userID != WCF::getUser()->userID) {
-                                       UserNotificationHandler::getInstance()->fireEvent('commentResponseOwner', $objectType->objectType.'.response.notification', $notificationObject, array($userID), array(
+                       if ($notificationObjectType instanceof IMultiRecipientCommentUserNotificationObjectType) {
+                               $recipientIDs = $notificationObjectType->getRecipientIDs($this->comment);
+                               
+                               // make sure that the active user gets no notification
+                               $recipientIDs = array_diff($recipientIDs, [WCF::getUser()->userID]);
+                               
+                               if (!empty($recipientIDs)) {
+                                       UserNotificationHandler::getInstance()->fireEvent('commentResponse', $objectType->objectType.'.response.notification', $notificationObject, $recipientIDs, [
+                                               'commentID' => $this->comment->commentID,
+                                               'objectID' => $this->comment->objectID,
+                                               'userID' => $this->comment->userID
+                                       ]);
+                               }
+                       }
+                       else {
+                               $userID = $notificationObjectType->getOwnerID($this->comment->commentID);
+                               
+                               if ($this->comment->userID != WCF::getUser()->userID) {
+                                       UserNotificationHandler::getInstance()->fireEvent('commentResponse', $objectType->objectType.'.response.notification', $notificationObject, [$this->comment->userID], [
                                                'commentID' => $this->comment->commentID,
                                                'objectID' => $this->comment->objectID,
                                                'objectUserID' => $userID,
                                                'userID' => $this->comment->userID
-                                       ));
+                                       ]);
+                               }
+                               
+                               // notify the container owner
+                               if (UserNotificationHandler::getInstance()->getObjectTypeID($objectType->objectType.'.notification')) {
+                                       if ($userID != $this->comment->userID && $userID != WCF::getUser()->userID) {
+                                               UserNotificationHandler::getInstance()->fireEvent('commentResponseOwner', $objectType->objectType . '.response.notification', $notificationObject, [$userID], [
+                                                       'commentID' => $this->comment->commentID,
+                                                       'objectID' => $this->comment->objectID,
+                                                       'objectUserID' => $userID,
+                                                       'userID' => $this->comment->userID
+                                               ]);
+                                       }
                                }
                        }
                }
@@ -395,11 +426,11 @@ class CommentAction extends AbstractDatabaseObjectAction {
                        }
                }
                
-               return array(
+               return [
                        'commentID' => $this->comment->commentID,
                        'template' => $this->renderResponse($this->createdResponse),
                        'responses' => $responses
-               );
+               ];
        }
        
        /**
@@ -450,10 +481,10 @@ class CommentAction extends AbstractDatabaseObjectAction {
                        $message = $this->response->message;
                }
                
-               $returnValues = array(
+               $returnValues = [
                        'action' => 'prepare',
                        'message' => $message
-               );
+               ];
                if ($this->comment !== null) {
                        $returnValues['commentID'] = $this->comment->commentID;
                }
@@ -465,7 +496,7 @@ class CommentAction extends AbstractDatabaseObjectAction {
        }
        
        /**
-        * @see \wcf\data\comment\CommentAction::validatePrepareEdit()
+        * @inheritDoc
         */
        public function validateEdit() {
                $this->validatePrepareEdit();
@@ -479,24 +510,22 @@ class CommentAction extends AbstractDatabaseObjectAction {
         * @return      array
         */
        public function edit() {
-               $returnValues = array(
-                       'action' => 'saved',
-               );
+               $returnValues = ['action' => 'saved'];
                
                if ($this->response === null) {
                        $editor = new CommentEditor($this->comment);
-                       $editor->update(array(
+                       $editor->update([
                                'message' => $this->parameters['data']['message']
-                       ));
+                       ]);
                        $comment = new Comment($this->comment->commentID);
                        $returnValues['commentID'] = $this->comment->commentID;
                        $returnValues['message'] = $comment->getFormattedMessage();
                }
                else {
                        $editor = new CommentResponseEditor($this->response);
-                       $editor->update(array(
+                       $editor->update([
                                'message' => $this->parameters['data']['message']
-                       ));
+                       ]);
                        $response = new CommentResponse($this->response->responseID);
                        $returnValues['responseID'] = $this->response->responseID;
                        $returnValues['message'] = $response->getFormattedMessage();
@@ -542,24 +571,20 @@ class CommentAction extends AbstractDatabaseObjectAction {
        /**
         * Removes a comment or response.
         * 
-        * @return      array
+        * @return      integer[]
         */
        public function remove() {
                if ($this->comment !== null) {
-                       $objectAction = new CommentAction(array($this->comment), 'delete');
+                       $objectAction = new CommentAction([$this->comment], 'delete');
                        $objectAction->executeAction();
                        
-                       return array(
-                               'commentID' => $this->comment->commentID
-                       );
+                       return ['commentID' => $this->comment->commentID];
                }
                else {
-                       $objectAction = new CommentResponseAction(array($this->response), 'delete');
+                       $objectAction = new CommentResponseAction([$this->response], 'delete');
                        $objectAction->executeAction();
                        
-                       return array(
-                               'responseID' => $this->response->responseID
-                       );
+                       return ['responseID' => $this->response->responseID];
                }
        }
        
@@ -608,21 +633,21 @@ class CommentAction extends AbstractDatabaseObjectAction {
                        }
                }
                
-               return array(
+               return [
                        'useCaptcha' => $captchaObjectType !== null,
-                       'template' => WCF::getTPL()->fetch('commentAddGuestDialog', 'wcf', array(
+                       'template' => WCF::getTPL()->fetch('commentAddGuestDialog', 'wcf', [
                                'ajaxCaptcha' => true,
                                'captchaID' => 'commentAdd',
                                'captchaObjectType' => $captchaObjectType,
                                'username' => WCF::getSession()->getVar('username')
-                       ))
-               );
+                       ])
+               ];
        }
        
        /**
         * Renders a comment.
         * 
-        * @param       \wcf\data\comment\Comment       $comment
+        * @param       Comment         $comment
         * @return      string
         */
        protected function renderComment(Comment $comment) {
@@ -630,17 +655,17 @@ class CommentAction extends AbstractDatabaseObjectAction {
                $comment->setIsDeletable($this->commentProcessor->canDeleteComment($comment->getDecoratedObject()));
                $comment->setIsEditable($this->commentProcessor->canEditComment($comment->getDecoratedObject()));
                
-               WCF::getTPL()->assign(array(
-                       'commentList' => array($comment),
+               WCF::getTPL()->assign([
+                       'commentList' => [$comment],
                        'commentManager' => $this->commentProcessor
-               ));
+               ]);
                return WCF::getTPL()->fetch('commentList');
        }
        
        /**
         * Renders a response.
         * 
-        * @param       \wcf\data\comment\response\CommentResponse      $response
+        * @param       CommentResponse $response
         * @return      string
         */
        protected function renderResponse(CommentResponse $response) {
@@ -649,10 +674,10 @@ class CommentAction extends AbstractDatabaseObjectAction {
                $response->setIsEditable($this->commentProcessor->canEditResponse($response->getDecoratedObject()));
                
                // render response
-               WCF::getTPL()->assign(array(
-                       'responseList' => array($response),
+               WCF::getTPL()->assign([
+                       'responseList' => [$response],
                        'commentManager' => $this->commentProcessor
-               ));
+               ]);
                return WCF::getTPL()->fetch('commentResponseList');
        }
        
@@ -673,7 +698,7 @@ class CommentAction extends AbstractDatabaseObjectAction {
        /**
         * Validates object type id parameter.
         * 
-        * @return      \wcf\data\object\type\ObjectType
+        * @return      ObjectType
         */
        protected function validateObjectType() {
                $this->readInteger('objectTypeID', false, 'data');
@@ -755,18 +780,14 @@ class CommentAction extends AbstractDatabaseObjectAction {
                        $this->captchaObjectType->getProcessor()->validate();
                }
                catch (UserInputException $e) {
-                       $this->validationErrors = array_merge($this->validationErrors,
-                               array(
-                                       $e->getField() => $e->getType()
-                               )
-                       );
+                       $this->validationErrors = array_merge($this->validationErrors, [$e->getField() => $e->getType()]);
                }
        }
        
        /**
         * Returns the comment object.
         * 
-        * @return      \wcf\data\comment\Comment
+        * @return      Comment
         */
        public function getComment() {
                return $this->comment;
@@ -775,7 +796,7 @@ class CommentAction extends AbstractDatabaseObjectAction {
        /**
         * Returns the comment response object.
         * 
-        * @return      \wcf\data\comment\response\CommentResponse
+        * @return      CommentResponse
         */
        public function getResponse() {
                return $this->response;
@@ -784,7 +805,7 @@ class CommentAction extends AbstractDatabaseObjectAction {
        /**
         * Returns the comment manager.
         * 
-        * @return      \wcf\system\comment\manager\ICommentManager
+        * @return      ICommentManager
         */
        public function getCommentManager() {
                return $this->commentProcessor;
index ab849485659566e47e45e93d0014265870d015eb..0f1fdd8b7b1ee9055f173f68e107c88875fb9483 100644 (file)
@@ -1,10 +1,12 @@
 <?php
 namespace wcf\data\moderation\queue;
+use wcf\data\ILinkableObject;
 use wcf\data\object\type\ObjectTypeCache;
 use wcf\data\user\User;
 use wcf\data\user\UserProfile;
 use wcf\data\user\UserProfileCache;
 use wcf\data\DatabaseObjectDecorator;
+use wcf\data\ITitledObject;
 use wcf\data\IUserContent;
 use wcf\system\bbcode\SimpleMessageParser;
 use wcf\system\moderation\queue\ModerationQueueManager;
@@ -20,15 +22,15 @@ use wcf\system\visitTracker\VisitTracker;
  * @subpackage data.moderation.queue
  * @category   Community Framework
  */
-class ViewableModerationQueue extends DatabaseObjectDecorator {
+class ViewableModerationQueue extends DatabaseObjectDecorator implements ILinkableObject, ITitledObject {
        /**
-        * @see \wcf\data\DatabaseObject::$baseClass
+        * @inheritDoc
         */
-       protected static $baseClass = 'wcf\data\moderation\queue\ModerationQueue';
+       protected static $baseClass = ModerationQueue::class;
        
        /**
         * affected object
-        * @var \wcf\data\IUserContent
+        * @var IUserContent
         */
        protected $affectedObject = null;
        
@@ -40,32 +42,28 @@ class ViewableModerationQueue extends DatabaseObjectDecorator {
        
        /**
         * user profile object
-        * @var \wcf\data\user\UserProfile
+        * @var UserProfile
         */
        protected $userProfile = null;
        
        /**
         * Sets link for viewing/editing.
         * 
-        * @param       \wcf\data\IUserContent          $object
+        * @param       IUserContent            $object
         */
        public function setAffectedObject(IUserContent $object) {
                $this->affectedObject = $object;
        }
        
        /**
-        * Returns the link for viewing/editing this object.
-        * 
-        * @return      string
+        * @inheritDoc
         */
        public function getLink() {
                return ModerationQueueManager::getInstance()->getLink($this->objectTypeID, $this->queueID);
        }
        
        /**
-        * Returns the title for this entry.
-        * 
-        * @return      string
+        * @inheritDoc
         */
        public function getTitle() {
                return ($this->affectedObject === null ? '' : $this->affectedObject->getTitle());
@@ -74,7 +72,7 @@ class ViewableModerationQueue extends DatabaseObjectDecorator {
        /**
         * Returns affected object.
         * 
-        * @return      \wcf\data\IUserContent
+        * @return      IUserContent
         */
        public function getAffectedObject() {
                return $this->affectedObject;
@@ -83,7 +81,7 @@ class ViewableModerationQueue extends DatabaseObjectDecorator {
        /**
         * Sets associated user profile object.
         * 
-        * @param       \wcf\data\user\UserProfile      $userProfile
+        * @param       UserProfile     $userProfile
         */
        public function setUserProfile(UserProfile $userProfile) {
                if ($this->affectedObject !== null && ($userProfile->userID == $this->affectedObject->getUserID())) {
@@ -94,7 +92,7 @@ class ViewableModerationQueue extends DatabaseObjectDecorator {
        /**
         * Returns associated user profile object.
         * 
-        * @return      \wcf\data\user\UserProfile
+        * @return      UserProfile
         */
        public function getUserProfile() {
                if ($this->affectedObject !== null && $this->userProfile === null) {
@@ -102,7 +100,7 @@ class ViewableModerationQueue extends DatabaseObjectDecorator {
                                $this->userProfile = UserProfileCache::getInstance()->getUserProfile($this->affectedObject->getUserID());
                        }
                        else {
-                               $this->userProfile = new UserProfile(new User(null, array()));
+                               $this->userProfile = new UserProfile(new User(null, []));
                        }
                }
                
@@ -136,11 +134,11 @@ class ViewableModerationQueue extends DatabaseObjectDecorator {
         * Returns a viewable moderation queue entry.
         * 
         * @param       integer         $queueID
-        * @return      \wcf\data\moderation\queue\ViewableModerationQueue
+        * @return      ViewableModerationQueue
         */
        public static function getViewableModerationQueue($queueID) {
                $queueList = new ViewableModerationQueueList();
-               $queueList->getConditionBuilder()->add("moderation_queue.queueID = ?", array($queueID));
+               $queueList->getConditionBuilder()->add("moderation_queue.queueID = ?", [$queueID]);
                $queueList->sqlLimit = 1;
                $queueList->readObjects();
                $queues = $queueList->getObjects();
index 74696623681b095436eeec382f820a3efe15a398..3b05bab02220c48d1dfc5d47399307528efb37fe 100644 (file)
@@ -6,13 +6,15 @@ use wcf\data\user\User;
 use wcf\data\user\UserProfile;
 use wcf\system\database\util\PreparedStatementConditionBuilder;
 use wcf\system\exception\SystemException;
+use wcf\system\moderation\queue\activation\IModerationQueueActivationHandler;
+use wcf\system\moderation\queue\report\IModerationQueueReportHandler;
 use wcf\system\WCF;
 
 /**
  * Default implementation for moderation queue handlers.
  * 
  * @author     Alexander Ebert
- * @copyright  2001-2015 WoltLab GmbH
+ * @copyright  2001-2016 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
  * @subpackage system.moderation.queue
@@ -44,7 +46,7 @@ abstract class AbstractModerationQueueHandler implements IModerationQueueHandler
        protected $requiredPermission = 'mod.general.canUseModeration';
        
        /**
-        * @see \wcf\system\moderation\queue\IModerationQueueHandler::identifyOrphans()
+        * @inheritDoc
         */
        public function identifyOrphans(array $queues) {
                if (empty($this->className) || !class_exists($this->className) || !is_subclass_of($this->className, 'wcf\data\DatabaseObject')) {
@@ -70,7 +72,7 @@ abstract class AbstractModerationQueueHandler implements IModerationQueueHandler
        }
        
        /**
-        * @see \wcf\system\moderation\queue\IModerationQueueHandler::removeQueues()
+        * @inheritDoc
         */
        public function removeQueues(array $objectIDs) {
                $objectTypeID = ModerationQueueManager::getInstance()->getObjectTypeID($this->definitionName, $this->objectType);
@@ -99,17 +101,35 @@ abstract class AbstractModerationQueueHandler implements IModerationQueueHandler
        }
        
        /**
-        * @see \wcf\system\moderation\queue\IModerationQueueHandler::canRemoveContent()
+        * @inheritDoc
         */
        public function canRemoveContent(ModerationQueue $queue) {
                return true;
        }
        
        /**
-        * @see \wcf\system\moderation\queue\IModerationQueueHandler::isAffectedUser()
+        * @inheritDoc
         */
        public function isAffectedUser(ModerationQueue $queue, $userID) {
                $user = new UserProfile(new User($userID));
                return $user->getPermission($this->requiredPermission);
        }
+       
+       /**
+        * @inheritDoc
+        * @since       2.2
+        */
+       public function getCommentNotificationLanguageItemPrefix() {
+               // this implementation exists to provide backwards compatibility;
+               // as there are no abstract implementations of the two interfaces,
+               // this is the best approach
+               if ($this instanceof IModerationQueueActivationHandler) {
+                       return 'wcf.moderation.activation.notification';
+               }
+               else if ($this instanceof IModerationQueueReportHandler) {
+                       return 'wcf.moderation.activation.notification';
+               }
+               
+               return 'wcf.moderation.notification';
+       }
 }
index 693645262b556102ab8f16666453bc8b752749b7..569ff39222bf6c2e5e225cec2b91b2bb7e62d793 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 namespace wcf\system\moderation\queue;
 use wcf\data\moderation\queue\ModerationQueue;
+use wcf\data\moderation\queue\ViewableModerationQueue;
 
 /**
  * Default interface for moderation queue handlers.
@@ -16,7 +17,7 @@ interface IModerationQueueHandler {
        /**
         * Creates queue assignments for matching object ids.
         * 
-        * @param       array<\wcf\data\moderation\queue\ModerationQueue>       $queues
+        * @param       ModerationQueue[]       $queues
         */
        public function assignQueues(array $queues);
        
@@ -31,8 +32,8 @@ interface IModerationQueueHandler {
        /**
         * Validates object ids and returns orphaned queue ids.
         * 
-        * @param       array<integer>          $queues
-        * @return      array<integer>
+        * @param       integer[]               $queues
+        * @return      integer[]
         */
        public function identifyOrphans(array $queues);
        
@@ -47,7 +48,7 @@ interface IModerationQueueHandler {
        /**
         * Populates object properties for viewing.
         * 
-        * @param       array<\wcf\data\moderation\queue\ViewableModerationQueue>       $queues
+        * @param       ViewableModerationQueue[]       $queues
         */
        public function populate(array $queues);
        
@@ -55,8 +56,8 @@ interface IModerationQueueHandler {
         * Removes affected content. It is up to the processing class to either
         * soft-delete the content or remove it permanently.
         * 
-        * @param       \wcf\data\moderation\queue\ModerationQueue      $queue
-        * @param       string                                          $message
+        * @param       ModerationQueue         $queue
+        * @param       string                  $message
         */
        public function removeContent(ModerationQueue $queue, $message);
        
@@ -71,16 +72,25 @@ interface IModerationQueueHandler {
         * Removes queses from database, should only be called if the referenced
         * object is permanently deleted.
         * 
-        * @param       array<integer>          $objectIDs
+        * @param       integer[]               $objectIDs
         */
        public function removeQueues(array $objectIDs);
        
        /**
         * Returns true, if given user is affected by given queue entry.
         * 
-        * @param       \wcf\data\moderation\queue\ModerationQueue      $queue
-        * @param       integer                                         $userID
+        * @param       ModerationQueue         $queue
+        * @param       integer                 $userID
         * @return      boolean
         */
        public function isAffectedUser(ModerationQueue $queue, $userID);
+       
+       /**
+        * Returns the prefix of language items for notifications for comments
+        * and comment reponses on moderation queues of this type. 
+        * 
+        * @return      string
+        * @since       2.2
+        */
+       public function getCommentNotificationLanguageItemPrefix();
 }
diff --git a/wcfsetup/install/files/lib/system/user/notification/event/ModerationQueueCommentResponseUserNotificationEvent.class.php b/wcfsetup/install/files/lib/system/user/notification/event/ModerationQueueCommentResponseUserNotificationEvent.class.php
new file mode 100644 (file)
index 0000000..ff63e0b
--- /dev/null
@@ -0,0 +1,200 @@
+<?php
+namespace wcf\system\user\notification\event;
+use wcf\data\moderation\queue\ViewableModerationQueue;
+use wcf\data\object\type\ObjectTypeCache;
+use wcf\system\comment\CommentDataHandler;
+use wcf\system\moderation\queue\report\IModerationQueueReportHandler;
+use wcf\system\WCF;
+
+/**
+ * User notification event for moderation queue commments.
+ *
+ * @author     Matthias Schmidt
+ * @copyright  2001-2016 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.user.notification.event
+ * @category   Community Framework
+ * @since      2.2
+ */
+class ModerationQueueCommentResponseUserNotificationEvent extends AbstractSharedUserNotificationEvent {
+       /**
+        * language item prefix for the notification texts
+        * @var string
+        */
+       protected $languageItemPrefix = null;
+       
+       /**
+        * moderation queue object the notifications (indirectly) belong to
+        * @var ViewableModerationQueue
+        */
+       protected $moderationQueue = null;
+       
+       /**
+        * true if the moderation queue is already loaded
+        * @var boolean
+        */
+       protected $moderationQueueLoaded = false;
+       
+       /**
+        * @inheritDoc
+        */
+       protected $stackable = true;
+       
+       /**
+        * @inheritDoc
+        */
+       public function checkAccess() {
+               if (!WCF::getSession()->getPermission('mod.general.canUseModeration') || $this->getModerationQueue() ===  null) {
+                       return false;
+               }
+               
+               return $this->getModerationQueue()->canEdit();
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function getEmailMessage($notificationType = 'instant') {
+               $authors = $this->getAuthors();
+               if (count($authors) > 1) {
+                       if (isset($authors[0])) {
+                               unset($authors[0]);
+                       }
+                       $count = count($authors);
+                       
+                       return $this->getLanguage()->getDynamicVariable($this->getLanguageItemPrefix().'.commentResponse.mail.stacked', [
+                               'author' => $this->author,
+                               'authors' => array_values($authors),
+                               'count' => $count,
+                               'notificationType' => $notificationType,
+                               'others' => $count - 1,
+                               'moderationQueue' => $this->getModerationQueue(),
+                               'response' => $this->userNotificationObject
+                       ]);
+               }
+               
+               $comment = CommentDataHandler::getInstance()->getComment($this->userNotificationObject->commentID);
+               if ($comment->userID) {
+                       $commentAuthor = CommentDataHandler::getInstance()->getUser($comment->userID);
+               }
+               else {
+                       $commentAuthor = new User(null, [
+                               'username' => $comment->username
+                       ]);
+               }
+               
+               return $this->getLanguage()->getDynamicVariable($this->getLanguageItemPrefix().'.commentResponse.mail', [
+                       'author' => $this->author,
+                       'commentAuthor' => $commentAuthor,
+                       'moderationQueue' => $this->getModerationQueue(),
+                       'notificationType' => $notificationType,
+                       'response' => $this->userNotificationObject
+               ]);
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function getEventHash() {
+               return sha1($this->eventID . '-' . $this->getModerationQueue()->queueID);
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function getLink() {
+               return $this->getModerationQueue()->getLink() . '#comments';
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function getMessage() {
+               $authors = $this->getAuthors();
+               if (count($authors) > 1) {
+                       if (isset($authors[0])) {
+                               unset($authors[0]);
+                       }
+                       $count = count($authors);
+                       
+                       return $this->getLanguage()->getDynamicVariable($this->getLanguageItemPrefix().'.commentResponse.message.stacked', [
+                               'authors' => array_values($authors),
+                               'count' => $count,
+                               'others' => $count - 1,
+                               'moderationQueue' => $this->getModerationQueue()
+                       ]);
+               }
+               
+               $comment = CommentDataHandler::getInstance()->getComment($this->userNotificationObject->commentID);
+               if ($comment->userID) {
+                       $commentAuthor = CommentDataHandler::getInstance()->getUser($comment->userID);
+               }
+               else {
+                       $commentAuthor = new User(null, [
+                               'username' => $comment->username
+                       ]);
+               }
+               
+               return $this->getLanguage()->getDynamicVariable($this->getLanguageItemPrefix().'.commentResponse.message', [
+                       'author' => $this->author,
+                       'commentAuthor' => $commentAuthor,
+                       'moderationQueue' => $this->getModerationQueue()
+               ]);
+       }
+       
+       /**
+        * Returns the moderation queue object the responded to comment belongs to.
+        * Returns null if the active user has no access to the moderation queue.
+        * 
+        * @return      ViewableModerationQueue
+        */
+       public function getModerationQueue() {
+               if (!$this->moderationQueueLoaded) {
+                       $comment = CommentDataHandler::getInstance()->getComment($this->userNotificationObject->commentID);
+                       
+                       $this->moderationQueue = ViewableModerationQueue::getViewableModerationQueue($comment->objectID);
+                       $this->moderationQueueLoaded = true;
+               }
+               
+               return $this->moderationQueue;
+       }
+       
+       /**
+        * Returns the language item prefix for the notification texts.
+        * 
+        * @return string
+        */
+       public function getLanguageItemPrefix() {
+               if ($this->languageItemPrefix === null) {
+                       /** @var IModerationQueueReportHandler $moderationHandler */
+                       $moderationHandler = ObjectTypeCache::getInstance()->getObjectType($this->getModerationQueue()->objectTypeID)->getProcessor();
+                       $this->languageItemPrefix = $moderationHandler->getCommentNotificationLanguageItemPrefix();
+               }
+               
+               return $this->languageItemPrefix;
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function getTitle() {
+               $count = count($this->getAuthors());
+               if ($count > 1) {
+                       return $this->getLanguage()->getDynamicVariable($this->getLanguageItemPrefix().'.commentResponse.title.stacked', [
+                               'count' => $count,
+                               'timesTriggered' => $this->notification->timesTriggered
+                       ]);
+               }
+               
+               return $this->getLanguage()->get($this->getLanguageItemPrefix().'.commentResponse.title');
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       protected function prepare() {
+               CommentDataHandler::getInstance()->cacheCommentID($this->userNotificationObject->commentID);
+               CommentDataHandler::getInstance()->cacheUserID($this->additionalData['userID']);
+       }
+}
diff --git a/wcfsetup/install/files/lib/system/user/notification/event/ModerationQueueCommentUserNotificationEvent.class.php b/wcfsetup/install/files/lib/system/user/notification/event/ModerationQueueCommentUserNotificationEvent.class.php
new file mode 100644 (file)
index 0000000..5701989
--- /dev/null
@@ -0,0 +1,150 @@
+<?php
+namespace wcf\system\user\notification\event;
+use wcf\data\moderation\queue\ViewableModerationQueue;
+use wcf\data\object\type\ObjectTypeCache;
+use wcf\data\user\notification\UserNotification;
+use wcf\data\user\UserProfile;
+use wcf\system\moderation\queue\IModerationQueueHandler;
+use wcf\system\user\notification\object\IUserNotificationObject;
+use wcf\system\WCF;
+
+/**
+ * User notification event for moderation queue commments.
+ * 
+ * @author     Matthias Schmidt
+ * @copyright  2001-2016 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.user.notification.event
+ * @category   Community Framework
+ * @since      2.2
+ */
+class ModerationQueueCommentUserNotificationEvent extends AbstractUserNotificationEvent {
+       /**
+        * language item prefix for the notification texts
+        * @var string
+        */
+       protected $languageItemPrefix = '';
+       
+       /**
+        * moderation queue object the notifications (indirectly) belong to
+        * @var ViewableModerationQueue
+        */
+       protected $moderationQueue = null;
+       
+       /**
+        * @inheritDoc
+        */
+       protected $stackable = true;
+       
+       /**
+        * @inheritDoc
+        */
+       public function checkAccess() {
+               if ($this->moderationQueue === null || !WCF::getSession()->getPermission('mod.general.canUseModeration')) {
+                       return false;
+               }
+               
+               return $this->moderationQueue->canEdit();
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function getEmailMessage($notificationType = 'instant') {
+               $authors = $this->getAuthors();
+               if (count($authors) > 1) {
+                       if (isset($authors[0])) {
+                               unset($authors[0]);
+                       }
+                       $count = count($authors);
+                       
+                       return $this->getLanguage()->getDynamicVariable($this->languageItemPrefix.'.comment.mail.stacked', [
+                               'author' => $this->author,
+                               'authors' => array_values($authors),
+                               'count' => $count,
+                               'others' => $count - 1,
+                               'moderationQueue' => $this->moderationQueue,
+                               'notificationType' => $notificationType
+                       ]);
+               }
+               
+               return $this->getLanguage()->getDynamicVariable($this->languageItemPrefix.'.comment.mail', [
+                       'comment' => $this->userNotificationObject,
+                       'author' => $this->author,
+                       'moderationQueue' => $this->moderationQueue,
+                       'notificationType' => $notificationType
+               ]);
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function getEventHash() {
+               return sha1($this->eventID . '-' . $this->moderationQueue->queueID);
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function getLink() {
+               return $this->moderationQueue->getLink() . '#comments';
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function getMessage() {
+               $authors = $this->getAuthors();
+               if (count($authors) > 1) {
+                       if (isset($authors[0])) {
+                               unset($authors[0]);
+                       }
+                       $count = count($authors);
+                       
+                       return $this->getLanguage()->getDynamicVariable($this->languageItemPrefix.'.comment.message.stacked', [
+                               'author' => $this->author,
+                               'authors' => array_values($authors),
+                               'count' => $count,
+                               'others' => $count - 1,
+                               'moderationQueue' => $this->moderationQueue
+                       ]);
+               }
+               
+               return $this->getLanguage()->getDynamicVariable($this->languageItemPrefix.'.comment.message', [
+                       'author' => $this->author,
+                       'moderationQueue' => $this->moderationQueue
+               ]);
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function getTitle() {
+               $count = count($this->getAuthors());
+               if ($count > 1) {
+                       return $this->getLanguage()->getDynamicVariable($this->languageItemPrefix.'.comment.title.stacked', [
+                               'count' => $count,
+                               'timesTriggered' => $this->notification->timesTriggered
+                       ]);
+               }
+               
+               return $this->getLanguage()->get($this->languageItemPrefix.'.comment.title');
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function setObject(UserNotification $notification, IUserNotificationObject $object, UserProfile $author, array $additionalData = []) {
+               parent::setObject($notification, $object, $author, $additionalData);
+               
+               // if the active user has no access, $this->moderationQueue is null
+               $this->moderationQueue = ViewableModerationQueue::getViewableModerationQueue($this->userNotificationObject->objectID);
+               
+               if ($this->moderationQueue) {
+                       /** @var IModerationQueueHandler $moderationHandler */
+                       $moderationHandler = ObjectTypeCache::getInstance()->getObjectType($this->moderationQueue->objectTypeID)->getProcessor();
+                       $this->languageItemPrefix = $moderationHandler->getCommentNotificationLanguageItemPrefix();
+               }
+       }
+}
diff --git a/wcfsetup/install/files/lib/system/user/notification/object/type/IMultiRecipientCommentUserNotificationObjectType.class.php b/wcfsetup/install/files/lib/system/user/notification/object/type/IMultiRecipientCommentUserNotificationObjectType.class.php
new file mode 100644 (file)
index 0000000..315a8de
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+namespace wcf\system\user\notification\object\type;
+use wcf\data\comment\Comment;
+
+/**
+ * Default interface for comment user notification object types with notifications
+ * being sent to multiple recipients.
+ * 
+ * This interface can also be implemented by user notification object types for
+ * comment responses. In this case, there is no distinction between commentResponse
+ * and commentResponseOwner event and only a commentResponse event is fired.
+ * 
+ * @author     Matthias Schmidt
+ * @copyright  2001-2016 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.user.notification.object.type
+ * @category   Community Framework
+ * @since      2.2
+ */
+interface IMultiRecipientCommentUserNotificationObjectType {
+       /**
+        * Returns the user ids of the notification recipients. If an empty array
+        * is returned, no notifications should be sent.
+        * 
+        * @param       integer         $comment
+        * @return      integer[]
+        */
+       public function getRecipientIDs(Comment $comment);
+}
diff --git a/wcfsetup/install/files/lib/system/user/notification/object/type/ModerationQueueCommentResponseUserNotificationObjectType.class.php b/wcfsetup/install/files/lib/system/user/notification/object/type/ModerationQueueCommentResponseUserNotificationObjectType.class.php
new file mode 100644 (file)
index 0000000..7eaa0f7
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+namespace wcf\system\user\notification\object\type;
+use wcf\data\comment\response\CommentResponse;
+use wcf\data\comment\response\CommentResponseList;
+use wcf\system\user\notification\object\CommentResponseUserNotificationObject;
+
+/**
+ * User notification object type implementation for moderation queue comment responses.
+ *
+ * @author     Mathias Schmidt
+ * @copyright  2001-2016 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.user.notification.object.type
+ * @category   Community Framework
+ * @since      2.2
+ */
+class ModerationQueueCommentResponseUserNotificationObjectType extends AbstractUserNotificationObjectType implements IMultiRecipientCommentUserNotificationObjectType { 
+       use TMultiRecipientModerationQueueCommentUserNotificationObjectType;
+       
+       /**
+        * @inheritDoc
+        */
+       protected static $decoratorClassName = CommentResponseUserNotificationObject::class;
+       
+       /**
+        * @inheritDoc
+        */
+       protected static $objectClassName = CommentResponse::class;
+       
+       /**
+        * @inheritDoc
+        */
+       protected static $objectListClassName = CommentResponseList::class;
+}
diff --git a/wcfsetup/install/files/lib/system/user/notification/object/type/ModerationQueueCommentUserNotificationObjectType.class.php b/wcfsetup/install/files/lib/system/user/notification/object/type/ModerationQueueCommentUserNotificationObjectType.class.php
new file mode 100644 (file)
index 0000000..2dc8525
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+namespace wcf\system\user\notification\object\type;
+use wcf\data\comment\Comment;
+use wcf\data\comment\CommentList;
+use wcf\system\user\notification\object\CommentUserNotificationObject;
+
+/**
+ * User notification object type implementation for moderation queue comments.
+ * 
+ * @author     Mathias Schmidt
+ * @copyright  2001-2016 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.user.notification.object.type
+ * @category   Community Framework
+ * @since      2.2
+ */
+class ModerationQueueCommentUserNotificationObjectType extends AbstractUserNotificationObjectType implements IMultiRecipientCommentUserNotificationObjectType {
+       use TMultiRecipientModerationQueueCommentUserNotificationObjectType;
+       
+       /**
+        * @inheritDoc
+        */
+       protected static $decoratorClassName = CommentUserNotificationObject::class;
+       
+       /**
+        * @inheritDoc
+        */
+       protected static $objectClassName = Comment::class;
+       
+       /**
+        * @inheritDoc
+        */
+       protected static $objectListClassName = CommentList::class;
+}
diff --git a/wcfsetup/install/files/lib/system/user/notification/object/type/TMultiRecipientModerationQueueCommentUserNotificationObjectType.class.php b/wcfsetup/install/files/lib/system/user/notification/object/type/TMultiRecipientModerationQueueCommentUserNotificationObjectType.class.php
new file mode 100644 (file)
index 0000000..0891a29
--- /dev/null
@@ -0,0 +1,101 @@
+<?php
+namespace wcf\system\user\notification\object\type;
+use wcf\data\comment\Comment;
+use wcf\data\user\UserProfile;
+use wcf\data\user\UserProfileCache;
+use wcf\system\comment\CommentHandler;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\user\storage\UserStorageHandler;
+use wcf\system\WCF;
+
+/**
+ * Implements IMultiRecipientCommentUserNotificationObjectType::getRecipientIDs()
+ * for moderation queue comment user notification object types.
+ *
+ * @author     Mathias Schmidt
+ * @copyright  2001-2016 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.user.notification.object.type
+ * @category   Community Framework
+ * @since      2.2
+ */
+trait TMultiRecipientModerationQueueCommentUserNotificationObjectType {
+       /**
+        * @see IMultiRecipientCommentUserNotificationObjectType::getRecipientIDs()
+        */
+       public function getRecipientIDs(Comment $comment) {
+               $objectTypeID = CommentHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.moderation.queue');
+               if ($comment->objectTypeID != $objectTypeID) {
+                       return [];
+               }
+               
+               $recipientIDs = [];
+               
+               // 1. fetch assigned user
+               // 2. fetch users who commented on the moderation queue entry
+               // 3. fetch users who responded to a comment on the moderation queue entry
+               $sql = "(
+                               SELECT  assignedUserID
+                               FROM    wcf".WCF_N."_moderation_queue
+                               WHERE   queueID = ?
+                                       AND assignedUserID IS NOT NULL
+                       )
+                       UNION
+                       (
+                               SELECT          DISTINCT userID
+                               FROM            wcf".WCF_N."_comment
+                               WHERE           objectID = ?
+                                               AND objectTypeID = ?
+                       )
+                       UNION
+                       (
+                               SELECT          DISTINCT comment_response.userID
+                               FROM            wcf".WCF_N."_comment_response comment_response
+                               LEFT JOIN       wcf".WCF_N."_comment comment
+                               ON              (comment.commentID = comment_response.commentID)
+                               WHERE           comment.objectID = ?
+                                               AND comment.objectTypeID = ?
+                       )";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute([
+                       $comment->objectID,
+                       $comment->objectID,
+                       $objectTypeID,
+                       $comment->objectID,
+                       $objectTypeID
+               ]);
+               while ($userID = $statement->fetchColumn()) {
+                       $recipientIDs[] = $userID;
+               }
+               
+               // make sure that all users can (still) access the moderation queue entry
+               if (!empty($recipientIDs)) {
+                       $conditionBuilder = new PreparedStatementConditionBuilder();
+                       $conditionBuilder->add('userID IN (?)', [$recipientIDs]);
+                       $conditionBuilder->add('queueID = ?', [$comment->objectID]);
+                       $conditionBuilder->add('isAffected = ?', [1]);
+                       $sql = "SELECT          userID
+                               FROM            wcf".WCF_N."_moderation_queue_to_user
+                               ".$conditionBuilder;
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute($conditionBuilder->getParameters());
+                       
+                       $recipientIDs = [];
+                       while ($userID = $statement->fetchColumn()) {
+                               $recipientIDs[] = $userID;
+                       }
+                       
+                       // make sure that all users (still) have permission to access moderation
+                       if (!$recipientIDs) {
+                               UserStorageHandler::getInstance()->loadStorage($recipientIDs);
+                               $userProfiles = UserProfileCache::getInstance()->getUserProfiles($recipientIDs);
+                               $recipientIDs = array_keys(array_filter($userProfiles, function(UserProfile $userProfile) {
+                                       return $userProfile->getPermission('mod.general.canUseModeration');
+                               }));
+                       }
+               }
+               
+               return $recipientIDs;
+       }
+}
index a4868e8e090f27842d4b5207403267be215e0c9b..3e70b9a135190e90cc789c61224b034f41894c58 100644 (file)
@@ -2434,6 +2434,30 @@ Fehler sind beispielsweise:
                <item name="wcf.moderation.markAllAsRead.confirmMessage"><![CDATA[Wollen Sie wirklich alle Einträge als gelesen markieren?]]></item>
                <item name="wcf.moderation.moderation"><![CDATA[Moderation]]></item>
                <item name="wcf.moderation.noMoreItems"><![CDATA[Keine weiteren Einträge]]></item>
+               <item name="wcf.moderation.notification.comment.mail"><![CDATA[{if !$author->userID}ein Gast{else}{@$author->username}{/if} hat einen Kommentar zum Moderationseintrag "{$moderationQueue->getTitle()}" verfasst:
+{if $notificationType == 'instant'}
+---------------------------------
+{@$comment->message} 
+---------------------------------
+{/if}{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.notification.comment.mail.stacked"><![CDATA[{if $count < 4}{@$authors[0]->username}{if $count != 1}{if $count == 2} und {else}, {/if}{@$authors[1]->username}{if $count == 3} und {@$authors[2]->username}{/if}{/if}{else}{@$authors[0]->username} und {#$others} weitere Benutzer{/if} haben Kommentare zum Moderationseintrag "{$moderationQueue->getTitle()}" verfasst:
+{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.notification.comment.message"><![CDATA[{if !$author->userID}Ein Gast{else}{@$author->getAnchorTag()}{/if} hat einen Kommentar zum Moderationseintrag <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a> verfasst.]]></item>
+               <item name="wcf.moderation.notification.comment.message.stacked"><![CDATA[{if $count < 4}{@$authors[0]->getAnchorTag()}{if $count != 1}{if $count == 2} und {else}, {/if}{@$authors[1]->getAnchorTag()}{if $count == 3} und {@$authors[2]->getAnchorTag()}{/if}{/if}{else}{@$authors[0]->getAnchorTag()} und {#$others} weitere Benutzer{/if} haben Kommentare zum Moderationseintrag <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a> verfasst.]]></item>
+               <item name="wcf.moderation.notification.comment.title"><![CDATA[Neuer Kommentar (Moderation)]]></item>
+               <item name="wcf.moderation.notification.comment.title.stacked"><![CDATA[{#$timesTriggered} neue Kommentare (Moderation)]]></item>
+               <item name="wcf.moderation.notification.commentResponse.mail"><![CDATA[{if !$author->userID}ein Gast{else}{@$author->username}{/if} hat eine Antwort zum Kommentar von "{@$commentAuthor->username}" zum Moderationseintrag "{$moderationQueue->getTitle()}" verfasst:
+{if $notificationType == 'instant'}
+---------------------------------
+{@$response->message} 
+---------------------------------
+{/if}{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.notification.commentResponse.mail.stacked"><![CDATA[{if $count < 4}{@$authors[0]->username}{if $count != 1}{if $count == 2} und {else}, {/if}{@$authors[1]->username}{if $count == 3} und {@$authors[2]->username}{/if}{/if}{else}{@$authors[0]->username} und {#$others} weitere Benutzer{/if} haben Antworten zu Kommentare zum Moderationseintrag "{$moderationQueue->getTitle()}" verfasst:
+{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.notification.commentResponse.message"><![CDATA[{if !$author->userID}Ein Gast{else}{@$author->getAnchorTag()}{/if} hat eine Antwort zum Kommentar von {if $commentAuthor->userID}<a href="{link controller='User' object=$commentAuthor}{/link}" class="userLink" data-user-id="{@$commentAuthor->userID}">{$commentAuthor->username}</a>{else}{$commentAuthor->username}{/if} zum Moderationseintrag <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a> verfasst.]]></item>
+               <item name="wcf.moderation.notification.commentResponse.message.stacked"><![CDATA[{if $count < 4}{@$authors[0]->getAnchorTag()}{if $count != 1}{if $count == 2} und {else}, {/if}{@$authors[1]->getAnchorTag()}{if $count == 3}und {@$authors[2]->getAnchorTag()}{/if}{/if}{else}{@$authors[0]->getAnchorTag()} und {#$others} weitere Benutzer{/if} haben Kommentare zum Moderationseintrag <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a> verfasst.]]></item>
+               <item name="wcf.moderation.notification.commentResponse.title"><![CDATA[Neue Antwort (Moderation)]]></item>
+               <item name="wcf.moderation.notification.commentResponse.title.stacked"><![CDATA[{#$timesTriggered} neue Antworten (Moderation)]]></item>
                <item name="wcf.moderation.status"><![CDATA[Status]]></item>
                <item name="wcf.moderation.status.outstanding"><![CDATA[Ausstehend]]></item>
                <item name="wcf.moderation.status.processing"><![CDATA[In Bearbeitung]]></item>
@@ -2467,6 +2491,30 @@ Fehler sind beispielsweise:
                <item name="wcf.moderation.activation.content"><![CDATA[Freizuschaltender Inhalt]]></item>
                <item name="wcf.moderation.activation.enableContent"><![CDATA[Inhalt freischalten]]></item>
                <item name="wcf.moderation.activation.enableContent.confirmMessage"><![CDATA[Wollen Sie diesen Inhalt wirklich freischalten?]]></item>
+               <item name="wcf.moderation.activation.notification.comment.mail"><![CDATA[{if !$author->userID}ein Gast{else}{@$author->username}{/if} hat einen Kommentar zum freizuschaltenden Inhalt "{$moderationQueue->getTitle()}" verfasst:
+{if $notificationType == 'instant'}
+---------------------------------
+{@$comment->message} 
+---------------------------------
+{/if}{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.activation.notification.comment.mail.stacked"><![CDATA[{if $count < 4}{@$authors[0]->username}{if $count != 1}{if $count == 2} und {else}, {/if}{@$authors[1]->username}{if $count == 3}und {@$authors[2]->username}{/if}{/if}{else}{@$authors[0]->username} {#$others} weitere Benutzer {/if} haben Kommentare zum freizuschaltenden Inhalt "{$moderationQueue->getTitle()}" verfasst:
+{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.activation.notification.comment.message"><![CDATA[{if !$author->userID}Ein Gast{else}{@$author->getAnchorTag()}{/if} hat einen Kommentar zum freizuschaltenden Inhalt <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a> verfasst.]]></item>
+               <item name="wcf.moderation.activation.notification.comment.message.stacked"><![CDATA[{if $count < 4}{@$authors[0]->getAnchorTag()}{if $count != 1}{if $count == 2} und {else}, {/if}{@$authors[1]->getAnchorTag()}{if $count == 3}und {@$authors[2]->getAnchorTag()}{/if}{/if}{else}{@$authors[0]->getAnchorTag()} und {#$others} weitere Benutzer{/if} haben Kommentare zum freizuschaltenden Inhalt <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a> verfasst.]]></item>
+               <item name="wcf.moderation.activation.notification.comment.title"><![CDATA[Neuer Kommentar (Freischaltung)]]></item>
+               <item name="wcf.moderation.activation.notification.comment.title.stacked"><![CDATA[{#$timesTriggered} neue Kommentare (Freischaltung)]]></item>
+               <item name="wcf.moderation.activation.notification.commentResponse.mail"><![CDATA[{if !$author->userID}ein Gast{else}{@$author->username}{/if} hat eine Antwort zum Kommentar von "{@$commentAuthor->username}" zum freizuschaltenden Inhalt "{$moderationQueue->getTitle()}" verfasst:
+{if $notificationType == 'instant'}
+---------------------------------
+{@$response->message} 
+---------------------------------
+{/if}{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.activation.notification.commentResponse.mail.stacked"><![CDATA[{if $count < 4}{@$authors[0]->username}{if $count != 1}{if $count == 2} und {else}, {/if}{@$authors[1]->username}{if $count == 3} und {@$authors[2]->username}{/if}{/if}{else}{@$authors[0]->username} und {#$others} weitere Benutzer{/if} haben Antworten zu Kommentare zum freizuschaltenden Inhalt "{$moderationQueue->getTitle()}" verfasst:
+{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.activation.notification.commentResponse.message"><![CDATA[{if !$author->userID}Ein Gast{else}{@$author->getAnchorTag()}{/if} hat eine Antwort zum Kommentar von {if $commentAuthor->userID}<a href="{link controller='User' object=$commentAuthor}{/link}" class="userLink" data-user-id="{@$commentAuthor->userID}">{$commentAuthor->username}</a>{else}{$commentAuthor->username}{/if} zum freizuschaltenden Inhalt <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a> verfasst.]]></item>
+               <item name="wcf.moderation.activation.notification.commentResponse.message.stacked"><![CDATA[{if $count < 4}{@$authors[0]->getAnchorTag()}{if $count != 1}{if $count == 2} und {else}, {/if}{@$authors[1]->getAnchorTag()}{if $count == 3} und {@$authors[2]->getAnchorTag()}{/if}{/if}{else}{@$authors[0]->getAnchorTag()} und {#$others} weitere Benutzer{/if} haben Antworten zu Kommentare zum freizuschaltenden Inhalt <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a> verfasst.]]></item>
+               <item name="wcf.moderation.activation.notification.commentResponse.title"><![CDATA[Neue Antwort (Freischaltung)]]></item>
+               <item name="wcf.moderation.activation.notification.commentResponse.title.stacked"><![CDATA[{#$timesTriggered} neue Antworten (Freischaltung)]]></item>
                <item name="wcf.moderation.activation.removeContent"><![CDATA[Inhalt löschen]]></item>
                <item name="wcf.moderation.activation.removeContent.confirmMessage"><![CDATA[Wollen Sie diesen Inhalt wirklich löschen?]]></item>
        </category>
@@ -2475,6 +2523,30 @@ Fehler sind beispielsweise:
                <item name="wcf.moderation.report"><![CDATA[Meldung]]></item>
                <item name="wcf.moderation.report.alreadyReported"><![CDATA[Dieser Inhalt wurde bereits gemeldet.]]></item>
                <item name="wcf.moderation.report.details"><![CDATA[Informationen]]></item>
+               <item name="wcf.moderation.report.notification.comment.mail"><![CDATA[{if !$author->userID}ein Gast{else}{@$author->username}{/if} hat einen Kommentar zur Meldung "{$moderationQueue->getTitle()}" verfasst:
+{if $notificationType == 'instant'}
+---------------------------------
+{@$comment->message} 
+---------------------------------
+{/if}{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.report.notification.comment.mail.stacked"><![CDATA[{if $count < 4}{@$authors[0]->username}{if $count != 1}{if $count == 2} und {else}, {/if}{@$authors[1]->username}{if $count == 3} und {@$authors[2]->username}{/if}{/if}{else}{@$authors[0]->username} und {#$others} weitere Benutzer{/if} haben Kommentare zur Meldung "{$moderationQueue->getTitle()}" verfasst:
+{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.report.notification.comment.message"><![CDATA[{if !$author->userID}Ein Gast{else}{@$author->getAnchorTag()}{/if} hat einen Kommentar zur Meldung <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a> verfasst.]]></item>
+               <item name="wcf.moderation.report.notification.comment.message.stacked"><![CDATA[{if $count < 4}{@$authors[0]->getAnchorTag()}{if $count != 1}{if $count == 2} und {else}, {/if}{@$authors[1]->getAnchorTag()}{if $count == 3} und {@$authors[2]->getAnchorTag()}{/if}{/if}{else}{@$authors[0]->getAnchorTag()} und {#$others} weitere Benutzer{/if} haben Kommentare zur Meldung <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a> verfasst.]]></item>
+               <item name="wcf.moderation.report.notification.comment.title"><![CDATA[Neuer Kommentar (Meldung)]]></item>
+               <item name="wcf.moderation.report.notification.comment.title.stacked"><![CDATA[{#$timesTriggered} neue Kommentare (Meldung)]]></item>
+               <item name="wcf.moderation.report.notification.commentResponse.mail"><![CDATA[{if !$author->userID}ein Gast{else}{@$author->username}{/if} hat eine Antwort zum Kommentar von "{@$commentAuthor->username}" zur Meldung "{$moderationQueue->getTitle()}" verfasst:
+{if $notificationType == 'instant'}
+---------------------------------
+{@$response->message} 
+---------------------------------
+{/if}{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.report.notification.commentResponse.mail.stacked"><![CDATA[{if $count < 4}{@$authors[0]->username}{if $count != 1}{if $count == 2} und {else}, {/if}{@$authors[1]->username}{if $count == 3} und {@$authors[2]->username}{/if}{/if}{else}{@$authors[0]->username} und {#$others} weitere Benutzer{/if} haben Antworten zu Kommentare zur Meldung "{$moderationQueue->getTitle()}" verfasst:
+{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.report.notification.commentResponse.message"><![CDATA[{if !$author->userID}Ein Gast{else}{@$author->getAnchorTag()}{/if} hat eine Antwort zum Kommentar von {if $commentAuthor->userID}<a href="{link controller='User' object=$commentAuthor}{/link}" class="userLink" data-user-id="{@$commentAuthor->userID}">{$commentAuthor->username}</a>{else}{$commentAuthor->username}{/if} zur Meldung <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a> verfasst.]]></item>
+               <item name="wcf.moderation.report.notification.commentResponse.message.stacked"><![CDATA[{if $count < 4}{@$authors[0]->getAnchorTag()}{if $count != 1}{if $count == 2} und {else}, {/if}{@$authors[1]->getAnchorTag()}{if $count == 3}und {@$authors[2]->getAnchorTag()}{/if}{/if}{else}{@$authors[0]->getAnchorTag()} und {#$others} weitere Benutzer{/if} haben Antworten zu Kommentare zur Meldung <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a> verfasst.]]></item>
+               <item name="wcf.moderation.report.notification.commentResponse.title"><![CDATA[Neue Antwort (Meldung)]]></item>
+               <item name="wcf.moderation.report.notification.commentResponse.title.stacked"><![CDATA[{#$timesTriggered} neue Antworten (Meldung)]]></item>
                <item name="wcf.moderation.report.reason"><![CDATA[Grund der Meldung]]></item>
                <item name="wcf.moderation.report.reason.description"><![CDATA[Diese Funktion ist ausschließlich zu verwenden bei: Spam, Werbung und anderen problematischen (rassistischen, gewaltverherrlichenden, aggressiven, beleidigenden oder sexistischen) Inhalten.]]></item>
                <item name="wcf.moderation.report.removeContent"><![CDATA[Gemeldeten Inhalt löschen]]></item>
@@ -3167,6 +3239,10 @@ Möchten Sie diese E-Mail-Benachrichtigung in Zukunft nicht mehr erhalten, könn
                <item name="wcf.user.notification.com.woltlab.wcf.user.profileComment.response.notification.commentResponseOwner"><![CDATA[Neue Antwort auf einen Kommentar an Ihrer Pinnwand]]></item>
                <item name="wcf.user.notification.com.woltlab.wcf.user.profileComment.like.notification.like"><![CDATA[Jemandem gefällt Ihr Kommentar]]></item>
                <item name="wcf.user.notification.com.woltlab.wcf.user.profileComment.response.like.notification.like"><![CDATA[Jemandem gefällt Ihre Antwort auf einen Kommentar]]></item>
+               
+               <item name="wcf.user.notification.com.woltlab.wcf.moderation"><![CDATA[Moderation]]></item>
+               <item name="wcf.user.notification.com.woltlab.wcf.moderation.queue.notification.comment"><![CDATA[Neuer Kommentar in der Moderation]]></item>
+               <item name="wcf.user.notification.com.woltlab.wcf.moderation.queue.response.notification.commentResponse"><![CDATA[Neue Antwort auf einen Kommentar in der Moderation]]></item>
        </category>
        
        <category name="wcf.user.profile">
index 1998832daf969e88b0a27999d36ac058c1387cd6..9eaf33e3c5fd503e02c27c7d1733bd83d0042020 100644 (file)
@@ -2464,6 +2464,30 @@ Errors are:
                <item name="wcf.moderation.markAllAsRead.confirmMessage"><![CDATA[Do you really want to mark all entries as read?]]></item>
                <item name="wcf.moderation.moderation"><![CDATA[Moderation]]></item>
                <item name="wcf.moderation.noMoreItems"><![CDATA[No more items]]></item>
+               <item name="wcf.moderation.notification.comment.mail"><![CDATA[{if !$author->userID}a guest{else}{@$author->username}{/if} wrote a comment on the moderation entry "{$moderationQueue->getTitle()}":
+{if $notificationType == 'instant'}
+---------------------------------
+{@$comment->message} 
+---------------------------------
+{/if}{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.notification.comment.mail.stacked"><![CDATA[{if $count < 4}{@$authors[0]->username}{if $count != 1}{if $count == 2} and {else}, {/if}{@$authors[1]->username}{if $count == 3} and {@$authors[2]->username}{/if}{/if}{else}{@$authors[0]->username} and {#$others} other users{/if} wrote comments on the moderation entry "{$moderationQueue->getTitle()}":
+{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.notification.comment.message"><![CDATA[{if !$author->userID}A guest{else}{@$author->getAnchorTag()}{/if} wrote a comment on the moderation entry <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a>.]]></item>
+               <item name="wcf.moderation.notification.comment.message.stacked"><![CDATA[{if $count < 4}{@$authors[0]->getAnchorTag()}{if $count != 1}{if $count == 2} and {else}, {/if}{@$authors[1]->getAnchorTag()}{if $count == 3} and {@$authors[2]->getAnchorTag()}{/if}{/if}{else}{@$authors[0]->getAnchorTag()} and {#$others} other users{/if} wrote comments on the moderation entry <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a>.]]></item>
+               <item name="wcf.moderation.notification.comment.title"><![CDATA[New comment (Moderation)]]></item>
+               <item name="wcf.moderation.notification.comment.title.stacked"><![CDATA[{#$timesTriggered} new comments (Moderation)]]></item>
+               <item name="wcf.moderation.notification.commentResponse.mail"><![CDATA[{if !$author->userID}a guest{else}{@$author->username}{/if} wrote a reply to {@$commentAuthor->username}’s comment on the moderation entry "{$moderationQueue->getTitle()}":
+{if $notificationType == 'instant'}
+---------------------------------
+{@$response->message} 
+---------------------------------
+{/if}{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.notification.commentResponse.mail.stacked"><![CDATA[{if $count < 4}{@$authors[0]->username}{if $count != 1}{if $count == 2} and {else}, {/if}{@$authors[1]->username}{if $count == 3} and {@$authors[2]->username}{/if}{/if}}{else}{@$authors[0]->username} and {#$others} other users{/if} wrote replies to comments on the moderation entry "{$moderationQueue->getTitle()}":
+{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.notification.commentResponse.message"><![CDATA[{if !$author->userID}A guest{else}{@$author->getAnchorTag()}{/if} wrote a reply to a comment by {if $commentAuthor->userID}<a href="{link controller='User' object=$commentAuthor}{/link}" class="userLink" data-user-id="{@$commentAuthor->userID}">{$commentAuthor->username}</a>{else}{$commentAuthor->username}{/if} on the moderation entry <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a>.]]></item>
+               <item name="wcf.moderation.notification.commentResponse.message.stacked"><![CDATA[{if $count < 4}{@$authors[0]->getAnchorTag()}{if $count != 1}{if $count == 2} and {else}, {/if}{@$authors[1]->getAnchorTag()}{if $count == 3} and {@$authors[2]->getAnchorTag()}{/if}{/if}{else}{@$authors[0]->getAnchorTag()} and {#$others} other users{/if} wrote replies to comments on the moderation entry <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a>.]]></item>
+               <item name="wcf.moderation.notification.commentResponse.title"><![CDATA[New reply (Moderation)]]></item>
+               <item name="wcf.moderation.notification.commentResponse.title.stacked"><![CDATA[{#$timesTriggered} new replies (Moderation)]]></item>
                <item name="wcf.moderation.status"><![CDATA[Status]]></item>
                <item name="wcf.moderation.status.outstanding"><![CDATA[Pending]]></item>
                <item name="wcf.moderation.status.processing"><![CDATA[In Progress]]></item>
@@ -2497,6 +2521,30 @@ Errors are:
                <item name="wcf.moderation.activation.content"><![CDATA[Content Awaiting Approval]]></item>
                <item name="wcf.moderation.activation.enableContent"><![CDATA[Approve]]></item>
                <item name="wcf.moderation.activation.enableContent.confirmMessage"><![CDATA[Do you really want to approve this content?]]></item>
+               <item name="wcf.moderation.activation.notification.comment.mail"><![CDATA[{if !$author->userID}a guest{else}{@$author->username}{/if} wrote a comment on "{$moderationQueue->getTitle()}" waiting for approval:
+{if $notificationType == 'instant'}
+---------------------------------
+{@$comment->message} 
+---------------------------------
+{/if}{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.activation.notification.comment.mail.stacked"><![CDATA[{if $count < 4}{@$authors[0]->username}{if $count != 1}{if $count == 2} and {else}, {/if}{@$authors[1]->username}{if $count == 3} and {@$authors[2]->username}{/if}{/if}{else}{@$authors[0]->username} and {#$others} other users{/if} wrote comments on "{$moderationQueue->getTitle()}" waiting for approval:
+{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.activation.notification.comment.message"><![CDATA[{if !$author->userID}A guest{else}{@$author->getAnchorTag()}{/if} wrote a comment on <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a> waiting for approval.]]></item>
+               <item name="wcf.moderation.activation.notification.comment.message.stacked"><![CDATA[{if $count < 4}{@$authors[0]->getAnchorTag()}{if $count != 1}{if $count == 2} and {else}, {/if}{@$authors[1]->getAnchorTag()}{if $count == 3} and {@$authors[2]->getAnchorTag()}{/if}{/if}{else}{@$authors[0]->getAnchorTag()} and {#$others} other users{/if} wrote comments on <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a> waiting for approval.]]></item>
+               <item name="wcf.moderation.activation.notification.comment.title"><![CDATA[New comment (Approval)]]></item>
+               <item name="wcf.moderation.activation.notification.comment.title.stacked"><![CDATA[{#$timesTriggered} new comments (Approval)]]></item>
+               <item name="wcf.moderation.activation.notification.commentResponse.mail"><![CDATA[{if !$author->userID}a guest{else}{@$author->username}{/if} wrote a reply to {@$commentAuthor->username}’s comment on "{$moderationQueue->getTitle()}" waiting for approval:
+{if $notificationType == 'instant'}
+---------------------------------
+{@$response->message} 
+---------------------------------
+{/if}{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.activation.notification.commentResponse.mail.stacked"><![CDATA[{if $count < 4}{@$authors[0]->username}{if $count != 1}{if $count == 2} and {else}, {/if}{@$authors[1]->username}{if $count == 3} and {@$authors[2]->username}{/if}{/if}}{else}{@$authors[0]->username} and {#$others} other users{/if} wrote replies to comments on "{$moderationQueue->getTitle()}" waiting for approval:
+{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.activation.notification.commentResponse.message"><![CDATA[{if !$author->userID}A guest{else}{@$author->getAnchorTag()}{/if} wrote a reply to a comment by {if $commentAuthor->userID}<a href="{link controller='User' object=$commentAuthor}{/link}" class="userLink" data-user-id="{@$commentAuthor->userID}">{$commentAuthor->username}</a>{else}{$commentAuthor->username}{/if} on <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a> waiting for approval.]]></item>
+               <item name="wcf.moderation.activation.notification.commentResponse.message.stacked"><![CDATA[{if $count < 4}{@$authors[0]->getAnchorTag()}{if $count != 1}{if $count == 2} and {else}, {/if}{@$authors[1]->getAnchorTag()}{if $count == 3} and {@$authors[2]->getAnchorTag()}{/if}{/if}{else}{@$authors[0]->getAnchorTag()} and {#$others} other users{/if} wrote replies to comments on <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a> waiting for approval.]]></item>
+               <item name="wcf.moderation.activation.notification.commentResponse.title"><![CDATA[New reply (Approval)]]></item>
+               <item name="wcf.moderation.activation.notification.commentResponse.title.stacked"><![CDATA[{#$timesTriggered} new replies (Approval)]]></item>
                <item name="wcf.moderation.activation.removeContent"><![CDATA[Delete Content]]></item>
                <item name="wcf.moderation.activation.removeContent.confirmMessage"><![CDATA[Do you really want to delete this content?]]></item>
        </category>
@@ -2505,6 +2553,30 @@ Errors are:
                <item name="wcf.moderation.report"><![CDATA[Report]]></item>
                <item name="wcf.moderation.report.alreadyReported"><![CDATA[This content has already been reported.]]></item>
                <item name="wcf.moderation.report.details"><![CDATA[Information]]></item>
+               <item name="wcf.moderation.report.notification.comment.mail"><![CDATA[{if !$author->userID}a guest{else}{@$author->username}{/if} wrote a comment on the report "{$moderationQueue->getTitle()}":
+{if $notificationType == 'instant'}
+---------------------------------
+{@$comment->message} 
+---------------------------------
+{/if}{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.report.notification.comment.mail.stacked"><![CDATA[{if $count < 4}{@$authors[0]->username}{if $count != 1}{if $count == 2} and {else}, {/if}{@$authors[1]->username}{if $count == 3} and {@$authors[2]->username}{/if}{/if}{else}{@$authors[0]->username} and {#$others} other users{/if} wrote comments on the report "{$moderationQueue->getTitle()}":
+{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.report.notification.comment.message"><![CDATA[{if !$author->userID}A guest{else}{@$author->getAnchorTag()}{/if} wrote a comment on <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a> waiting for approval.]]></item>
+               <item name="wcf.moderation.report.notification.comment.message.stacked"><![CDATA[{if $count < 4}{@$authors[0]->getAnchorTag()}{if $count != 1}{if $count == 2} and {else}, {/if}{@$authors[1]->getAnchorTag()}{if $count == 3} and {@$authors[2]->getAnchorTag()}{/if}{/if}{else}{@$authors[0]->getAnchorTag()} and {#$others} other users{/if} wrote comments on the report <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a>.]]></item>
+               <item name="wcf.moderation.report.notification.comment.title"><![CDATA[New comment (Report)]]></item>
+               <item name="wcf.moderation.report.notification.comment.title.stacked"><![CDATA[{#$timesTriggered} new comments (Report)]]></item>
+               <item name="wcf.moderation.report.notification.commentResponse.mail"><![CDATA[{if !$author->userID}a guest{else}{@$author->username}{/if} wrote a reply to {@$commentAuthor->username}’s comment on the report "{$moderationQueue->getTitle()}":
+{if $notificationType == 'instant'}
+---------------------------------
+{@$response->message} 
+---------------------------------
+{/if}{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.report.notification.commentResponse.mail.stacked"><![CDATA[{if $count < 4}{@$authors[0]->username}{if $count != 1}{if $count == 2} and {else}, {/if}{@$authors[1]->username}{if $count == 3} and {@$authors[2]->username}{/if}{/if}{else}{@$authors[0]->username} and {#$others} other users{/if} wrote replies to comments on the report "{$moderationQueue->getTitle()}":
+{$moderationQueue->getLink()}#comments]]></item>
+               <item name="wcf.moderation.report.notification.commentResponse.message"><![CDATA[{if !$author->userID}A guest{else}{@$author->getAnchorTag()}{/if} wrote a reply to a comment by {if $commentAuthor->userID}<a href="{link controller='User' object=$commentAuthor}{/link}" class="userLink" data-user-id="{@$commentAuthor->userID}">{$commentAuthor->username}</a>{else}{$commentAuthor->username}{/if} on the report <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a>.]]></item>
+               <item name="wcf.moderation.report.notification.commentResponse.message.stacked"><![CDATA[{if $count < 4}{@$authors[0]->getAnchorTag()}{if $count != 1}{if $count == 2} and {else}, {/if}{@$authors[1]->getAnchorTag()}{if $count == 3} and {@$authors[2]->getAnchorTag()}{/if}{/if}{else}{@$authors[0]->getAnchorTag()}{if $guestTimesTriggered},{else} and{/if} {#$others} other users{/if} wrote replies to comments on the report <a href="{@$moderationQueue->getLink()}">{$moderationQueue->getTitle()}</a>.]]></item>
+               <item name="wcf.moderation.report.notification.commentResponse.title"><![CDATA[New reply (Report)]]></item>
+               <item name="wcf.moderation.report.notification.commentResponse.title.stacked"><![CDATA[{#$timesTriggered} new replies (Report)]]></item>
                <item name="wcf.moderation.report.reason"><![CDATA[Reason]]></item>
                <item name="wcf.moderation.report.reason.description"><![CDATA[This function is reserved for: Spam, Advertisement and other questionable (racism, glorification of violence, offending or sexist) content]]></item>
                <item name="wcf.moderation.report.removeContent"><![CDATA[Delete Reported Content]]></item>
@@ -3192,6 +3264,10 @@ If you do not want to receive further email notifications for this event, you ca
                <item name="wcf.user.notification.com.woltlab.wcf.user.profileComment.response.notification.commentResponseOwner"><![CDATA[New reply to a comment on your wall]]></item>
                <item name="wcf.user.notification.com.woltlab.wcf.user.profileComment.like.notification.like"><![CDATA[Your comment was liked]]></item>
                <item name="wcf.user.notification.com.woltlab.wcf.user.profileComment.response.like.notification.like"><![CDATA[Reply to your comment was liked]]></item>
+               
+               <item name="wcf.user.notification.com.woltlab.wcf.moderation"><![CDATA[Moderation]]></item>
+               <item name="wcf.user.notification.com.woltlab.wcf.moderation.queue.notification.comment"><![CDATA[New comment in moderation]]></item>
+               <item name="wcf.user.notification.com.woltlab.wcf.moderation.queue.response.notification.commentResponse"><![CDATA[New reply to a comment in moderation]]></item>
        </category>
        
        <category name="wcf.user.profile">