/** * @see \wcf\data\like\object\ILikeObject::sendNotification() */ public function sendNotification(Like $like) { if ($this->object->userID != WCF::getUser()->userID) { $notificationObject = new LikeUserNotificationObject($like); UserNotificationHandler::getInstance()->fireEvent('like', 'de.incendium.cms.like.likeableNews.notification', $notificationObject, array($this->object->userID), array('objectID' => $this->object->entryID)); } }
/** * @see \wcf\data\like\object\ILikeObject::sendNotification() */ public function sendNotification(Like $like) { $objectType = CommentHandler::getInstance()->getObjectType($this->object->objectTypeID); if (UserNotificationHandler::getInstance()->getObjectTypeID($objectType->objectType . '.like.notification')) { $notificationObjectType = UserNotificationHandler::getInstance()->getObjectTypeProcessor($objectType->objectType . '.like.notification'); if ($this->userID != WCF::getUser()->userID) { $notificationObject = new LikeUserNotificationObject($like); UserNotificationHandler::getInstance()->fireEvent('like', $objectType->objectType . '.like.notification', $notificationObject, array($this->userID), array('objectID' => $this->object->objectID, 'objectOwnerID' => $this->userID)); } } }
/** * Marks all news categories as read. */ public function markAllAsRead() { VisitTracker::getInstance()->trackTypeVisit('de.incendium.cms.news.entry'); // reset the user storage data and delete notifications if (WCF::getUser()->userID) { // user storage data UserStorageHandler::getInstance()->reset(array(WCF::getUser()->userID), 'cmsUnreadNewsEntries'); // user notifications UserNotificationHandler::getInstance()->markAsConfirmed('news', 'de.incendium.cms.news.entry', array(WCF::getUser()->userID)); } }
/** * Fires notification event to notify all subscribers when added a commit. */ protected function addComment() { // Fetch latest comment, it's the one we want to work with. // WCF 2.1 will provide direct access to the comment $sql = "SELECT\t\t*\n\t\t\tFROM\t\twcf" . WCF_N . "_comment\n\t\t\tORDER BY\tcommentID DESC"; $statement = WCF::getDB()->prepareStatement($sql, 1); $statement->execute(); $comment = $statement->fetchObject('wcf\\data\\comment\\Comment'); $notificationObjectType = UserNotificationHandler::getInstance()->getObjectTypeProcessor(self::OBJECT_TYPE); $notificationObject = new CommentUserNotificationObject($comment); UserObjectWatchHandler::getInstance()->updateObject('de.codequake.cms.page', $comment->objectID, 'comment', self::OBJECT_TYPE, $notificationObject); }
/** * Marks all news categories as read. */ public function markAllAsRead() { VisitTracker::getInstance()->trackTypeVisit('de.voolia.news.entry'); // reset the user storage data and delete notifications if (WCF::getUser()->userID) { // user storage data UserStorageHandler::getInstance()->reset(array(WCF::getUser()->userID), 'newsUnreadEntries'); UserStorageHandler::getInstance()->reset(array(WCF::getUser()->userID), 'newsUnreadWatchedEntries'); // user notifications UserNotificationHandler::getInstance()->deleteNotifications('news', 'de.voolia.news.entry', array(WCF::getUser()->userID)); } }
/** * Updates session's last activity time to prevent it from expiring. In addition this method * will return updated counters for notifications and 3rd party components. * * @return array<mixed> */ public function keepAlive() { // ignore sessions created by this request if (WCF::getSession()->lastActivityTime == TIME_NOW) { return; } // update last activity time SessionHandler::getInstance()->keepAlive(); // update notification counts $this->keepAliveData = array('userNotificationCount' => UserNotificationHandler::getInstance()->getNotificationCount(true)); // notify 3rd party components EventHandler::getInstance()->fireAction($this, 'keepAlive'); return $this->keepAliveData; }
/** * Follows an user. * * @return array */ public function follow() { $follow = UserFollow::getFollow(WCF::getUser()->userID, $this->parameters['data']['userID']); // not following right now if (!$follow->followID) { $follow = UserFollowEditor::create(array('userID' => WCF::getUser()->userID, 'followUserID' => $this->parameters['data']['userID'], 'time' => TIME_NOW)); // send notification UserNotificationHandler::getInstance()->fireEvent('following', 'com.woltlab.wcf.user.follow', new UserFollowUserNotificationObject($follow), array($follow->followUserID)); // fire activity event UserActivityEventHandler::getInstance()->fireEvent('com.woltlab.wcf.user.recentActivityEvent.follow', $this->parameters['data']['userID']); // reset storage UserStorageHandler::getInstance()->reset(array($this->parameters['data']['userID']), 'followerUserIDs'); UserStorageHandler::getInstance()->reset(array(WCF::getUser()->userID), 'followingUserIDs'); } return array('following' => 1); }
/** * @see \wcf\page\IPage::readParameters() */ public function readParameters() { parent::readParameters(); $this->events = UserNotificationHandler::getInstance()->getAvailableEvents(); // filter events foreach ($this->events as $objectTypeID => $events) { foreach ($events as $eventName => $event) { if (!$event->isVisible()) { unset($this->events[$objectTypeID][$eventName]); } } if (empty($this->events[$objectTypeID])) { unset($this->events[$objectTypeID]); } } }
/** * @see \wcf\action\IAction::execute() */ public function execute() { parent::execute(); if (!$this->notification->confirmTime) { UserNotificationHandler::getInstance()->markAsConfirmedByID($this->notification->notificationID); } $event = new UserNotificationEvent($this->notification->eventID); $objectType = ObjectTypeCache::getInstance()->getObjectType($event->objectTypeID); $objects = $objectType->getProcessor()->getObjectsByIDs(array($this->notification->objectID)); $userProfile = null; if ($this->notification->authorID) { $userProfile = new UserProfile(new User($this->notification->authorID)); } else { $userProfile = new UserProfile(new User(null, array('userID' => null, 'username' => WCF::getLanguage()->get('wcf.user.guest')))); } $className = $event->className; $notificationEvent = new $className($event); $notificationEvent->setObject($this->notification, $objects[$this->notification->objectID], $userProfile, $this->notification->additionalData); HeaderUtil::redirect($notificationEvent->getLink()); exit; }
/** * @see \wcf\page\AbstractPage::readData() */ public function readData() { parent::readData(); $this->notifications = UserNotificationHandler::getInstance()->getNotifications($this->sqlLimit, $this->sqlOffset, true); }
/** * Marks entries as read. */ public function markAsRead() { if (empty($this->parameters['visitTime'])) { $this->parameters['visitTime'] = TIME_NOW; } if (empty($this->objects)) { $this->readObjects(); } $entryIDs = array(); foreach ($this->objects as $entry) { $entryIDs[] = $entry->entryID; VisitTracker::getInstance()->trackObjectVisit('de.incendium.filebase.entry', $entry->entryID, $this->parameters['visitTime']); } // reset storage if (WCF::getUser()->userID) { UserStorageHandler::getInstance()->reset(array(WCF::getUser()->userID), 'filebaseUnreadEntries'); UserStorageHandler::getInstance()->reset(array(WCF::getUser()->userID), 'filebaseUnreadWatchedEntries'); // user notifications if (!empty($entryIDs)) { UserNotificationHandler::getInstance()->markAsConfirmed('file', 'de.incendium.filebase.file', array(WCF::getUser()->userID), $entryIDs); } } }
/** * @see \wcf\system\cronjob\ICronjob::execute() */ public function execute(Cronjob $cronjob) { parent::execute($cronjob); // get user ids $userIDs = array(); $sql = "SELECT\tDISTINCT userID\n\t\t\tFROM\twcf" . WCF_N . "_user_notification\n\t\t\tWHERE\tmailNotified = ?\n\t\t\t\tAND time < ?\n\t\t\t\tAND confirmTime = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array(0, TIME_NOW - 3600 * 23, 0)); while ($row = $statement->fetchArray()) { $userIDs[] = $row['userID']; } if (empty($userIDs)) { return; } // get users $userList = new UserList(); $userList->setObjectIDs($userIDs); $userList->readObjects(); $users = $userList->getObjects(); // get notifications $conditions = new PreparedStatementConditionBuilder(); $conditions->add("notification.userID IN (?)", array($userIDs)); $conditions->add("notification.mailNotified = ?", array(0)); $conditions->add("notification.confirmTime = ?", array(0)); $sql = "SELECT\t\tnotification.*, notification_event.eventID, object_type.objectType\n\t\t\tFROM\t\twcf" . WCF_N . "_user_notification notification\n\t\t\tLEFT JOIN\twcf" . WCF_N . "_user_notification_event notification_event\n\t\t\tON\t\t(notification_event.eventID = notification.eventID)\n\t\t\tLEFT JOIN\twcf" . WCF_N . "_object_type object_type\n\t\t\tON\t\t(object_type.objectTypeID = notification_event.objectTypeID)\n\t\t\t" . $conditions . "\n\t\t\tORDER BY\tnotification.time"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditions->getParameters()); // mark notifications as done $conditions = new PreparedStatementConditionBuilder(); $conditions->add("userID IN (?)", array($userIDs)); $conditions->add("mailNotified = ?", array(0)); $sql = "UPDATE\twcf" . WCF_N . "_user_notification\n\t\t\tSET\tmailNotified = 1\n\t\t\t" . $conditions; $statement2 = WCF::getDB()->prepareStatement($sql); $statement2->execute($conditions->getParameters()); // collect data $eventsToUser = $objectTypes = $eventIDs = $notificationObjects = array(); $availableObjectTypes = UserNotificationHandler::getInstance()->getAvailableObjectTypes(); while ($row = $statement->fetchArray()) { if (!isset($eventsToUser[$row['userID']])) { $eventsToUser[$row['userID']] = array(); } $eventsToUser[$row['userID']][] = $row['notificationID']; // cache object types if (!isset($objectTypes[$row['objectType']])) { $objectTypes[$row['objectType']] = array('objectType' => $availableObjectTypes[$row['objectType']], 'objectIDs' => array(), 'objects' => array()); } $objectTypes[$row['objectType']]['objectIDs'][] = $row['objectID']; $eventIDs[] = $row['eventID']; $notificationObjects[$row['notificationID']] = new UserNotification(null, $row); } // load authors $conditions = new PreparedStatementConditionBuilder(); $conditions->add("notificationID IN (?)", array(array_keys($notificationObjects))); $sql = "SELECT\t\tnotificationID, authorID\n\t\t\tFROM\t\twcf" . WCF_N . "_user_notification_author\n\t\t\t" . $conditions . "\n\t\t\tORDER BY\ttime ASC"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditions->getParameters()); $authorIDs = $authorToNotification = array(); while ($row = $statement->fetchArray()) { if ($row['authorID']) { $authorIDs[] = $row['authorID']; } if (!isset($authorToNotification[$row['notificationID']])) { $authorToNotification[$row['notificationID']] = array(); } $authorToNotification[$row['notificationID']][] = $row['authorID']; } // load authors $authors = UserProfile::getUserProfiles($authorIDs); $unknownAuthor = new UserProfile(new User(null, array('userID' => null, 'username' => WCF::getLanguage()->get('wcf.user.guest')))); // load objects associated with each object type foreach ($objectTypes as $objectType => $objectData) { $objectTypes[$objectType]['objects'] = $objectData['objectType']->getObjectsByIDs($objectData['objectIDs']); } // load required events $eventList = new UserNotificationEventList(); $eventList->getConditionBuilder()->add("user_notification_event.eventID IN (?)", array($eventIDs)); $eventList->readObjects(); $eventObjects = $eventList->getObjects(); foreach ($eventsToUser as $userID => $events) { if (!isset($users[$userID])) { continue; } $user = $users[$userID]; // no notifications for disabled or banned users if ($user->activationCode) { continue; } if ($user->banned) { continue; } // add mail header $message = $user->getLanguage()->getDynamicVariable('wcf.user.notification.mail.header', array('user' => $user)); foreach ($events as $notificationID) { $notification = $notificationObjects[$notificationID]; $className = $eventObjects[$notification->eventID]->className; $class = new $className($eventObjects[$notification->eventID]); $class->setObject($notification, $objectTypes[$notification->objectType]['objects'][$notification->objectID], isset($authors[$notification->authorID]) ? $authors[$notification->authorID] : $unknownAuthor, $notification->additionalData); $class->setLanguage($user->getLanguage()); if (isset($authorToNotification[$notification->notificationID])) { $eventAuthors = array(); foreach ($authorToNotification[$notification->notificationID] as $userID) { if (!$userID) { $eventAuthors[0] = $unknownAuthor; } else { if (isset($authors[$userID])) { $eventAuthors[$userID] = $authors[$userID]; } } } if (!empty($eventAuthors)) { $class->setAuthors($eventAuthors); } } $message .= "\n\n"; $message .= $class->getEmailMessage('daily'); } // append notification mail footer $token = $user->notificationMailToken; if (!$token) { // generate token if not present $token = mb_substr(StringUtil::getHash(serialize(array($user->userID, StringUtil::getRandomID()))), 0, 20); $editor = new UserEditor($user); $editor->update(array('notificationMailToken' => $token)); } $message .= "\n\n"; $message .= $user->getLanguage()->getDynamicVariable('wcf.user.notification.mail.daily.footer', array('user' => $user, 'token' => $token)); // build mail $mail = new Mail(array($user->username => $user->email), $user->getLanguage()->getDynamicVariable('wcf.user.notification.mail.daily.subject', array('count' => count($events))), $message); $mail->setLanguage($user->getLanguage()); $mail->send(); } }
/** * @see \wcf\data\AbstractDatabaseObjectAction::delete() */ public function delete() { $this->prepareObjects(); $ignoreEntries = isset($this->parameters['ignoreEntries']) && $this->parameters['ignoreEntries']; $entryIDs = array(); foreach ($this->objects as $file) { if (!isset($entryIDs[$file->entryID])) { $entryIDs[$file->entryID] = $file->entryID; } } $fileStats = $this->getDetailedFileStats($entryIDs); parent::delete(); // update entries $entryEditors = $fileIDs = array(); foreach ($this->objects as $file) { $entryEditors[$file->entryID] = new EntryEditor($file->getEntry()); $fileIDs[] = $file->fileID; $fileStats[$file->entryID]['files']--; if ($file->isDisabled) { $fileStats[$file->entryID]['disabledFiles']--; } // entry has no files anymore -> delete it if (!$ignoreEntries && !$fileStats[$file->entryID]['files']) { unset($entryIDs[$file->entryID]); // deleted entries need no data update $entryEditors[$file->entryID]->delete(); EntryModificationLogHandler::getInstance()->delete($file->getEntry()); $this->addEntryData($file->entryID, 'deleted', LinkHandler::getInstance()->getLink('FilebaseOverview', array('application' => 'filebase'))); continue; } FileModificationLogHandler::getInstance()->delete($file->getDecoratedObject()); $this->addFileData($file->getDecoratedObject(), 'deleted', 1); @unlink($file->getLocation()); } if (!$ignoreEntries) { // check if the left files are all disabled and if the entry // is also disabled $disableEntries = array(); foreach ($entryIDs as $entryID) { if ($fileStats[$entryID]['files'] == $fileStats[$entryID]['disabledFiles'] && !$entryEditors[$entryID]->isDisabled) { $disableEntries[] = $fileStats[$entryID]; $this->addEntryData($entryID, 'isDisabled', 1); // after disabling the entry, the entry data // will be be rebuild in that method, so no need // to rebuild it here, too unset($entryIDs[$entryID]); } } if (!empty($disableEntries)) { $entryAction = new EntryAction($disableEntries, 'disable', array('ignoreFiles' => true)); $entryAction->executeAction(); } if (!empty($entryIDs)) { EntryEditor::rebuildEntryData($entryIDs); } } if (!empty($fileIDs)) { // delete user notifications UserNotificationHandler::getInstance()->deleteNotifications('file', 'de.incendium.filebase.file', array(), $fileIDs); // unmark files if (isset($this->parameters['unmarkItems'])) { $this->unmarkItems($fileIDs); } } return $this->getFileData(); }
/** * @see wcf\form\IForm::save() */ public function save() { parent::save(); foreach ($this->user as $user) { $this->statementAction = new UserJcoinsStatementAction(array(), 'create', array('data' => array('reason' => $this->reason, 'sum' => $this->sum, 'userID' => $user->userID, 'executedUserID' => WCF::getUser()->userID, 'isModTransfer' => $this->isModerativ), 'changeBalance' => 1)); $this->statementAction->validateAction(); $return = $this->statementAction->executeAction(); UserNotificationHandler::getInstance()->fireEvent('jCoinsTransfer', 'de.joshsboard.wcf.jcoins.transfer.notification', new JCoinsTransferNotificationObject($return['returnValues']), array($user->userID)); if (!$this->isModerativ) { $this->statementAction = new UserJcoinsStatementAction(array(), 'create', array('data' => array('reason' => $this->reason, 'sum' => $this->sum * -1, 'executedUserID' => $user->userID), 'changeBalance' => 1)); $this->statementAction->validateAction(); $this->statementAction->executeAction(); } } $this->saved(); $this->sum = 0; $this->reason = ""; $this->user = array(); $this->success = true; $this->isModerativ = 0; }
/** * Removes all comments for given objects. * * @param string $objectType * @param array<integer> $objectIDs */ public function deleteObjects($objectType, array $objectIDs) { $objectTypeID = $this->getObjectTypeID($objectType); $objectTypeObj = $this->getObjectType($objectTypeID); // get comment ids $commentList = new CommentList(); $commentList->getConditionBuilder()->add('comment.objectTypeID = ?', array($objectTypeID)); $commentList->getConditionBuilder()->add('comment.objectID IN (?)', array($objectIDs)); $commentList->readObjectIDs(); $commentIDs = $commentList->getObjectIDs(); // no comments -> skip if (empty($commentIDs)) { return; } // get response ids $responseList = new CommentResponseList(); $responseList->getConditionBuilder()->add('comment_response.commentID IN (?)', array($commentIDs)); $responseList->readObjectIDs(); $responseIDs = $responseList->getObjectIDs(); // delete likes $notificationObjectTypes = array(); if (UserNotificationHandler::getInstance()->getObjectTypeID($objectTypeObj->objectType . '.like.notification')) { $notificationObjectTypes[] = $objectTypeObj->objectType . '.like.notification'; } LikeHandler::getInstance()->removeLikes('com.woltlab.wcf.comment', $commentIDs, $notificationObjectTypes); // delete activity events if (UserActivityEventHandler::getInstance()->getObjectTypeID($objectTypeObj->objectType . '.recentActivityEvent')) { UserActivityEventHandler::getInstance()->removeEvents($objectTypeObj->objectType . '.recentActivityEvent', $commentIDs); } // delete notifications if (UserNotificationHandler::getInstance()->getObjectTypeID($objectTypeObj->objectType . '.notification')) { UserNotificationHandler::getInstance()->removeNotifications($objectTypeObj->objectType . '.notification', $commentIDs); } if (!empty($responseIDs)) { // delete likes (for responses) $notificationObjectTypes = array(); if (UserNotificationHandler::getInstance()->getObjectTypeID($objectTypeObj->objectType . '.response.like.notification')) { $notificationObjectTypes[] = $objectTypeObj->objectType . '.response.like.notification'; } LikeHandler::getInstance()->removeLikes('com.woltlab.wcf.comment.response', $responseIDs, $notificationObjectTypes); // delete activity events (for responses) if (UserActivityEventHandler::getInstance()->getObjectTypeID($objectTypeObj->objectType . '.response.recentActivityEvent')) { UserActivityEventHandler::getInstance()->removeEvents($objectTypeObj->objectType . '.response.recentActivityEvent', $responseIDs); } // delete notifications (for responses) if (UserNotificationHandler::getInstance()->getObjectTypeID($objectTypeObj->objectType . '.response.notification')) { UserNotificationHandler::getInstance()->removeNotifications($objectTypeObj->objectType . '.response.notification', $responseIDs); } } // delete comments / responses CommentEditor::deleteAll($commentIDs); }
/** * @see \wcf\data\AbstractDatabaseObjectAction::delete() */ public function delete() { $count = parent::delete(); $attachmentMessageIDs = $conversationIDs = array(); foreach ($this->objects as $message) { if (!in_array($message->conversationID, $conversationIDs)) { $conversationIDs[] = $message->conversationID; } if ($message->attachments) { $attachmentMessageIDs[] = $message->messageID; } } // rebuild conversations if (!empty($conversationIDs)) { $conversationAction = new ConversationAction($conversationIDs, 'rebuild'); $conversationAction->executeAction(); } if (!empty($this->objectIDs)) { // delete notifications UserNotificationHandler::getInstance()->deleteNotifications('conversationMessage', 'com.woltlab.wcf.conversation.message.notification', array(), $this->objectIDs); // update search index SearchIndexManager::getInstance()->delete('com.woltlab.wcf.conversation.message', $this->objectIDs); // update embedded objects MessageEmbeddedObjectManager::getInstance()->removeObjects('com.woltlab.wcf.conversation.message', $this->objectIDs); // remove moderation queues ModerationQueueManager::getInstance()->removeQueues('com.woltlab.wcf.conversation.message', $this->objectIDs); } // remove attachments if (!empty($attachmentMessageIDs)) { AttachmentHandler::removeAttachments('com.woltlab.wcf.conversation.message', $attachmentMessageIDs); } return $count; }
/** * Marks a news as read. */ public function markAsRead() { if (empty($this->parameters['visitTime'])) { $this->parameters['visitTime'] = TIME_NOW; } if (empty($this->objects)) { $this->readObjects(); } $newsIDs = array(); foreach ($this->objects as $news) { $newsIDs[] = $news->newsID; VisitTracker::getInstance()->trackObjectVisit('de.voolia.news.entry', $news->newsID, $this->parameters['visitTime']); } // reset the user storage data if (WCF::getUser()->userID) { UserStorageHandler::getInstance()->reset(array(WCF::getUser()->userID), 'newsUnreadEntries'); UserStorageHandler::getInstance()->reset(array(WCF::getUser()->userID), 'newsUnreadWatchedEntries'); // delete obsolete user notifications if (!empty($newsIDs)) { UserNotificationHandler::getInstance()->deleteNotifications('news', 'de.voolia.news.entry', array(WCF::getUser()->userID), $newsIDs); } } }
/** * @see \wcf\data\AbstractDatabaseObjectAction::delete() */ public function delete() { if (empty($this->objects)) { $this->readObjects(); } if (empty($this->objects)) { return 0; } $ignoreCounters = !empty($this->parameters['ignoreCounters']); // read object type ids for comments $commentIDs = array(); foreach ($this->objects as $response) { $commentIDs[] = $response->commentID; } $commentList = new CommentList(); $commentList->getConditionBuilder()->add("comment.commentID IN (?)", array($commentIDs)); $commentList->readObjects(); $comments = $commentList->getObjects(); // update counters $processors = $responseIDs = $updateComments = array(); foreach ($this->objects as $response) { $objectTypeID = $comments[$response->commentID]->objectTypeID; if (!isset($processors[$objectTypeID])) { $objectType = ObjectTypeCache::getInstance()->getObjectType($objectTypeID); $processors[$objectTypeID] = $objectType->getProcessor(); $responseIDs[$objectTypeID] = array(); } $responseIDs[$objectTypeID][] = $response->responseID; if (!$ignoreCounters) { $processors[$objectTypeID]->updateCounter($comments[$response->commentID]->objectID, -1); if (!isset($updateComments[$response->commentID])) { $updateComments[$response->commentID] = 0; } $updateComments[$response->commentID]++; } } // remove responses $count = parent::delete(); // update comment responses and cached response ids if (!$ignoreCounters) { foreach ($comments as $comment) { $commentEditor = new CommentEditor($comment); $commentEditor->updateResponseIDs(); $commentEditor->updateCounters(array('responses' => -1 * $updateComments[$comment->commentID])); } } $likeObjectIDs = array(); $notificationObjectTypes = array(); foreach ($responseIDs as $objectTypeID => $objectIDs) { // remove activity events $objectType = ObjectTypeCache::getInstance()->getObjectType($objectTypeID); if (UserActivityEventHandler::getInstance()->getObjectTypeID($objectType->objectType . '.response.recentActivityEvent')) { UserActivityEventHandler::getInstance()->removeEvents($objectType->objectType . '.response.recentActivityEvent', $objectIDs); } // delete notifications if (UserNotificationHandler::getInstance()->getObjectTypeID($objectType->objectType . '.response.notification')) { UserNotificationHandler::getInstance()->removeNotifications($objectType->objectType . '.response.notification', $objectIDs); } $likeObjectIDs = array_merge($likeObjectIDs, $objectIDs); if (UserNotificationHandler::getInstance()->getObjectTypeID($objectType->objectType . '.response.like.notification')) { $notificationObjectTypes[] = $objectType->objectType . '.response.like.notification'; } } // remove likes if (!empty($likeObjectIDs)) { LikeHandler::getInstance()->removeLikes('com.woltlab.wcf.comment.response', $likeObjectIDs, $notificationObjectTypes); } return $count; }
/** * @see \wcf\page\IPage::readParameters() */ public function readParameters() { parent::readParameters(); $this->events = UserNotificationHandler::getInstance()->getAvailableEvents(); }
/** * Marks all conversations as read. */ public function markAllAsRead() { $sql = "UPDATE\twcf" . WCF_N . "_conversation_to_user\n\t\t\tSET\tlastVisitTime = ?\n\t\t\tWHERE\tparticipantID = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array(TIME_NOW, WCF::getUser()->userID)); // reset storage UserStorageHandler::getInstance()->reset(array(WCF::getUser()->userID), 'unreadConversationCount'); // delete obsolete notifications UserNotificationHandler::getInstance()->deleteNotifications('conversation', 'com.woltlab.wcf.conversation.notification', array(WCF::getUser()->userID)); UserNotificationHandler::getInstance()->deleteNotifications('conversationMessage', 'com.woltlab.wcf.conversation.message.notification', array(WCF::getUser()->userID)); return array('markAllAsRead' => true); }
/** * Removes all likes for given objects. * * @param string $objectType * @param array<integer> $objectIDs * @param array<string> $notificationObjectTypes */ public function removeLikes($objectType, array $objectIDs, array $notificationObjectTypes = array()) { $objectTypeObj = $this->getObjectType($objectType); // get like objects $likeObjectList = new LikeObjectList(); $likeObjectList->getConditionBuilder()->add('like_object.objectTypeID = ?', array($objectTypeObj->objectTypeID)); $likeObjectList->getConditionBuilder()->add('like_object.objectID IN (?)', array($objectIDs)); $likeObjectList->readObjects(); $likeObjects = $likeObjectList->getObjects(); $likeObjectIDs = $likeObjectList->getObjectIDs(); // reduce count of received users $users = array(); foreach ($likeObjects as $likeObject) { if ($likeObject->likes) { if (!isset($users[$likeObject->objectUserID])) { $users[$likeObject->objectUserID] = 0; } $users[$likeObject->objectUserID] += $likeObject->likes; } } foreach ($users as $userID => $receivedLikes) { $userEditor = new UserEditor(new User(null, array('userID' => $userID))); $userEditor->updateCounters(array('likesReceived' => $receivedLikes * -1)); } // get like ids $likeList = new LikeList(); $likeList->getConditionBuilder()->add('like_table.objectTypeID = ?', array($objectTypeObj->objectTypeID)); $likeList->getConditionBuilder()->add('like_table.objectID IN (?)', array($objectIDs)); $likeList->readObjects(); if (count($likeList)) { $likeData = array(); foreach ($likeList as $like) { $likeData[$like->likeID] = $like->userID; } // delete like notifications if (!empty($notificationObjectTypes)) { foreach ($notificationObjectTypes as $notificationObjectType) { UserNotificationHandler::getInstance()->removeNotifications($notificationObjectType, $likeList->getObjectIDs()); } } else { if (UserNotificationHandler::getInstance()->getObjectTypeID($objectType . '.notification')) { UserNotificationHandler::getInstance()->removeNotifications($objectType . '.notification', $likeList->getObjectIDs()); } } // revoke activity points UserActivityPointHandler::getInstance()->removeEvents('com.woltlab.wcf.like.activityPointEvent.receivedLikes', $likeData); // delete likes LikeEditor::deleteAll(array_keys($likeData)); } // delete like objects if (!empty($likeObjectIDs)) { LikeObjectEditor::deleteAll($likeObjectIDs); } // delete activity events if (UserActivityEventHandler::getInstance()->getObjectTypeID($objectTypeObj->objectType . '.recentActivityEvent')) { UserActivityEventHandler::getInstance()->removeEvents($objectTypeObj->objectType . '.recentActivityEvent', $objectIDs); } }
/** * Updates a watched object for all subscriber. * * @param string $objectType * @param integer $objectIDs * @param string $notificationEventName * @param string $notificationObjectType * @param \wcf\system\user\notification\object\IUserNotificationObject $notificationObject * @param array $additionalData */ public function updateObject($objectType, $objectID, $notificationEventName, $notificationObjectType, IUserNotificationObject $notificationObject, array $additionalData = array()) { // get object type id $objectTypeObj = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.user.objectWatch', $objectType); // get subscriber $userIDs = $recipientIDs = array(); $sql = "SELECT\t\tuserID, notification\n\t\t\tFROM\t\twcf" . WCF_N . "_user_object_watch\n\t\t\tWHERE\t\tobjectTypeID = ?\n\t\t\t\t\tAND objectID = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($objectTypeObj->objectTypeID, $objectID)); while ($row = $statement->fetchArray()) { $userIDs[] = $row['userID']; if ($row['notification'] && $notificationObject->getAuthorID() != $row['userID']) { $recipientIDs[] = $row['userID']; } } if (!empty($userIDs)) { // reset user storage $objectTypeObj->getProcessor()->resetUserStorage($userIDs); if (!empty($recipientIDs)) { // create notifications UserNotificationHandler::getInstance()->fireEvent($notificationEventName, $notificationObjectType, $notificationObject, $recipientIDs, $additionalData); } } }
/** * modify forum post * * @param $oMbqEtForumPost */ public function mdfMbqEtForumPost($oMbqEtForumPost, $mbqOpt) { $oBoard = $oMbqEtForumPost->oMbqEtForumTopic->oMbqEtForum->mbqBind['oDetailedBoardNode']->getBoard(); $oThread = $oMbqEtForumPost->oMbqEtForumTopic->mbqBind['oViewableThread']->getDecoratedObject(); $oPost = $oMbqEtForumPost->mbqBind['oViewablePost']->getDecoratedObject(); //ref wbb\form\PostEditForm,wcf\form\MessageForm,wbb\form\ThreadAddForm $oMbqEtForumPost->postTitle->setOriValue(StringUtil::trim($oMbqEtForumPost->postTitle->oriValue)); $oMbqEtForumPost->postContent->setOriValue(MessageUtil::stripCrap(StringUtil::trim($oMbqEtForumPost->postContent->oriValue))); $editReason = ''; $attachmentObjectType = 'com.woltlab.wbb.post'; $attachmentObjectID = $oMbqEtForumPost->postId->oriValue; if ($oThread->firstPostID == $oMbqEtForumPost->postId->oriValue) { $enableMultilingualism = true; $isFirstPost = true; } $tmpHash = StringUtil::getRandomID(); $attachmentParentObjectID = $oBoard->boardID; //$attachmentParentObjectID = 0; //settings $preParse = $enableSmilies = $enableBBCodes = $showSignature = $subscribeThread = $enableHtml = 0; $preParse = 1; if (WCF::getSession()->getPermission('user.message.canUseSmilies')) { $enableSmilies = 1; } //if (WCF::getSession()->getPermission('user.message.canUseHtml')) $enableHtml = 1; if (WCF::getSession()->getPermission('user.message.canUseBBCodes')) { $enableBBCodes = 1; } $showSignature = 1; $subscribeThread = 1; $type = Thread::TYPE_DEFAULT; if ($oThread->isSticky) { $type = Thread::TYPE_STICKY; } elseif ($oThread->isAnnouncement) { MbqError::alert('', __METHOD__ . ',line:' . __LINE__ . '.' . 'Sorry,do not support announcement type.'); } if ($oBoard->getPermission('canHideEditNote')) { $hideEditNote = true; } else { $hideEditNote = false; } // get max text length $maxTextLength = WCF::getSession()->getPermission('user.board.maxPostLength'); $minCharLength = WBB_POST_MIN_CHAR_LENGTH; $minWordCount = WBB_POST_MIN_WORD_COUNT; //begin validate $allowedBBCodesPermission = 'user.message.allowedBBCodes'; //validateSubject if (StringUtil::length($oMbqEtForumPost->postTitle->oriValue) > 255) { MbqError::alert('', "Post title is too long.", '', MBQ_ERR_APP); } // search for censored words if (ENABLE_CENSORSHIP) { $result = Censorship::getInstance()->test($oMbqEtForumPost->postTitle->oriValue); if ($result) { MbqError::alert('', "Found censored words in post title.", '', MBQ_ERR_APP); } } //validateText if (empty($oMbqEtForumPost->postContent->oriValue)) { MbqError::alert('', "Need post content.", '', MBQ_ERR_APP); } // check text length if ($maxTextLength != 0 && StringUtil::length($oMbqEtForumPost->postContent->oriValue) > $maxTextLength) { MbqError::alert('', "Post content is too long.", '', MBQ_ERR_APP); } if ($enableBBCodes && $allowedBBCodesPermission) { $disallowedBBCodes = BBCodeParser::getInstance()->validateBBCodes($oMbqEtForumPost->postContent->oriValue, ArrayUtil::trim(explode(',', WCF::getSession()->getPermission($allowedBBCodesPermission)))); if (!empty($disallowedBBCodes)) { MbqError::alert('', "Post content included disallowed bbcodes.", '', MBQ_ERR_APP); } } // search for censored words if (ENABLE_CENSORSHIP) { $result = Censorship::getInstance()->test($oMbqEtForumPost->postContent->oriValue); if ($result) { MbqError::alert('', "Found censored words in post content.", '', MBQ_ERR_APP); } } if ($minCharLength && StringUtil::length($oMbqEtForumPost->postContent->oriValue) < $minCharLength) { MbqError::alert('', "Post content is too short.", '', MBQ_ERR_APP); } if ($minWordCount && count(explode(' ', $oMbqEtForumPost->postContent->oriValue)) < $minWordCount) { MbqError::alert('', "Need more words in Post content", '', MBQ_ERR_APP); } //attachment if (MODULE_ATTACHMENT && $attachmentObjectType) { $attachmentHandler = new AttachmentHandler($attachmentObjectType, $attachmentObjectID, $tmpHash, $attachmentParentObjectID); } //save if ($preParse) { // BBCodes are enabled if ($enableBBCodes) { if ($allowedBBCodesPermission) { $oMbqEtForumPost->postContent->setOriValue(PreParser::getInstance()->parse($oMbqEtForumPost->postContent->oriValue, ArrayUtil::trim(explode(',', WCF::getSession()->getPermission($allowedBBCodesPermission))))); } else { $oMbqEtForumPost->postContent->setOriValue(PreParser::getInstance()->parse($oMbqEtForumPost->postContent->oriValue)); } } else { $oMbqEtForumPost->postContent->setOriValue(PreParser::getInstance()->parse($oMbqEtForumPost->postContent->oriValue, array())); } } // save post $data = array('subject' => $oMbqEtForumPost->postTitle->oriValue, 'message' => $oMbqEtForumPost->postContent->oriValue, 'enableBBCodes' => $enableBBCodes, 'enableHtml' => $enableHtml, 'enableSmilies' => $enableSmilies, 'showSignature' => $showSignature); if (!$hideEditNote && (WCF::getUser()->userID != $oPost->userID || $oPost->time <= TIME_NOW - WBB_POST_EDIT_HIDE_EDIT_NOTE_PERIOD * 60)) { $data['editCount'] = $oPost->editCount + 1; $data['editReason'] = $editReason; $data['editor'] = WCF::getUser()->username; $data['editorID'] = WCF::getUser()->userID; $data['lastEditTime'] = TIME_NOW; } $oPostAction = new PostAction(array($oPost), 'update', array('attachmentHandler' => $attachmentHandler, 'data' => $data, 'isEdit' => true)); $oPostAction->executeAction(); $threadData = array(); if (isset($isFirstPost) && $isFirstPost) { // update title if ($oMbqEtForumPost->postTitle->oriValue != $oMbqEtForumPost->oMbqEtForumTopic->topicTitle->oriValue) { $threadData['topic'] = $oMbqEtForumPost->postTitle->oriValue; } // handle thread type switch ($type) { case Thread::TYPE_DEFAULT: $threadData['isSticky'] = 0; $threadData['isAnnouncement'] = 0; break; case Thread::TYPE_STICKY: $threadData['isSticky'] = 1; $threadData['isAnnouncement'] = 0; break; case Thread::TYPE_ANNOUNCEMENT: $threadData['isSticky'] = 0; $threadData['isAnnouncement'] = 1; break; } } if (isset($isFirstPost) && $isFirstPost || !empty($threadData)) { $threadData = array('data' => $threadData); if ($isFirstPost) { $threadData['announcementBoardIDs'] = array(); } //!!! $threadAction = new ThreadAction(array($oThread), 'update', $threadData); $threadAction->executeAction(); } // save subscription if (WCF::getUser()->userID) { if ($subscribeThread && !$oThread->isSubscribed()) { $action = new UserObjectWatchAction(array(), 'subscribe', array('data' => array('objectID' => $oPost->threadID, 'objectType' => 'com.woltlab.wbb.thread'), 'enableNotification' => UserNotificationHandler::getInstance()->getEventSetting('com.woltlab.wbb.post', 'post') !== false ? 1 : 0)); $action->executeAction(); } else { if (!$subscribeThread && $oThread->isSubscribed()) { $action = new UserObjectWatchAction(array(), 'unsubscribe', array('data' => array('objectID' => $oPost->threadID, 'objectType' => 'com.woltlab.wbb.thread'))); $action->executeAction(); } } } return $oMbqEtForumPost; }
/** * Marks a notification as confirmed. * * @return array */ public function markAsConfirmed() { UserNotificationHandler::getInstance()->markAsConfirmedByID($this->notificationEditor->notificationID); return array('markAsRead' => $this->notificationEditor->notificationID, 'totalCount' => UserNotificationHandler::getInstance()->getNotificationCount(true)); }
/** * Adds a response. * * @return array */ public function addResponse() { if (!empty($this->validationErrors)) { if (!empty($this->parameters['data']['username'])) { WCF::getSession()->register('username', $this->parameters['data']['username']); } WCF::getTPL()->assign('errorType', $this->validationErrors); $guestDialog = $this->getGuestDialog(); return array('useCaptcha' => $guestDialog['useCaptcha'], 'guestDialog' => $guestDialog['template']); } // create response $this->createdResponse = CommentResponseEditor::create(array('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(); if (count($responseIDs) < 5) { $responseIDs[] = $this->createdResponse->responseID; } $responses = $this->comment->responses + 1; // update comment $commentEditor = new CommentEditor($this->comment); $commentEditor->update(array('responseIDs' => serialize($responseIDs), 'responses' => $responses)); // update counter $this->commentProcessor->updateCounter($this->parameters['data']['objectID'], 1); // fire activity event $objectType = ObjectTypeCache::getInstance()->getObjectType($this->comment->objectTypeID); if ($this->createdResponse->userID && UserActivityEventHandler::getInstance()->getObjectTypeID($objectType->objectType . '.response.recentActivityEvent')) { UserActivityEventHandler::getInstance()->fireEvent($objectType->objectType . '.response.recentActivityEvent', $this->createdResponse->responseID); } // 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('commentID' => $this->comment->commentID, 'objectID' => $this->comment->objectID, 'objectUserID' => $userID, 'userID' => $this->comment->userID)); } } } if (!$this->createdResponse->userID) { // save user name is session WCF::getSession()->register('username', $this->createdResponse->username); // save last comment time for flood control WCF::getSession()->register('lastCommentTime', $this->createdResponse->time); // reset captcha for future requests if ($this->captchaObjectType) { $this->captchaObjectType->getProcessor()->reset(); } } return array('commentID' => $this->comment->commentID, 'template' => $this->renderResponse($this->createdResponse), 'responses' => $responses); }