From fd88dcf025cfd23996e3627fbb128c796c71f829 Mon Sep 17 00:00:00 2001 From: Viktor Miller Date: Wed, 14 Jan 2026 20:59:56 +0900 Subject: [PATCH] docs(06): create Phase 6 email notifications plans Phase 6: Email Notifications - 3 plans created - 6 total tasks defined - Parallel execution: 06-01 and 06-02 in Wave 1, 06-03 in Wave 2 - Ready for execution Plans: - 06-01: Mentor notification opt-in (2 tasks) - 06-02: Action Scheduler integration (2 tasks) - 06-03: Async batch email processing (2 tasks) Co-Authored-By: Claude Sonnet 4.5 --- .../06-email-notifications/06-01-PLAN.md | 115 ++++++++++++++++ .../06-email-notifications/06-02-PLAN.md | 119 ++++++++++++++++ .../06-email-notifications/06-03-PLAN.md | 128 ++++++++++++++++++ 3 files changed, 362 insertions(+) create mode 100644 .planning/phases/06-email-notifications/06-01-PLAN.md create mode 100644 .planning/phases/06-email-notifications/06-02-PLAN.md create mode 100644 .planning/phases/06-email-notifications/06-03-PLAN.md diff --git a/.planning/phases/06-email-notifications/06-01-PLAN.md b/.planning/phases/06-email-notifications/06-01-PLAN.md new file mode 100644 index 0000000..79eb204 --- /dev/null +++ b/.planning/phases/06-email-notifications/06-01-PLAN.md @@ -0,0 +1,115 @@ +--- +phase: 06-email-notifications +plan: 01 +type: execute +depends_on: [] +files_modified: [includes/class-user-preferences.php, includes/class-ddhh-job-manager.php, ddhh-job-manager.php] +--- + + +Enable mentors to opt-in to email notifications for new published jobs via user profile toggle. + +Purpose: Allow mentors (subscribers) to control whether they receive notifications when new jobs are published, respecting user preferences and avoiding unwanted emails. +Output: User meta field for notification preference with profile UI toggle for opt-in/opt-out. + + + +~/.claude/get-shit-done/workflows/execute-plan.md +./summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/STATE.md + +# Prior work this plan builds on: +@.planning/phases/03-job-management-core/03-03-SUMMARY.md + +# Relevant context: +PROJECT.md line 42: "Existing users: Mentors already exist as subscribers" +PROJECT.md line 27: "Mentor opt-in notification system for new published jobs" + +**Tech stack available:** User meta functions (get_user_meta, update_user_meta), profile hooks (show_user_profile, edit_user_profile, personal_options_update, edit_user_profile_update) +**Established patterns:** +- Singleton pattern for classes (Phase 01-02) +- Static setup_hooks() method for initialization (all phases) +- German labels for UI (Phase 01-02, 02-01, 03-01) +- Class file loading in main plugin file (all phases) + +**Constraining decisions:** +- PROJECT.md: Mentors are WordPress subscribers (existing role) +- PROJECT.md: Opt-in system (not opt-out) - users must explicitly enable notifications +- Phase 03-03: Email notifications use wp_mail with error logging + + + + + + Task 1: Create user preferences class with notification opt-in meta + includes/class-user-preferences.php, includes/class-ddhh-job-manager.php, ddhh-job-manager.php + Create new file includes/class-user-preferences.php with class DDHH_JM_User_Preferences. Add static method setup_hooks() that registers hooks for user profile display and saving. User meta key: 'ddhh_jm_notify_new_jobs' (boolean, default false = opt-out by default). Add method show_notification_toggle() that hooks to show_user_profile and edit_user_profile (both hooks needed - one for viewing own profile, one for admin editing). Display only for users with 'subscriber' role (mentors). Use checkbox input with label "Benachrichtigungen über neue Stellenangebote erhalten" (German: "Receive notifications about new job offers"). Add method save_notification_preference() that hooks to personal_options_update and edit_user_profile_update. Sanitize input with checkbox pattern: isset($_POST['ddhh_jm_notify_new_jobs']) ? '1' : '0'. Use update_user_meta() to save. Add nonce verification for security. Initialize class in includes/class-ddhh-job-manager.php by calling DDHH_JM_User_Preferences::setup_hooks() in init_hooks(). Add require_once in main plugin file ddhh-job-manager.php following established pattern. + Check includes/class-user-preferences.php exists with DDHH_JM_User_Preferences class. Verify setup_hooks() registered for profile display and save hooks. Confirm checkbox appears on subscriber user profiles. Verify user meta saves correctly when checkbox toggled. + User preferences class created, notification opt-in checkbox appears on mentor profiles, preference saves to user meta 'ddhh_jm_notify_new_jobs', class initialized in main plugin + + + + Task 2: Add helper method to query opted-in mentors + includes/class-user-preferences.php + Add static method get_opted_in_mentors() to DDHH_JM_User_Preferences class. Method returns array of user IDs who have opted in. Use WP_User_Query with arguments: role='subscriber' (mentors), meta_query for ddhh_jm_notify_new_jobs='1', fields='ID' (return only IDs for efficiency). Return empty array if no results. This provides clean API for Phase 06-03 to get notification recipients. Add error_log if query fails for debugging. Example usage: $mentor_ids = DDHH_JM_User_Preferences::get_opted_in_mentors(); foreach ($mentor_ids as $user_id) { /* send email */ } + Check get_opted_in_mentors() method exists. Verify it returns array of user IDs. Confirm WP_User_Query filters by subscriber role and meta value. Verify returns empty array when no opt-ins exist. + Helper method get_opted_in_mentors() exists, returns filtered list of opted-in mentor user IDs, ready for use in email batch processing + + + + + +Before declaring plan complete: +- [ ] User preferences class exists in includes/class-user-preferences.php +- [ ] Checkbox appears on subscriber user profiles (both own profile and admin edit) +- [ ] Preference saves correctly to user meta ddhh_jm_notify_new_jobs +- [ ] Helper method get_opted_in_mentors() returns correct user IDs +- [ ] Class properly initialized in main plugin +- [ ] German labels used for UI elements + + + + +- User preferences class created following singleton pattern +- Notification opt-in checkbox displayed on mentor (subscriber) profiles +- User meta field 'ddhh_jm_notify_new_jobs' saves preference (default: false/opt-out) +- Helper method available to query opted-in mentors by user ID +- UI uses German labels for consistency +- Nonce verification for security + + + +After completion, create `.planning/phases/06-email-notifications/06-01-SUMMARY.md`: + +# Phase 6 Plan 1: Mentor Notification Opt-In Summary + +**[Substantive one-liner - what shipped, not "phase complete"]** + +## Accomplishments + +- [Key outcome 1] +- [Key outcome 2] + +## Files Created/Modified + +- `includes/class-user-preferences.php` - Description +- `includes/class-ddhh-job-manager.php` - Description +- `ddhh-job-manager.php` - Description + +## Decisions Made + +[Key decisions and rationale, or "None"] + +## Issues Encountered + +[Problems and resolutions, or "None"] + +## Next Step + +Ready for parallel execution with 06-02 (Action Scheduler integration). Both 06-01 and 06-02 are independent and can run concurrently. + diff --git a/.planning/phases/06-email-notifications/06-02-PLAN.md b/.planning/phases/06-email-notifications/06-02-PLAN.md new file mode 100644 index 0000000..5658987 --- /dev/null +++ b/.planning/phases/06-email-notifications/06-02-PLAN.md @@ -0,0 +1,119 @@ +--- +phase: 06-email-notifications +plan: 02 +type: execute +depends_on: [] +files_modified: [vendor/action-scheduler/, includes/class-scheduler.php, includes/class-ddhh-job-manager.php, ddhh-job-manager.php] +--- + + +Integrate Action Scheduler library for async background job processing to enable non-blocking bulk email sends. + +Purpose: Prevent timeouts when sending emails to many mentors by processing email batches asynchronously in the background using WordPress's job queue system. +Output: Action Scheduler library loaded, scheduler helper class for managing async actions, ready for email batch processing in Phase 06-03. + + + +~/.claude/get-shit-done/workflows/execute-plan.md +./summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/STATE.md + +# Prior work this plan builds on: +@.planning/phases/03-job-management-core/03-03-SUMMARY.md + +**Tech stack available:** Action Scheduler (WooCommerce library), WordPress hooks, wp_mail +**Established patterns:** +- Static setup_hooks() method for class initialization (all phases) +- Singleton pattern for utility classes (Phase 01-02) +- German email templates with error logging (Phase 03-03, 04-02, 05-02) + +**Constraining decisions:** +- PROJECT.md line 29: "Async email processing via WP-Cron/Action Scheduler" +- ROADMAP.md Phase 6: Action Scheduler integration required for bulk email patterns +- PROJECT.md line 43: "Email: WP Mail SMTP on production; disabled in Local WP dev" + +**Action Scheduler integration requirements** (from Context7 discovery): +- Include library via require_once before plugins_loaded +- Load from vendor/action-scheduler/action-scheduler.php +- Register callbacks with add_action() for scheduled hooks +- Use as_enqueue_async_action() for ASAP background processing +- Use unique flag to prevent duplicate actions +- Group actions logically (e.g., 'email-notifications') + + + + + + Task 1: Download and include Action Scheduler library + vendor/action-scheduler/, ddhh-job-manager.php + Download Action Scheduler library (https://github.com/woocommerce/action-scheduler/releases) and place in vendor/action-scheduler/ directory. Use latest stable release (3.x). Include library in main plugin file ddhh-job-manager.php by adding require_once( plugin_dir_path( __FILE__ ) . 'vendor/action-scheduler/action-scheduler.php' ) BEFORE any other includes and class initializations (must load early for proper initialization). Add comment explaining why it loads first. Verify action-scheduler.php exists after download. Do NOT use Composer for this - manual download and include following WordPress plugin patterns. The library will auto-initialize itself when required. + Check vendor/action-scheduler/ directory exists with action-scheduler.php file. Verify require_once added to main plugin file before other includes. Confirm no PHP errors on plugin activation (action scheduler loaded successfully). + Action Scheduler library downloaded to vendor/action-scheduler/, included in main plugin file before other code, library successfully initialized + + + + Task 2: Create scheduler helper class for email batch actions + includes/class-scheduler.php, includes/class-ddhh-job-manager.php + Create includes/class-scheduler.php with class DDHH_JM_Scheduler. Add static method setup_hooks() (empty for now - Phase 06-03 will register callbacks). Add static method schedule_mentor_notification_batch() that takes array of user IDs and job post ID as parameters. Method chunks user IDs into batches of 50 (to avoid email provider limits and timeouts). For each batch, call as_enqueue_async_action() with hook 'ddhh_jm_send_mentor_notification_batch', args array containing batch user IDs and job ID, group 'email-notifications', unique flag true (prevent duplicates), priority 10. Return count of batches scheduled. Add error_log for debugging. Initialize class in includes/class-ddhh-job-manager.php by calling DDHH_JM_Scheduler::setup_hooks() in init_hooks(). Add require_once in main plugin file following established pattern (after Action Scheduler include). + Check includes/class-scheduler.php exists with DDHH_JM_Scheduler class. Verify schedule_mentor_notification_batch() method chunks users into batches of 50. Confirm as_enqueue_async_action() called for each batch with correct parameters. Verify class initialized in main plugin. + Scheduler helper class created, batch scheduling method exists with 50-user chunks, async actions enqueued via Action Scheduler, class initialized in plugin + + + + + +Before declaring plan complete: +- [ ] Action Scheduler library exists in vendor/action-scheduler/ +- [ ] Library loaded in main plugin file before other includes +- [ ] Scheduler helper class created in includes/class-scheduler.php +- [ ] Batch scheduling method chunks users appropriately +- [ ] Action Scheduler functions available (as_enqueue_async_action works) +- [ ] No PHP errors on plugin activation + + + + +- Action Scheduler library downloaded and included in plugin +- Library loads without errors before other plugin code +- Scheduler helper class provides batch scheduling API +- Email batches limited to 50 recipients per async action +- Async actions properly enqueued with unique flag and grouping +- Infrastructure ready for Phase 06-03 email processing + + + +After completion, create `.planning/phases/06-email-notifications/06-02-SUMMARY.md`: + +# Phase 6 Plan 2: Action Scheduler Integration Summary + +**[Substantive one-liner - what shipped, not "phase complete"]** + +## Accomplishments + +- [Key outcome 1] +- [Key outcome 2] + +## Files Created/Modified + +- `vendor/action-scheduler/` - Description +- `includes/class-scheduler.php` - Description +- `includes/class-ddhh-job-manager.php` - Description +- `ddhh-job-manager.php` - Description + +## Decisions Made + +[Key decisions and rationale, or "None"] + +## Issues Encountered + +[Problems and resolutions, or "None"] + +## Next Step + +Ready for parallel execution with 06-01 (Mentor opt-in). Both 06-01 and 06-02 are independent and can run concurrently. + diff --git a/.planning/phases/06-email-notifications/06-03-PLAN.md b/.planning/phases/06-email-notifications/06-03-PLAN.md new file mode 100644 index 0000000..f7903ca --- /dev/null +++ b/.planning/phases/06-email-notifications/06-03-PLAN.md @@ -0,0 +1,128 @@ +--- +phase: 06-email-notifications +plan: 03 +type: execute +depends_on: ["06-01", "06-02"] +files_modified: [includes/class-notifications.php, includes/class-scheduler.php] +--- + + +Send async batch email notifications to opted-in mentors when jobs are published, preventing timeouts with background processing. + +Purpose: Notify mentors about new job opportunities in real-time without blocking the admin's publish action, respecting user opt-in preferences and email provider limits. +Output: Automated email notifications to opted-in mentors on job publish, processed asynchronously in batches. + + + +~/.claude/get-shit-done/workflows/execute-plan.md +./summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/STATE.md + +# Prior work this plan builds on: +@.planning/phases/03-job-management-core/03-03-SUMMARY.md +@.planning/phases/04-job-deactivation-system/04-02-SUMMARY.md +@.planning/phases/05-mentor-job-board/05-02-SUMMARY.md +@.planning/phases/06-email-notifications/06-01-SUMMARY.md +@.planning/phases/06-email-notifications/06-02-SUMMARY.md + +# Source files: +@includes/class-notifications.php +@includes/class-scheduler.php +@includes/class-user-preferences.php + +**Tech stack available:** Action Scheduler (from 06-02), wp_mail, get_user_meta, WP_User_Query, get_field (ACF), transition_post_status hook +**Established patterns:** +- German email templates with error logging (Phase 03-03, 04-02, 05-02) +- transition_post_status hook for detecting status changes (Phase 03-03, 04-02) +- Notification class with static methods (Phase 03-03) +- Action Scheduler batch processing (Phase 06-02) + +**Constraining decisions:** +- Phase 06-01: User meta 'ddhh_jm_notify_new_jobs' indicates opt-in status +- Phase 06-01: get_opted_in_mentors() returns array of opted-in user IDs +- Phase 06-02: schedule_mentor_notification_batch() handles batch scheduling +- Phase 06-02: Callback hook 'ddhh_jm_send_mentor_notification_batch' needs implementation +- Phase 03-03: Email templates in German, use error_log for failures +- Phase 03-03: Only trigger on specific transitions (avoid spam on every save) +- PROJECT.md line 27: "Mentor opt-in notification system for new published jobs" + + + + + + Task 1: Add job publish hook to schedule mentor notifications + includes/class-notifications.php + Add method notify_mentors_on_job_publish() to DDHH_JM_Notifications class. Hook to transition_post_status at priority 10 following established pattern. Method parameters: $new_status, $old_status, $post. Check: (1) post_type is 'job_offer', (2) new_status is 'publish', (3) old_status is NOT 'publish' (only notify on initial publish, not updates). If checks pass, get opted-in mentors via DDHH_JM_User_Preferences::get_opted_in_mentors(). If empty array, log "No opted-in mentors to notify" and return (no error - valid scenario). If mentors found, call DDHH_JM_Scheduler::schedule_mentor_notification_batch() with mentor IDs and $post->ID. Log success with count: "Scheduled X notification batches for job ID Y". Register hook in setup_hooks() method: add_action('transition_post_status', array(__CLASS__, 'notify_mentors_on_job_publish'), 10, 3). This triggers async batch processing without blocking the publish action. + Check includes/class-notifications.php contains notify_mentors_on_job_publish() method. Verify transition_post_status hook registered in setup_hooks(). Confirm method only triggers on pending/draft→publish transitions. Verify calls to user preferences and scheduler classes. + Job publish hook implemented, triggers only on initial publish, queries opted-in mentors, schedules async batches via scheduler, hook registered in notifications class + + + + Task 2: Implement async batch email processor callback + includes/class-scheduler.php + Add method process_mentor_notification_batch() to DDHH_JM_Scheduler class. Method parameters: $user_ids (array), $job_id (int). For each user ID in batch: (1) Get user data with get_userdata($user_id), skip if null (user deleted). (2) Get user email. (3) Get job details: post_title, get_field('job_location'), get_field('job_type'), permalink (for "View Job" link). (4) Prepare German email subject: "Neues Stellenangebot: {job_title}". (5) Prepare German email body: "Hallo,\n\nein neues Stellenangebot wurde veröffentlicht:\n\nStelle: {job_title}\nStandort: {job_location}\nArt: {job_type}\n\nSie können das Angebot hier ansehen:\n{permalink}\n\nUm keine weiteren Benachrichtigungen zu erhalten, können Sie diese in Ihrem Profil deaktivieren.\n\nDiese E-Mail wurde automatisch gesendet." (6) Send email with wp_mail($email, $subject, $body). (7) If wp_mail fails, log error: "Failed to send mentor notification to user {$user_id} for job {$job_id}". (8) Add small delay (usleep(100000) = 0.1 seconds) between emails to avoid rate limits. After loop, log success: "Processed notification batch: {count} emails sent for job {$job_id}". Register callback in setup_hooks(): add_action('ddhh_jm_send_mentor_notification_batch', array(__CLASS__, 'process_mentor_notification_batch'), 10, 2). This executes asynchronously when Action Scheduler processes the queue. + Check includes/class-scheduler.php contains process_mentor_notification_batch() method. Verify callback registered in setup_hooks() for hook 'ddhh_jm_send_mentor_notification_batch'. Confirm German email template with job details and permalink. Verify error logging for failed sends. Confirm rate limit delay between emails. + Batch processor callback implemented, sends German emails with job details, includes unsubscribe hint, logs errors, has rate limit delay, callback registered for Action Scheduler hook + + + + + +Before declaring plan complete: +- [ ] Job publish hook triggers only on initial publish (not updates) +- [ ] Opted-in mentors queried via user preferences class +- [ ] Batch scheduling called via scheduler class +- [ ] Async callback registered for Action Scheduler hook +- [ ] Email template in German with job details +- [ ] Error logging for failures +- [ ] Rate limit delay between emails +- [ ] Unsubscribe hint included in emails + + + + +- Job publish triggers async mentor notifications +- Only opted-in mentors receive emails +- Emails processed in background (no blocking) +- Batches of 50 users prevent timeouts +- German email template with job details and link +- Error logging for debugging +- Rate limit compliance (0.1s delay between sends) +- Users informed how to opt-out in email +- Phase 6 complete - async notification system fully functional + + + +After completion, create `.planning/phases/06-email-notifications/06-03-SUMMARY.md`: + +# Phase 6 Plan 3: Async Mentor Notifications Summary + +**[Substantive one-liner - what shipped, not "phase complete"]** + +## Accomplishments + +- [Key outcome 1] +- [Key outcome 2] + +## Files Created/Modified + +- `includes/class-notifications.php` - Description +- `includes/class-scheduler.php` - Description + +## Decisions Made + +[Key decisions and rationale, or "None"] + +## Issues Encountered + +[Problems and resolutions, or "None"] + +## Next Step + +Phase 6 complete. Ready for Phase 7: Testing & Polish (end-to-end testing, UI refinement, deployment preparation). +