69 protected $subject =
'';
84 protected $summary =
'';
93 protected $composed_common =
false;
96 protected $pageStatus =
'';
99 protected $mailTargets = [];
118 return $this->pageStatus;
143 $pageStatus =
'changed'
149 $mwServices = MediaWikiServices::getInstance();
150 $config = $mwServices->getMainConfig();
154 if ( $config->get(
'EnotifWatchlist' ) || $config->get(
'ShowUpdatedMarker' ) ) {
155 $watchers = $mwServices->getWatchedItemStore()->updateNotificationTimestamp(
167 if ( $watchers === [] && !count( $config->get(
'UsersNotifiedOnAllChanges' ) ) ) {
171 ( $config->get(
'EnotifMinorEdits' ) && !$editor->
isAllowed(
'nominornewtalk' ) )
174 if ( $config->get(
'EnotifUserTalk' )
187 'editor' => $editor->
getUser()->getName(),
188 'editorID' => $editor->
getUser()->getId(),
189 'timestamp' => $timestamp,
190 'summary' => $summary,
191 'minorEdit' => $minorEdit,
193 'watchers' => $watchers,
194 'pageStatus' => $pageStatus
226 $pageStatus =
'changed'
228 # we use $wgPasswordSender as sender's address
230 $mwServices = MediaWikiServices::getInstance();
231 $messageCache = $mwServices->getMessageCache();
232 $config = $mwServices->getMainConfig();
234 # The following code is only run, if several conditions are met:
235 # 1. EmailNotification for pages (other than user_talk pages) must be enabled
236 # 2. minor edits (changes) are only regarded if the global flag indicates so
241 $this->timestamp = $timestamp;
242 $this->summary = $summary;
243 $this->minorEdit = $minorEdit;
244 $this->oldid = $oldid;
245 $this->editor = MediaWikiServices::getInstance()->getUserFactory()->newFromAuthority( $editor );
246 $this->composed_common =
false;
247 $this->pageStatus = $pageStatus;
249 $formattedPageStatus = [
'deleted',
'created',
'moved',
'restored',
'changed' ];
251 Hooks::runner()->onUpdateUserMailerFormattedPageStatus( $formattedPageStatus );
252 if ( !in_array( $this->pageStatus, $formattedPageStatus ) ) {
253 throw new MWException(
'Not a valid page status!' );
259 ( $config->get(
'EnotifMinorEdits' ) && !$editor->
isAllowed(
'nominornewtalk' ) )
261 if ( $config->get(
'EnotifUserTalk' )
263 && $this->canSendUserTalkEmail( $editor->
getUser(),
$title, $minorEdit )
266 $this->compose( $targetUser, self::USER_TALK, $messageCache );
267 $userTalkId = $targetUser->getId();
270 if ( $config->get(
'EnotifWatchlist' ) ) {
274 foreach ( $userArray as $watchingUser ) {
275 if ( $watchingUser->getOption(
'enotifwatchlistpages' )
276 && ( !$minorEdit || $watchingUser->getOption(
'enotifminoredits' ) )
277 && $watchingUser->isEmailConfirmed()
278 && $watchingUser->getId() != $userTalkId
279 && !in_array( $watchingUser->getName(), $config->get(
'UsersNotifiedOnAllChanges' ) )
282 && !( $config->get(
'BlockDisablesLogin' ) && $watchingUser->getBlock() )
283 && Hooks::runner()->onSendWatchlistEmailNotification( $watchingUser,
$title, $this )
285 $this->compose( $watchingUser, self::WATCHLIST, $messageCache );
291 foreach ( $config->get(
'UsersNotifiedOnAllChanges' ) as $name ) {
292 if ( $editor->
getUser()->getName() == $name ) {
297 $this->compose( $user, self::ALL_CHANGES, $messageCache );
310 $config = MediaWikiServices::getInstance()->getMainConfig();
313 if ( !$config->get(
'EnotifUserTalk' ) || !$isUserTalkPage ) {
319 if ( !$targetUser || $targetUser->isAnon() ) {
320 wfDebug( __METHOD__ .
": user talk page edited, but user does not exist" );
321 } elseif ( $targetUser->getId() == $editor->
getId() ) {
322 wfDebug( __METHOD__ .
": user edited their own talk page, no notification sent" );
323 } elseif ( $config->get(
'BlockDisablesLogin' ) && $targetUser->getBlock() ) {
326 wfDebug( __METHOD__ .
": talk page owner is blocked and cannot login, no notification sent" );
327 } elseif ( $targetUser->getOption(
'enotifusertalkpages' )
328 && ( !$minorEdit || $targetUser->getOption(
'enotifminoredits' ) )
330 if ( !$targetUser->isEmailConfirmed() ) {
331 wfDebug( __METHOD__ .
": talk page owner doesn't have validated email" );
332 } elseif ( !Hooks::runner()->onAbortTalkPageEmailNotification( $targetUser,
$title ) ) {
333 wfDebug( __METHOD__ .
": talk page update notification is aborted for this user" );
335 wfDebug( __METHOD__ .
": sending talk page update notification" );
339 wfDebug( __METHOD__ .
": talk page owner doesn't want notifications" );
349 $config = MediaWikiServices::getInstance()->getMainConfig();
351 $this->composed_common =
true;
353 # You as the WikiAdmin and Sysops can make use of plenty of
354 # named variables when composing your notification emails while
355 # simply editing the Meta pages
358 $postTransformKeys = [];
359 $pageTitleUrl = $this->title->getCanonicalURL();
360 $pageTitle = $this->title->getPrefixedText();
362 if ( $this->oldid ) {
366 $this->title->getCanonicalURL( [
'diff' =>
'next',
'oldid' => $this->oldid ] )
367 )->inContentLanguage()->text();
369 if ( !$config->get(
'EnotifImpersonal' ) ) {
373 'enotif_lastvisited',
374 $this->title->getCanonicalURL( [
'diff' =>
'0',
'oldid' => $this->oldid ] )
375 )->inContentLanguage()->text();
377 $keys[
'$OLDID'] = $this->oldid;
379 $keys[
'$CHANGEDORCREATED'] =
wfMessage(
'changed' )->inContentLanguage()->text();
381 # clear $OLDID placeholder in the message template
382 $keys[
'$OLDID'] =
'';
383 $keys[
'$NEWPAGE'] =
'';
385 $keys[
'$CHANGEDORCREATED'] =
wfMessage(
'created' )->inContentLanguage()->text();
388 $keys[
'$PAGETITLE'] = $this->title->getPrefixedText();
389 $keys[
'$PAGETITLE_URL'] = $this->title->getCanonicalURL();
390 $keys[
'$PAGEMINOREDIT'] = $this->minorEdit ?
391 "\n\n" .
wfMessage(
'enotif_minoredit' )->inContentLanguage()->text() :
393 $keys[
'$UNWATCHURL'] = $this->title->getCanonicalURL(
'action=unwatch' );
395 if ( !$this->editor->isRegistered() ) {
396 # real anon (user:xxx.xxx.xxx.xxx)
397 $keys[
'$PAGEEDITOR'] =
wfMessage(
'enotif_anon_editor', $this->editor->getName() )
398 ->inContentLanguage()->text();
399 $keys[
'$PAGEEDITOR_EMAIL'] =
wfMessage(
'noemailtitle' )->inContentLanguage()->text();
402 $keys[
'$PAGEEDITOR'] = $config->get(
'EnotifUseRealName' ) && $this->editor->getRealName() !==
''
403 ? $this->editor->getRealName() : $this->editor->getName();
405 $keys[
'$PAGEEDITOR_EMAIL'] = $emailPage->getCanonicalURL();
408 $keys[
'$PAGEEDITOR_WIKI'] = $this->editor->getUserPage()->getCanonicalURL();
410 Skin::makeInternalOrExternalUrl(
wfMessage(
'helppage' )->inContentLanguage()->text() )
413 # Replace this after transforming the message, T37019
414 $postTransformKeys[
'$PAGESUMMARY'] = $this->summary ==
'' ?
' - ' : $this->summary;
421 $this->subject =
wfMessage(
'enotif_subject_' . $this->pageStatus )->inContentLanguage()
422 ->params( $pageTitle,
$keys[
'$PAGEEDITOR'] )->text();
427 $keys[
'$PAGEINTRO'] =
wfMessage(
'enotif_body_intro_' . $this->pageStatus )
428 ->inContentLanguage()
429 ->params( $pageTitle,
$keys[
'$PAGEEDITOR'], $pageTitleUrl )
432 $body =
wfMessage(
'enotif_body' )->inContentLanguage()->plain();
433 $body = strtr( $body,
$keys );
434 $body = $messageCache->
transform( $body,
false,
null, $this->title );
435 $this->body = wordwrap( strtr( $body, $postTransformKeys ), 72 );
437 # Reveal the page editor's address as REPLY-TO address only if
438 # the user has not opted-out and the option is enabled at the
439 # global configuration level.
441 $config->get(
'PasswordSender' ),
442 wfMessage(
'emailsender' )->inContentLanguage()->text()
444 if ( $config->get(
'EnotifRevealEditorAddress' )
445 && ( $this->editor->getEmail() !=
'' )
446 && $this->editor->getOption(
'enotifrevealaddr' )
448 $editorAddress = MailAddress::newFromUser( $this->editor );
449 if ( $config->get(
'EnotifFromEditor' ) ) {
450 $this->from = $editorAddress;
452 $this->from = $adminAddress;
453 $this->replyto = $editorAddress;
456 $this->from = $adminAddress;
458 $config->get(
'NoReplyAddress' )
473 if ( !$this->composed_common ) {
474 $this->composeCommonMailtext( $messageCache );
477 if ( MediaWikiServices::getInstance()->getMainConfig()->
get(
'EnotifImpersonal' ) ) {
478 $this->mailTargets[] = MailAddress::newFromUser( $user );
480 $this->sendPersonalised( $user,
$source );
488 if ( MediaWikiServices::getInstance()->getMainConfig()->
get(
'EnotifImpersonal' ) ) {
489 $this->sendImpersonal( $this->mailTargets );
508 $to = MailAddress::newFromUser( $watchingUser );
510 # $PAGEEDITDATE is the time and date of the page change
511 # expressed in terms of individual local time of the notification
512 # recipient, i.e. watching user
513 $mwServices = MediaWikiServices::getInstance();
514 $contLang = $mwServices->getContentLanguage();
515 $watchingUserName = (
516 $mwServices->getMainConfig()->get(
'EnotifUseRealName' ) &&
527 $contLang->userDate( $this->timestamp, $watchingUser->
getUser() ),
528 $contLang->userTime( $this->timestamp, $watchingUser->
getUser() )
534 if (
$source === self::WATCHLIST ) {
535 $headers[
'List-Help'] =
'https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Watchlist';
538 return UserMailer::send( $to, $this->from, $this->subject, $body, [
539 'replyTo' => $this->replyto,
540 'headers' => $headers,
551 if ( empty( $addresses ) ) {
555 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
563 wfMessage(
'enotif_impersonal_salutation' )->inContentLanguage()->text(),
564 $contLang->date( $this->timestamp,
false,
false ),
565 $contLang->time( $this->timestamp,
false,
false )
570 return UserMailer::send( $addresses, $this->from, $this->subject, $body, [
571 'replyTo' => $this->replyto,
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
if(ini_get('mbstring.func_overload')) if(!defined('MW_ENTRY_POINT'))
Pre-config setup: Before loading LocalSettings.php.
This module processes the email notifications when the current page is changed.
sendPersonalised(UserEmailContact $watchingUser, $source)
Does the per-user customizations to a notification e-mail (name, timestamp in proper timezone,...
sendImpersonal( $addresses)
Same as sendPersonalised but does impersonal mail suitable for bulk mailing.
MailAddress null $replyto
const ALL_CHANGES
Notification because user is notified for all changes.
sendMails()
Send any queued mails.
canSendUserTalkEmail(UserIdentity $editor, $title, $minorEdit)
actuallyNotifyOnPageChange(Authority $editor, $title, $timestamp, $summary, $minorEdit, $oldid, $watchers, $pageStatus='changed')
Immediate version of notifyOnPageChange().
const WATCHLIST
Notification is due to a watchlisted page being edited.
notifyOnPageChange(Authority $editor, $title, $timestamp, $summary, $minorEdit, $oldid=false, $pageStatus='changed')
Send emails corresponding to the user $editor editing the page $title.
const USER_TALK
Notification is due to user's user talk being edited.
composeCommonMailtext(MessageCache $messageCache)
Generate the generic "this page has been changed" e-mail text.
compose(UserEmailContact $user, $source, MessageCache $messageCache)
Compose a mail to a given user and either queue it for sending, or send it now, depending on settings...
getPageStatus()
Extensions that have hooks for UpdateUserMailerFormattedPageStatus (to provide additional pageStatus ...
MailAddress[] $mailTargets
Job for email notification mails.
static singleton( $domain=false)
Stores a single person's name and email address.
Cache of messages that are defined by MediaWiki namespace pages or by hooks.
transform( $message, $interface=false, $language=null, PageReference $page=null)
static getSafeTitleFor( $name, $subpage=false)
Get a localised Title object for a page name with a possibly unvalidated subpage.
Represents a title within MediaWiki.
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
static newFromName( $name, $validate='valid')
isAllowed(string $permission)
Checks whether this authority has the given permission in general.