Page MenuHomePhabricator

RFE: Hook to change Enotif recipient list
Open, LowPublicFeature

Description

Author: software

Description:
Move variable instantiation out of the actuallyNotifyOnPageChange() function

This is a request for enhancement, but it must be fixed in Mediawiki, and can not be solved by writing an extension (actually it is a blocker for my extension).

The core of the problem is that the function EmailNotification::actuallyNotifyOnPageChange in UserMailer.php does three very distinct things in one functions:

  1. Initialise protected instance variables
  2. Compose a list of email addresses (using the watchlist and $wgUsersNotifiedOnAllChanges setting)
  3. Send email (through the use of the compose() and sendMails() helper functions)

This mix of functionality in a single function makes it impossible to:

  1. Change the list of email addresses
  2. Use the helper functions to send emails, since both compose() and sendMails() require that the instance variables ($this->title, $this->editor, etc.) are set, and EmailNotification::actuallyNotifyOnPageChange is the only function that can set this.

I'm currently writing an extension that sends email notification for unpatrolled (= not autopatrolled) changes (implementing $wgUsersNotifiedOnUnpatrolledChanges, similar to the existing $wgUsersNotifiedOnAllChanges). Unfortunately, the above limitations make it impossible for me to use the EmailNotification class.

The ideal would be if there is a hook that allows alteration of the list of recipients (as hinted on by r44960), but failing that, please at least move the initialisation of protected variables to its own function (e.g. using the attached patch)

Notes:

Note 1: The patch removes the unused $to and $user instances variables, since they are not used anywhere.

Note 2: I'm not sure why this class does not have a construct() function, but there may have design reasons I'm not aware of. For that reason, I did not change any behaviour and used construct() instead of construct() in the patch.

Note 3: Adding a hook function is the best solution because of flexibility and performance reasons (composeCommonMailtext() would only be called once; and the JobQueue would automatically be used if $wgEnotifUseJobQ is set). However, I'm not very familiar how MediaWiki uses hooks, so I rather have some feedback on that from experienced developers.

Note 4: I'm note sure what the best place for the hook function is. My intended extension needs access to the (auto)patrol flag of the RecentChange, but this does not seem available to the EmailNotification class. Again, it is highly desirable to make a first split between the function of selecting email addresses on one hand, and sending the actual mail on the other hand.


Version: 1.20.x
Severity: enhancement

Attached:

Details

Reference
bz33537

Event Timeline

bzimport raised the priority of this task from to Low.Nov 22 2014, 12:10 AM
bzimport added a project: MediaWiki-Email.
bzimport set Reference to bz33537.
bzimport added a subscriber: Unknown Object (MLST).

The more standard "mediawiki way" is usually to build up the list, and then insert a hook after the building, but before the action, to allow extensions to add/remove from the array

software wrote:

I can contribute to one or more patches that:

  1. First build a list of recipients before sending them all (curently, the compose() function is called at multiple places.)
  2. Add a hook function with (a pointer to) the recipient list, so extension can modify the list.
  3. Modify the parameters in the existing function so the hook can include a pointer to the recentchange flags, or even to the recentchange instance.

Does this sound reasonable?

What should the hook function look like?

'ActionModifyEnotifRecipients': before sending email notifications about page
changes or creations; allows change the list of recipients.
&$recipients: list of recipients
$editor: User object
$title: Title object
$timestamp: string representing timestamp of the edit
$summary: string summary of the edit, provided by the editor
$rc: RecentChange object

This proposal only allows modifications to the recipient list. It does not allow modifications of the mail body, subject, etc. Would it be useful to include those parameters as well, or would those be subject of another hook?

actuallyNotifyOnPageChange() currently only knows about oldid (to distinguish between page change and page create) and minorEdit. It seems to me that the parameters bot, patrolled, old_len and new_len (to check if it really is such a minor edit) and perhaps others are relevant as well to judge if an email alert is warranted or not. To make it flexible, I propose to include a pointer to the RecentChange object, even it requires a modification of the parameters of actuallyNotifyOnPageChange().

A last issue is that the above proposal places the extension hook in EmailNotification class. It is also possible to put the hook in the RecentChange class. In fact the aforementioned r44960 added line 217 to RecentChange.php, just when calling EmailNotification:

  1. @todo FIXME: This would be better as an extension hook

Once we agree on the location and syntax of the hook, I can write a patch.

Created attachment 9815
the mediawiki way?

I think the attached diff would be more in line with Reedy's proposal. It'd be nice if RecentChanges handled Status objects, too.

Attached:

You are returning a Status object, but notifyOnPageChange() doesn't return anything (so the user-mail-enotif-list message is also unneeded).
Also, I think you are passing too few parameters. You would want at least $watchers there, which could be modified to add/remove addresses (eg. you could have an extension which mailed a different team depending on the day of the week), something like the parameters of actuallyNotifyOnPageChange.
Probably placed above "if ( $watchers ) {", but moving it outside its outer if.

Aklapper changed the subtype of this task from "Task" to "Feature Request".Feb 4 2022, 11:14 AM
Aklapper removed a subscriber: wikibugs-l-list.