/** * Triggers a notification event. * * @param string $eventName * @param string $objectType * @param \wcf\system\user\notification\object\IUserNotificationObject $notificationObject * @param array<integer> $recipientIDs * @param array<mixed> $additionalData * @param integer $baseObjectID */ public function fireEvent($eventName, $objectType, IUserNotificationObject $notificationObject, array $recipientIDs, array $additionalData = array(), $baseObjectID = 0) { // check given object type and event name if (!isset($this->availableEvents[$objectType][$eventName])) { throw new SystemException("Unknown event " . $objectType . "-" . $eventName . " given"); } // get objects $objectTypeObject = $this->availableObjectTypes[$objectType]; $event = $this->availableEvents[$objectType][$eventName]; // get author's profile $userProfile = null; if ($notificationObject->getAuthorID()) { if ($notificationObject->getAuthorID() == WCF::getUser()->userID) { $userProfile = new UserProfile(WCF::getUser()); } else { $userProfile = UserProfile::getUserProfile($notificationObject->getAuthorID()); } } if ($userProfile === null) { $userProfile = new UserProfile(new User(null, array())); } // set object data $event->setObject(new UserNotification(null, array()), $notificationObject, $userProfile, $additionalData); $parameters = array('eventName' => $eventName, 'objectType' => $objectType, 'notificationObject' => $notificationObject, 'recipientIDs' => $recipientIDs, 'additionalData' => $additionalData, 'baseObjectID' => $baseObjectID, 'objectTypeObject' => $objectTypeObject, 'userProfile' => $userProfile, 'event' => $event); EventHandler::getInstance()->fireAction($this, 'fireEvent', $parameters); // find existing notifications $conditions = new PreparedStatementConditionBuilder(); $conditions->add("userID IN (?)", array($recipientIDs)); $conditions->add("eventID = ?", array($event->eventID)); $conditions->add("eventHash = ?", array($event->getEventHash())); $conditions->add("confirmTime = ?", array(0)); $sql = "SELECT\tnotificationID, userID\n\t\t\tFROM\twcf" . WCF_N . "_user_notification\n\t\t\t" . $conditions; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditions->getParameters()); $notifications = array(); while ($row = $statement->fetchArray()) { $notifications[$row['userID']] = $row['notificationID']; } // check if event supports stacking and author should be added if (!empty($notifications) && $event->isStackable()) { $conditions = new PreparedStatementConditionBuilder(); $conditions->add("notificationID IN (?)", array(array_values($notifications))); if ($notificationObject->getAuthorID()) { $conditions->add("authorID = ?", array($notificationObject->getAuthorID())); } else { $conditions->add("authorID IS NULL"); } $sql = "SELECT\tnotificationID\n\t\t\t\tFROM\twcf" . WCF_N . "_user_notification_author\n\t\t\t\t" . $conditions; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditions->getParameters()); $notificationIDs = array(); while ($row = $statement->fetchArray()) { $notificationIDs[] = $row['notificationID']; } // filter array of existing notifications and remove values which // do not have a notification from this author yet (inverse logic!) foreach ($notifications as $userID => $notificationID) { if (!in_array($notificationID, $notificationIDs)) { unset($notifications[$userID]); } } if (!empty($notificationIDs)) { // update trigger count $sql = "UPDATE\twcf" . WCF_N . "_user_notification\n\t\t\t\t\tSET\ttimesTriggered = timesTriggered + ?,\n\t\t\t\t\t\tguestTimesTriggered = guestTimesTriggered + ?\n\t\t\t\t\tWHERE\tnotificationID = ?"; $statement = WCF::getDB()->prepareStatement($sql); WCF::getDB()->beginTransaction(); foreach ($notificationIDs as $notificationID) { $statement->execute(array(1, $notificationObject->getAuthorID() ? 0 : 1, $notificationID)); } WCF::getDB()->commitTransaction(); } } $recipientIDs = array_diff($recipientIDs, array_keys($notifications)); if (empty($recipientIDs)) { return; } // get recipients $recipientList = new UserNotificationEventRecipientList(); $recipientList->getConditionBuilder()->add('event_to_user.eventID = ?', array($event->eventID)); $recipientList->getConditionBuilder()->add('event_to_user.userID IN (?)', array($recipientIDs)); $recipientList->readObjects(); $recipients = $recipientList->getObjects(); if (!empty($recipients)) { $data = array('authorID' => $event->getAuthorID() ?: null, 'data' => array('eventID' => $event->eventID, 'authorID' => $event->getAuthorID() ?: null, 'objectID' => $notificationObject->getObjectID(), 'baseObjectID' => $baseObjectID, 'eventHash' => $event->getEventHash(), 'packageID' => $objectTypeObject->packageID, 'mailNotified' => $event->supportsEmailNotification() ? 0 : 1, 'time' => TIME_NOW, 'additionalData' => serialize($additionalData)), 'recipients' => $recipients); if ($event->isStackable()) { $data['notifications'] = $notifications; $action = new UserNotificationAction(array(), 'createStackable', $data); } else { $data['data']['timesTriggered'] = 1; $action = new UserNotificationAction(array(), 'createDefault', $data); } $result = $action->executeAction(); $notifications = $result['returnValues']; // send notifications if ($event->supportsEmailNotification()) { foreach ($recipients as $recipient) { if ($recipient->mailNotificationType == 'instant') { if (isset($notifications[$recipient->userID]) && $notifications[$recipient->userID]['isNew']) { $this->sendInstantMailNotification($notifications[$recipient->userID]['object'], $recipient, $event); } } } } // reset notification count UserStorageHandler::getInstance()->reset(array_keys($recipients), 'userNotificationCount'); } }
/** * 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); } } }
/** * @see \wcf\system\user\notification\event\IUserNotificationEvent::getEventHash() */ public function getEventHash() { return sha1($this->eventID . '-' . $this->userNotificationObject->getObjectID()); }