Suggestion: let members opt out of announcement emails, per space (FluentCommunity 2.9.1)
Writing this one as a community operator rather than as a translator. We run a
German-speaking community on FluentCommunity with a few hundred members, and
this is the single setting our members ask for most often.
Everything below is measured against 2.9.1 on a live install, not inferred
from the docs.
What members see today
Under Notification Settings, the per-space table is exactly right in shape:
New Posts Notifications
Subscribe to new posts notifications by space.| Space | Email Disabled | Notify only for Admin Posts | Notify for all posts |
Three choices per space, stored as np_by_member_mail_<id> and
np_by_admin_mail_<id>. Clear, and members understand it immediately.
What it does not cover
When an admin ticks Email everyone while posting, that email reaches every
member of the space regardless of what they chose in this table. Someone who
set Email Disabled for a space still gets it.
That is not a bug in the table β the announcement path simply never reads those
keys. emailNotifyUsersForEveryoneTag() in
app/Hooks/Handlers/EmailNotificationHandler.php builds its own recipient
query, and the only preference it honours is the mention key:
->where('event_key', 'mention')
So the one way a member can currently escape announcement emails is to switch
off Someone mentions me β and lose every mention notification along with it.
The global switch has the same problem from the admin side:
public static function hasEmailAnnouncementEnabled()
{
$settings = self::getEmailNotificationSettings();
return Arr::get($settings, 'mention_mail', 'no') === 'yes';
}
Utility.php:502. Turning announcements off site-wide means turning mention
emails off site-wide. The two are not related features, and tying them together
means neither can be configured on its own.
For us this is not theoretical. Members who like the community but not the
volume of announcement mail have no option except unsubscribing from mentions,
which is the notification they actually want.
And the table currently tells them something that is not true. A member
with no stored row for a space sees Email Disabled selected β that is what
getNotificationPreferance() returns for an empty preference β and then
receives announcement emails from that very space. The radio button is not
just missing an option; the one it shows is wrong.
Suggestion A: a fourth choice in the same row
The table already has the right shape, and the two storage keys already exist
separately. One more option turns the row into a proper scale:
| Space | Email Disabled | Notify only for announcements | Notify only for Admin Posts | Notify for all posts |
Reading left to right: nothing β only what the admin explicitly sends to
everyone β also ordinary admin posts β everything. The new value would sit
alongside all_member_posts and admin_only_posts in
ProfileController::getNotificationPreferance() and
saveNotificationPreferance(), say as announcements_only, plus one new
string:
'Notify only for announcements' => __('Notify only for announcements', 'fluent-community'),
And emailNotifyUsersForEveryoneTag() would read that per-space value instead
of the mention key.
This is the version we would prefer, because it puts the setting where members
already look for it, and because it is the same table, not a second place to
configure notifications.
And it should be the new default
Not as a change of behaviour β as a name for the behaviour you already have.
A member with no stored row for a space receives no email about ordinary
posts: notifyOnPostCreated() only queries members who have a row with
value = 1 for that space, so no row means no mail. The same member receives
every announcement, because that path ignores those rows entirely. In
other words, the state announcements only is what almost everybody is in
right now. It simply has no name and no radio button.
On our installation, measured today: 233 members, 26 of them with any
per-space preference at all. For the other 207 β 89 percent β selecting
announcements_only as the default would describe exactly what they already
experience, and change nothing about what lands in their inbox.
That makes the migration free: no data to convert, no behaviour to
communicate, no surprise for anyone on upgrade. What changes is that the
table starts telling the truth, and that a member who wants out can finally
click Email Disabled and have it mean what it says.
Suggestion B: if that is not wanted, three hooks
We built our own plugin for this, and it works, but every one of its three
moving parts exists only because there is no hook at the right spot. Each of the
following is a one-line addition.
1. A filter on the announcement recipients. This is the important one.
// EmailNotificationHandler::emailNotifyUsersForEveryoneTag(), before the send loop
$users = apply_filters('fluent_community/announcement_email_recipients', $users, $feed);
Today the only filter in that method is
fluent_community/new_feed_everybody_notification/email_sections, which shapes
the body of a mail that has already been decided on. To suppress a single
recipient we have to hook pre_wp_mail and match on the address β which works,
but means reimplementing a decision the loop has already made, and it breaks the
moment the mail is sent through anything but wp_mail.
2. A hook when preferences are saved. saveNotificationPreferance()
currently has neither filter nor action, and NotificationPref::updateUserPrefs()
silently drops any key it does not recognise (resolveCell() returns null,
the loop does continue). So an extra preference cannot travel through the
existing form at all:
do_action('fluent_community/notification_prefs_saved', $xProfile->user_id, $request->all());
3. The per-space column list in the API response. The three radio columns
are hardcoded in the Vue app, so even though
fluent_community/profile_notification_pref_api_response lets us add data to
the payload, there is no way to render a fourth column. Shipping the options as
part of the response β and filtering them β would make the table extensible
without touching the frontend:
$data['space_pref_options'] = apply_filters('fluent_community/space_pref_options', [
['value' => '', 'label' => __('Email Disabled', 'fluent-community')],
['value' => 'admin_only_posts', 'label' => __('Notify only for Admin Posts', 'fluent-community')],
['value' => 'all_member_posts', 'label' => __('Notify for all posts', 'fluent-community')],
]);
With just number 1 we could drop the pre_wp_mail workaround. With all three we
could offer the setting inside your table instead of on a separate page, which
is where members expect it.
One more thing, independent of the above
Even if neither suggestion lands: please decouple
hasEmailAnnouncementEnabled() from mention_mail. An admin who wants to stop
announcement emails site-wide should not have to stop mention emails as well.
A separate setting key, defaulting to the current value so nothing changes on
upgrade, would fix that on its own.
Happy to send a PR for any of this.