/**
  * 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());
 }