Index: trunk/phase3/includes/UserMailer.php |
— | — | @@ -242,31 +242,108 @@ |
243 | 243 | } |
244 | 244 | } |
245 | 245 | |
246 | | -/** |
247 | | - * This module processes the email notifications when the current page is |
248 | | - * changed. It looks up the table watchlist to find out which users are watching |
249 | | - * that page. |
250 | | - * |
251 | | - * The current implementation sends independent emails to each watching user for |
252 | | - * the following reason: |
253 | | - * |
254 | | - * - Each watching user will be notified about the page edit time expressed in |
255 | | - * his/her local time (UTC is shown additionally). To achieve this, we need to |
256 | | - * find the individual timeoffset of each watching user from the preferences.. |
257 | | - * |
258 | | - * Suggested improvement to slack down the number of sent emails: We could think |
259 | | - * of sending out bulk mails (bcc:user1,user2...) for all these users having the |
260 | | - * same timeoffset in their preferences. |
261 | | - * |
262 | | - * Visit the documentation pages under http://meta.wikipedia.com/Enotif |
263 | | - * |
264 | | - * |
265 | | - */ |
| 246 | + |
266 | 247 | class EmailNotification { |
267 | | - private $to, $subject, $body, $replyto, $from; |
268 | | - private $user, $title, $timestamp, $summary, $minorEdit, $oldid, $composed_common, $editor; |
269 | | - private $mailTargets = array(); |
| 248 | + |
| 249 | + /* |
| 250 | + * Send users an email. |
| 251 | + * |
| 252 | + * @param $editor User whose action precipitated the notification. |
| 253 | + * @param $timestamp of the event. |
| 254 | + * @param Callback that returns an an array of Users who will recieve the notification. |
| 255 | + * @param Callback that returns an array($keys, $body, $subject) where |
| 256 | + * * $keys is a dictionary whose keys will be replaced with the corresponding |
| 257 | + * values within the subject and body of the message. |
| 258 | + * * $body is the name of the message that will be used for the email body. |
| 259 | + * * $subject is the name of the message that will be used for the subject. |
| 260 | + * Both messages are resolved using the content language. |
| 261 | + * The messageCompositionFunction is invoked for each recipient user; |
| 262 | + * The keys returned are merged with those given by EmailNotification::commonMessageKeys(). |
| 263 | + * The recipient is appended to the arguments given to messageCompositionFunction. |
| 264 | + * Both callbacks are to be given in the same formats accepted by the hook system. |
| 265 | + */ |
| 266 | + function notify($editor, $timestamp, $userListFunction, $messageCompositionFunction) { |
| 267 | + global $wgEnotifUseRealName, $wgEnotifImpersonal; |
| 268 | + global $wgLang; |
270 | 269 | |
| 270 | + $common_keys = self::commonMessageKeys($editor); |
| 271 | + $users = wfInvoke($userListFunction); |
| 272 | + foreach($users as $u) { |
| 273 | + list($user_keys, $body_msg_name, $subj_msg_name) = |
| 274 | + wfInvoke($messageCompositionFunction, array($u)); |
| 275 | + $keys = array_merge($common_keys, $user_keys); |
| 276 | + |
| 277 | + if( $wgEnotifImpersonal ) { |
| 278 | + $keys['$WATCHINGUSERNAME'] = wfMsgForContent('enotif_impersonal_salutation'); |
| 279 | + $keys['$PAGEEDITDATE'] = $wgLang->timeanddate($timestamp, true, false, false); |
| 280 | + } else { |
| 281 | + $keys['$WATCHINGUSERNAME'] = $wgEnotifUseRealName ? $u->getRealName() : $u->getName(); |
| 282 | + $keys['$PAGEEDITDATE'] = $wgLang->timeAndDate($timestamp, true, false, |
| 283 | + $u->getOption('timecorrection')); |
| 284 | + } |
| 285 | + |
| 286 | + $subject = strtr(wfMsgForContent( $subj_msg_name ), $keys); |
| 287 | + $body = wordwrap( strtr( wfMsgForContent( $body_msg_name ), $keys ), 72 ); |
| 288 | + |
| 289 | + $to = new MailAddress($u); |
| 290 | + $from = $keys['$FROM_HEADER']; |
| 291 | + $replyto = $keys['$REPLYTO_HEADER']; |
| 292 | + UserMailer::send($to, $from, $subject, $body, $replyto); |
| 293 | + } |
| 294 | + } |
| 295 | + |
| 296 | + |
| 297 | + static function commonMessageKeys($editor) { |
| 298 | + global $wgEnotifUseRealName, $wgEnotifRevealEditorAddress; |
| 299 | + global $wgNoReplyAddress, $wgPasswordSender; |
| 300 | + |
| 301 | + $keys = array(); |
| 302 | + |
| 303 | + $name = $wgEnotifUseRealName ? $editor->getRealName() : $editor->getName(); |
| 304 | + |
| 305 | + $adminAddress = new MailAddress( $wgPasswordSender, 'WikiAdmin' ); |
| 306 | + $editorAddress = new MailAddress( $editor ); |
| 307 | + if( $wgEnotifRevealEditorAddress |
| 308 | + && $editor->getEmail() != '' |
| 309 | + && $editor->getOption( 'enotifrevealaddr' ) ) { |
| 310 | + if( $wgEnotifFromEditor ) { |
| 311 | + $from = $editorAddress; |
| 312 | + } else { |
| 313 | + $from = $adminAddress; |
| 314 | + $replyto = $editorAddress; |
| 315 | + } |
| 316 | + } else { |
| 317 | + $from = $adminAddress; |
| 318 | + $replyto = new MailAddress( $wgNoReplyAddress ); |
| 319 | + } |
| 320 | + $keys['$FROM_HEADER'] = $from; |
| 321 | + $keys['$REPLYTO_HEADER'] = $replyto; |
| 322 | + |
| 323 | + if( $editor->isAnon() ) { |
| 324 | + $keys['$PAGEEDITOR'] = wfMsgForContent('enotif_anon_editor', $name); |
| 325 | + $keys['$PAGEEDITOR_EMAIL'] = wfMsgForContent( 'noemailtitle' ); |
| 326 | + } else{ |
| 327 | + $keys['$PAGEEDITOR'] = $name; |
| 328 | + $keys['$PAGEEDITOR_EMAIL'] = SpecialPage::getSafeTitleFor('Emailuser', $name)->getFullUrl(); |
| 329 | + } |
| 330 | + $keys['$PAGEEDITOR_WIKI'] = $editor->getUserPage()->getFullUrl(); |
| 331 | + |
| 332 | + return $keys; |
| 333 | + } |
| 334 | + |
| 335 | + |
| 336 | + |
| 337 | + /* |
| 338 | + * @deprecated |
| 339 | + * Use PageChangeNotification::notifyOnPageChange instead. |
| 340 | + */ |
| 341 | + function notifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid = false) { |
| 342 | + PageChangeNotification::notifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid); |
| 343 | + } |
| 344 | +} |
| 345 | + |
| 346 | +class PageChangeNotification { |
| 347 | + |
271 | 348 | /** |
272 | 349 | * Send emails corresponding to the user $editor editing the page $title. |
273 | 350 | * Also updates wl_notificationtimestamp. |
— | — | @@ -280,7 +357,7 @@ |
281 | 358 | * @param $minorEdit |
282 | 359 | * @param $oldid (default: false) |
283 | 360 | */ |
284 | | - function notifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid = false) { |
| 361 | + static function notifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid = false) { |
285 | 362 | global $wgEnotifUseJobQ; |
286 | 363 | |
287 | 364 | if( $title->getNamespace() < 0 ) |
— | — | @@ -297,7 +374,7 @@ |
298 | 375 | $job = new EnotifNotifyJob( $title, $params ); |
299 | 376 | $job->insert(); |
300 | 377 | } else { |
301 | | - $this->actuallyNotifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid); |
| 378 | + self::actuallyNotifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid); |
302 | 379 | } |
303 | 380 | |
304 | 381 | } |
— | — | @@ -315,94 +392,16 @@ |
316 | 393 | * @param $minorEdit |
317 | 394 | * @param $oldid (default: false) |
318 | 395 | */ |
319 | | - function actuallyNotifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid=false) { |
320 | | - |
321 | | - # we use $wgPasswordSender as sender's address |
322 | | - global $wgEnotifWatchlist; |
323 | | - global $wgEnotifMinorEdits, $wgEnotifUserTalk, $wgShowUpdatedMarker; |
324 | | - global $wgEnotifImpersonal; |
325 | | - |
| 396 | + static function actuallyNotifyOnPageChange($editor, $title, $timestamp, |
| 397 | + $summary, $minorEdit, $oldid=false) { |
| 398 | + global $wgShowUpdatedMarker, $wgEnotifWatchlist; |
| 399 | + |
326 | 400 | wfProfileIn( __METHOD__ ); |
327 | | - |
328 | | - # The following code is only run, if several conditions are met: |
329 | | - # 1. EmailNotification for pages (other than user_talk pages) must be enabled |
330 | | - # 2. minor edits (changes) are only regarded if the global flag indicates so |
331 | | - |
332 | | - $isUserTalkPage = ($title->getNamespace() == NS_USER_TALK); |
333 | | - $enotifusertalkpage = ($isUserTalkPage && $wgEnotifUserTalk); |
334 | | - $enotifwatchlistpage = $wgEnotifWatchlist; |
335 | | - |
336 | | - $this->title = $title; |
337 | | - $this->timestamp = $timestamp; |
338 | | - $this->summary = $summary; |
339 | | - $this->minorEdit = $minorEdit; |
340 | | - $this->oldid = $oldid; |
341 | | - $this->editor = $editor; |
342 | | - $this->composed_common = false; |
343 | | - |
344 | | - $userTalkId = false; |
345 | | - |
346 | | - if ( (!$minorEdit || $wgEnotifMinorEdits) ) { |
347 | | - if ( $wgEnotifUserTalk && $isUserTalkPage ) { |
348 | | - $targetUser = User::newFromName( $title->getText() ); |
349 | | - if ( !$targetUser || $targetUser->isAnon() ) { |
350 | | - wfDebug( __METHOD__.": user talk page edited, but user does not exist\n" ); |
351 | | - } elseif ( $targetUser->getId() == $editor->getId() ) { |
352 | | - wfDebug( __METHOD__.": user edited their own talk page, no notification sent\n" ); |
353 | | - } elseif( $targetUser->getOption( 'enotifusertalkpages' ) ) { |
354 | | - if( $targetUser->isEmailConfirmed() ) { |
355 | | - wfDebug( __METHOD__.": sending talk page update notification\n" ); |
356 | | - $this->compose( $targetUser ); |
357 | | - $userTalkId = $targetUser->getId(); |
358 | | - } else { |
359 | | - wfDebug( __METHOD__.": talk page owner doesn't have validated email\n" ); |
360 | | - } |
361 | | - } else { |
362 | | - wfDebug( __METHOD__.": talk page owner doesn't want notifications\n" ); |
363 | | - } |
364 | | - } |
365 | | - |
366 | | - if ( $wgEnotifWatchlist ) { |
367 | | - // Send updates to watchers other than the current editor |
368 | | - $userCondition = 'wl_user != ' . $editor->getID(); |
369 | | - if ( $userTalkId !== false ) { |
370 | | - // Already sent an email to this person |
371 | | - $userCondition .= ' AND wl_user != ' . intval( $userTalkId ); |
372 | | - } |
373 | | - $dbr = wfGetDB( DB_SLAVE ); |
374 | | - |
375 | | - list( $user ) = $dbr->tableNamesN( 'user' ); |
376 | | - |
377 | | - $res = $dbr->select( array( 'watchlist', 'user' ), |
378 | | - array( "$user.*" ), |
379 | | - array( |
380 | | - 'wl_user=user_id', |
381 | | - 'wl_title' => $title->getDBkey(), |
382 | | - 'wl_namespace' => $title->getNamespace(), |
383 | | - $userCondition, |
384 | | - 'wl_notificationtimestamp IS NULL', |
385 | | - ), __METHOD__ ); |
386 | | - $userArray = UserArray::newFromResult( $res ); |
387 | | - |
388 | | - foreach ( $userArray as $watchingUser ) { |
389 | | - if ( $watchingUser->getOption( 'enotifwatchlistpages' ) && |
390 | | - ( !$minorEdit || $watchingUser->getOption('enotifminoredits') ) && |
391 | | - $watchingUser->isEmailConfirmed() ) |
392 | | - { |
393 | | - $this->compose( $watchingUser ); |
394 | | - } |
395 | | - } |
396 | | - } |
397 | | - } |
398 | | - |
399 | | - global $wgUsersNotifiedOnAllChanges; |
400 | | - foreach ( $wgUsersNotifiedOnAllChanges as $name ) { |
401 | | - $user = User::newFromName( $name ); |
402 | | - $this->compose( $user ); |
403 | | - } |
404 | | - |
405 | | - $this->sendMails(); |
406 | | - |
| 401 | + |
| 402 | + EmailNotification::notify($editor, $timestamp, |
| 403 | + array('PageChangeNotification::usersList', array($editor, $title, $minorEdit)), |
| 404 | + array('PageChangeNotification::message', array($oldid, $minorEdit, $summary, $title, $editor) ) ); |
| 405 | + |
407 | 406 | $latestTimestamp = Revision::getTimestampFromId( $title, $title->getLatestRevID() ); |
408 | 407 | // Do not update watchlists if something else already did. |
409 | 408 | if ( $timestamp >= $latestTimestamp && ($wgShowUpdatedMarker || $wgEnotifWatchlist) ) { |
— | — | @@ -423,38 +422,22 @@ |
424 | 423 | } |
425 | 424 | |
426 | 425 | wfProfileOut( __METHOD__ ); |
427 | | - } # function NotifyOnChange |
| 426 | + } |
| 427 | + |
| 428 | + |
| 429 | + static function message( $stuff ) { |
| 430 | + global $wgEnotifImpersonal; |
428 | 431 | |
429 | | - /** |
430 | | - * @private |
431 | | - */ |
432 | | - function composeCommonMailtext() { |
433 | | - global $wgPasswordSender, $wgNoReplyAddress; |
434 | | - global $wgEnotifFromEditor, $wgEnotifRevealEditorAddress; |
435 | | - global $wgEnotifImpersonal, $wgEnotifUseRealName; |
| 432 | + list($oldid, $medit, $summary, $title, $user) = $stuff; |
| 433 | + $keys = array(); |
436 | 434 | |
437 | | - $this->composed_common = true; |
438 | | - |
439 | | - $summary = ($this->summary == '') ? ' - ' : $this->summary; |
440 | | - $medit = ($this->minorEdit) ? wfMsg( 'minoredit' ) : ''; |
441 | | - |
442 | | - # You as the WikiAdmin and Sysops can make use of plenty of |
443 | | - # named variables when composing your notification emails while |
444 | | - # simply editing the Meta pages |
445 | | - |
446 | | - $subject = wfMsgForContent( 'enotif_subject' ); |
447 | | - $body = wfMsgForContent( 'enotif_body' ); |
448 | | - $from = ''; /* fail safe */ |
449 | | - $replyto = ''; /* fail safe */ |
450 | | - $keys = array(); |
451 | | - |
452 | 435 | # regarding the use of oldid as an indicator for the last visited version, see also |
453 | 436 | # http://bugzilla.wikipeda.org/show_bug.cgi?id=603 "Delete + undelete cycle doesn't preserve old_id" |
454 | 437 | # However, in the case of a new page which is already watched, we have no previous version to compare |
455 | | - if( $this->oldid ) { |
456 | | - $difflink = $this->title->getFullUrl( 'diff=0&oldid=' . $this->oldid ); |
| 438 | + if( $oldid ) { |
| 439 | + $difflink = $title->getFullUrl( 'diff=0&oldid=' . $oldid ); |
457 | 440 | $keys['$NEWPAGE'] = wfMsgForContent( 'enotif_lastvisited', $difflink ); |
458 | | - $keys['$OLDID'] = $this->oldid; |
| 441 | + $keys['$OLDID'] = $oldid; |
459 | 442 | $keys['$CHANGEDORCREATED'] = wfMsgForContent( 'changed' ); |
460 | 443 | } else { |
461 | 444 | $keys['$NEWPAGE'] = wfMsgForContent( 'enotif_newpagetext' ); |
— | — | @@ -463,151 +446,92 @@ |
464 | 447 | $keys['$CHANGEDORCREATED'] = wfMsgForContent( 'created' ); |
465 | 448 | } |
466 | 449 | |
467 | | - if ($wgEnotifImpersonal && $this->oldid) |
468 | | - /* |
469 | | - * For impersonal mail, show a diff link to the last |
470 | | - * revision. |
471 | | - */ |
| 450 | + if ($wgEnotifImpersonal && $oldid) { |
| 451 | + # For impersonal mail, show a diff link to the last revision. |
472 | 452 | $keys['$NEWPAGE'] = wfMsgForContent('enotif_lastdiff', |
473 | | - $this->title->getFullURL("oldid={$this->oldid}&diff=prev")); |
| 453 | + $title->getFullURL("oldid={$oldid}&diff=prev")); |
| 454 | + } |
474 | 455 | |
475 | | - $body = strtr( $body, $keys ); |
476 | | - $pagetitle = $this->title->getPrefixedText(); |
477 | | - $keys['$PAGETITLE'] = $pagetitle; |
478 | | - $keys['$PAGETITLE_URL'] = $this->title->getFullUrl(); |
| 456 | + $keys['$PAGETITLE'] = $title->getPrefixedText(); |
| 457 | + $keys['$PAGETITLE_URL'] = $title->getFullUrl(); |
| 458 | + $keys['$PAGEMINOREDIT'] = $medit ? wfMsg( 'minoredit' ) : ''; |
| 459 | + $keys['$PAGESUMMARY'] = ($summary == '') ? ' - ' : $summary; |
479 | 460 | |
480 | | - $keys['$PAGEMINOREDIT'] = $medit; |
481 | | - $keys['$PAGESUMMARY'] = $summary; |
| 461 | + return array($keys, 'enotif_body', 'enotif_subject'); |
| 462 | + } |
482 | 463 | |
483 | | - $subject = strtr( $subject, $keys ); |
| 464 | + static function usersList($stuff) { |
| 465 | + global $wgEnotifWatchlist, $wgEnotifMinorEdits, $wgUsersNotifiedOnAllChanges; |
484 | 466 | |
485 | | - # Reveal the page editor's address as REPLY-TO address only if |
486 | | - # the user has not opted-out and the option is enabled at the |
487 | | - # global configuration level. |
488 | | - $editor = $this->editor; |
489 | | - $name = $wgEnotifUseRealName ? $editor->getRealName() : $editor->getName(); |
490 | | - $adminAddress = new MailAddress( $wgPasswordSender, 'WikiAdmin' ); |
491 | | - $editorAddress = new MailAddress( $editor ); |
492 | | - if( $wgEnotifRevealEditorAddress |
493 | | - && ( $editor->getEmail() != '' ) |
494 | | - && $editor->getOption( 'enotifrevealaddr' ) ) { |
495 | | - if( $wgEnotifFromEditor ) { |
496 | | - $from = $editorAddress; |
497 | | - } else { |
498 | | - $from = $adminAddress; |
499 | | - $replyto = $editorAddress; |
500 | | - } |
501 | | - } else { |
502 | | - $from = $adminAddress; |
503 | | - $replyto = new MailAddress( $wgNoReplyAddress ); |
504 | | - } |
| 467 | + list($editor, $title, $minorEdit) = $stuff; |
| 468 | + $recipients = array(); |
505 | 469 | |
506 | | - if( $editor->isIP( $name ) ) { |
507 | | - #real anon (user:xxx.xxx.xxx.xxx) |
508 | | - $utext = wfMsgForContent('enotif_anon_editor', $name); |
509 | | - $subject = str_replace('$PAGEEDITOR', $utext, $subject); |
510 | | - $keys['$PAGEEDITOR'] = $utext; |
511 | | - $keys['$PAGEEDITOR_EMAIL'] = wfMsgForContent( 'noemailtitle' ); |
512 | | - } else { |
513 | | - $subject = str_replace('$PAGEEDITOR', $name, $subject); |
514 | | - $keys['$PAGEEDITOR'] = $name; |
515 | | - $emailPage = SpecialPage::getSafeTitleFor( 'Emailuser', $name ); |
516 | | - $keys['$PAGEEDITOR_EMAIL'] = $emailPage->getFullUrl(); |
517 | | - } |
518 | | - $userPage = $editor->getUserPage(); |
519 | | - $keys['$PAGEEDITOR_WIKI'] = $userPage->getFullUrl(); |
520 | | - $body = strtr( $body, $keys ); |
521 | | - $body = wordwrap( $body, 72 ); |
| 470 | + # User talk pages: |
| 471 | + $userTalkId = false; |
| 472 | + if( $title->getNamespace() == NS_USER_TALK && (!$minorEdit || $wgEnotifMinorEdits) ) { |
| 473 | + $targetUser = User::newFromName($title->getText()); |
522 | 474 | |
523 | | - # now save this as the constant user-independent part of the message |
524 | | - $this->from = $from; |
525 | | - $this->replyto = $replyto; |
526 | | - $this->subject = $subject; |
527 | | - $this->body = $body; |
528 | | - } |
| 475 | + if ( !$targetUser || $targetUser->isAnon() ) |
| 476 | + $msg = "user talk page edited, but user does not exist"; |
529 | 477 | |
530 | | - /** |
531 | | - * Compose a mail to a given user and either queue it for sending, or send it now, |
532 | | - * depending on settings. |
533 | | - * |
534 | | - * Call sendMails() to send any mails that were queued. |
535 | | - */ |
536 | | - function compose( $user ) { |
537 | | - global $wgEnotifImpersonal; |
| 478 | + else if ( $targetUser->getId() == $editor->getId() ) |
| 479 | + $msg = "user edited their own talk page, no notification sent"; |
538 | 480 | |
539 | | - if ( !$this->composed_common ) |
540 | | - $this->composeCommonMailtext(); |
| 481 | + else if ( !$targetUser->getOption('enotifusertalkpages') ) |
| 482 | + $msg = "talk page owner doesn't want notifications"; |
541 | 483 | |
542 | | - if ( $wgEnotifImpersonal ) { |
543 | | - $this->mailTargets[] = new MailAddress( $user ); |
544 | | - } else { |
545 | | - $this->sendPersonalised( $user ); |
546 | | - } |
547 | | - } |
| 484 | + else if ( !$targetUser->isEmailConfirmed() ) |
| 485 | + $msg = "talk page owner doesn't have validated email"; |
548 | 486 | |
549 | | - /** |
550 | | - * Send any queued mails |
551 | | - */ |
552 | | - function sendMails() { |
553 | | - global $wgEnotifImpersonal; |
554 | | - if ( $wgEnotifImpersonal ) { |
555 | | - $this->sendImpersonal( $this->mailTargets ); |
| 487 | + else { |
| 488 | + $msg = "sending talk page update notification"; |
| 489 | + $recipients[] = $targetUser; |
| 490 | + $userTalkId = $targetUser->getId(); # won't be included in watchlist, below. |
| 491 | + } |
| 492 | + wfDebug( __METHOD__ .": ". $msg . "\n" ); |
556 | 493 | } |
557 | | - } |
| 494 | + wfDebug("Did not send a user-talk notification.\n"); |
558 | 495 | |
559 | | - /** |
560 | | - * Does the per-user customizations to a notification e-mail (name, |
561 | | - * timestamp in proper timezone, etc) and sends it out. |
562 | | - * Returns true if the mail was sent successfully. |
563 | | - * |
564 | | - * @param User $watchingUser |
565 | | - * @param object $mail |
566 | | - * @return bool |
567 | | - * @private |
568 | | - */ |
569 | | - function sendPersonalised( $watchingUser ) { |
570 | | - global $wgLang, $wgEnotifUseRealName; |
571 | | - // From the PHP manual: |
572 | | - // Note: The to parameter cannot be an address in the form of "Something <someone@example.com>". |
573 | | - // The mail command will not parse this properly while talking with the MTA. |
574 | | - $to = new MailAddress( $watchingUser ); |
575 | | - $name = $wgEnotifUseRealName ? $watchingUser->getRealName() : $watchingUser->getName(); |
576 | | - $body = str_replace( '$WATCHINGUSERNAME', $name , $this->body ); |
| 496 | + if( $wgEnotifWatchlist && (!$minorEdit || $wgEnotifMinorEdits) ) { |
| 497 | + // Send updates to watchers other than the current editor |
| 498 | + $userCondition = 'wl_user != ' . $editor->getID(); |
577 | 499 | |
578 | | - $timecorrection = $watchingUser->getOption( 'timecorrection' ); |
| 500 | + if ( $userTalkId !== false ) { |
| 501 | + // Already sent an email to this person |
| 502 | + $userCondition .= ' AND wl_user != ' . intval( $userTalkId ); |
| 503 | + } |
| 504 | + $dbr = wfGetDB( DB_SLAVE ); |
579 | 505 | |
580 | | - # $PAGEEDITDATE is the time and date of the page change |
581 | | - # expressed in terms of individual local time of the notification |
582 | | - # recipient, i.e. watching user |
583 | | - $body = str_replace('$PAGEEDITDATE', |
584 | | - $wgLang->timeanddate( $this->timestamp, true, false, $timecorrection ), |
585 | | - $body); |
| 506 | + list( $user ) = $dbr->tableNamesN( 'user' ); |
586 | 507 | |
587 | | - return UserMailer::send($to, $this->from, $this->subject, $body, $this->replyto); |
588 | | - } |
| 508 | + $res = $dbr->select( array( 'watchlist', 'user' ), |
| 509 | + array( "$user.*" ), |
| 510 | + array( |
| 511 | + 'wl_user=user_id', |
| 512 | + 'wl_title' => $title->getDBkey(), |
| 513 | + 'wl_namespace' => $title->getNamespace(), |
| 514 | + $userCondition, |
| 515 | + 'wl_notificationtimestamp IS NULL', |
| 516 | + ), __METHOD__ ); |
| 517 | + $userArray = UserArray::newFromResult( $res ); |
589 | 518 | |
590 | | - /** |
591 | | - * Same as sendPersonalised but does impersonal mail suitable for bulk |
592 | | - * mailing. Takes an array of MailAddress objects. |
593 | | - */ |
594 | | - function sendImpersonal( $addresses ) { |
595 | | - global $wgLang; |
| 519 | + foreach ( $userArray as $watchingUser ) { |
| 520 | + if ( $watchingUser->getOption( 'enotifwatchlistpages' ) && |
| 521 | + ( !$minorEdit || $watchingUser->getOption('enotifminoredits') ) && |
| 522 | + $watchingUser->isEmailConfirmed() ) { |
| 523 | + $recipients[] = $watchingUser; |
| 524 | + } |
| 525 | + } |
| 526 | + } |
596 | 527 | |
597 | | - if (empty($addresses)) |
598 | | - return; |
| 528 | + foreach ( $wgUsersNotifiedOnAllChanges as $name ) { |
| 529 | + $recipients[] = User::newFromName($name); |
| 530 | + } |
599 | 531 | |
600 | | - $body = str_replace( |
601 | | - array( '$WATCHINGUSERNAME', |
602 | | - '$PAGEEDITDATE'), |
603 | | - array( wfMsgForContent('enotif_impersonal_salutation'), |
604 | | - $wgLang->timeanddate($this->timestamp, true, false, false)), |
605 | | - $this->body); |
606 | | - |
607 | | - return UserMailer::send($addresses, $this->from, $this->subject, $body, $this->replyto); |
| 532 | + return $recipients; |
608 | 533 | } |
| 534 | +} |
609 | 535 | |
610 | | -} # end of class EmailNotification |
611 | | - |
612 | 536 | /** |
613 | 537 | * Backwards compatibility functions |
614 | 538 | */ |
Index: trunk/phase3/includes/AutoLoader.php |
— | — | @@ -55,6 +55,7 @@ |
56 | 56 | 'EditPage' => 'includes/EditPage.php', |
57 | 57 | 'EmaillingJob' => 'includes/EmaillingJob.php', |
58 | 58 | 'EmailNotification' => 'includes/UserMailer.php', |
| 59 | + 'PageChangeNotification' => 'includes/UserMailer.php', |
59 | 60 | 'EnhancedChangesList' => 'includes/ChangesList.php', |
60 | 61 | 'EnotifNotifyJob' => 'includes/EnotifNotifyJob.php', |
61 | 62 | 'ErrorPageError' => 'includes/Exception.php', |
Index: trunk/phase3/includes/RecentChange.php |
— | — | @@ -184,10 +184,8 @@ |
185 | 185 | $editor = ($wgUser->getName() == $this->mAttribs['rc_user_text']) ? |
186 | 186 | $wgUser : User::newFromName( $this->mAttribs['rc_user_text'], false ); |
187 | 187 | } |
188 | | - # FIXME: this would be better as an extension hook |
189 | | - $enotif = new EmailNotification(); |
190 | 188 | $title = Title::makeTitle( $this->mAttribs['rc_namespace'], $this->mAttribs['rc_title'] ); |
191 | | - $enotif->notifyOnPageChange( $editor, $title, |
| 189 | + PageChangeNotification::notifyOnPageChange( $editor, $title, |
192 | 190 | $this->mAttribs['rc_timestamp'], |
193 | 191 | $this->mAttribs['rc_comment'], |
194 | 192 | $this->mAttribs['rc_minor'], |
Index: trunk/phase3/includes/EnotifNotifyJob.php |
— | — | @@ -12,7 +12,6 @@ |
13 | 13 | } |
14 | 14 | |
15 | 15 | function run() { |
16 | | - $enotif = new EmailNotification(); |
17 | 16 | // Get the user from ID (rename safe). Anons are 0, so defer to name. |
18 | 17 | if( isset($this->params['editorID']) && $this->params['editorID'] ) { |
19 | 18 | $editor = User::newFromId( $this->params['editorID'] ); |
— | — | @@ -20,7 +19,7 @@ |
21 | 20 | } else { |
22 | 21 | $editor = User::newFromName( $this->params['editor'], false ); |
23 | 22 | } |
24 | | - $enotif->actuallyNotifyOnPageChange( |
| 23 | + PageChangeNotification::actuallyNotifyOnPageChange( |
25 | 24 | $editor, |
26 | 25 | $this->title, |
27 | 26 | $this->params['timestamp'], |