Index: classes/core/PKPApplication.inc.php =================================================================== RCS file: /cvs/pkp/classes/core/PKPApplication.inc.php,v retrieving revision 1.9 diff -u -r1.9 PKPApplication.inc.php --- classes/core/PKPApplication.inc.php 16 Oct 2008 17:47:29 -0000 1.9 +++ classes/core/PKPApplication.inc.php 21 Jan 2009 18:27:40 -0000 @@ -186,6 +186,8 @@ 'CurrencyDAO' => 'currency.CurrencyDAO', 'HelpTocDAO' => 'help.HelpTocDAO', 'HelpTopicDAO' => 'help.HelpTopicDAO', + 'NotificationDAO' => 'notification.NotificationDAO', + 'NotificationSettingsDAO' => 'notification.NotificationSettingsDAO', 'ScheduledTaskDAO' => 'scheduledTask.ScheduledTaskDAO', 'SessionDAO' => 'session.SessionDAO', 'SiteDAO' => 'site.SiteDAO', Index: classes/notification/Notification.inc.php =================================================================== RCS file: classes/notification/Notification.inc.php diff -N classes/notification/Notification.inc.php --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ classes/notification/Notification.inc.php 21 Jan 2009 18:27:40 -0000 @@ -0,0 +1,306 @@ +getId(); + + $notification->setUserId($userId); + $notification->setContents($contents); + $notification->setParam($param); + $notification->setLocation($location); + $notification->setIsLocalized($isLocalized); + $notification->setAssocType($assocType); + $notification->setContext($contextId); + + $notificationDao = &DAORegistry::getDAO('NotificationDAO'); + $notificationDao->insertNotification($notification); + + return $notification; + } + + /** + * get notification id + * @return int + */ + function getNotificationId() { + return $this->getData('notificationId'); + } + + /** + * set notification id + * @param $commentId int + */ + function setNotificationId($notificationId) { + return $this->setData('notificationId', $notificationId); + } + + /** + * get user id associated with this notification + * @return int + */ + function getUserId() { + return $this->getData('userId'); + } + + /** + * set user id associated with this notification + * @param $userId int + */ + function setUserId($userId) { + return $this->setData('userId', $userId); + } + + /** + * get date notification was created + * @return date (YYYY-MM-DD HH:MM:SS) + */ + function getDateCreated() { + return $this->getData('dateCreated'); + } + + /** + * set date notification was created + * @param $dateCreated date (YYYY-MM-DD HH:MM:SS) + */ + function setDateCreated($dateCreated) { + return $this->setData('dateCreated', $dateCreated); + } + + /** + * get date notification is read by user + * @return date (YYYY-MM-DD HH:MM:SS) + */ + function getDateRead() { + return $this->getData('dateRead'); + } + + /** + * set date notification is read by user + * Also sets setisUnread() if $dateRead is null + * @param $dateRead date (YYYY-MM-DD HH:MM:SS) + */ + function setDateRead($dateRead) { + if(!isset($dateRead)) { + $this->setIsUnread(true); + $notificationDao = &DAORegistry::getDAO('NotificationDAO'); + $notificationDao->setDateRead($this->getNotificationId()); + } else { + $this->setIsUnread(false); + return $this->setData('dateRead', $dateRead); + } + } + + /** + * return true if reading for the first time + * @return bool + */ + function getIsUnread() { + return $this->getData('isUnread'); + } + + /** + * set to true if notification has not been read + * @param $isUnread bool + */ + function setIsUnread($isUnread) { + return $this->setData('isUnread', $isUnread); + } + + /** + * get notification contents + * @return string + */ + function getContents() { + return $this->getData('contents'); + } + + /** + * set notification contents + * @param $contents int + */ + function setContents($contents) { + return $this->setData('contents', $contents); + } + + /** + * get optional parameter (e.g. article title) + * @return string + */ + function getParam() { + return $this->getData('param'); + } + + /** + * set optional parameter + * @param $param int + */ + function setParam($param) { + return $this->setData('param', $param); + } + + /** + * get URL that notification refers to + * @return int + */ + function getLocation() { + return $this->getData('location'); + } + + /** + * set URL that notification refers to + * @param $location int + */ + function setLocation($location) { + return $this->setData('location', $location); + } + + /** + * return true if message is localized (i.e. a system message) + * @return int + */ + function getIsLocalized() { + return $this->getData('isLocalized'); + } + + /** + * set to true if message is localized (i.e. is a system message) + * @param $isLocalized int + */ + function setIsLocalized($isLocalized) { + return $this->setData('isLocalized', $isLocalized); + } + + /** + * get notification type + * @return int + */ + function getAssocType() { + return $this->getData('assocType'); + } + + /** + * set notification type + * @param $assocType int + */ + function setAssocType($assocType) { + return $this->setData('assocType', $assocType); + } + + /** + * get context id + * @return int + */ + function getContext() { + return $this->getData('context'); + } + /** + * set context id + * @param $context int + */ + function setContext($context) { + return $this->setData('context', $context); + } + + /** + * return the path to the icon for this type + * @return string + */ + function getIconLocation() { + $baseUrl = Request::getBaseUrl() . '/lib/pkp/templates/images/icons/'; + switch ($this->getAssocType()) { + case NOTIFICATION_TYPE_ARTICLE_SUBMITTED: + case NOTIFICATION_TYPE_GALLEY_ADDED: + case NOTIFICATION_TYPE_SUPP_FILE_ADDED: + return $baseUrl . 'page_new.png'; + break; + case NOTIFICATION_TYPE_SUPP_FILE_MODIFIED: + case NOTIFICATION_TYPE_SUPP_FILE_ADDED: + return $baseUrl . 'page_attachment.png'; + break; + + case NOTIFICATION_TYPE_METADATA_MODIFIED: + case NOTIFICATION_TYPE_GALLEY_MODIFIED: + return $baseUrl . 'edit.png'; + break; + case NOTIFICATION_TYPE_SUBMISSION_COMMENT: + case NOTIFICATION_TYPE_LAYOUT_COMMENT: + case NOTIFICATION_TYPE_COPYEDIT_COMMENT: + case NOTIFICATION_TYPE_PROOFREAD_COMMENT: + case NOTIFICATION_TYPE_REVIEWER_COMMENT: + case NOTIFICATION_TYPE_REVIEWER_FORM_COMMENT: + case NOTIFICATION_TYPE_EDITOR_DECISION_COMMENT: + case NOTIFICATION_TYPE_USER_COMMENT: + return $baseUrl . 'comment_new.png'; + break; + case NOTIFICATION_TYPE_PUBLISHED_ISSUE: + return $baseUrl . 'list_world.png'; + break; + default: + return $baseUrl . 'page_alert.png'; + } + + + } + + } + +?> Index: classes/notification/NotificationDAO.inc.php =================================================================== RCS file: classes/notification/NotificationDAO.inc.php diff -N classes/notification/NotificationDAO.inc.php --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ classes/notification/NotificationDAO.inc.php 21 Jan 2009 18:27:41 -0000 @@ -0,0 +1,324 @@ +retrieve( + 'SELECT * FROM notifications WHERE notification_id = ?', $notificationId + ); + + $notification = &$this->_returnNotificationFromRow($result->GetRowAssoc(false)); + + $result->Close(); + unset($result); + + return $notification; + } + + /** + * Retrieve Notifications by user id + * @param $userId int + * @return Notification objects array + */ + function &getNotificationsByUserId($userId) { + $application =& PKPApplication::getApplication(); + $productName = $application->getName(); + $context =& Request::getContext(); + $contextId = $context->getId(); + + $notifications = array(); + + $result = &$this->retrieve( + 'SELECT * FROM notifications WHERE user_id = ? AND product = ? AND context = ? ORDER BY date_created DESC', + array($userId, $productName, $contextId) + ); + + $returner = new DAOResultFactory($result, $this, '_returnNotificationFromRow'); + + return $returner; + } + + /** + * Retrieve Notifications by notification id + * @param $notificationId int + * @return boolean + */ + function setDateRead($notificationId) { + $returner = $this->update( + sprintf('UPDATE notifications + SET date_read = %s + WHERE notification_id = ?', + $this->datetimeToDB(date('Y-m-d H:i:s'))), + array( + $notificationId + ) + ); + + return $returner; + } + + /** + * Creates and returns an notification object from a row + * @param $row array + * @return Notification object + */ + function &_returnNotificationFromRow($row) { + $notification = new Notification(); + $notification->setNotificationId($row['notification_id']); + $notification->setUserId($row['user_id']); + $notification->setDateCreated($row['date_created']); + $notification->setDateRead($row['date_read']); + $notification->setContents($row['contents']); + $notification->setParam($row['param']); + $notification->setLocation($row['location']); + $notification->setIsLocalized($row['is_localized']); + $notification->setContext($row['context']); + $notification->setAssocType($row['assoc_type']); + + HookRegistry::call('NotificationDAO::_returnNotificationFromRow', array(&$notification, &$row)); + + return $notification; + } + + /** + * Inserts a new notification into notifications table + * @param Notification object + * @return int Notification Id + */ + function insertNotification(&$notification) { + $application =& PKPApplication::getApplication(); + $productName = $application->getName(); + + if ($this->notificationAlreadyExists($notification)) { + return 0; + } + + $notificationSettingsDao = &DAORegistry::getDAO('NotificationSettingsDAO'); + $notificationSettings = $notificationSettingsDao->getNotificationSettings($notification->getUserId()); + $notificationEmailSettings = $notificationSettingsDao->getNotificationEmailSettings($notification->getUserId()); + + if(in_array($notification->getAssocType(), $notificationEmailSettings)) { + $this->sendNotificationEmail($notification); + } + + if(!in_array($notification->getAssocType(), $notificationSettings)) { + $this->update( + sprintf('INSERT INTO notifications + (user_id, date_created, contents, param, location, is_localized, context, product, assoc_type) + VALUES + (?, %s, ?, ?, ?, ?, ?, ?, ?)', + $this->datetimeToDB(date('Y-m-d H:i:s'))), + array( + $notification->getUserId(), + $notification->getContents(), + $notification->getParam(), + $notification->getLocation(), + $notification->getIsLocalized(), + $notification->getContext(), + $productName, + $notification->getAssocType(), + ) + ); + + $notification->setNotificationId($this->getInsertNotificationId()); + return $notification->getNotificationId(); + } else return 0; + } + + /** + * Delete Notification by notification id + * @param $notificationId int + * @return boolean + */ + function deleteNotificationById($notificationId, $userId = null) { + return $this->update('DELETE FROM notifications WHERE notification_id = ?' . (isset($userId) ? ' AND user_id = ?' : ''), + isset($userId) ? array($notificationId, $userId) : $notificationId + ); + } + + /** + * Check if the same notification was added in the last hour + * Will prevent multiple notifications to show up in a user's feed e.g. + * if a user edits a submission multiple times in a short time span + * @param notification object + * @return boolean + */ + function notificationAlreadyExists(&$notification) { + $application =& PKPApplication::getApplication(); + $productName = $application->getName(); + $context =& Request::getContext(); + $contextId = $context->getId(); + + $result = &$this->retrieve( + 'SELECT date_created FROM notifications WHERE user_id = ? AND contents = ? AND product = ? AND assoc_type = ? AND context = ?', + array( + $notification->getUserId(), + $notification->getContents(), + $productName, + $notification->getAssocType(), + $contextId + ) + ); + + $date = isset($result->fields[0]) ? $result->fields[0] : 0; + + if ($date == 0) { + return false; + } else { + $timeDiff = strtotime($date) - time(); + if ($timeDiff < 3600) { // 1 hour (in seconds) + return true; + } else return false; + } + } + + /** + * Get the ID of the last inserted notification + * @return int + */ + function getInsertNotificationId() { + return $this->getInsertId('notifications', 'notification_id'); + } + + /** + * Get the number of unread messages for a user + * @param $userId int + * @return int + */ + function getUnreadNotificationCount($userId) { + $application =& PKPApplication::getApplication(); + $productName = $application->getName(); + $context =& Request::getContext(); + $contextId = $context->getId(); + + $result = &$this->retrieve( + 'SELECT count(*) FROM notifications WHERE user_id = ? AND date_read IS NULL AND product = ? AND context = ?', + array($userId, $productName, $contextId) + ); + + $returner = $result->fields[0]; + + $result->Close(); + unset($result); + + return $returner; + } + + /** + * Get the number of read messages for a user + * @param $userId int + * @return int + */ + function getReadNotificationCount($userId) { + $application =& PKPApplication::getApplication(); + $productName = $application->getName(); + $context =& Request::getContext(); + $contextId = $context->getId(); + + $result = &$this->retrieve( + 'SELECT count(*) FROM notifications WHERE user_id = ? AND date_read IS NOT NULL AND product = ? AND context = ?', + array($userId, $productName, $contextId) + ); + + $returner = $result->fields[0]; + + $result->Close(); + unset($result); + + return $returner; + } + + /** + * Send an email to a user regarding the notification + * @param $notification object Notification + */ + function sendNotificationEmail($notification) { + $userId = $notification->getUserId(); + $userDao = &DAORegistry::getDAO('UserDAO'); + $user = $userDao->getUser($userId); + + if ($notification->getIsLocalized()) { + $params = array('param' => $notification->getParam()); + $notificationContents = Locale::translate($notification->getContents(), $params); + } else { + $notificationContents = $notification->getContents(); + } + + import('mail.MailTemplate'); + $site = &Request::getSite(); + $mail = new MailTemplate('NOTIFICATION'); + $mail->setFrom($site->getSiteContactEmail(), $site->getSiteContactName()); + $mail->assignParams(array( + 'notificationContents' => $notificationContents, + 'url' => $notification->getLocation(), + 'siteTitle' => $site->getSiteTitle() + )); + $mail->addRecipient($user->getEmail(), $user->getFullName()); + $mail->send(); + } + + /** + * Send an update to all users on the mailing list + * @param $notification object Notification + */ + function sendToMailingList($notification) { + $notificationSettingsDao = &DAORegistry::getDAO('NotificationSettingsDAO'); + $guestList = $notificationSettingsDao->getGuestList(); + + foreach ($guestList as $email) { + if ($notification->getIsLocalized()) { + $params = array('param' => $notification->getParam()); + $notificationContents = Locale::translate($notification->getContents(), $params); + } else { + $notificationContents = $notification->getContents(); + } + + import('mail.MailTemplate'); + $journal = Request::getJournal(); + $site = &Request::getSite(); + + $mail = new MailTemplate('NOTIFICATION_MAILLIST'); + $mail->setFrom($site->getSiteContactEmail(), $site->getSiteContactName()); + $mail->assignParams(array( + 'notificationContents' => $notificationContents, + 'url' => $notification->getLocation(), + 'siteTitle' => $journal->getJournalTitle(), + 'unsubscribeLink' => Request::url(null, 'notification', 'unsubscribeMailList') + )); + $mail->addRecipient($email); + $mail->send(); + } + + + } +} + +?> Index: classes/notification/NotificationSettingsDAO.inc.php =================================================================== RCS file: classes/notification/NotificationSettingsDAO.inc.php diff -N classes/notification/NotificationSettingsDAO.inc.php --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ classes/notification/NotificationSettingsDAO.inc.php 21 Jan 2009 18:27:41 -0000 @@ -0,0 +1,431 @@ +getName(); + $context =& Request::getContext(); + $contextId = $context->getId(); + + $notificationSettings = array(); + + $result = &$this->retrieve( + 'SELECT setting_value FROM notification_settings WHERE user_id = ? AND product = ? AND setting_name = ? AND context = ?', + array($userId, $productName, 'notify', $contextId) + ); + + while (!$result->EOF) { + $row = $result->GetRowAssoc(false); + $notificationSettings[] = (int) $row['setting_value']; + $result->moveNext(); + } + + $result->Close(); + unset($result); + + return $notificationSettings; + } + + /** + * Retrieve Notifications email settings by user id + * Returns an array of notification types that the user + * DOES want to be emailed about + * @param $userId int + * @return array + */ + function &getNotificationEmailSettings($userId) { + $application =& PKPApplication::getApplication(); + $productName = $application->getName(); + $context =& Request::getContext(); + $contextId = $context->getId(); + + $emailSettings = array(); + + $result = &$this->retrieve( + 'SELECT setting_value FROM notification_settings WHERE user_id = ? AND product = ? AND setting_name = ? AND context = ?', + array($userId, $productName, 'email', $contextId) + ); + + while (!$result->EOF) { + $row = $result->GetRowAssoc(false); + $emailSettings[] = (int) $row['setting_value']; + $result->moveNext(); + } + + $result->Close(); + unset($result); + + return $emailSettings; + } + + /** + * Update a user's notification settings + * @param $notificationSettings array + * @param $userId int + */ + function updateNotificationSettings($notificationSettings, $userId) { + $application =& PKPApplication::getApplication(); + $productName = $application->getName(); + $context =& Request::getContext(); + $contextId = $context->getId(); + + // Delete old settings first, then insert new settings + $this->update('DELETE FROM notification_settings WHERE user_id = ? AND product = ? AND setting_name = ? AND context = ?', + array($userId, $productName, 'notify', $contextId)); + + for ($i=0; $iupdate( + 'INSERT INTO notification_settings + (setting_name, setting_value, user_id, product, context) + VALUES + (?, ?, ?, ?, ?)', + array( + "notify", + $notificationSettings[$i], + $userId, + $productName, + $contextId + ) + ); + } + } + + /** + * Update a user's notification email settings + * @param $notificationEmailSettings array + * @param $userId int + */ + function updateNotificationEmailSettings($emailSettings, $userId) { + $application =& PKPApplication::getApplication(); + $productName = $application->getName(); + $context =& Request::getContext(); + $contextId = $context->getId(); + + // Delete old settings first, then insert new settings + $this->update('DELETE FROM notification_settings WHERE user_id = ? AND product = ? AND setting_name = ? AND context = ?', + array($userId, $productName, 'email', $contextId)); + + for ($i=0; $iupdate( + 'INSERT INTO notification_settings + (setting_name, setting_value, user_id, product, context) + VALUES + (?, ?, ?, ?, ?)', + array( + "email", + $emailSettings[$i], + $userId, + $productName, + $contextId + ) + ); + } + } + + /** + * Gets a user id by an RSS token value + * @param $token int + * @return int + */ + function getUserIdByRSSToken($token) { + $application =& PKPApplication::getApplication(); + $productName = $application->getName(); + $context =& Request::getContext(); + $contextId = $context->getId(); + + $result = &$this->retrieve( + 'SELECT user_id FROM notification_settings WHERE setting_value = ? AND setting_name = ? AND product = ? AND context = ?', + array($token, 'token', $productName, $contextId) + ); + + $row = $result->GetRowAssoc(false); + $userId = $row['user_id']; + + $result->Close(); + unset($result); + + return $userId; + } + + /** + * Gets an RSS token for a user id + * @param $userId int + * @return int + */ + function getRSSTokenByUserId($userId) { + $application =& PKPApplication::getApplication(); + $productName = $application->getName(); + $context =& Request::getContext(); + $contextId = $context->getId(); + + $result = &$this->retrieve( + 'SELECT setting_value FROM notification_settings WHERE user_id = ? AND setting_name = ? AND product = ? AND context = ?', + array($userId, 'token', $productName, $contextId) + ); + + $row = $result->GetRowAssoc(false); + $userId = $row['setting_value']; + + $result->Close(); + unset($result); + + return $userId; + } + + /** + * Generates and inserts a new token for a user's RSS feed + * @param $userId int + * @return int + */ + function insertNewRSSToken($userId) { + $application =& PKPApplication::getApplication(); + $productName = $application->getName(); + $context =& Request::getContext(); + $contextId = $context->getId(); + + $token = uniqid(rand()); + + $this->update( + 'INSERT INTO notification_settings + (setting_name, setting_value, user_id, product, context) + VALUES + (?, ?, ?, ?, ?)', + array( + 'token', + $token, + $userId, + $productName, + $contextId + ) + ); + + return $token; + } + + /** + * Generates an access key for the guest user and adds them to the settings table + * @param $userId int + * @return int + */ + function subscribeGuest($email) { + $application =& PKPApplication::getApplication(); + $productName = $application->getName(); + $context =& Request::getContext(); + $contextId = $context->getId(); + + + // Check that the email doesn't already exist + $result = &$this->retrieve( + 'SELECT * FROM notification_settings WHERE setting_name = ? AND setting_value = ? AND product = ? AND context = ?', + array( + 'guestList', + $email, + $productName, + $contextId + ) + ); + + if ($result->RecordCount() != 0) { + return false; + } else { + $this->update( + 'INSERT INTO notification_settings + (setting_name, setting_value, user_id, product, context) + VALUES + (?, ?, ?, ?, ?)', + array( + 'guestList', + $email, + 0, + $productName, + $contextId + ) + ); + } + + // Get assoc_id into notification_settings table, also used as user_id for access key + $assocId = $this->getInsertNotificationSettingId(); + + import('security.AccessKeyManager'); + $accessKeyManager = new AccessKeyManager(); + + $password = $accessKeyManager->createKey('MailListContext', $assocId, $assocId, 10000); + return $password; + } + + + + /** + * Removes an email address and associated access key from email notifications + * @param $email string + * @param $password string + * @return boolean + */ + function unsubscribeGuest($email, $password) { + $application =& PKPApplication::getApplication(); + $productName = $application->getName(); + $context =& Request::getContext(); + $contextId = $context->getId(); + + $result = &$this->retrieve( + 'SELECT setting_id FROM notification_settings WHERE setting_name = ? AND product = ? AND context = ?', + array( + 'guestList', + $productName, + $contextId + ) + ); + + $row = $result->GetRowAssoc(false); + $userId = $row['setting_id']; + + $result->Close(); + unset($result); + + import('security.AccessKeyManager'); + $accessKeyManager = new AccessKeyManager(); + $accessKeyHash = AccessKeyManager::generateKeyHash($password); + $accessKey = $accessKeyManager->validateKey('MailListContext', $userId, $accessKeyHash); + + if ($accessKey) { + $this->update( + 'DELETE FROM notification_settings WHERE setting_name = ? AND setting_value = ? AND product = ? AND context = ?', + array( + 'guestList', + $email, + $productName, + $contextId + ) + ); + $accessKeyDao =& DAORegistry::getDAO('AccessKeyDAO'); + $accessKeyDao->deleteAccessKey($accessKey); + return true; + } else return false; + + + } + + /** + * Gets a list of email addresses of users subscribed to the mailing list + * @return array + */ + function getGuestList() { + $application =& PKPApplication::getApplication(); + $productName = $application->getName(); + $context =& Request::getContext(); + $contextId = $context->getId(); + $guestList = array(); + + $result = &$this->retrieve( + 'SELECT setting_value FROM notification_settings WHERE setting_name = ? AND product = ? AND context = ?', + array( + 'guestList', + $productName, + $contextId + ) + ); + + while (!$result->EOF) { + $row = $result->GetRowAssoc(false); + $guestList[] = $row['setting_value']; + $result->moveNext(); + } + + $result->Close(); + unset($result); + + return $guestList; + } + + /** + * Generates and inserts a new password for a mailing list user + * @param $email string + * @return string + */ + function resetPassword($email) { + $application =& PKPApplication::getApplication(); + $productName = $application->getName(); + $context =& Request::getContext(); + $contextId = $context->getId(); + + $result = &$this->retrieve( + 'SELECT setting_id FROM notification_settings WHERE setting_name = ? AND setting_value = ? AND product = ? AND context = ?', + array( + 'guestList', + $email, + $productName, + $contextId + ) + ); + + $row = $result->GetRowAssoc(false); + $settingId = $row['setting_id']; + + $result->Close(); + unset($result); + + $accessKeyDao =& DAORegistry::getDAO('AccessKeyDAO'); + $accessKey = $accessKeyDao->getAccessKeyByUserId('MailListContext', $settingId); + + if ($accessKey) { + $key = Validation::generatePassword(); + $accessKey->setKeyHash(md5($key)); + + $accessKeyDao =& DAORegistry::getDAO('AccessKeyDAO'); + $accessKeyDao->updateAccessKey($accessKey); + return $key; + } else return false; + } + + + + + + + + + + + + + + /** + * Get the ID of the last inserted notification + * @return int + */ + function getInsertNotificationSettingId() { + return $this->getInsertId('notification_settings', 'setting_id'); + } + +} + +?> Index: classes/security/AccessKeyDAO.inc.php =================================================================== RCS file: /cvs/pkp/classes/security/AccessKeyDAO.inc.php,v retrieving revision 1.4 diff -u -r1.4 AccessKeyDAO.inc.php --- classes/security/AccessKeyDAO.inc.php 2 Dec 2008 21:01:13 -0000 1.4 +++ classes/security/AccessKeyDAO.inc.php 21 Jan 2009 18:27:41 -0000 @@ -41,6 +41,30 @@ unset($result); return $accessKey; } + + /** + * Retrieve a accessKey object user ID. + * @param $context string + * @param $userId int + * @return AccessKey + */ + function &getAccessKeyByUserId($context, $userId) { + $result =& $this->retrieve( + sprintf( + 'SELECT * FROM access_keys WHERE context = ? AND user_id = ? AND expiry_date > %s', + $this->datetimeToDB(Core::getCurrentDate()) + ), + array($context, $userId) + ); + + $returner = null; + if ($result->RecordCount() != 0) { + $returner =& $this->_returnAccessKeyFromRow($result->GetRowAssoc(false)); + } + $result->Close(); + unset($result); + return $returner; + } /** * Retrieve a accessKey object by key. @@ -118,7 +142,7 @@ */ function updateAccessKey(&$accessKey) { return $this->update( - sprintf('UPDATE accessKeys + sprintf('UPDATE access_keys SET key_hash = ?, expiry_date = %s, Index: classes/template/PKPTemplateManager.inc.php =================================================================== RCS file: /cvs/pkp/classes/template/PKPTemplateManager.inc.php,v retrieving revision 1.9 diff -u -r1.9 PKPTemplateManager.inc.php --- classes/template/PKPTemplateManager.inc.php 12 Jan 2009 11:52:43 -0000 1.9 +++ classes/template/PKPTemplateManager.inc.php 21 Jan 2009 18:27:42 -0000 @@ -415,9 +415,9 @@ if (isset($params['name'])) { // build image tag with standarized size of 16x16 $disabled = (isset($params['disabled']) && !empty($params['disabled'])); - if (!isset($params['path'])) $params['path'] = 'templates/images/icons/'; + if (!isset($params['path'])) $params['path'] = 'lib/pkp/templates/images/icons/'; $iconHtml = '';
+				$iconHtml .= $params['name'] . ($disabled ? '_disabled' : '') . '.pngStep {$step} User Home User + Allow these types of notifications to appear in my notification feed. + Also send me an email for these types of notifications. + Go To URL + Notification mailing list + Enter your email address to receive immediate notifications of important new content added to the journal. + Privacy protection policy + Subscribe to protected content.]]> + submit an article?]]> + review?]]> + You have no notifications at this time. + Notification + Notifications + You have {$unreadCount} unread notifications and {$readCount} read notifications.Click here to change your notification settings.]]> + This page shows important updates associated with this journal such as new issues or announcements. You may subscribe to these notifications through RSS feeds (by clicking on the images to the right), or through email.]]> + Notification Settings + Select the system events that you wish to be notified about. Unchecking an item will prevent notifications of the event from showing up in your notification feed. + Your email address is already subscribed to notifications. + Your email address has been successfully added to the mailing list. + There was an error sending your password, please ensure you've entered your email address correctly. + Your new password has been sent to the email address provided. + A new article, "{$param}", has been submitted. + A copyeditor has left a comment on "{$param}". + A comment has been left on the editor decision for "{$param}". + A galley has been added for "{$param}". + An galley has been modified for "{$param}". + An issue has been published. + A comment has been left about "{$param}'s" layout. + "{$param}'s" metadata has been modified. + Other Events + A comment has been left by a proofreader on "{$param}". + A reviewer has commented on "{$param}". + A review form review has been submitted for "{$param}". + An editor has made a comment on "{$param}". + Submission Events + A supplementary file has been added to "{$param}". + "{$param}'s" supplementary file(s) has been modified. + A reader has made a comment on "{$param}" + Enter your email address and password below to unsubscribe from email notifications. If you do not remember your password, leave the password field blank and a new one will be emailed to you at the given email address. + There was an error unsubscribing you. Please ensure your email address and password are correct. + You were successfully unsubscribed. Abstract All Coverage Index: pages/notification/NotificationHandler.inc.php =================================================================== RCS file: pages/notification/NotificationHandler.inc.php diff -N pages/notification/NotificationHandler.inc.php --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ pages/notification/NotificationHandler.inc.php 21 Jan 2009 18:27:44 -0000 @@ -0,0 +1,319 @@ +getUserId(); + $templateMgr->assign('isUserLoggedIn', true); + } else { + $userId = 0; + $templateMgr->assign('emailUrl', Request::url(null, 'notification', 'subscribeMailList')); + $templateMgr->assign('isUserLoggedIn', false); + } + + $notificationDao = &DAORegistry::getDAO('NotificationDAO'); + $notifications = $notificationDao->getNotificationsByUserId($userId); + + $templateMgr->assign('notifications', $notifications); + $templateMgr->assign('unread', $notificationDao->getUnreadNotificationCount($userId)); + $templateMgr->assign('read', $notificationDao->getReadNotificationCount($userId)); + $templateMgr->assign('url', Request::url(null, 'notification', 'settings')); + $templateMgr->display('notification/index.tpl'); + } + + /** + * Delete a notification + */ + function delete($args) { + parent::validate(); + + $user = Request::getUser(); + if(isset($user)) { + $userId = $user->getUserId(); + $notificationDao = &DAORegistry::getDAO('NotificationDAO'); + $notifications = $notificationDao->deleteNotificationById($args[0], $userId); + } + + Request::redirect(null, 'notification'); + } + + /** + * Delete a notification + */ + function deleteAjax($args) { + parent::validate(); + + $user = Request::getUser(); + if(isset($user)) { + $userId = $user->getUserId(); + $notificationDao = &DAORegistry::getDAO('NotificationDAO'); + $notifications = $notificationDao->deleteNotificationById($args[0], $userId); + } + } + + /** + * View and modify notification settings + */ + function settings() { + parent::validate(); + + $user = Request::getUser(); + if(isset($user)) { + $userId = $user->getUserId(); + + $notificationSettingsDao = &DAORegistry::getDAO('NotificationSettingsDAO'); + $notificationSettings = $notificationSettingsDao->getNotificationSettings($userId); + $emailSettings = $notificationSettingsDao->getNotificationEmailSettings($userId); + + $templateMgr = &TemplateManager::getManager(); + $templateMgr->assign('notificationSettings', $notificationSettings); + $templateMgr->assign('emailSettings', $emailSettings); + $templateMgr->assign('titleVar', Locale::translate('common.title')); + $templateMgr->assign('userVar', Locale::translate('common.user')); + $templateMgr->display('notification/settings.tpl'); + } else Request::redirect(null, 'notification'); + } + + /** + * Save user notification settings + */ + function saveSettings() { + parent::validate(); + + $settings = array(); + + $user = Request::getUser(); + if(isset($user)) { + $userId = $user->getUserId(); + $notificationSettingsDao = &DAORegistry::getDAO('NotificationSettingsDAO'); + + // Notification settings + $settings = array(); + if(!Request::getUserVar('notificationArticleSubmitted')) $settings[] = NOTIFICATION_TYPE_ARTICLE_SUBMITTED; + if(!Request::getUserVar('notificationMetadataModified')) $settings[] = NOTIFICATION_TYPE_METADATA_MODIFIED; + if(!Request::getUserVar('notificationSuppFileAdded')) $settings[] = NOTIFICATION_TYPE_SUPP_FILE_ADDED; + if(!Request::getUserVar('notificationSuppFileModified')) $settings[] = NOTIFICATION_TYPE_SUPP_FILE_MODIFIED; + if(!Request::getUserVar('notificationGalleyAdded')) $settings[] = NOTIFICATION_TYPE_GALLEY_ADDED; + if(!Request::getUserVar('notificationGalleyModified')) $settings[] = NOTIFICATION_TYPE_GALLEY_MODIFIED; + if(!Request::getUserVar('notificationSubmissionComment')) $settings[] = NOTIFICATION_TYPE_SUBMISSION_COMMENT; + if(!Request::getUserVar('notificationLayoutComment')) $settings[] = NOTIFICATION_TYPE_LAYOUT_COMMENT; + if(!Request::getUserVar('notificationCopyeditComment')) $settings[] = NOTIFICATION_TYPE_COPYEDIT_COMMENT; + if(!Request::getUserVar('notificationProofreadComment')) $settings[] = NOTIFICATION_TYPE_PROOFREAD_COMMENT; + if(!Request::getUserVar('notificationReviewerComment')) $settings[] = NOTIFICATION_TYPE_REVIEWER_COMMENT; + if(!Request::getUserVar('notificationReviewerFormComment')) $settings[] = NOTIFICATION_TYPE_REVIEWER_FORM_COMMENT; + if(!Request::getUserVar('notificationEditorDecisionComment')) $settings[] = NOTIFICATION_TYPE_EDITOR_DECISION_COMMENT; + if(!Request::getUserVar('notificationPublishedIssue')) $settings[] = NOTIFICATION_TYPE_PUBLISHED_ISSUE; + if(!Request::getUserVar('notificationUserComment')) $settings[] = NOTIFICATION_TYPE_USER_COMMENT; + + // Email settings + $emailSettings = array(); + if(Request::getUserVar('emailNotificationArticleSubmitted')) $emailSettings[] = NOTIFICATION_TYPE_ARTICLE_SUBMITTED; + if(Request::getUserVar('emailNotificationMetadataModified')) $emailSettings[] = NOTIFICATION_TYPE_METADATA_MODIFIED; + if(Request::getUserVar('emailNotificationSuppFileAdded')) $emailSettings[] = NOTIFICATION_TYPE_SUPP_FILE_ADDED; + if(Request::getUserVar('emailNotificationSuppFileModified')) $emailSettings[] = NOTIFICATION_TYPE_SUPP_FILE_MODIFIED; + if(Request::getUserVar('emailNotificationGalleyAdded')) $emailSettings[] = NOTIFICATION_TYPE_GALLEY_ADDED; + if(Request::getUserVar('emailNotificationGalleyModified')) $emailSettings[] = NOTIFICATION_TYPE_GALLEY_MODIFIED; + if(Request::getUserVar('emailNotificationSubmissionComment')) $emailSettings[] = NOTIFICATION_TYPE_SUBMISSION_COMMENT; + if(Request::getUserVar('emailNotificationLayoutComment')) $emailSettings[] = NOTIFICATION_TYPE_LAYOUT_COMMENT; + if(Request::getUserVar('emailNotificationCopyeditComment')) $emailSettings[] = NOTIFICATION_TYPE_COPYEDIT_COMMENT; + if(Request::getUserVar('emailNotificationProofreadComment')) $emailSettings[] = NOTIFICATION_TYPE_PROOFREAD_COMMENT; + if(Request::getUserVar('emailNotificationReviewerComment')) $emailSettings[] = NOTIFICATION_TYPE_REVIEWER_COMMENT; + if(Request::getUserVar('emailNotificationReviewerFormComment')) $emailSettings[] = NOTIFICATION_TYPE_REVIEWER_FORM_COMMENT; + if(Request::getUserVar('emailNotificationEditorDecisionComment')) $emailSettings[] = NOTIFICATION_TYPE_EDITOR_DECISION_COMMENT; + if(Request::getUserVar('emailNotificationPublishedIssue')) $emailSettings[] = NOTIFICATION_TYPE_PUBLISHED_ISSUE; + if(Request::getUserVar('emailNotificationUserComment')) $emailSettings[] = NOTIFICATION_TYPE_USER_COMMENT; + + $notificationSettingsDao->updateNotificationSettings($settings, $userId); + $notificationSettingsDao->updateNotificationEmailSettings($emailSettings, $userId); + Request::redirect(null, 'notification'); + } else Request::redirect(null, 'notification'); + } + + /** + * Fetch the existing or create a new URL for the user's RSS feed + */ + function getNotificationFeedUrl($args) { + $user = Request::getUser(); + if(isset($user)) { + $userId = $user->getUserId(); + $notificationSettingsDao = &DAORegistry::getDAO('NotificationSettingsDAO'); + $feedType = $args[0]; + + $token = $notificationSettingsDao->getRSSTokenByUserId($userId); + + if ($token) { + Request::redirect(null, 'notification', 'notificationFeed', array($feedType, $token)); + } else { + $token = $notificationSettingsDao->insertNewRSSToken($userId); + Request::redirect(null, 'notification', 'notificationFeed', $feedType, $token); + } + } else Request::redirect(null, 'notification'); + } + + /** + * Fetch the actual RSS feed + */ + function notificationFeed($args) { + if(isset($args[0]) && isset($args[1])) { + $type = $args[0]; + $token = $args[1]; + } else return false; + + $application = PKPApplication::getApplication(); + $appName = $application->getNameKey(); + + $site =& Request::getSite(); + $siteTitle = $site->getSiteTitle(); + + $notificationDao = &DAORegistry::getDAO('NotificationDAO'); + $notificationSettingsDao = &DAORegistry::getDAO('NotificationSettingsDAO'); + + $userId = $notificationSettingsDao->getUserIdByRSSToken($token); + $notifications = $notificationDao->getNotificationsByUserId($userId); + + // Make sure the feed type is specified and valid + $typeMap = array( + 'rss' => 'rss.tpl', + 'rss2' => 'rss2.tpl', + 'atom' => 'atom.tpl' + ); + $mimeTypeMap = array( + 'rss' => 'application/rdf+xml', + 'rss2' => 'application/rss+xml', + 'atom' => 'application/atom+xml' + ); + if (!isset($typeMap[$type])) return false; + + $versionDao =& DAORegistry::getDAO('VersionDAO'); + $version = $versionDao->getCurrentVersion(); + + $templateMgr = &TemplateManager::getManager(); + $templateMgr->assign('version', $version->getVersionString()); + $templateMgr->assign('selfUrl', Request::getCompleteUrl()); + $templateMgr->assign('locale', Locale::getPrimaryLocale()); + $templateMgr->assign('appName', $appName); + $templateMgr->assign('siteTitle', $siteTitle); + $templateMgr->assign_by_ref('notifications', $notifications->toArray()); + + $templateMgr->display(Core::getBaseDir() . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . + 'pkp' . DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR . 'notification' . DIRECTORY_SEPARATOR . $typeMap[$type], $mimeTypeMap[$type]); + + return true; + } + + + /** + * Display the public notification email subscription form + */ + function subscribeMailList() { + $templateMgr = &TemplateManager::getManager(); + $templateMgr->assign('new', true); + + $user = Request::getUser(); + // FIXME: Need to abstract subscription enabled check + // import('payment.PaymentManager'); + // $subscriptionEnabled = PaymentManager::isConfigured(); + + if(!isset($user)) { + // $templateMgr->assign('subscriptionEnabled', $subscriptionEnabled); + + if($userEmail = Request::getUserVar('email')) { + $notificationSettingsDao = &DAORegistry::getDAO('NotificationSettingsDAO'); + if($password = $notificationSettingsDao->subscribeGuest($userEmail)) { + NotificationHandler::sendMailingListEmail($userEmail, $password, 'NOTIFICATION_MAILLIST_WELCOME'); + $templateMgr->assign('success', "notification.subscribeSuccess"); + $templateMgr->display('notification/maillist.tpl'); + } else { + $templateMgr->assign('error', "notification.subscribeError"); + $templateMgr->display('notification/maillist.tpl'); + + } + } else { + $templateMgr->display('notification/maillist.tpl'); + } + } else Request::redirect(null, 'notification'); + } + + /** + * Display the public notification email subscription form + */ + function unsubscribeMailList() { + $templateMgr = &TemplateManager::getManager(); + $templateMgr->assign('remove', true); + + $user = Request::getUser(); + if(!isset($user)) { + $userEmail = Request::getUserVar('email'); + $userPassword = Request::getUserVar('password'); + + if($userEmail != '' && $userPassword != '') { + $notificationSettingsDao = &DAORegistry::getDAO('NotificationSettingsDAO'); + if($notificationSettingsDao->unsubscribeGuest($userEmail, $userPassword)) { + $templateMgr->assign('success', "notification.unsubscribeSuccess"); + $templateMgr->display('notification/maillist.tpl'); + } else { + $templateMgr->assign('error', "notification.unsubscribeError"); + $templateMgr->display('notification/maillist.tpl'); + } + } else if($userEmail != '' && $userPassword == '') { + $notificationSettingsDao = &DAORegistry::getDAO('NotificationSettingsDAO'); + if($newPassword = $notificationSettingsDao->resetPassword($userEmail)) { + NotificationHandler::sendMailingListEmail($userEmail, $userPassword, 'NOTIFICATION_MAILLIST_PASSWORD'); + $templateMgr->assign('success', "notification.reminderSent"); + $templateMgr->display('notification/maillist.tpl'); + } else { + $templateMgr->assign('error', "notification.reminderError"); + $templateMgr->display('notification/maillist.tpl'); + } + } else { + $templateMgr->assign('remove', true); + $templateMgr->display('notification/maillist.tpl'); + } + } else Request::redirect(null, 'notification'); + } + + /** + * Send an email to a mailing list user regarding signup or a lost password + */ + function sendMailingListEmail($email, $password, $template) { + import('mail.MailTemplate'); + $journal = Request::getJournal(); + $site = Request::getSite(); + + $mail = new MailTemplate($template); + $mail->setFrom($site->getSiteContactEmail(), $site->getSiteContactName()); + $mail->assignParams(array( + 'password' => $password, + 'siteTitle' => $journal->getJournalTitle(), + 'unsubscribeLink' => Request::url(null, 'notification', 'unsubscribeMailList') + )); + $mail->addRecipient($email); + $mail->send(); + } +} + +?> Index: pages/notification/index.php =================================================================== RCS file: pages/notification/index.php diff -N pages/notification/index.php --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ pages/notification/index.php 21 Jan 2009 18:27:44 -0000 @@ -0,0 +1,23 @@ + Index: templates/images/atom10_logo.png =================================================================== RCS file: templates/images/atom10_logo.png diff -N templates/images/atom10_logo.png Binary files /dev/null and atom10_logo.png differ Index: templates/images/rss10_logo.png =================================================================== RCS file: templates/images/rss10_logo.png diff -N templates/images/rss10_logo.png Binary files /dev/null and rss10_logo.png differ Index: templates/images/rss20_logo.png =================================================================== RCS file: templates/images/rss20_logo.png diff -N templates/images/rss20_logo.png Binary files /dev/null and rss20_logo.png differ Index: templates/notification/atom.tpl =================================================================== RCS file: templates/notification/atom.tpl diff -N templates/notification/atom.tpl --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ templates/notification/atom.tpl 21 Jan 2009 18:27:44 -0000 @@ -0,0 +1,43 @@ +{** + * atom.tpl + * + * Copyright (c) 2003-2008 John Willinsky + * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING. + * + * Atom feed template + * + * $Id: atom.tpl,v 1.3 2008/06/11 21:52:26 asmecher Exp $ + *} + + + {$selfUrl} + {$siteTitle} {translate key="notification.notifications"} + + + + {translate key=$appName} + +{foreach from=$notifications item=notification} + + $notification->getNotificationId() + {translate key="notification.notification"} : {$notification->getDateCreated()|date_format:"%a, %d %b %Y %T %z"} + {if $notification->getLocation() != null} + + {else} + + {/if} + + + {if $notification->getIsLocalized()} + {translate key=$notification->getContents() param=$notification->getParam()} + {else} + {$notification->getContents()} + {/if} + + + {$notification->getDateCreated()|date_format:"%Y-%m-%dT%T%z"|regex_replace:"/00$/":":00"} + +{/foreach} + + + Index: templates/notification/index.tpl =================================================================== RCS file: templates/notification/index.tpl diff -N templates/notification/index.tpl --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ templates/notification/index.tpl 21 Jan 2009 18:27:44 -0000 @@ -0,0 +1,83 @@ +{** + * index.tpl + * + * Copyright (c) 2000-2008 John Willinsky + * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING. + * + * Display list of notifications. + * + *} +{strip} +{assign var="pageTitle" value="notification.notifications"} +{include file="common/header.tpl"} +{/strip} + + + + + + +
{if $isUserLoggedIn} +

{translate key="notification.notificationsDescription" unreadCount=$unread readCount=$read settingsUrl=$url}

+ {else} +

{translate key="notification.notificationsPublicDescription" emailUrl=$emailUrl}

+ {/if} +
    +
  • RSS 1.0
  • +
  • RSS 2.0
  • +
  • Atom 1.0
  • +
+ +
+ +
+{iterate from=notifications item=notification} + + + + + {if $notification->getLocation() != null} + + {else} + + {/if} + + + + + + +
» + {$notification->getDateCreated()} + getNotificationId()}">{translate key="common.delete"}
  + {if $notification->getIsUnread()} + {if $notification->getIsLocalized()}

{translate key=$notification->getContents() param=$notification->getParam()}

+ {else}

{$notification->getContents()}{/if} + {else} + {if $notification->getIsLocalized()}

{translate key=$notification->getContents() param=$notification->getParam()}

+ {else}

{$notification->getContents()}

{/if} + {/if} +
+
+{/iterate} +{if $notifications->wasEmpty()} + + + + + + + +
{translate key="notification.noneExist"}
 
+{else} + + + + + +
{page_info iterator=$notifications}{page_links anchor="notifications" name="notifications" iterator=$notifications}
+{/if} + +
+ +{include file="common/footer.tpl"} Index: templates/notification/maillist.tpl =================================================================== RCS file: templates/notification/maillist.tpl diff -N templates/notification/maillist.tpl --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ templates/notification/maillist.tpl 21 Jan 2009 18:27:44 -0000 @@ -0,0 +1,85 @@ +{** + * index.tpl + * + * Copyright (c) 2000-2008 John Willinsky + * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING. + * + * Displays the notification settings page and unchecks + * + *} +{strip} +{assign var="pageTitle" value="notification.mailList"} +{include file="common/header.tpl"} +{/strip} + +{if $new} +

{translate key="notification.mailListDescription"}

+
+ + {if $error} +

{translate key="$error"}

+ {/if} + + {if $success} +

{translate key="$success"}

+ {/if} + +
+ + + + + + + + + + +
{translate key="email.email"}
 

+
+ +