Add an opt-in, per-instructor email notice sent when someone books one of their lessons or enrols in one of their group classes. Off by default and set from My Availability → Notifications; covers both the student/guardian REST flows and the studio's wp-admin "book/add for a student" forms. The opt-in check lives in InstructorNotificationMailer so no booking path can drift on who is mailed; lessons fire from LessonBooker::settle (the one step both booking paths reach), enrolments from EnrollmentEndpoint::enroll and GroupClassController::addDirect. The notice is a courtesy and never fails a booking or enrolment that otherwise succeeded. Co-authored-by: anthropic/claude-opus-4-8
4.4 KiB
Feature: Instructor Booking Notifications
Overview
An instructor can ask to be emailed whenever someone books one of their private lessons or enrols in one of their group classes. It is off by default and set per instructor — the people it emails decide whether they want it.
The notice fires whichever way the booking or enrolment was made: a student (or a guardian for their child) doing it themselves through the front-end, or the studio doing it on their behalf from wp-admin. There is no separate "the studio booked it" case to forget — every path funnels through one place per registration type, and the opt-in check lives in the mailer, not at each call site, so no path can drift on who gets mailed.
Preference us_notify_on_booking (user meta)
'1' or '0', stored against the instructor's WordPress user. Absent — the
default for every account — reads as off. Stored as '0' rather than deleted when
an instructor turns it off, so a deliberate "no" is told apart from never having
chosen.
Default off because the notification is a new capability: turning it on for every instructor on an existing site the day it ships would mail people who never asked.
Admin Interface
My Availability → Notifications (manage_availability — every instructor sees
their own availability page):
- Email me when someone books a lesson or enrols in one of my group classes —
a single checkbox, off by default, saved on its own form (
usc_action=save_notify).
The page an instructor sets availability on is the one they already visit to shape their teaching schedule, so the preference about that schedule lives beside it.
What triggers a notice
| Registration | Path | Where the notice fires |
|---|---|---|
| Private lesson | student/guardian REST and studio wp-admin form | Booking\LessonBooker::settle() — the single step both paths reach once a slot is claimed |
| Group class | student/guardian REST | GroupClass\EnrollmentEndpoint::enroll(), after the roster row is written |
| Group class | studio "Add students directly" (wp-admin) | GroupClass\GroupClassController::addDirect(), per student added |
A weekly lesson reservation reports the number of occurrences claimed, so a single booking and a term booked at once each read correctly.
The notice is an opt-in courtesy, never a step a booking or enrolment depends on: a missing or failed send can never fail a booking that otherwise succeeded, and the mailer returns false (without sending) when the instructor has not opted in, their account is gone, or it carries no email.
Implementation
Unsupervised\Schedular\Auth\InstructorNotificationPref— the per-instructor user-meta preference (wants()/set()), default offUnsupervised\Schedular\Auth\InstructorNotificationMailer—notifyLessonBooked()andnotifyEnrollment(); the opt-in check and recipient resolution live hereUnsupervised\Schedular\Booking\LessonBooker::settle()— fires the lesson notice for both booking pathsUnsupervised\Schedular\GroupClass\EnrollmentEndpoint::enroll()— student/guardian enrolment noticeUnsupervised\Schedular\GroupClass\GroupClassController::addDirect()— studio enrolment noticeUnsupervised\Schedular\Availability\AvailabilityController— reads the preference for the page and saves the toggle (save_notify)templates/admin/availability.php— the Notifications checkbox
All three consumers take the mailer (and the controller its preference) as a
constructor dependency defaulting to a fresh instance, so existing wiring in
Plugin, RestRegistrar and AdminMenu is unchanged.
Tests
tests/Unit/Auth/InstructorNotificationPrefTest.php— default-off, opt-in read, string-boolean write, non-user guardstests/Unit/Auth/InstructorNotificationMailerTest.php— sends to an opted-in instructor, weekly occurrence count, and sends nothing when opted out / account gone / no emailtests/Unit/GroupClass/EnrollmentEndpointTest.php— a successful enrolment notifies the class instructortests/Unit/Availability/AvailabilityControllerTest.php— the toggle saves an opt-in and an opt-out- The booking-path tests (
BookingEndpointTest,AdminBookingTest) inject a mock mailer, keeping them about booking
Related
lesson-booking.md— the booking core the lesson notice hangs offgroup-classes.md— the enrolment paths the class notice hangs offuser-roles.md— the instructor role andmanage_availabilitycapability