r105969 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r105968‎ | r105969 | r105970 >
Date:01:56, 13 December 2011
Author:bsitu
Status:ok (Comments)
Tags:
Comment:
Add HTML email notification support for Moodbar Feedback Response
Modified paths:
  • /trunk/extensions/MoodBar/ApiFeedbackDashboardResponse.php (modified) (history)
  • /trunk/extensions/MoodBar/MoodBar.i18n.php (modified) (history)
  • /trunk/extensions/MoodBar/MoodBar.php (modified) (history)
  • /trunk/extensions/MoodBar/include (added) (history)
  • /trunk/extensions/MoodBar/include/MoodBarHTMLEmailNotification.php (added) (history)
  • /trunk/extensions/MoodBar/include/MoodBarHTMLMailerJob.php (added) (history)

Diff [purge]

Index: trunk/extensions/MoodBar/include/MoodBarHTMLMailerJob.php
@@ -0,0 +1,31 @@
 2+<?php
 3+
 4+class MoodBarHTMLMailerJob extends Job {
 5+
 6+ function __construct( $title, $params, $id = 0 ) {
 7+ parent::__construct( __CLASS__, $title, $params, $id );
 8+ }
 9+
 10+ function run() {
 11+ $enotif = new MoodBarHTMLEmailNotification();
 12+ // Get the user from ID (rename safe). Anons are 0, so defer to name.
 13+ if( isset( $this->params['editorID'] ) && $this->params['editorID'] ) {
 14+ $editor = User::newFromId( $this->params['editorID'] );
 15+ // B/C, only the name might be given.
 16+ } else {
 17+ # FIXME: newFromName could return false on a badly configured wiki.
 18+ $editor = User::newFromName( $this->params['editor'], false );
 19+ }
 20+ $enotif->actuallyNotifyOnRespond(
 21+ $editor,
 22+ $this->title,
 23+ $this->params['timestamp'],
 24+ $this->params['feedbackResponse'],
 25+ $this->params['response']
 26+ );
 27+ return true;
 28+ }
 29+
 30+}
 31+
 32+?>
Index: trunk/extensions/MoodBar/include/MoodBarHTMLEmailNotification.php
@@ -0,0 +1,238 @@
 2+<?php
 3+
 4+/**
 5+ * A custom Mailer for MoodBar that sends HTML Email notification
 6+ * This is a hacksish solution till we revamp the email system
 7+ */
 8+class MoodBarHTMLEmailNotification {
 9+
 10+ protected $to, $subject, $body, $replyto, $from;
 11+ protected $timestamp, $composed_common, $feedbackResponse, $response;
 12+ protected $mime_boundary;
 13+
 14+ /**
 15+ * @var Title
 16+ */
 17+ protected $title;
 18+
 19+ /**
 20+ * @var User
 21+ */
 22+ protected $editor;
 23+ protected $targetUser;
 24+
 25+ public function __construct() {
 26+ $this->mime_boundary = 'PHP_Alt_Boundary_'. md5( time() );
 27+ }
 28+
 29+ /**
 30+ * Send emails corresponding to the user $editor editing the page $title.
 31+ * Also updates wl_notificationtimestamp.
 32+ *
 33+ * May be deferred via the job queue.
 34+ *
 35+ * @param $editor User object
 36+ * @param $title Title object
 37+ * @param $timestamp string Edit timestamp
 38+ * @param $feedbackResponse integer response id
 39+ * @param $response string response text
 40+ */
 41+ public function notifyOnRespond( $editor, $title, $timestamp, $feedbackResponse, $response ) {
 42+ global $wgEnotifUseJobQ, $wgEnotifUserTalk;
 43+
 44+ if ( $title->getNamespace() != NS_USER_TALK || !$wgEnotifUserTalk ||
 45+ !$this->canSendUserTalkEmail( $editor, $title ) ) {
 46+ return;
 47+ }
 48+
 49+ if ( $wgEnotifUseJobQ ) {
 50+ $params = array(
 51+ 'editor' => $editor->getName(),
 52+ 'editorID' => $editor->getID(),
 53+ 'timestamp' => $timestamp,
 54+ 'response' => $response,
 55+ 'feedbackResponse' => $feedbackResponse
 56+ );
 57+ $job = new MoodBarHTMLMailerJob( $title, $params );
 58+ $job->insert();
 59+ } else {
 60+ $this->actuallyNotifyOnRespond( $editor, $title, $timestamp, $feedbackResponse, $response );
 61+ }
 62+ }
 63+
 64+ /**
 65+ * Immediate version of notifyOnRespond().
 66+ *
 67+ * Send emails corresponding to the user $editor editing the page $title.
 68+ * Also updates wl_notificationtimestamp.
 69+ *
 70+ * @param $editor User object
 71+ * @param $title Title object
 72+ * @param $timestamp string Edit timestamp
 73+ * @param $feedbackResponse integer response id
 74+ * @param $response string response text
 75+ */
 76+ public function actuallyNotifyOnRespond( $editor, $title, $timestamp, $feedbackResponse, $response ) {
 77+
 78+ global $wgEnotifUserTalk;
 79+
 80+ wfProfileIn( __METHOD__ );
 81+
 82+ if ( $title->getNamespace() != NS_USER_TALK ) {
 83+ return;
 84+ }
 85+
 86+ $this->title = $title;
 87+ $this->timestamp = $timestamp;
 88+ $this->editor = $editor;
 89+ $this->composed_common = false;
 90+ $this->feedbackResponse = $feedbackResponse;
 91+ $this->response = $response;
 92+
 93+ if ( $wgEnotifUserTalk && $this->canSendUserTalkEmail( $editor, $title ) ) {
 94+ $this->compose( $this->targetUser );
 95+ }
 96+
 97+ wfProfileOut( __METHOD__ );
 98+
 99+ }
 100+
 101+ /**
 102+ * @param $editor User
 103+ * @param $title Title bool
 104+ * @return bool
 105+ */
 106+ protected function canSendUserTalkEmail( $editor, $title ) {
 107+ global $wgEnotifUserTalk;
 108+
 109+ if ( $wgEnotifUserTalk ) {
 110+ $this->targetUser = User::newFromName( $title->getText() );
 111+
 112+ if ( !$this->targetUser || $this->targetUser->isAnon() ) {
 113+ wfDebug( __METHOD__ . ": user talk page edited, but user does not exist\n" );
 114+ } elseif ( $this->targetUser->getId() == $editor->getId() ) {
 115+ wfDebug( __METHOD__ . ": user edited their own talk page, no notification sent\n" );
 116+ } elseif ( $this->targetUser->getOption( 'enotifusertalkpages' ) )
 117+ {
 118+ if ( $this->targetUser->isEmailConfirmed() ) {
 119+ wfDebug( __METHOD__ . ": sending talk page update notification\n" );
 120+ return true;
 121+ } else {
 122+ wfDebug( __METHOD__ . ": talk page owner doesn't have validated email\n" );
 123+ }
 124+ } else {
 125+ wfDebug( __METHOD__ . ": talk page owner doesn't want notifications\n" );
 126+ }
 127+ }
 128+ return false;
 129+ }
 130+
 131+ /**
 132+ * Generate the generic "this page has been changed" e-mail text.
 133+ */
 134+ protected function composeCommonMailtext() {
 135+ global $wgPasswordSender, $wgPasswordSenderName, $wgNoReplyAddress;
 136+ global $wgEnotifFromEditor, $wgEnotifRevealEditorAddress;
 137+ global $wgEnotifUseRealName;
 138+
 139+ $this->composed_common = true;
 140+
 141+ $keys = array();
 142+
 143+ if ( $this->editor->isAnon() ) {
 144+ $pageEditor = wfMsgForContent( 'enotif_anon_editor', $this->editor->getName() );
 145+ } else {
 146+ $pageEditor = $wgEnotifUseRealName ? $this->editor->getRealName() : $this->editor->getName();
 147+ }
 148+
 149+ $talkPageUrl = $this->title->getCanonicalURL() . '#feedback-dashboard-response-' . $this->feedbackResponse;
 150+
 151+ // build the subject
 152+ $this->subject = wfMessage( 'moodbar-enotif-subject')->params($pageEditor)->escaped();
 153+
 154+ // build section for the email body
 155+ $textUserResponseMessage = wfMessage('moodbar-enotif-text-body-user-response-message')
 156+ ->params($this->editor->getName(), $talkPageUrl)->escaped();
 157+
 158+ $htmlUserResponseMessage = wfMsgExt('moodbar-enotif-html-body-user-response-message',
 159+ array('parse'),
 160+ $this->editor->getUserPage()->getCanonicalURL(),
 161+ $this->editor->getName(),
 162+ $talkPageUrl);
 163+
 164+ $userReplyTitle = wfMessage('moodbar-enotif-body-user-response-title')->escaped();
 165+
 166+
 167+ $textResponse = htmlspecialchars( $this->response );
 168+
 169+ $messageCache = MessageCache::singleton();
 170+ $htmlResponse = $messageCache->parse( $this->response )->getText();
 171+
 172+ //assemable the email body
 173+ $this->body = <<<HTML
 174+--$this->mime_boundary
 175+Content-Type: text/plain; charset=UTF-8
 176+Content-Transfer-Encoding: 8bit
 177+
 178+$textUserResponseMessage
 179+$userReplyTitle
 180+$textResponse
 181+
 182+--$this->mime_boundary
 183+Content-Type: text/html; charset=UTF-8
 184+Content-Transfer-Encoding: 8bit
 185+
 186+<html>
 187+ <body>
 188+ $htmlUserResponseMessage
 189+ $userReplyTitle
 190+ $htmlResponse
 191+ </body>
 192+</html>
 193+
 194+--$this->mime_boundary--
 195+HTML;
 196+
 197+ # Reveal the page editor's address as REPLY-TO address only if
 198+ # the user has not opted-out and the option is enabled at the
 199+ # global configuration level.
 200+ $adminAddress = new MailAddress( $wgPasswordSender, $wgPasswordSenderName );
 201+ if ( $wgEnotifRevealEditorAddress
 202+ && ( $this->editor->getEmail() != '' )
 203+ && $this->editor->getOption( 'enotifrevealaddr' ) )
 204+ {
 205+ $editorAddress = new MailAddress( $this->editor );
 206+ if ( $wgEnotifFromEditor ) {
 207+ $this->from = $editorAddress;
 208+ } else {
 209+ $this->from = $adminAddress;
 210+ $this->replyto = $editorAddress;
 211+ }
 212+ } else {
 213+ $this->from = $adminAddress;
 214+ $this->replyto = new MailAddress( $wgNoReplyAddress );
 215+ }
 216+ }
 217+
 218+ /**
 219+ * Compose a mail to a given user and either queue it for sending, or send it now,
 220+ * depending on settings.
 221+ * @param $user User
 222+ */
 223+ protected function compose( $user ) {
 224+
 225+ global $wgContLang, $wgEnotifUseRealName;
 226+
 227+ if ( !$this->composed_common ) {
 228+ $this->composeCommonMailtext();
 229+ }
 230+
 231+ $to = new MailAddress( $user );
 232+
 233+ return UserMailer::send( $to, $this->from, $this->subject, $this->body, $this->replyto, $contentType = 'multipart/alternative; boundary=' . $this->mime_boundary );
 234+
 235+ }
 236+
 237+}
 238+
 239+?>
Index: trunk/extensions/MoodBar/MoodBar.i18n.php
@@ -159,6 +159,11 @@
160160 'response-ajax-success-body' => 'Your response has been added.',
161161 'response-ajax-error-head' => 'Oops!',
162162 'response-ajax-error-body' => 'There was an error adding your response. <br />Please try again later.',
 163+ //Email notification
 164+ 'moodbar-enotif-subject' => '$1 replied to your feedback',
 165+ 'moodbar-enotif-text-body-user-response-message' => '$1 replied to your feedback, see the response: $2',
 166+ 'moodbar-enotif-html-body-user-response-message' => '[$1 $2] replied to your feedback, see the [$3 response] for more detail',
 167+ 'moodbar-enotif-body-user-response-title' => 'User response: '
163168 );
164169
165170 /** Message documentation (Message documentation)
@@ -292,6 +297,10 @@
293298 'response-ajax-success-body' => 'Text for ajax status body on successful response (can be html)',
294299 'response-ajax-error-head' => 'Text for ajax status heading on error',
295300 'response-ajax-error-body' => 'Text for ajax status body on error (can be html)',
 301+ 'moodbar-enotif-subject' => 'Feedback response email subject',
 302+ 'moodbar-enotif-text-body-user-response-message' => 'The text version response message, $1 is the user name, $2 is the link to the response',
 303+ 'moodbar-enotif-html-body-user-response-message' => 'The html version response message, $1 is the the user page link, $2 is user name, $3 is the link to response',
 304+ 'moodbar-enotif-body-user-response-title' => 'User response: '
296305 );
297306
298307 /** Afrikaans (Afrikaans)
Index: trunk/extensions/MoodBar/ApiFeedbackDashboardResponse.php
@@ -2,6 +2,9 @@
33
44 class ApiFeedbackDashboardResponse extends ApiBase {
55
 6+ private $EnotifUserTalk;
 7+ private $EnotifWatchlist;
 8+
69 public function execute() {
710 global $wgRequest, $wgUser;
811
@@ -40,7 +43,9 @@
4144
4245 $summary = wfMessage('moodbar-feedback-edit-summary')->inContentLanguage()->
4346 rawParams( $item->getProperty('feedback'), $response)->escaped();
44 -
 47+
 48+ $this->disableUserTalkEmailNotification();
 49+
4550 $api = new ApiMain( new FauxRequest( array(
4651 'action' => 'edit',
4752 'title' => $talkPage->getFullText(),
@@ -54,12 +59,47 @@
5560 ), true, array( 'wsEditToken' => $wgRequest->getSessionData( 'wsEditToken' ) ) ), true );
5661
5762 $api->execute();
 63+
 64+ $this->restoreUserTalkEmailNotification();
 65+
 66+ global $wgLang;
 67+
 68+ $EMailNotif = new MoodBarHTMLEmailNotification();
 69+ $EMailNotif->notifyOnRespond( $wgUser, $talkPage, wfTimestampNow(), $item->getProperty( 'id' ), $wgLang->truncate( $response, 250 ) );
 70+
5871 }
5972
6073 $result = array( 'result' => 'success' );
6174 $this->getResult()->addValue( null, $this->getModuleName(), $result );
6275 }
6376
 77+ /**
 78+ * temporarily disable the talk page email notification
 79+ * for user and watchers
 80+ */
 81+ private function disableUserTalkEmailNotification() {
 82+ global $wgEnotifUserTalk, $wgEnotifWatchlist;
 83+
 84+ $this->EnotifUserTalk = $wgEnotifUserTalk;
 85+ $this->EnotifWatchlist = $wgEnotifWatchlist;
 86+
 87+ $wgEnotifUserTalk = $wgEnotifWatchlist = false;
 88+ }
 89+
 90+ /**
 91+ * restore the default state of talk page email notification
 92+ */
 93+ private function restoreUserTalkEmailNotification() {
 94+ global $wgEnotifUserTalk, $wgEnotifWatchlist;
 95+
 96+ if ( !is_null( $this->EnotifUserTalk ) ) {
 97+ $wgEnotifUserTalk = $this->EnotifUserTalk;
 98+ }
 99+ if ( !is_null( $this->EnotifWatchlist ) ) {
 100+ $wgEnotifWatchlist = $this->EnotifWatchlist;
 101+ }
 102+ }
 103+
64104 public function needsToken() {
65105 return true;
66106 }
Index: trunk/extensions/MoodBar/MoodBar.php
@@ -17,6 +17,8 @@
1818 $wgAutoloadClasses['MBFeedbackItem'] = dirname(__FILE__).'/FeedbackItem.php';
1919 $wgAutoloadClasses['MBFeedbackResponseItem'] = dirname(__FILE__).'/FeedbackResponseItem.php';
2020 $wgAutoloadClasses['MoodBarFormatter'] = dirname(__FILE__).'/Formatter.php';
 21+$wgAutoloadClasses['MoodBarHTMLEmailNotification'] = dirname(__FILE__).'/include/MoodBarHTMLEmailNotification.php';
 22+$wgAutoloadClasses['MoodBarHTMLMailerJob'] = dirname( __FILE__ ) . '/include/MoodBarHTMLMailerJob.php';
2123
2224 // API
2325 $wgAutoloadClasses['ApiMoodBar'] = dirname(__FILE__).'/ApiMoodBar.php';
@@ -57,6 +59,9 @@
5860 'moodbar/restore' => 'moodbar-log-restore',
5961 );
6062
 63+// Jobs
 64+$wgJobClasses['MoodBarHTMLMailerJob'] = 'MoodBarHTMLMailerJob';
 65+
6166 // User rights
6267 $wgAvailableRights[] = 'moodbar-view';
6368 $wgAvailableRights[] = 'moodbar-admin';

Follow-up revisions

RevisionCommit summaryAuthorDate
r105991r105969: Remove trailing whitespace...raymond08:05, 13 December 2011
r106078followup to r105969 - removed ?> from php files and updated response email wi...bsitu20:17, 13 December 2011
r106130followup to -r105969 - adding domain name to wiki link so it can be linked fr...bsitu23:30, 13 December 2011
r106225followup to r105969 - add padding space for feedback response email copybsitu18:58, 14 December 2011
r106229followup to r105969 - add margin right to the feedback response emailbsitu19:12, 14 December 2011
r106232followup to r105969 - update "Responder" to the real user namebsitu19:21, 14 December 2011

Comments

#Comment by Nikerabbit (talk | contribs)   05:52, 13 December 2011

We usually (always) drop the ?> from the end of the file.

#Comment by Nikerabbit (talk | contribs)   05:53, 13 December 2011

+ 'moodbar-enotif-body-user-response-title' => 'User response: ' Trailing whitespace is not allowed in messages. Did you also forget to update contents of message documentation for this message?

#Comment by Bsitu (talk | contribs)   20:19, 13 December 2011

Fixed in r106078, removed ?> from end of file and updated email text with latest copy

Thanks,

Status & tagging log