this._items[$container.data('notificationID')] = $container;
$container.find('.jsMarkAsConfirmed').data('notificationID', $container.data('notificationID')).click($.proxy(this._click, this));
- $container.find('p').html(function(index, oldHTML) {
- return '<a>' + oldHTML + '</a>';
- }).children('a').data('notificationID', $container.data('notificationID')).click($.proxy(this._clickLink, this));
+ if (!$container.data('isGrouped')) {
+ $container.find('p').html(function(index, oldHTML) {
+ return '<a>' + oldHTML + '</a>';
+ }).children('a').data('notificationID', $container.data('notificationID')).click($.proxy(this._clickLink, this));
+ }
}, this));
this._badge = $('.jsNotificationsBadge:eq(0)');
return $username;
}
+
+ /**
+ * Returns a HTML anchor link pointing to the decorated user.
+ *
+ * @return string
+ */
+ public function getAnchorTag() {
+ $link = LinkHandler::getInstance()->getLink('User', array('object' => $this->getDecoratedObject()));
+
+ return '<a href="'.$link.'" class="userLink" data-user-id="'.$this->userID.'">'.$this->username.'</a>';
+ }
}
<?php
namespace wcf\data\user\notification;
-use wcf\data\user\notification\UserNotificationEditor;
use wcf\data\AbstractDatabaseObjectAction;
use wcf\system\user\notification\UserNotificationHandler;
use wcf\system\user\storage\UserStorageHandler;
use wcf\system\WCF;
+use wcf\system\exception\UserInputException;
+use wcf\system\exception\PermissionDeniedException;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
/**
* Executes user notification-related actions.
*/
class UserNotificationAction extends AbstractDatabaseObjectAction {
/**
- * Adds notification recipients.
+ * notification object
+ * @var \wcf\data\user\notification\UserNotification
*/
- public function addRecipients() {
- $sql = "INSERT IGNORE INTO wcf".WCF_N."_user_notification_to_user
- (notificationID, userID, mailNotified)
- VALUES (?, ?, ?)";
- $statement = WCF::getDB()->prepareStatement($sql);
-
- foreach ($this->objects as $notification) {
- foreach ($this->parameters['recipients'] as $recipient) {
- $statement->execute(array($notification->notificationID, $recipient->userID, ($recipient->mailNotificationType == 'daily' ? 0 : 1)));
- }
- }
- }
+ public $notification = null;
/**
* @see \wcf\data\AbstractDatabaseObjectAction::create()
*/
public function create() {
- // create notification
$notification = parent::create();
- // save recpients
- if (!empty($this->parameters['recipients'])) {
- $action = new UserNotificationAction(array($notification), 'addRecipients', array(
- 'recipients' => $this->parameters['recipients']
+ $sql = "INSERT INTO wcf".WCF_N."_user_notification_to_user
+ (notificationID, userID)
+ VALUES (?, ?)";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute(array(
+ $notification->notificationID,
+ $notification->userID
+ ));
+
+ return $notification;
+ }
+
+ public function createDefault() {
+ die("createDefault");
+ }
+
+ public function createStackable() {
+ // get existing notifications
+ $notificationList = new UserNotificationList();
+ $notificationList->getConditionBuilder()->add("eventID = ?", array($this->parameters['data']['eventID']));
+ $notificationList->getConditionBuilder()->add("objectID = ?", array($this->parameters['data']['objectID']));
+ $notificationList->getConditionBuilder()->add("userID IN (?)", array(array_keys($this->parameters['recipients'])));
+ $notificationList->getConditionBuilder()->add("confirmed = ?", array(0));
+ $notificationList->readObjects();
+ $existingNotifications = array();
+ foreach ($notificationList as $notification) {
+ $existingNotifications[$notification->userID] = $notification;
+ }
+
+ $notifications = array();
+ foreach ($this->parameters['recipients'] as $recipient) {
+ $notification = (isset($existingNotifications[$recipient->userID]) ? $existingNotifications[$recipient->userID] : null);
+ $isNew = ($notification === null);
+
+ if ($notification === null) {
+ $this->parameters['data']['userID'] = $recipient->userID;
+ $notification = $this->create();
+ }
+
+ $notifications[$recipient->userID] = array(
+ 'isNew' => $isNew,
+ 'object' => $notification
+ );
+ }
+
+ // insert author
+ $sql = "INSERT INTO wcf".WCF_N."_user_notification_author
+ (notificationID, authorID, time)
+ VALUES (?, ?, ?)";
+ $statement = WCF::getDB()->prepareStatement($sql);
+
+ WCF::getDB()->beginTransaction();
+ foreach ($notifications as $notificationData) {
+ $statement->execute(array(
+ $notificationData['object']->notificationID,
+ ($this->parameters['authorID'] ?: null),
+ TIME_NOW
));
- $action->executeAction();
}
+ WCF::getDB()->commitTransaction();
- return $notification;
+ return $notifications;
}
/**
'notifications' => $notifications
));
- $totalCount = UserNotificationHandler::getInstance()->getNotificationCount();
- if (count($notifications) < $totalCount) {
- UserStorageHandler::getInstance()->reset(array(WCF::getUser()->userID), 'userNotificationCount');
- }
-
return array(
'template' => WCF::getTPL()->fetch('notificationListOustanding'),
- 'totalCount' => $totalCount
+ 'totalCount' => UserNotificationHandler::getInstance()->getNotificationCount(true)
);
}
*/
public function validateMarkAsConfirmed() {
$this->readInteger('notificationID');
+ $this->notification = new UserNotification($this->parameters['notificationID']);
- $sql = "SELECT COUNT(*) AS count
- FROM wcf".WCF_N."_user_notification_to_user
- WHERE notificationID = ?
- AND userID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
- $this->parameters['notificationID'],
- WCF::getUser()->userID
- ));
- $row = $statement->fetchArray();
-
- // pretend it was marked as confirmed
- if (!$row['count']) {
- $this->parameters['alreadyConfirmed'] = true;
+ if (!$this->notification->notificationID) {
+ throw new UserInputException('notificationID');
+ }
+ else if ($this->notification->userID != WCF::getUser()->userID) {
+ throw new PermissionDeniedException();
}
}
* @return array
*/
public function markAsConfirmed() {
- if (!isset($this->parameters['alreadyConfirmed'])) {
- $sql = "UPDATE wcf".WCF_N."_user_notification_to_user
- SET confirmed = ?
- WHERE notificationID = ?
- AND userID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array(
- 1,
- $this->parameters['notificationID'],
- WCF::getUser()->userID
- ));
-
- // reset notification count
- UserStorageHandler::getInstance()->reset(array(WCF::getUser()->userID), 'userNotificationCount');
- }
+ $notificationEditor = new UserNotificationEditor($this->notification);
+ $notificationEditor->markAsConfirmed();
+
+ // reset notification count
+ UserStorageHandler::getInstance()->reset(array(WCF::getUser()->userID), 'userNotificationCount');
return array(
'notificationID' => $this->parameters['notificationID'],
<?php
namespace wcf\data\user\notification;
use wcf\data\DatabaseObjectEditor;
+use wcf\system\WCF;
/**
* Provides functions to edit user notifications.
* @see \wcf\data\DatabaseObjectDecorator::$baseClass
*/
protected static $baseClass = 'wcf\data\user\notification\UserNotification';
+
+ /**
+ * Marks this notification as confirmed.
+ */
+ public function markAsConfirmed() {
+ $this->update(array(
+ 'confirmed' => 1
+ ));
+
+ // delete notification_to_user assignment (mimic legacy notification system)
+ $sql = "DELETE FROM wcf".WCF_N."_user_notification_to_user
+ WHERE notificationID = ?";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute(array($this->notificationID));
+ }
}
// set object data
$event->setObject(new UserNotification(null, array()), $notificationObject, $userProfile, $additionalData);
- // find existing events
- $userIDs = array();
- $conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('notification_to_user.notificationID = notification.notificationID');
- $conditionBuilder->add('notification_to_user.userID IN (?)', array($recipientIDs));
- $conditionBuilder->add('notification.eventHash = ?', array($event->getEventHash()));
- $sql = "SELECT notification_to_user.userID
- FROM wcf".WCF_N."_user_notification notification,
- wcf".WCF_N."_user_notification_to_user notification_to_user
- ".$conditionBuilder;
+ // find existing notifications
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("userID IN (?)", array($recipientIDs));
+ $conditions->add("eventID = ?", array($event->eventID));
+ $conditions->add("objectID = ?", array($notificationObject->getObjectID()));
+ $conditions->add("confirmed = ?", array(0));
+
+ $sql = "SELECT notificationID, userID
+ FROM wcf".WCF_N."_user_notification
+ ".$conditions;
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditionBuilder->getParameters());
- while ($row = $statement->fetchArray()) $userIDs[] = $row['userID'];
+ $statement->execute($conditions->getParameters());
+ $notifications = array();
+ while ($row = $statement->fetchArray()) {
+ $notifications[$row['userID']] = $row['notificationID'];
+ }
// skip recipients with outstanding notifications
- if (!empty($userIDs)) {
- $recipientIDs = array_diff($recipientIDs, $userIDs);
+ if (!empty($notifications)) {
+ // filter by author
+ if ($notificationObject->getAuthorID()) {
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("notificationID IN (?)", array(array_values($notifications)));
+ $conditions->add("authorID = ?", array($notificationObject->getAuthorID()));
+
+ $sql = "SELECT notificationID
+ FROM wcf".WCF_N."_user_notification_author
+ ".$conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+ $notificationIDs = array();
+ while ($row = $statement->fetchArray()) {
+ $notificationIDs[] = $row['notificationID'];
+ }
+
+ foreach ($notifications as $userID => $notificationID) {
+ // do not skip recipients with a similar notification but authored by somebody else
+ if (!in_array($notificationID, $notificationIDs)) {
+ unset($notifications[$userID]);
+ }
+ }
+ }
+
+ $recipientIDs = array_diff($recipientIDs, array_keys($notifications));
if (empty($recipientIDs)) return;
}
$recipientList->getConditionBuilder()->add('event_to_user.eventID = ?', array($event->eventID));
$recipientList->getConditionBuilder()->add('event_to_user.userID IN (?)', array($recipientIDs));
$recipientList->readObjects();
- if (count($recipientList)) {
- // find existing notification
- $notification = UserNotification::getNotification($objectTypeObject->packageID, $event->eventID, $notificationObject->getObjectID());
- if ($notification !== null) {
- // only update recipients
- $action = new UserNotificationAction(array($notification), 'addRecipients', array(
- 'recipients' => $recipientList->getObjects()
- ));
- $action->executeAction();
+ $recipients = $recipientList->getObjects();
+ if (!empty($recipients)) {
+ $data = array(
+ 'authorID' => ($event->getAuthorID() ?: null),
+ 'data' => array(
+ 'eventID' => $event->eventID,
+ 'authorID' => ($event->getAuthorID() ?: null),
+ 'objectID' => $notificationObject->getObjectID(),
+ 'time' => TIME_NOW,
+ 'additionalData' => serialize($additionalData)
+ ),
+ 'recipients' => $recipients
+ );
+
+ if ($event->isStackable()) {
+ $data['notifications'] = $notifications;
+
+ $action = new UserNotificationAction(array(), 'createStackable', $data);
}
else {
- // create new notification
- $action = new UserNotificationAction(array(), 'create', array(
- 'data' => array(
- 'packageID' => $objectTypeObject->packageID,
- 'eventID' => $event->eventID,
- 'objectID' => $notificationObject->getObjectID(),
- 'authorID' => ($event->getAuthorID() ?: null),
- 'time' => TIME_NOW,
- 'eventHash' => $event->getEventHash(),
- 'additionalData' => serialize($additionalData)
- ),
- 'recipients' => $recipientList->getObjects()
- ));
- $result = $action->executeAction();
- $notification = $result['returnValues'];
+ $action = new UserNotificationAction(array(), 'createDefault', $data);
}
- // sends notifications
- foreach ($recipientList->getObjects() as $recipient) {
+ $result = $action->executeAction();
+ $notifications = $result['returnValues'];
+
+ /*
+ // create new notification
+ $action = new UserNotificationAction(array(), 'create', array(
+ 'authorID' => ($event->getAuthorID() ?: null),
+ 'data' => array(
+ 'eventID' => $event->eventID,
+ 'authorID' => ($event->getAuthorID() ?: null),
+ 'objectID' => $notificationObject->getObjectID(),
+ 'time' => TIME_NOW,
+ 'additionalData' => serialize($additionalData)
+ ),
+ 'recipients' => $recipients
+ ));
+ $result = $action->executeAction();
+ $notifications = $result['returnValues'];
+ */
+
+ // TODO: move -> DBOAction?
+ // send notifications
+ foreach ($recipients as $recipient) {
if ($recipient->mailNotificationType == 'instant') {
- $this->sendInstantMailNotification($notification, $recipient, $event);
+ if (isset($notifications[$recipient->userID]) && $notifications[$recipient->userID]['isNew']) {
+ $this->sendInstantMailNotification($notifications[$recipient->userID]['object'], $recipient, $event);
+ }
}
}
// reset notification count
- UserStorageHandler::getInstance()->reset($recipientList->getObjectIDs(), 'userNotificationCount');
+ UserStorageHandler::getInstance()->reset(array_keys($recipients), 'userNotificationCount');
}
}
/**
* Returns the number of outstanding notifications for the active user.
*
+ * @param boolean $skipCache
* @return integer
*/
- public function getNotificationCount() {
- if ($this->notificationCount === null) {
+ public function getNotificationCount($skipCache = false) {
+ if ($this->notificationCount === null || $skipCache) {
$this->notificationCount = 0;
if (WCF::getUser()->userID) {
$data = UserStorageHandler::getInstance()->getStorage(array(WCF::getUser()->userID), 'userNotificationCount');
// cache does not exist or is outdated
- if ($data[WCF::getUser()->userID] === null) {
- $conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('notification.notificationID = notification_to_user.notificationID');
- $conditionBuilder->add('notification_to_user.userID = ?', array(WCF::getUser()->userID));
- $conditionBuilder->add('notification_to_user.confirmed = ?', array(0));
-
+ if ($data[WCF::getUser()->userID] === null || $skipCache) {
$sql = "SELECT COUNT(*) AS count
- FROM wcf".WCF_N."_user_notification_to_user notification_to_user,
- wcf".WCF_N."_user_notification notification
- ".$conditionBuilder->__toString();
+ FROM wcf".WCF_N."_user_notification
+ WHERE userID = ?
+ AND confirmed = ?";
$statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditionBuilder->getParameters());
+ $statement->execute(array(
+ WCF::getUser()->userID,
+ 0
+ ));
+
$row = $statement->fetchArray();
$this->notificationCount = $row['count'];
*/
public function countAllNotifications() {
$sql = "SELECT COUNT(*) AS count
- FROM wcf".WCF_N."_user_notification_to_user
+ FROM wcf".WCF_N."_user_notification
WHERE userID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute(array(WCF::getUser()->userID));
public function getNotifications($limit = 5, $offset = 0, $showConfirmedNotifications = false) {
// build enormous query
$conditions = new PreparedStatementConditionBuilder();
- $conditions->add("notification_to_user.userID = ?", array(WCF::getUser()->userID));
- if (!$showConfirmedNotifications) $conditions->add("notification_to_user.confirmed = ?", array(0));
- $conditions->add("notification.notificationID = notification_to_user.notificationID");
-
- $sql = "SELECT notification_to_user.notificationID, notification_event.eventID,
- object_type.objectType, notification.objectID,
- notification.additionalData, notification.authorID,
- notification.time".($showConfirmedNotifications ? ", notification_to_user.confirmed" : "")."
- FROM wcf".WCF_N."_user_notification_to_user notification_to_user,
- wcf".WCF_N."_user_notification notification
+ $conditions->add("notification.userID = ?", array(WCF::getUser()->userID));
+ if (!$showConfirmedNotifications) $conditions->add("notification.confirmed = ?", array(0));
+
+ $sql = "SELECT notification.notificationID, notification_event.eventID, notification.authorID,
+ notification.moreAuthors, object_type.objectType, notification.objectID,
+ notification.additionalData,
+ notification.time".($showConfirmedNotifications ? ", notification.confirmed" : "")."
+ FROM wcf".WCF_N."_user_notification notification
LEFT JOIN wcf".WCF_N."_user_notification_event notification_event
ON (notification_event.eventID = notification.eventID)
LEFT JOIN wcf".WCF_N."_object_type object_type
ON (object_type.objectTypeID = notification_event.objectTypeID)
".$conditions."
- ORDER BY notification.time DESC";
+ ORDER BY ".($showConfirmedNotifications ? "notification.confirmed ASC, " : "")."notification.time DESC";
$statement = WCF::getDB()->prepareStatement($sql, $limit, $offset);
$statement->execute($conditions->getParameters());
$objectTypes[$row['objectType']]['objectIDs'][] = $row['objectID'];
$eventIDs[] = $row['eventID'];
$notificationIDs[] = $row['notificationID'];
- $authorIDs[] = $row['authorID'];
}
// return an empty set if no notifications exist
);
}
+ // load authors
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("notificationID IN (?)", array($notificationIDs));
+ $sql = "SELECT notificationID, authorID
+ FROM wcf".WCF_N."_user_notification_author
+ ".$conditions."
+ ORDER BY time ASC";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+ $authorIDs = $authorToNotification = array();
+ while ($row = $statement->fetchArray()) {
+ if (!$row['authorID']) {
+ continue;
+ }
+
+ if (!isset($authorToNotification[$row['notificationID']])) {
+ $authorToNotification[$row['notificationID']] = array();
+ }
+
+ $authorIDs[] = $row['authorID'];
+ $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'))));
foreach ($events as $event) {
$className = $eventObjects[$event['eventID']]->className;
$class = new $className($eventObjects[$event['eventID']]);
+ $notificationID = $event['notificationID'];
$class->setObject(
- $notificationObjects[$event['notificationID']],
+ $notificationObjects[$notificationID],
$objectTypes[$event['objectType']]['objects'][$event['objectID']],
(isset($authors[$event['authorID']]) ? $authors[$event['authorID']] : $unknownAuthor),
unserialize($event['additionalData'])
);
+ if (isset($authorToNotification[$notificationID])) {
+ $eventAuthors = array();
+ foreach ($authorToNotification[$notificationID] as $userID) {
+ if (isset($authors[$userID])) {
+ $eventAuthors[$userID] = $authors[$userID];
+ }
+ }
+ if (!empty($eventAuthors)) {
+ $class->setAuthors($eventAuthors);
+ }
+ }
+
$data = array(
+ 'authors' => count($class->getAuthors()),
'event' => $class,
'notificationID' => $event['notificationID'],
'time' => $event['time']
$objectTypeObject = $this->availableObjectTypes[$objectType];
$event = $this->availableEvents[$objectType][$eventName];
- // delete notifications
- $sql = "UPDATE wcf".WCF_N."_user_notification_to_user
+ // mark as confirmed
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("eventID = ?", array($event->eventID));
+ if (!empty($recipientIDs)) $conditions->add("userID IN (?)", array($recipientIDs));
+ if (!empty($objectIDs)) $conditions->add("objectID IN (?)", array($objectIDs));
+
+ $sql = "UPDATE wcf".WCF_N."_user_notification
SET confirmed = ?
- WHERE notificationID IN (
- SELECT notificationID
- FROM wcf".WCF_N."_user_notification
- WHERE packageID = ?
- AND eventID = ?
- ".(!empty($objectIDs) ? "AND objectID IN (?".(count($objectIDs) > 1 ? str_repeat(',?', count($objectIDs) - 1) : '').")" : '')."
- )
- ".(!empty($recipientIDs) ? ("AND userID IN (?".(count($recipientIDs) > 1 ? str_repeat(',?', count($recipientIDs) - 1) : '').")") : '');
- $parameters = array(1, $objectTypeObject->packageID, $event->eventID);
- if (!empty($objectIDs)) $parameters = array_merge($parameters, $objectIDs);
- if (!empty($recipientIDs)) $parameters = array_merge($parameters, $recipientIDs);
+ ".$conditions;
$statement = WCF::getDB()->prepareStatement($sql);
+ $parameters = $conditions->getParameters();
+ array_unshift($parameters, 1);
$statement->execute($parameters);
+ // delete notification_to_user assignments (mimic legacy notification system)
+ $sql = "DELETE FROM wcf".WCF_N."_user_notification_to_user
+ WHERE notificationID NOT IN (
+ SELECT notificationID
+ FROM wcf".WCF_N."_user_notification
+ WHERE confirmed = ?
+ )";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute(array(0));
+
// reset storage
if (!empty($recipientIDs)) {
UserStorageHandler::getInstance()->reset($recipientIDs, 'userNotificationCount');
*/
protected $author = null;
+ /**
+ * list of authors for stacked notifications
+ * @var array<\wcf\data\user\UserProfile>
+ */
+ protected $authors = array();
+
+ /**
+ * notification stacking support
+ * @var boolean
+ */
+ protected $isStackable = false;
+
/**
* user notification
* @var \wcf\data\user\notification\UserNotification
*/
protected $language = null;
+ /**
+ * @see \wcf\system\user\notification\event\IUserNotificationEvent::setAuthors()
+ */
+ public function setAuthors(array $authors) {
+ $this->authors = $authors;
+ }
+
/**
* @see \wcf\system\user\notification\event\IUserNotificationEvent::setObject()
*/
return $this->author;
}
+ /**
+ * @see \wcf\system\user\notification\event\IUserNotificationEvent::getAuthors()
+ */
+ public function getAuthors() {
+ return $this->authors;
+ }
+
/**
* @see \wcf\system\user\notification\event\IUserNotificationEvent::isVisible()
*/
return $this->getMessage();
}
- /**
- * @see \wcf\system\user\notification\event\IUserNotificationEvent::getEventHash()
- */
- public function getEventHash() {
- return StringUtil::getHash($this->packageID . '-'. $this->eventID . '-' . $this->userNotificationObject->getObjectID());
- }
-
/**
* @see \wcf\system\user\notification\event\IUserNotificationEvent::setLanguage()
*/
if ($this->language !== null) return $this->language;
return WCF::getLanguage();
}
+
+ /**
+ * @see \wcf\system\user\notification\event\IUserNotificationEvent::isStackable()
+ */
+ public function isStackable() {
+ return $this->isStackable;
+ }
}
*/
public function getAuthor();
+ /**
+ * Returns a list of authors for stacked notifications sorted by time.
+ *
+ * @return array<\wcf\data\user\UserProfile>
+ */
+ public function getAuthors();
+
/**
* Returns true if this notification event is visible for the active user.
*
public function isVisible();
/**
- * Returns a unique identifier of the event.
+ * Sets a list of authors for stacked notifications.
*
- * @return string
+ * @param array<\wcf\data\user\UserProfile> $authors
*/
- public function getEventHash();
+ public function setAuthors(array $authors);
/**
* Sets the object for the event.
* @param \wcf\data\language\Language $language
*/
public function setLanguage(Language $language);
+
+ /**
+ * Returns true if this notification event supports stacking.
+ *
+ * @return boolean
+ */
+ public function isStackable();
}
<?php
namespace wcf\system\user\notification\event;
use wcf\system\request\LinkHandler;
-use wcf\system\user\notification\event\AbstractUserNotificationEvent;
-use wcf\util\StringUtil;
/**
* Notification event for followers.
* @category Community Framework
*/
class UserFollowFollowingUserNotificationEvent extends AbstractUserNotificationEvent {
+ /**
+ * @see \wcf\system\user\notification\event\AbstractUserNotificationEvent::$isStackable
+ */
+ protected $isStackable = true;
+
/**
* @see \wcf\system\user\notification\event\IUserNotificationEvent::getTitle()
*/
public function getTitle() {
+ $count = count($this->getAuthors());
+ if ($count > 1) {
+ return $this->getLanguage()->getDynamicVariable('wcf.user.notification.follow.title.stacked', array('count' => $count));
+ }
+
return $this->getLanguage()->get('wcf.user.notification.follow.title');
}
* @see \wcf\system\user\notification\event\IUserNotificationEvent::getMessage()
*/
public function getMessage() {
+ $authors = array_values($this->getAuthors());
+ $count = count($authors);
+
+ if ($count > 1) {
+ return $this->getLanguage()->getDynamicVariable('wcf.user.notification.follow.message.stacked', array(
+ 'author' => $this->author,
+ 'authors' => $authors,
+ 'count' => $count,
+ 'others' => max($count - 1, 0)
+ ));
+ }
+
return $this->getLanguage()->getDynamicVariable('wcf.user.notification.follow.message', array('author' => $this->author));
}
return $this->getLanguage()->getDynamicVariable('wcf.user.notification.follow.mail', array('author' => $this->author));
}
- /**
- * @see \wcf\system\user\notification\event\IUserNotificationEvent::getEventHash()
- */
- public function getEventHash() {
- return StringUtil::getHash($this->packageID . '-'. $this->eventID . '-' . $this->author->userID);
- }
-
/**
* @see \wcf\system\user\notification\event\IUserNotificationEvent::getLink()
*/
public function getAuthorID() {
return $this->userID;
}
+
+ /**
+ * @see \wcf\data\DatabaseObjectDecorator::getObjectID()
+ */
+ public function getObjectID() {
+ return $this->followUserID;
+ }
}
}
&.notificationItem {
+ &.groupedNotificationItem > a {
+ > div:first-child {
+ padding: 4px 2px 2px;
+ }
+
+ > div + div {
+ margin-left: 32px;
+ }
+ }
+
> a {
white-space: normal;
}
width: 16px;
}
+.icon24 {
+ font-size: 18px;
+ height: 24px;
+ width: 24px;
+}
+
.icon32 {
font-size: 28px;
height: 32px;
<item name="wcf.user.notification.button.confirmed"><![CDATA[OK]]></item>
<item name="wcf.user.notification.count"><![CDATA[if (data.returnValues.count == 0) { "Keine Benachrichtigungen" } else if (data.returnValues.count == 1) { "Eine Benachrichtigung" } else { data.returnValues.count + " Benachrichtigungen" }]]></item>
<item name="wcf.user.notification.follow.message"><![CDATA[„{$author->username}“ folgt Ihnen.]]></item>
+ <item name="wcf.user.notification.follow.message.stacked"><![CDATA[{if $count < 4}{@$authors[0]->getAnchorTag()}{if $count == 2} und {else}, {/if}{@$authors[1]->getAnchorTag()}{if $count == 3} und {@$authors[2]->getAnchorTag()}{/if}{else}{@$authors[0]->getAnchorTag()} und {#$count} weiteren{/if} folgen Ihnen.]]></item>
<item name="wcf.user.notification.follow.title"><![CDATA[Neuer Follower]]></item>
+ <item name="wcf.user.notification.follow.title.stacked"><![CDATA[{#$count} neue Follower]]></item>
<item name="wcf.user.notification.follow.mail"><![CDATA[{@$author->username} folgt Ihnen.]]></item>
<item name="wcf.user.notification.mail.disabled"><![CDATA[Die E-Mail-Benachrichtigung wurde erfolgreich abgeschaltet.]]></item>
<item name="wcf.user.notification.mail.footer"><![CDATA[Diese E-Mail ist eine automatische Benachrichtigung. BITTE ANTWORTEN SIE NICHT AUF DIESE E-MAIL.
<item name="wcf.user.notification.mailNotificationType.none"><![CDATA[Keine E-Mail-Benachrichtigung]]></item>
<item name="wcf.user.notification.mailNotificationType.instant"><![CDATA[Sofortige E-Mail-Benachrichtigung]]></item>
<item name="wcf.user.notification.mailNotificationType.daily"><![CDATA[Tägliche E-Mail-Benachrichtigung]]></item>
- <item name="wcf.user.notification.markAllAsConfirmed"><![CDATA[Alle Benachrichtigungen verwerfen]]></item>
+ <item name="wcf.user.notification.markAllAsConfirmed"><![CDATA[Alle als gelesen markieren]]></item>
<item name="wcf.user.notification.markAllAsConfirmed.confirmMessage"><![CDATA[Wollen Sie wirklich alle Benachrichtigungen als gelesen markieren?]]></item>
<item name="wcf.user.notification.markAsConfirmed"><![CDATA[Alls gelesen markieren]]></item>
<item name="wcf.user.notification.noMoreNotifications"><![CDATA[Keine neuen Benachrichtigungen]]></item>
<item name="wcf.user.notification.button.confirmed"><![CDATA[OK]]></item>
<item name="wcf.user.notification.count"><![CDATA[if (data.returnValues.count == 0) { "No Notifications" } else if (data.returnValues.count == 1) { "1 Notification" } else { data.returnValues.count + " Notifications" }]]></item>
<item name="wcf.user.notification.follow.message"><![CDATA[“{$author->username}” follows you.]]></item>
+ <item name="wcf.user.notification.follow.message.stacked"><![CDATA[{if $count < 4}{@$authors[0]->getAnchorTag()}{if $count == 2} and {else}, {/if}{@$authors[1]->getAnchorTag()}{if $count == 3} and {@$authors[2]->getAnchorTag()}{/if}{else}{@$authors[0]->getAnchorTag()} and {#$count} others{/if} follow you.]]></item>
<item name="wcf.user.notification.follow.mail"><![CDATA[{@$author->username} follows you.]]></item>
<item name="wcf.user.notification.follow.title"><![CDATA[New Follower]]></item>
+ <item name="wcf.user.notification.follow.title.stacked"><![CDATA[{#$count} new followers]]></item>
<item name="wcf.user.notification.mail.disabled"><![CDATA[Email notification has been disabled.]]></item>
<item name="wcf.user.notification.mail.footer"><![CDATA[This is an automatic notification, PLEASE DO NOT REPLY TO THIS EMAIL!
DROP TABLE IF EXISTS wcf1_user_notification;
CREATE TABLE wcf1_user_notification (
notificationID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
- packageID INT(10) NOT NULL,
eventID INT(10) NOT NULL,
objectID INT(10) NOT NULL DEFAULT 0,
- eventHash VARCHAR(40) NOT NULL DEFAULT '',
- authorID INT(10),
+ authorID INT(10) NULL,
+ moreAuthors INT(10) NOT NULL DEFAULT 0,
+ userID INT(10) NOT NULL,
time INT(10) NOT NULL DEFAULT 0,
+ mailNotified TINYINT(1) NOT NULL DEFAULT 0,
+ confirmed TINYINT(1) NOT NULL DEFAULT 0,
additionalData TEXT,
- KEY (eventHash),
- UNIQUE KEY (packageID, eventID, objectID)
+ KEY (userID, eventID, objectID, confirmed)
+);
+
+-- notification authors (stacking)
+DROP TABLE IF EXISTS wcf1_user_notification_author;
+CREATE TABLE wcf1_user_notification_author (
+ notificationID INT(10) NOT NULL,
+ authorID INT(10) NOT NULL,
+ time INT(10) NOT NULL DEFAULT 0,
+ canceled TINYINT(1) NOT NULL DEFAULT 0,
+ UNIQUE KEY (notificationID, authorID)
);
-- notification recipients
+-- DEPRECATED
DROP TABLE IF EXISTS wcf1_user_notification_to_user;
CREATE TABLE wcf1_user_notification_to_user (
notificationID INT(10) NOT NULL,
userID INT(10) NOT NULL,
- mailNotified TINYINT(1) NOT NULL DEFAULT 0,
- confirmed TINYINT(1) NOT NULL DEFAULT 0,
UNIQUE KEY notificationID (notificationID, userID)
);
ALTER TABLE wcf1_user_menu_item ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;
-ALTER TABLE wcf1_user_notification ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;
ALTER TABLE wcf1_user_notification ADD FOREIGN KEY (eventID) REFERENCES wcf1_user_notification_event (eventID) ON DELETE CASCADE;
ALTER TABLE wcf1_user_notification ADD FOREIGN KEY (authorID) REFERENCES wcf1_user (userID) ON DELETE SET NULL;
+ALTER TABLE wcf1_user_notification ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;
+
+ALTER TABLE wcf1_user_notification_author ADD FOREIGN KEY (notificationID) REFERENCES wcf1_user_notification (notificationID) ON DELETE CASCADE;
+ALTER TABLE wcf1_user_notification_author ADD FOREIGN KEY (authorID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;
ALTER TABLE wcf1_user_notification_to_user ADD FOREIGN KEY (notificationID) REFERENCES wcf1_user_notification (notificationID) ON DELETE CASCADE;
ALTER TABLE wcf1_user_notification_to_user ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;