/** * Send a Notification to a user by email * * @param $user User to notify. * @param $event EchoEvent to notify about. * @return bool */ public static function notifyWithEmail($user, $event) { // No valid email address or email notification if (!$user->isEmailConfirmed() || $user->getOption('echo-email-frequency') < 0) { return false; } // Final check on whether to send email for this user & event if (!wfRunHooks('EchoAbortEmailNotification', array($user, $event))) { return false; } // See if the user wants to receive emails for this category or the user is eligible to receive this email if (in_array($event->getType(), EchoNotificationController::getUserEnabledEvents($user, 'email'))) { global $wgEchoEnableEmailBatch, $wgEchoNotifications, $wgNotificationSender, $wgNotificationSenderName, $wgNotificationReplyName, $wgEchoBundleEmailInterval; $priority = EchoNotificationController::getNotificationPriority($event->getType()); $bundleString = $bundleHash = ''; // We should have bundling for email digest as long as either web or email bundling is on, for example, talk page // email bundling is off, but if a user decides to receive email digest, we should bundle those messages if (!empty($wgEchoNotifications[$event->getType()]['bundle']['web']) || !empty($wgEchoNotifications[$event->getType()]['bundle']['email'])) { wfRunHooks('EchoGetBundleRules', array($event, &$bundleString)); } if ($bundleString) { $bundleHash = md5($bundleString); } MWEchoEventLogging::logSchemaEcho($user, $event, 'email'); // email digest notification ( weekly or daily ) if ($wgEchoEnableEmailBatch && $user->getOption('echo-email-frequency') > 0) { // always create a unique event hash for those events don't support bundling // this is mainly for group by if (!$bundleHash) { $bundleHash = md5($event->getType() . '-' . $event->getId()); } MWEchoEmailBatch::addToQueue($user->getId(), $event->getId(), $priority, $bundleHash); return true; } $addedToQueue = false; // only send bundle email if email bundling is on if ($wgEchoBundleEmailInterval && $bundleHash && !empty($wgEchoNotifications[$event->getType()]['bundle']['email'])) { $bundler = MWEchoEmailBundler::newFromUserHash($user, $bundleHash); if ($bundler) { $addedToQueue = $bundler->addToEmailBatch($event->getId(), $priority); } } // send single notification if the email wasn't added to queue for bundling if (!$addedToQueue) { // instant email notification $toAddress = new MailAddress($user); $fromAddress = new MailAddress($wgNotificationSender, $wgNotificationSenderName); $replyAddress = new MailAddress($wgNotificationSender, $wgNotificationReplyName); // Since we are sending a single email, should set the bundle hash to null // if it is set with a value from somewhere else $event->setBundleHash(null); $email = EchoNotificationController::formatNotification($event, $user, 'email', 'email'); $subject = $email['subject']; $body = $email['body']; UserMailer::send($toAddress, $fromAddress, $subject, $body, $replyAddress); MWEchoEventLogging::logSchemaEchoMail($user, 'single'); } } return true; }
protected function mockEvent($type) { $methods = get_class_methods('EchoEvent'); $methods = array_diff($methods, array('userCan', 'getLinkMessage', 'getLinkDestination')); $event = $this->getMockBuilder('EchoEvent')->disableOriginalConstructor()->setMethods($methods)->getMock(); $event->expects($this->any())->method('getType')->will($this->returnValue($type)); $event->expects($this->any())->method('getCategory')->will($this->returnValue(EchoNotificationController::getNotificationCategory($type))); return $event; }
function run() { if (!empty($this->params['mainDbMasterPos'])) { wfGetLB()->waitFor($this->params['mainDbMasterPos']); } if (!empty($this->params['echoDbMasterPos'])) { global $wgEchoCluster; wfGetLBFactory()->getExternalLB($wgEchoCluster)->waitFor($this->params['echoDbMasterPos']); } EchoNotificationController::notify($this->event, false); return true; }
public function execute() { // To avoid API warning, register the parameter used to bust browser cache $this->getMain()->getVal('_'); $user = $this->getUser(); //XXCHANGEDXX - allow anons [sc|rs] // if ( $user->isAnon() ) { // $this->dieUsage( 'Login is required', 'login-required' ); // } $notifUser = MWEchoNotifUser::newFromUser($user); $params = $this->extractRequestParams(); // There is no need to trigger markRead if all notifications are read if ($notifUser->getNotificationCount() > 0) { if (count($params['list'])) { // Make sure there is a limit to the update $notifUser->markRead(array_slice($params['list'], 0, ApiBase::LIMIT_SML2)); } elseif ($params['all']) { $notifUser->markAllRead(); } } $rawCount = $notifUser->getNotificationCount(); $result = array('result' => 'success', 'rawcount' => $rawCount, 'count' => EchoNotificationController::formatNotificationCount($rawCount)); $this->getResult()->addValue('query', $this->getModuleName(), $result); }
/** * Prepares the user button. * @param QuickTemplate $tpl */ protected function prepareUserButton(QuickTemplate $tpl) { // Set user button to empty string by default $tpl->set('secondaryButton', ''); $notificationsTitle = ''; $countLabel = ''; $isZero = true; $user = $this->getUser(); $newtalks = $this->getNewtalks(); $currentTitle = $this->getTitle(); // If Echo is available, the user is logged in, and they are not already on the // notifications archive, show the notifications icon in the header. if ($this->useEcho() && $user->isLoggedIn()) { $notificationsTitle = SpecialPage::getTitleFor('Notifications'); $notificationsMsg = wfMessage('mobile-frontend-user-button-tooltip'); if ($currentTitle->getPrefixedText() !== $notificationsTitle->getPrefixedText()) { $count = MWEchoNotifUser::newFromUser($user)->getNotificationCount(); $isZero = $count === 0; $countLabel = EchoNotificationController::formatNotificationCount($count); } } elseif (!empty($newtalks)) { $notificationsTitle = SpecialPage::getTitleFor('Mytalk'); $notificationsMsg = wfMessage('mobile-frontend-user-newmessages')->text(); } if ($notificationsTitle) { $spanClass = $isZero ? 'zero notification-count' : 'notification-count'; $url = $notificationsTitle->getLocalURL(array('returnto' => $currentTitle->getPrefixedText())); $tpl->set('secondaryButton', $this->createSecondaryButton($notificationsMsg, $url, $countLabel, $spanClass)); } }
/** * Implements blacklist per active wiki expected to be initialized * from InitializeSettings.php * * @param $event EchoEvent The event to test for exclusion via global blacklist * @return boolean True when the event agent is in the global blacklist */ protected static function isBlacklisted(EchoEvent $event) { if (!$event->getAgent()) { return false; } if (self::$blacklist === null) { global $wgEchoAgentBlacklist, $wgEchoOnWikiBlacklist, $wgMemc; self::$blacklist = new EchoContainmentSet(); self::$blacklist->addArray($wgEchoAgentBlacklist); if ($wgEchoOnWikiBlacklist !== null) { self::$blacklist->addOnWiki(NS_MEDIAWIKI, $wgEchoOnWikiBlacklist, $wgMemc, wfMemcKey("echo_on_wiki_blacklist")); } } return self::$blacklist->contains($event->getAgent()->getName()); }
protected function format(EchoEvent $event, $format, $user = false, $type = 'web') { global $wgEchoNotifications; if ($user === false) { $user = User::newFromName('Notification-formatter-test'); } // Notification users can not be anonymous, use a fake user id return EchoNotificationController::formatNotification($event, $user, $format, $type); }
/** * Get a list of notifications based on the passed parameters * * @param $user User the user to get notifications for * @param $format string/bool false to not format any notifications, string to a specific output format * @param $limit int The maximum number of notifications to return * @param $continue string Used for offset * @return array */ public static function getNotifications($user, $format = false, $limit = 20, $continue = null) { global $wgEchoBackend; $output = array(); // TODO: Make 'web' based on a new API param? $res = $wgEchoBackend->loadNotifications($user, $limit, $continue, 'web'); foreach ($res as $row) { $event = EchoEvent::newFromRow($row); if ($row->notification_bundle_base && $row->notification_bundle_display_hash) { $event->setBundleHash($row->notification_bundle_display_hash); } $timestampMw = self::getUserLocalTime($user, $row->notification_timestamp); // Start creating date section header $now = wfTimestamp(); $dateFormat = substr($timestampMw, 0, 8); if (substr(self::getUserLocalTime($user, $now), 0, 8) === $dateFormat) { // 'Today' $date = wfMessage('echo-date-today')->escaped(); } elseif (substr(self::getUserLocalTime($user, $now - 86400), 0, 8) === $dateFormat) { // 'Yesterday' $date = wfMessage('echo-date-yesterday')->escaped(); } else { // 'May 10' or '10 May' (depending on user's date format preference) $lang = RequestContext::getMain()->getLanguage(); $dateFormat = $lang->getDateFormatString('pretty', $user->getDatePreference() ?: 'default'); $date = $lang->sprintfDate($dateFormat, $timestampMw); } // End creating date section header $thisEvent = array('id' => $event->getId(), 'type' => $event->getType(), 'category' => $event->getCategory(), 'timestamp' => array('utcunix' => wfTimestamp(TS_UNIX, $row->notification_timestamp), 'unix' => self::getUserLocalTime($user, $row->notification_timestamp, TS_UNIX), 'mw' => $timestampMw, 'date' => $date)); if ($event->getVariant()) { $thisEvent['variant'] = $event->getVariant(); } if ($event->getTitle()) { $thisEvent['title'] = array('full' => $event->getTitle()->getPrefixedText(), 'namespace' => $event->getTitle()->getNSText(), 'namespace-key' => $event->getTitle()->getNamespace(), 'text' => $event->getTitle()->getText()); } if ($event->getAgent()) { if ($event->userCan(Revision::DELETED_USER, $user)) { $thisEvent['agent'] = array('id' => $event->getAgent()->getId(), 'name' => $event->getAgent()->getName()); } else { $thisEvent['agent'] = array('userhidden' => ''); } } //if ( $row->notification_read_timestamp ) { $thisEvent['read'] = $row->notification_read_timestamp; //} if ($format) { $thisEvent['*'] = EchoNotificationController::formatNotification($event, $user, $format); } $output[$event->getID()] = $thisEvent; } return $output; }
/** * @param $user User object to check notifications for * @param $dbSource string use master or slave storage to pull count * @return int */ public function getNotificationCount($user, $dbSource) { // double check if (!in_array($dbSource, array(DB_SLAVE, DB_MASTER))) { $dbSource = DB_SLAVE; } $eventTypesToLoad = EchoNotificationController::getUserEnabledEvents($user, 'web'); if (!$eventTypesToLoad) { return 0; } global $wgEchoMaxNotificationCount; //XXCHANGEDXX - allow anons [sc|rs] $db = MWEchoDbFactory::getDB($dbSource); $res = $db->select(array('echo_notification', 'echo_event'), array('notification_event'), array('notification_user' => $user->getId(), 'notification_bundle_base' => 1, 'notification_read_timestamp' => null, 'event_type' => $eventTypesToLoad) + ($user->isAnon() ? array('notification_anon_ip' => $user->getName()) : array()), __METHOD__, array('LIMIT' => $wgEchoMaxNotificationCount + 1), array('echo_event' => array('LEFT JOIN', 'notification_event=event_id'))); return $db->numRows($res); }
/** * Retrieves formatted number of unread notifications that a user has. * @param $cached bool Set to false to bypass the cache. * @param $dbSource int use master or slave database to pull count * @return String: Number of unread notifications. */ public function getFormattedNotificationCount($cached = true, $dbSource = DB_SLAVE) { return EchoNotificationController::formatNotificationCount($this->getNotificationCount($cached, $dbSource)); }
/** * Handler for AbortWatchlistEmailNotification hook. * @see http://www.mediawiki.org/wiki/Manual:Hooks/AbortWatchlistEmailNotification * @param $targetUser User * @param $title Title * @param $emailNotification EmailNotification The email notification object that sends non-echo notifications * @return bool */ static function onSendWatchlistEmailNotification($targetUser, $title, $emailNotification) { // If a user is watching his/her own talk page, do not send talk page watchlist // email notification if the user is receiving Echo talk page notification if ($title->isTalkPage() && $targetUser->getTalkPage()->equals($title)) { if (!self::isEchoDisabled($targetUser) && in_array('edit-user-talk', EchoNotificationController::getUserEnabledEvents($targetUser, 'email'))) { // Do not send watchlist email notification, the user will receive an Echo notification return false; } } // Proceed to send watchlist email notification return true; }
/** * Generate the content for bundle email * @return string */ protected function generateEmailContent() { if (!$this->baseEvent) { return ''; } $this->baseEvent->setBundleHash($this->bundleHash); return EchoNotificationController::formatNotification($this->baseEvent, $this->mUser, 'email', 'email'); }
/** * Get the category of the event type * @return string */ public function getCategory() { return EchoNotificationController::getNotificationCategory($this->type); }
/** * Add individual event template to the big email content */ protected function appendContent($event, $hash) { // get the category for this event $category = $event->getCategory(); $event->setBundleHash($hash); $email = EchoNotificationController::formatNotification($event, $this->mUser, 'email', 'emaildigest'); if (!isset($this->content[$category])) { $this->content[$category] = array(); } $this->content[$category][] = $email; }