function execute($par)
 {
     $context = $this->getContext();
     $request = $context->getRequest();
     $out = $context->getOutput();
     if ($request->getVal('ac_created_dialog', 0)) {
         $out->setArticleBodyOnly(true);
         $out->addHtml($this->getCreatedDialogHtml());
         return;
     }
     $out->addCSSCode('acc');
     //$out->addJSCode('ac');
     $out->addJSCode('jqs');
     $out->addJSCode('tmc');
     $out->addModules('ext.guidedTour');
     // Used for showing validation responses
     $out->addModules('ext.wikihow.articlecreator');
     // Module to enable mw messages in javascript
     $t = Title::newFromText($request->getVal('t'));
     $out->setHTMLTitle(wfMessage('ac-html-title', $t->getText()));
     if ($request->wasPosted()) {
         $out->setArticleBodyOnly(true);
         $response = array();
         $token = $context->getUser()->getEditToken();
         if ($request->getVal('ac_token') != $token) {
             $response['error'] = wfMessage('ac-invalid-edit-token');
         } else {
             if ($this->onlyEditNewArticles && $t->exists()) {
                 $response['error'] = wfMessage('ac-title-exists', $t->getEditUrl());
             } else {
                 if (!$t->userCan('create', $context->getUser(), false)) {
                     $response['error'] = wfMessage('ac-cannot-create', $t->getEditUrl());
                 } else {
                     $a = new Article($t);
                     $a->doEdit($request->getVal('wikitext'), wfMessage('ac-edit-summary'));
                     // Add an author email notification
                     $aen = new AuthorEmailNotification();
                     $aen->addNotification($t->getText());
                     $response['success'] = wfMessage('ac-successful-publish');
                     $response['url'] = $t->getFullUrl();
                 }
             }
         }
         $out->addHtml(json_encode($response));
     } else {
         if ($this->onlyEditNewArticles && $t->exists()) {
             $out->redirect($t->getEditURL());
         } else {
             $this->outputStartupHtml();
         }
     }
 }
function attributeAnon($user)
{
    try {
        if (isset($_COOKIE["aen_anon_newarticleid"])) {
            $aid = $_COOKIE['aen_anon_newarticleid'];
            AuthorEmailNotification::reassignArticleAnon($aid);
            $user->incEditCount();
            if ($user->getEmail() != '') {
                AuthorEmailNotification::addUserWatch($aid, 1);
            }
        }
    } catch (Exception $e) {
    }
    return true;
}
    foreach ($res as $object) {
        $views += intval($object->pv_30day);
        $articles++;
    }
    if ($views < 50) {
        //echo "No email sent to " . $user->getName() . ". Not enough views ({$views})\n";
        continue;
    }
    $from_name = "Krystle <*****@*****.**>";
    $subject = wfMsg("viewership_subject");
    $cta = AuthorEmailNotification::getCTA('monthly_views', 'email');
    if ($articles == 1) {
        $article = "article";
    } else {
        $article = "articles";
    }
    $contribsPage = SpecialPage::getTitleFor('Contributions', $user->getName());
    $contribsLink = $contribsPage->getFullURL();
    $body = wfMsg("viewership_body", $user->getName(), number_format($articles), number_format($views), $cta, $article, $contribsLink);
    wfDebug($email . " " . $subject . " " . $body . "\n");
    $emailCount++;
    AuthorEmailNotification::notify($user, $from_name, $subject, $body, "", true);
    $userNames .= $user->getName() . " ";
    if ($emailCount > 500) {
        break;
    }
}
echo "\n\nEmail sent to:\t{$userNames}\n\n";
$endTime = microtime(true);
$timeDiff = $endTime - $startTime;
echo $emailCount . " viewership emails were sent, Finished in {$timeDiff} sec.\n";
 function processViewership()
 {
     $thresholds = array(25, 100, 500, 1000, 5000);
     $thresh2 = 10000;
     $dbr = wfGetDB(DB_SLAVE);
     $res = $dbr->select(array('email_notifications'), array('en_viewership_email', 'en_viewership', 'en_user', 'en_page'), array('en_watch' => 1), __METHOD__);
     while ($row = $dbr->fetchObject($res)) {
         $sendflag = 0;
         $viewership = 0;
         $milestone = 0;
         $title = Title::newFromID($row->en_page);
         $user = User::newFromID($row->en_user);
         if (isset($title)) {
             $viewership = $dbr->selectField('page', 'page_counter', array('page_id' => $title->getArticleID()), __METHOD__);
             $prev = $row->en_viewership;
             if ($viewership > $thresh2) {
                 $a = floor($prev / $thresh2);
                 $b = floor($viewership / $thresh2);
                 if ($b > $a) {
                     $milestone = $b * $thresh2;
                     $sendflag = 1;
                 }
             } else {
                 foreach ($thresholds as $level) {
                     if ($prev < $level && $level < $viewership) {
                         $milestone = $level;
                         $sendflag = 1;
                     }
                 }
             }
             if ($sendflag) {
                 echo "Processing: [TITLE] " . $title->getText() . "(" . $title->getArticleID() . ") [USER] " . $user->getName() . ", [VIEWS]" . $row->en_viewership . " - " . $viewership . " [MILESTONE] {$milestone} \n";
                 AuthorEmailNotification::notifyViewership($title, $user, $milestone, $viewership, $row->en_viewership_email);
             } else {
                 echo "Skipping: [TITLE] " . $title->getText() . "(" . $title->getArticleID() . ") [USER] " . $user->getName() . ", [VIEWS]" . $row->en_viewership . " - " . $viewership . " [MILESTONE] {$milestone} \n";
             }
         } else {
             echo "Article Removed: [PAGE] " . $row->en_page . " [USER] " . $row->en_user . "\n";
         }
     }
 }
 /**
  * Place the Rising-star-usertalk-msg on the user's talk page 
  * and emails the user
  */
 public function notifyUserOfRisingStar($title, $name)
 {
     global $wgUser, $wgLang;
     $user = $wgUser->getName();
     $real_name = User::whoIsReal($wgUser->getID());
     if ($real_name == "") {
         $real_name = $user;
     }
     $dateStr = $wgLang->timeanddate(wfTimestampNow());
     $wikitext = "";
     $article = "";
     $userObj = new User();
     $userObj->setName($name);
     $user_talk = $userObj->getTalkPage();
     $comment = '{{subst:Rising-star-usertalk-msg|[[' . $title->getText() . ']]}}' . "\n";
     $formattedComment = wfMsg('postcomment_formatted_comment', $dateStr, $user, $real_name, $comment);
     if ($user_talk->getArticleId() > 0) {
         $rev = Revision::newFromTitle($user_talk);
         $wikitext = $rev->getText();
     }
     $article = new Article($user_talk);
     $wikitext .= "\n\n{$formattedComment}\n\n";
     $article->doEdit($wikitext, wfMsg('nab-rs-usertalk-editsummary'));
     // Send author email notification
     AuthorEmailNotification::notifyRisingStar($title->getText(), $name, $real_name, $user);
 }
    AuthorEmailNotification::notifyFeatured($t);
}
// PROCESS VIEWERSHIP EMAILS
$ts = wfTimestamp(TS_MW, time() - 86400);
$sql = "SELECT page_namespace, page_title, page_counter, en_viewership, en_user\n\t\tFROM email_notifications \n\t\tLEFT JOIN page ON en_page=page_id\n\t\tWHERE en_viewership_email IS NULL\n\t\t\tOR en_viewership_email < '{$ts}'";
$res = $dbr->query($sql, __FILE__);
$milestones = array(10000, 5000, 1000, 500, 100);
while ($row = $dbr->fetchObject($res)) {
    $send = false;
    if (!$row->page_title) {
        continue;
    }
    if ($row->page_counter >= 10000 && $row->page_counter - $row->en_viewership >= 10000) {
        $milestone = floor($row->page_counter / 10000) * 10000;
        $send = true;
    } else {
        foreach ($milestones as $m) {
            if ($row->page_counter >= $m && $row->en_viewership < $m) {
                $milestone = $m;
                $send = true;
                break;
            }
        }
    }
    if ($send) {
        $title = Title::makeTitle($row->page_namespace, $row->page_title);
        $user = User::newFromID($row->en_user);
        $user->load();
        AuthorEmailNotification::notifyViewership($title, $user, $milestone, $milestone, null);
    }
}
<?php

require_once "commandLine.inc";
$t1 = time();
echo "Starting AuthorEmailNotifications - Featured Processing: " . date('m/d/Y H:i:s', time()) . "\n";
$debug = 0;
AuthorEmailNotification::processFeatured();
$t2 = time() - $t1;
echo "Took " . number_format($t2, 0, ".", ",") . " seconds...\n";
echo "Completed AuthorEmailNotifications - Featured Processing: " . date('m/d/Y H:i:s', time()) . "\n";
 function writeOutput($par)
 {
     global $wgUser, $wgOut, $wgLang, $wgTitle, $wgMemc, $wgDBname;
     global $wgRequest, $wgSitename, $wgLanguageCode;
     global $wgFeedClasses, $wgFilterCallback, $wgWhitelistEdit, $wgParser;
     wfLoadExtensionMessages('Postcomment');
     $wgOut->setRobotpolicy("noindex,nofollow");
     $fname = "wfSpecialPostcomment";
     //echo "topic: " . $wgRequest->getVal("topic_name") . "<BR>";
     //echo "title: " . $wgRequest->getVal("title") . "<BR>";
     //echo "comment: " . $wgRequest->getVal("comment_text") . "<BR>";
     //echo "new_topic id " . $wgRequest->getVal("new_topic") . "<BR>";
     $target = !empty($par) ? $par : $wgRequest->getVal("target");
     $t = Title::newFromDBKey($target);
     $update = true;
     if (!$t || !$t->userCanEdit()) {
         return;
     }
     if (!$wgUser->isAllowed('edit')) {
         return;
     }
     if ($t == null) {
         $wgOut->errorPage('postcomment', 'postcomment_invalidrequest');
         return;
     }
     $article = new Article($t);
     $user = $wgUser->getName();
     $real_name = User::whoIsReal($wgUser->getID());
     if ($real_name == "") {
         $real_name = $user;
     }
     $dateStr = $wgLang->timeanddate(wfTimestampNow());
     $comment = $wgRequest->getVal("comment_text");
     foreach ($wgRequest->getValues() as $key => $value) {
         if (strpos($key, "comment_text") === 0) {
             $comment = $value;
             break;
         }
     }
     $topic = $wgRequest->getVal("topic_name");
     //echo "$dateStr<br/>";
     // remove leading space, tends to be a problem with a lot of talk page comments as it breaks the
     // HTML on the page
     $comment = preg_replace('/\\n[ ]*/', "\n", trim($comment));
     // Check to see if the user is also getting a thumbs up. If so, append the thumbs message and give a thumbs up
     if ($wgRequest->getVal('thumb')) {
         $comment .= "\n\n" . wfMsg('qn_thumbs_up');
         $userName = explode(":", $wgRequest->getVal('target'));
         ThumbsUp::quickNoteThumb($wgRequest->getVal('revold'), $wgRequest->getVal('revnew'), $wgRequest->getVal('pageid'), $userName[1]);
     }
     $formattedComment = wfMsg('postcomment_formatted_comment', $dateStr, $user, $real_name, $comment);
     if ($wgRequest->getVal('fromajax') == 'true') {
         $wgOut->setArticleBodyOnly(true);
     }
     $text = "";
     $r = Revision::newFromTitle($t);
     if ($r) {
         $text = $r->getText();
     }
     $text .= "\n\n{$formattedComment}\n\n";
     $wgOut->setStatusCode(500);
     //echo "updating with text:<br/> $text";
     //exit;
     $tmp = "";
     if ($wgUser->isBlocked()) {
         $wgOut->blockedPage();
         return;
     }
     if (!$wgUser->getID() && $wgWhitelistEdit) {
         $this->userNotLoggedInPage();
         return;
     }
     if (wfReadOnly()) {
         $wgOut->readOnlyPage();
         return;
     }
     if ($target == "Spam-Blacklist") {
         $wgOut->readOnlyPage();
         return;
     }
     if ($wgUser->pingLimiter()) {
         $wgOut->rateLimited();
         return;
     }
     if ($wgFilterCallback && $wgFilterCallback($t, $text, $tmp)) {
         # Error messages or other handling should be performed by the filter function
         return;
     }
     $matches = array();
     $preg = "/http:\\/\\/[^] \n'\">]*/";
     $mod = str_ireplace('http://www.wikihow.com', '', $comment);
     preg_match_all($preg, $mod, $matches);
     if (sizeof($matches[0]) > 2) {
         $wgOut->errorPage("postcomment", "postcomment_urls_limit");
         return;
     }
     if (trim(strip_tags($comment)) == "") {
         $wgOut->errorpage("postcomment", "postcomment_nopostingtoadd");
         return;
     }
     if (!$t->userCanEdit()) {
         $wgOut->errorpage("postcomment", "postcomment_discussionprotected");
         return;
     }
     $watch = false;
     if ($wgUser->getID() > 0) {
         $watch = $wgUser->isWatched($t);
     }
     $fc = new FancyCaptcha();
     $pass_captcha = $fc->passCaptcha();
     if (!$pass_captcha && $wgUser->getID() == 0) {
         $wgOut->addHTML("Sorry, please enter the correct word. Click <a onclick='window.location.reload(true);'>here</a> to get a new one.<br/><br/>");
         return;
     }
     $article->doEdit($text, "");
     if ($wgRequest->getVal('jsonresponse') == 'true') {
         $article->loadLastEdit(true);
         $this->revId = $article->getRevIdFetched();
     }
     //XX Vu added to notify users of usertalk updates
     if ($t->getNamespace() == NS_USER_TALK) {
         AuthorEmailNotification::notifyUserTalk($t->getArticleID(), $wgUser->getID(), $comment);
     }
     $wgOut->setStatusCode(200);
     if ($wgRequest->getVal('fromajax') == 'true') {
         $wgOut->redirect('');
         $wgTitle = $t;
         $formattedComment = $wgParser->preSaveTransform($formattedComment, $t, $wgUser, new ParserOptions());
         $wgOut->addHTML($wgOut->parse("\n" . $formattedComment));
         return;
     }
 }
Exemple #9
0
 function notifyUserOfThumbsUp($t, $recipientId, $diffUrl, $revisionId, $recipientText)
 {
     global $wgUser, $wgLang;
     $fname = 'ThumbsUp::notifyUserOfThumbsUp';
     wfProfileIn($fname);
     $user = $wgUser->getName();
     $real_name = User::whoIsReal($wgUser->getID());
     if ($real_name == "") {
         $real_name = $user;
     }
     $dateStr = $wgLang->timeanddate(wfTimestampNow());
     $text = "";
     $article = "";
     if ($recipientId > 0) {
         $u = User::newFromId($recipientId);
         $user_talk = $u->getTalkPage();
     } else {
         $u = null;
         $user_talk = Title::makeTitle(NS_USER_TALK, $recipientText);
     }
     $comment = wfMsg('thumbs_talk_msg', $diffUrl, $t->getText());
     $formattedComment = wfMsg('postcomment_formatted_comment', $dateStr, $user, $real_name, $comment);
     if ($user_talk->getArticleId() > 0) {
         $r = Revision::newFromTitle($user_talk);
         $text = $r->getText();
     }
     $article = new Article($user_talk);
     $text .= "\n\n{$formattedComment}\n\n";
     $article->doEdit($text, wfMsg('thumbs-up-usertalk-editsummary'));
     // Auto patrol talk page messages to not anger the rc patrollers with thumbs up chatter
     self::autoPatrolTalkMessage($user_talk->getArticleId());
     if ($recipientId > 0) {
         // Send thumbs email notification (only if option set)
         //$thumbsEmailOption = $u->getOption('thumbsemailnotifications');
         // jsmall pref Ignore preference for right now and always send an email. Uncomment above when ready to use preference
         $thumbsEmailOption = 0;
         // If the option hasn't been initialized yet, set it to 1 by default
         if ($thumbsEmailOption === '') {
             $u->setOption('thumbsemailnotifications', 0);
             $u->saveSettings();
             $thumbsEmailOption = 0;
         }
         if ($thumbsEmailOption === 0) {
             $track_title = '?utm_source=thumbsup_message&utm_medium=email&utm_term=title_page&utm_campaign=talk_page_message';
             $track_diff = '&utm_source=thumbsup_message&utm_medium=email&utm_term=diff_page&utm_campaign=talk_page_message';
             $diffHref = "<a href='{$diffUrl}{$track_diff}'>edit</a>";
             $titleHref = "<a href='" . $t->getFullURL() . "{$track_title}'>" . $t->getText() . "</a>";
             $emailComment = wfMsg('thumbs_talk_email_msg', $diffHref, $titleHref);
             AuthorEmailNotification::notifyUserTalk($user_talk->getArticleId(), $wgUser->getID(), $emailComment, 'thumbsup');
         }
     }
     wfProfileOut($fname);
 }
<?php

require_once "commandLine.inc";
$t1 = time();
echo "Starting AuthorEmailNotifications - Viewership Processing: " . date('m/d/Y H:i:s', time()) . "\n";
$debug = 0;
AuthorEmailNotification::processViewership();
$t2 = time() - $t1;
echo "Took " . number_format($t2, 0, ".", ",") . " seconds...\n";
echo "Completed AuthorEmailNotifications - Viewership Processing: " . date('m/d/Y H:i:s', time()) . "\n";
 function writeOutput($par)
 {
     global $wgLang, $wgMemc, $wgDBname, $wgUser;
     global $wgSitename, $wgLanguageCode;
     global $wgFeedClasses, $wgFilterCallback, $wgWhitelistEdit, $wgParser;
     $this->getOutput()->setRobotpolicy("noindex,nofollow");
     $target = !empty($par) ? $par : $this->getRequest()->getVal("target");
     $t = Title::newFromDBKey($target);
     $update = true;
     if (!$t || !$t->userCan('edit')) {
         return;
     }
     if (!$this->getUser()->isAllowed('edit')) {
         return;
     }
     $article = new Article($t);
     $user = $this->getUser()->getName();
     $real_name = User::whoIsReal($this->getUser()->getID());
     if ($real_name == "") {
         $real_name = $user;
     }
     $dateStr = $wgLang->timeanddate(wfTimestampNow());
     $comment = $this->getRequest()->getVal("comment_text");
     foreach ($this->getRequest()->getValues() as $key => $value) {
         if (strpos($key, "comment_text") === 0) {
             $comment = $value;
             break;
         }
     }
     $topic = $this->getRequest()->getVal("topic_name");
     //echo "$dateStr<br/>";
     // remove leading space, tends to be a problem with a lot of talk page comments as it breaks the
     // HTML on the page
     $comment = preg_replace('/\\n[ ]*/', "\n", trim($comment));
     // Check to see if the user is also getting a thumbs up. If so, append the thumbs message and give a thumbs up
     if ($this->getRequest()->getVal('thumb')) {
         $comment .= "\n\n" . wfMsg('qn_thumbs_up');
         $userName = explode(":", $this->getRequest()->getVal('target'));
         ThumbsUp::quickNoteThumb($this->getRequest()->getVal('revold'), $this->getRequest()->getVal('revnew'), $this->getRequest()->getVal('pageid'), $userName[1]);
     }
     $formattedComment = wfMsg('postcomment_formatted_comment', $dateStr, $user, $real_name, $comment);
     if ($this->getRequest()->getVal('fromajax') == 'true') {
         $this->getOutput()->setArticleBodyOnly(true);
     }
     $text = "";
     $r = Revision::newFromTitle($t);
     if ($r) {
         $text = $r->getText();
     }
     $text .= "\n\n{$formattedComment}\n\n";
     $this->getOutput()->setStatusCode(409);
     //echo "updating with text:<br/> $text";
     //exit;
     $tmp = "";
     if ($this->getUser()->isBlocked()) {
         $this->getOutput()->blockedPage();
         return;
     }
     if (!$this->getUser()->getID() && $wgWhitelistEdit) {
         $this->userNotLoggedInPage();
         return;
     }
     if (wfReadOnly()) {
         $this->getOutput()->readOnlyPage();
         return;
     }
     if ($target == "Spam-Blacklist") {
         $this->getOutput()->readOnlyPage();
         return;
     }
     if ($this->getUser()->pingLimiter()) {
         $this->getOutput()->rateLimited();
         return;
     }
     $editPage = new EditPage($article);
     $contentModel = $t->getContentModel();
     $handler = ContentHandler::getForModelID($contentModel);
     $contentFormat = $handler->getDefaultFormat();
     $content = ContentHandler::makeContent($text, $t, $contentModel, $contentFormat);
     $status = Status::newGood();
     if (!wfRunHooks('EditFilterMergedContent', array($this->getContext(), $content, &$status, '', $wgUser, false))) {
         return;
     }
     if (!$status->isGood()) {
         $errors = $status->getErrorsArray(true);
         foreach ($errors as $error) {
             if (is_array($error)) {
                 $error = count($error) ? $error[0] : '';
             }
             if (preg_match('@^spamprotection@', $error)) {
                 $message = 'Error: found spam link';
                 $this->getOutput()->addHTML($message);
                 return;
             }
         }
         $message = 'EditFilterMergedContent returned an error -- cannot post comment';
         return;
     }
     $matches = array();
     $preg = "/http:\\/\\/[^] \n'\">]*/";
     $mod = str_ireplace('http://www.wikihow.com', '', $comment);
     preg_match_all($preg, $mod, $matches);
     if (sizeof($matches[0]) > 2) {
         $this->getOutput()->showErrorPage("postcomment", "postcomment_urls_limit");
         return;
     }
     if (trim(strip_tags($comment)) == "") {
         $this->getOutput()->showErrorPage("postcomment", "postcomment_nopostingtoadd");
         return;
     }
     if (!$t->userCan('edit')) {
         $this->getOutput()->showErrorPage("postcomment", "postcomment_discussionprotected");
         return;
     }
     $watch = false;
     if ($this->getUser()->getID() > 0) {
         $watch = $this->getUser()->isWatched($t);
     }
     $fc = new FancyCaptcha();
     $pass_captcha = $fc->passCaptcha();
     if (!$pass_captcha && $this->getUser()->getID() == 0) {
         $this->getOutput()->addHTML("Sorry, please enter the correct word. Click <a onclick='window.location.reload(true);'>here</a> to get a new one.<br/><br/>");
         return;
     }
     $article->doEdit($text, "");
     if ($this->getRequest()->getVal('jsonresponse') == 'true') {
         $this->revId = $article->getRevIdFetched();
     }
     // Notify users of usertalk updates
     if ($t->getNamespace() == NS_USER_TALK) {
         AuthorEmailNotification::notifyUserTalk($t->getArticleID(), $this->getUser()->getID(), $comment);
     }
     $this->getOutput()->setStatusCode(200);
     if ($this->getRequest()->getVal('fromajax') == 'true') {
         $this->getOutput()->redirect('');
         $this->getContext()->setTitle($t);
         $formattedComment = $wgParser->preSaveTransform($formattedComment, $t, $this->getUser(), new ParserOptions());
         $this->getOutput()->addHTML($this->getOutput()->parse("\n" . $formattedComment));
         return;
     }
 }
 function sendMilestoneEmails($datestamp)
 {
     wfLoadExtensionMessages('Milestones');
     $dbw = wfGetDB(DB_MASTER);
     $dbr = wfGetDB(DB_SLAVE);
     $users = $this->getMilestonesComplete($datestamp);
     $emailCount = 0;
     foreach ($users as $userInfo) {
         $user = User::newFromId($userInfo->{$this->userField});
         $email = $user->getEmail();
         if ($email == "") {
             continue;
         }
         $registration = $user->getRegistration();
         //need to check for false for the users who have no registration date
         //like Krystle and JackHerrick
         if ($registration == NULL || $registration <= $this->minRegistration) {
             echo "No email sent to " . $user->getName() . ". Not a new registration\n";
             wfDebug("No email sent to " . $user->getName() . ". Not a new registration\n");
             continue;
         }
         if ($user->getOption('disablemarketingemail') == '1') {
             wfDebug("No email sent to " . $user->getName() . ". Marketing email disabled.\n");
             continue;
         }
         $todayUnix = wfTimestamp(TS_UNIX, $datestamp + "000000");
         $minUnix = strtotime("-30 days", $todayUnix);
         $minDate = wfTimestamp(TS_MW, $minUnix);
         $views = 0;
         $articles = 0;
         $res = $dbr->select(array('revision', 'pageview'), array('pv_30day'), array('rev_page=pv_page', 'rev_user' => $user->getID(), "rev_timestamp > {$minDate}"), __METHOD__, array('GROUP BY' => 'rev_page'));
         foreach ($res as $object) {
             $views += intval($object->pv_30day);
             $articles++;
         }
         $from_name = wfMsg('milestone_from');
         $subject = wfMsg('milestone_subject');
         $message = wfMsg('milestone_message_' . $userInfo->ms_editcount);
         if ($views > 20) {
             $viewership = wfMsg('milestone_viewership', number_format($articles), number_format($views));
         } else {
             $viewership = "";
         }
         $cta = AuthorEmailNotification::getCTA('email_roll', 'email');
         $body = wfMsg('milestone_body', $user->getName(), $message, $viewership, $cta);
         wfDebug($user->getEmail() . " " . $subject . " " . $body . "\n");
         $emailCount++;
         AuthorEmailNotification::notify($user, $from_name, $subject, $body, "", true);
         $dbw->update($this->tableName, array($this->emailField => $datestamp), array($this->userField => $userInfo->{$this->userField}));
     }
     echo $emailCount . " milestone emails were sent\n";
 }