{if $notifications[notifications]}
<div class="container marginTop">
- <ul class="containerList">
+ <ul class="containerList" id="userNotificationItemList">
{foreach from=$notifications[notifications] item=$notification}
- <li class="jsNotificationItem" data-notification-id="{@$notification[notificationID]}" data-link="{$notification[event]->getLink()}">
+ <li class="jsNotificationItem{if $notification[authors] > 1} groupedNotificationItem{/if}" data-notification-id="{@$notification[notificationID]}" data-link="{$notification[event]->getLink()}" data-is-grouped="{if $notification[authors] > 1}true{else}false{/if}">
<div class="box48">
- {if $notification[event]->getAuthor()->userID}
- <a href="{link controller='User' object=$notification[event]->getAuthor()}{/link}" title="{$notification[event]->getAuthor()->username}" class="framed">{@$notification[event]->getAuthor()->getAvatar()->getImageTag(48)}</a>
- {else}
- <span class="framed">{@$notification[event]->getAuthor()->getAvatar()->getImageTag(48)}</span>
- {/if}
-
- <div class="details">
- <div class="containerHeadline">
- <h3>
- {if !$notification[confirmed]}<span class="badge label newContentBadge">{lang}wcf.message.new{/lang}</span>{/if}
-
- {if $notification[event]->getAuthor()->userID}
- <a href="{link controller='User' object=$notification[event]->getAuthor()}{/link}" class="userLink" data-user-id="{@$notification[event]->getAuthor()->userID}">{$notification[event]->getAuthor()->username}</a>
- {else}
- {$notification[event]->getAuthor()->username}
- {/if}
- </h3>
- <small>{@$notification[time]|time}</small>
- </div>
+ {if $notification[authors] < 2}
+ {if $notification[event]->getAuthor()->userID}
+ <a href="{link controller='User' object=$notification[event]->getAuthor()}{/link}" title="{$notification[event]->getAuthor()->username}" class="framed">{@$notification[event]->getAuthor()->getAvatar()->getImageTag(48)}</a>
+ {else}
+ <span class="framed">{@$notification[event]->getAuthor()->getAvatar()->getImageTag(48)}</span>
+ {/if}
- <p>{@$notification[event]->getMessage()}</p>
+ <div class="details">
+ <div class="containerHeadline">
+ <h3>
+ {if !$notification[confirmed]}<span class="badge label newContentBadge">{lang}wcf.message.new{/lang}</span>{/if}
+
+ {if $notification[event]->getAuthor()->userID}
+ <a href="{link controller='User' object=$notification[event]->getAuthor()}{/link}" class="userLink" data-user-id="{@$notification[event]->getAuthor()->userID}">{$notification[event]->getAuthor()->username}</a>
+ {else}
+ {$notification[event]->getAuthor()->username}
+ {/if}
+ </h3>
+ <small>{@$notification[time]|time}</small>
+ </div>
+
+ <p>{@$notification[event]->getMessage()}</p>
+
+ {if !$notification[confirmed]}
+ <nav class="jsMobileNavigation buttonGroupNavigation">
+ <ul class="buttonList iconList jsOnly">
+ <li><a class="jsMarkAsConfirmed jsTooltip" title="{lang}wcf.user.notification.markAsConfirmed{/lang}"><span class="icon icon16 fa-check"></span></a></li>
+ </ul>
+ </nav>
+ {/if}
+ </div>
+ {else}
+ <span class="icon icon48 fa-users"></span>
- {if !$notification[confirmed]}
- <nav class="jsMobileNavigation buttonGroupNavigation">
- <ul class="buttonList iconList jsOnly">
- <li><a class="jsMarkAsConfirmed jsTooltip" title="{lang}wcf.user.notification.markAsConfirmed{/lang}"><span class="icon icon16 fa-check"></span></a></li>
- </ul>
- </nav>
- {/if}
- </div>
+ <div class="details">
+ <div class="containerHeadline">
+ <h3>
+ {if !$notification[confirmed]}<span class="badge label newContentBadge">{lang}wcf.message.new{/lang}</span>{/if}
+
+ {$notification[event]->getTitle()}
+ </h3>
+ <small>{@$notification[time]|time}</small>
+ </div>
+
+ <p>{@$notification[event]->getMessage()}</p>
+
+ <ul style="margin-top: 4px">
+ {foreach from=$notification[event]->getAuthors() item=author}
+ <li style="display: inline-block" class="jsTooltip" title="{$author->username}"><a href="{link controller='User' object=$author}{/link}" class="framed">{@$author->getAvatar()->getImageTag(24)}</a></li>
+ {/foreach}
+ </ul>
+
+ {if !$notification[confirmed]}
+ <nav class="jsMobileNavigation buttonGroupNavigation">
+ <ul class="buttonList iconList jsOnly">
+ <li><a class="jsMarkAsConfirmed jsTooltip" title="{lang}wcf.user.notification.markAsConfirmed{/lang}"><span class="icon icon16 fa-check"></span></a></li>
+ </ul>
+ </nav>
+ {/if}
+ </div>
+ {/if}
</div>
</li>
{/foreach}
{foreach from=$notifications[notifications] item=notification}
- <li class="jsNotificationItem notificationItem" data-link="{$notification[event]->getLink()}" data-notification-id="{@$notification[notificationID]}">
+ <li class="jsNotificationItem notificationItem{if $notification[event]->getAuthors()|count > 1} groupedNotificationItem{/if}" data-link="{$notification[event]->getLink()}" data-notification-id="{@$notification[notificationID]}">
<a class="box24">
- <div class="framed">
- {@$notification[event]->getAuthor()->getAvatar()->getImageTag(24)}
- </div>
- <div>
- <h3>{@$notification[event]->getMessage()}</h3>
- <small>{$notification[event]->getAuthor()->username} - {@$notification[time]|time}</small>
- </div>
+ {if $notification[event]->getAuthors()|count < 2}
+ <div class="framed">
+ {@$notification[event]->getAuthor()->getAvatar()->getImageTag(24)}
+ </div>
+ <div>
+ <h3>{@$notification[event]->getMessage()}</h3>
+ <small>{$notification[event]->getAuthor()->username} - {@$notification[time]|time}</small>
+ </div>
+ {else}
+ <div>
+ <span class="icon icon24 fa-users"></span>
+ </div>
+ <div>
+ <h3>{$notification[event]->getTitle()}</h3>
+ <small>{@$notification[time]|time}</small>
+ </div>
+ {/if}
</a>
</li>
{/foreach}
\ No newline at end of file
<?php
namespace wcf\data\user\notification;
use wcf\data\AbstractDatabaseObjectAction;
+use wcf\system\exception\PermissionDeniedException;
+use wcf\system\exception\UserInputException;
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.
return $notification;
}
+ /**
+ * Creates a simple notification without stacking support, applies to legacy notifications too.
+ *
+ * @return array<array>
+ */
public function createDefault() {
- die("createDefault");
+ foreach ($this->parameters['recipients'] as $recipient) {
+ $this->parameters['data']['userID'] = $recipient->userID;
+ $notification = $this->create();
+
+ $notifications[$recipient->userID] = array(
+ 'isNew' => true,
+ '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
+ ));
+ }
+ WCF::getDB()->commitTransaction();
+
+ return $notifications;
}
+ /**
+ * Creates a notification or adds another author to an existing one.
+ *
+ * @return array<array>
+ */
public function createStackable() {
// get existing notifications
$notificationList = new UserNotificationList();
}
// insert author
- $sql = "INSERT INTO wcf".WCF_N."_user_notification_author
- (notificationID, authorID, time)
- VALUES (?, ?, ?)";
+ $sql = "INSERT IGNORE INTO wcf".WCF_N."_user_notification_author
+ (notificationID, authorID, time)
+ VALUES (?, ?, ?)";
$statement = WCF::getDB()->prepareStatement($sql);
WCF::getDB()->beginTransaction();
*/
public function markAllAsConfirmed() {
// remove notifications for this user
- $sql = "UPDATE wcf".WCF_N."_user_notification_to_user
+ $sql = "UPDATE wcf".WCF_N."_user_notification
SET confirmed = ?
WHERE userID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
use wcf\system\exception\SystemException;
use wcf\system\mail\Mail;
use wcf\system\user\notification\event\IUserNotificationEvent;
+use wcf\system\user\notification\object\IStackableUserNotificationObject;
use wcf\system\user\notification\object\IUserNotificationObject;
use wcf\system\user\storage\UserStorageHandler;
use wcf\system\SingletonFactory;
'data' => array(
'eventID' => $event->eventID,
'authorID' => ($event->getAuthorID() ?: null),
- 'objectID' => $notificationObject->getObjectID(),
+
+ 'packageID' => $objectTypeObject->packageID,
'time' => TIME_NOW,
'additionalData' => serialize($additionalData)
),
'recipients' => $recipients
);
- if ($event->isStackable()) {
+ if ($event->isStackable() && $notificationObject instanceof IStackableUserNotificationObject) {
+ $data['data']['objectID'] = $notificationObject->getRelatedObjectID();
$data['notifications'] = $notifications;
$action = new UserNotificationAction(array(), 'createStackable', $data);
}
else {
+ $data['data']['objectID'] = $notificationObject->getObjectID();
+
$action = new UserNotificationAction(array(), 'createDefault', $data);
}
$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') {
--- /dev/null
+<?php
+namespace wcf\system\user\notification\object;
+
+/**
+ * This interface should be implemented by every object which supports stackable notifications.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.user.notification.object
+ * @category Community Framework
+ */
+interface IStackableUserNotificationObject extends IUserNotificationObject {
+ /**
+ * Returns the ID of the related object.
+ *
+ * @return integer
+ */
+ public function getRelatedObjectID();
+}
<?php
namespace wcf\system\user\notification\object;
use wcf\data\DatabaseObjectDecorator;
-use wcf\system\user\notification\object\IUserNotificationObject;
/**
* Represents a following user as a notification object.
* @subpackage system.user.notification.object
* @category Community Framework
*/
-class UserFollowUserNotificationObject extends DatabaseObjectDecorator implements IUserNotificationObject {
+class UserFollowUserNotificationObject extends DatabaseObjectDecorator implements IStackableUserNotificationObject {
/**
* @see \wcf\data\DatabaseObjectDecorator::$baseClass
*/
}
/**
- * @see \wcf\data\DatabaseObjectDecorator::getObjectID()
+ * @see \wcf\system\user\notification\object\IStackableUserNotificationObject::getRelatedObjectID()
*/
- public function getObjectID() {
- return $this->followUserID;
+ public function getRelatedObjectID() {
+ return $this->followUserID;
}
}
}
}
}
+
+/* user notifications */
+#userNotificationItemList > .groupedNotificationItem p > a {
+ font-weight: bold;
+}
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, -- DEPRECATED
eventID INT(10) NOT NULL,
objectID INT(10) NOT NULL DEFAULT 0,
authorID INT(10) NULL,