Add notify_mentors_on_job_publish() method to trigger async batch notifications when jobs transition to publish status. Only triggers on initial publish (not updates). Queries opted-in mentors via User Preferences class and schedules batches via Scheduler class. Logs notification scheduling with mentor count and batch count. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
390 lines
11 KiB
PHP
390 lines
11 KiB
PHP
<?php
|
|
/**
|
|
* Email notification system for job submissions
|
|
*
|
|
* @package DDHH_Job_Manager
|
|
*/
|
|
|
|
// Exit if accessed directly.
|
|
defined( 'ABSPATH' ) || exit;
|
|
|
|
/**
|
|
* Handles email notifications for job submissions
|
|
*/
|
|
class DDHH_JM_Notifications {
|
|
|
|
/**
|
|
* Setup notification hooks
|
|
*/
|
|
public static function setup_hooks() {
|
|
// Hook into post status transitions to detect new pending job submissions
|
|
add_action( 'transition_post_status', array( __CLASS__, 'send_admin_new_job_notification' ), 10, 3 );
|
|
|
|
// Hook into post status transitions to detect job deactivations
|
|
add_action( 'transition_post_status', array( __CLASS__, 'send_admin_job_deactivation_notification' ), 10, 3 );
|
|
|
|
// Hook into post status transitions to notify mentors on job publish
|
|
add_action( 'transition_post_status', array( __CLASS__, 'notify_mentors_on_job_publish' ), 10, 3 );
|
|
|
|
// Hook into Formidable form submissions to send application notifications
|
|
add_action( 'frm_after_create_entry', array( __CLASS__, 'send_provider_application_notification' ), 30, 2 );
|
|
}
|
|
|
|
/**
|
|
* Send admin notification when a new job is submitted for moderation
|
|
*
|
|
* @param string $new_status New post status.
|
|
* @param string $old_status Old post status.
|
|
* @param WP_Post $post Post object.
|
|
*/
|
|
public static function send_admin_new_job_notification( $new_status, $old_status, $post ) {
|
|
// Only trigger on job_offer posts transitioning to pending
|
|
if ( 'job_offer' !== $post->post_type ) {
|
|
return;
|
|
}
|
|
|
|
// Only send notification on initial submission to pending
|
|
// Avoid sending on every save when already pending
|
|
if ( 'pending' !== $new_status || 'pending' === $old_status ) {
|
|
return;
|
|
}
|
|
|
|
// Get admin email
|
|
$admin_email = get_option( 'admin_email' );
|
|
if ( ! $admin_email ) {
|
|
error_log( 'DDHH Job Manager: Cannot send admin notification - admin_email option not set' );
|
|
return;
|
|
}
|
|
|
|
// Prepare email data
|
|
$job_title = $post->post_title;
|
|
$author = get_userdata( $post->post_author );
|
|
$author_name = $author ? $author->display_name : 'Unbekannt';
|
|
$author_org = get_user_meta( $post->post_author, 'ddhh_org_name', true );
|
|
if ( empty( $author_org ) ) {
|
|
$author_org = 'Nicht angegeben';
|
|
}
|
|
|
|
// Get ACF fields
|
|
$job_location = get_field( 'job_location', $post->ID );
|
|
$job_type = get_field( 'job_type', $post->ID );
|
|
|
|
// Get submission date
|
|
$submission_date = get_the_date( 'd.m.Y H:i', $post->ID );
|
|
|
|
// Get edit link
|
|
$edit_link = get_edit_post_link( $post->ID, '' );
|
|
|
|
// Build email subject
|
|
$subject = sprintf( 'Neues Stellenangebot zur Prüfung: %s', $job_title );
|
|
|
|
// Build email body
|
|
$body = sprintf(
|
|
"Ein neues Stellenangebot wurde eingereicht und wartet auf Ihre Prüfung.\n\n" .
|
|
"Titel: %s\n" .
|
|
"Anbieter: %s (%s)\n" .
|
|
"Standort: %s\n" .
|
|
"Art: %s\n" .
|
|
"Eingereicht am: %s\n\n" .
|
|
"Prüfen Sie das Stellenangebot hier:\n%s\n\n" .
|
|
"---\n" .
|
|
"Diese E-Mail wurde automatisch gesendet.",
|
|
$job_title,
|
|
$author_name,
|
|
$author_org,
|
|
$job_location ? $job_location : 'Nicht angegeben',
|
|
$job_type ? $job_type : 'Nicht angegeben',
|
|
$submission_date,
|
|
$edit_link
|
|
);
|
|
|
|
// Set email headers
|
|
$headers = array( 'Content-Type: text/html; charset=UTF-8' );
|
|
|
|
// Convert plain text to HTML with line breaks
|
|
$html_body = nl2br( esc_html( $body ) );
|
|
|
|
// Send email
|
|
$sent = wp_mail( $admin_email, $subject, $html_body, $headers );
|
|
|
|
// Log if email fails
|
|
if ( ! $sent ) {
|
|
error_log(
|
|
sprintf(
|
|
'DDHH Job Manager: Failed to send admin notification for job #%d "%s". Email may be disabled in Local WP environment.',
|
|
$post->ID,
|
|
$job_title
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Send admin notification when a job is deactivated by provider
|
|
*
|
|
* @param string $new_status New post status.
|
|
* @param string $old_status Old post status.
|
|
* @param WP_Post $post Post object.
|
|
*/
|
|
public static function send_admin_job_deactivation_notification( $new_status, $old_status, $post ) {
|
|
// Only trigger on job_offer posts transitioning from publish to draft
|
|
if ( 'job_offer' !== $post->post_type ) {
|
|
return;
|
|
}
|
|
|
|
// Only send notification when published job becomes draft (deactivation)
|
|
// Avoid notification on draft saves or initial draft creation
|
|
if ( 'draft' !== $new_status || 'publish' !== $old_status ) {
|
|
return;
|
|
}
|
|
|
|
// Get admin email
|
|
$admin_email = get_option( 'admin_email' );
|
|
if ( ! $admin_email ) {
|
|
error_log( 'DDHH Job Manager: Cannot send deactivation notification - admin_email option not set' );
|
|
return;
|
|
}
|
|
|
|
// Prepare email data
|
|
$job_title = $post->post_title;
|
|
$author = get_userdata( $post->post_author );
|
|
$author_name = $author ? $author->display_name : 'Unbekannt';
|
|
$author_org = get_user_meta( $post->post_author, 'ddhh_org_name', true );
|
|
if ( empty( $author_org ) ) {
|
|
$author_org = 'Nicht angegeben';
|
|
}
|
|
|
|
// Get ACF fields
|
|
$job_location = get_field( 'job_location', $post->ID );
|
|
$job_type = get_field( 'job_type', $post->ID );
|
|
|
|
// Get deactivation reason from ACF field
|
|
$deactivation_reason = get_field( 'job_deactivation_reason', $post->ID );
|
|
if ( empty( $deactivation_reason ) ) {
|
|
$deactivation_reason = 'Kein Grund angegeben';
|
|
}
|
|
|
|
// Get deactivation date
|
|
$deactivation_date = current_time( 'd.m.Y H:i' );
|
|
|
|
// Get edit link
|
|
$edit_link = get_edit_post_link( $post->ID, '' );
|
|
|
|
// Build email subject
|
|
$subject = sprintf( 'Stellenangebot deaktiviert: %s', $job_title );
|
|
|
|
// Build email body
|
|
$body = sprintf(
|
|
"Ein Stellenangebot wurde vom Anbieter deaktiviert.\n\n" .
|
|
"Titel: %s\n" .
|
|
"Anbieter: %s (%s)\n" .
|
|
"Standort: %s\n" .
|
|
"Art: %s\n" .
|
|
"Deaktiviert am: %s\n\n" .
|
|
"Grund für Deaktivierung:\n%s\n\n" .
|
|
"Stelle ansehen:\n%s\n\n" .
|
|
"---\n" .
|
|
"Diese E-Mail wurde automatisch gesendet.",
|
|
$job_title,
|
|
$author_name,
|
|
$author_org,
|
|
$job_location ? $job_location : 'Nicht angegeben',
|
|
$job_type ? $job_type : 'Nicht angegeben',
|
|
$deactivation_date,
|
|
$deactivation_reason ? $deactivation_reason : 'Nicht angegeben',
|
|
$edit_link
|
|
);
|
|
|
|
// Set email headers
|
|
$headers = array( 'Content-Type: text/html; charset=UTF-8' );
|
|
|
|
// Convert plain text to HTML with line breaks
|
|
$html_body = nl2br( esc_html( $body ) );
|
|
|
|
// Send email
|
|
$sent = wp_mail( $admin_email, $subject, $html_body, $headers );
|
|
|
|
// Log if email fails
|
|
if ( ! $sent ) {
|
|
error_log(
|
|
sprintf(
|
|
'DDHH Job Manager: Failed to send admin deactivation notification for job #%d "%s". Email may be disabled in Local WP environment.',
|
|
$post->ID,
|
|
$job_title
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Send provider notification when a mentor applies to their job
|
|
*
|
|
* @param int $entry_id Entry ID.
|
|
* @param int $form_id Form ID.
|
|
*/
|
|
public static function send_provider_application_notification( $entry_id, $form_id ) {
|
|
// Only process job application form submissions
|
|
$application_form_id = DDHH_JM_Formidable::get_job_application_form_id();
|
|
if ( $form_id !== $application_form_id ) {
|
|
return;
|
|
}
|
|
|
|
// Get entry data
|
|
$entry = FrmEntry::getOne( $entry_id, true );
|
|
if ( ! $entry ) {
|
|
return;
|
|
}
|
|
|
|
// Extract field values
|
|
$applicant_name = '';
|
|
$applicant_email = '';
|
|
$applicant_message = '';
|
|
$job_id = 0;
|
|
|
|
foreach ( $entry->metas as $field_id => $value ) {
|
|
$field = FrmField::getOne( $field_id );
|
|
if ( ! $field ) {
|
|
continue;
|
|
}
|
|
|
|
switch ( $field->field_key ) {
|
|
case 'applicant_name':
|
|
$applicant_name = sanitize_text_field( $value );
|
|
break;
|
|
case 'applicant_email':
|
|
$applicant_email = sanitize_email( $value );
|
|
break;
|
|
case 'applicant_message':
|
|
$applicant_message = sanitize_textarea_field( $value );
|
|
break;
|
|
case 'job_id':
|
|
$job_id = absint( $value );
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Validate required fields
|
|
if ( empty( $applicant_name ) || empty( $applicant_email ) || empty( $applicant_message ) || empty( $job_id ) ) {
|
|
error_log( 'DDHH Job Manager: Missing required fields in job application submission' );
|
|
return;
|
|
}
|
|
|
|
// Get job post
|
|
$post = get_post( $job_id );
|
|
if ( ! $post || 'job_offer' !== $post->post_type ) {
|
|
error_log( sprintf( 'DDHH Job Manager: Invalid job_id %d in application submission', $job_id ) );
|
|
return;
|
|
}
|
|
|
|
// Get job details
|
|
$job_title = $post->post_title;
|
|
$job_location = get_field( 'job_location', $job_id );
|
|
$job_type = get_field( 'job_type', $job_id );
|
|
|
|
// Get provider contact email from ACF field
|
|
$provider_email = get_field( 'job_contact_email', $job_id );
|
|
if ( empty( $provider_email ) ) {
|
|
error_log(
|
|
sprintf(
|
|
'DDHH Job Manager: Cannot send application notification for job #%d - job_contact_email not set',
|
|
$job_id
|
|
)
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Build email subject
|
|
$subject = sprintf( 'Neue Bewerbung für: %s', $job_title );
|
|
|
|
// Build email body
|
|
$body = sprintf(
|
|
"Sie haben eine neue Bewerbung für Ihr Stellenangebot erhalten.\n\n" .
|
|
"Stelle: %s\n" .
|
|
"Standort: %s\n" .
|
|
"Art: %s\n\n" .
|
|
"--- Bewerber ---\n" .
|
|
"Name: %s\n" .
|
|
"E-Mail: %s\n\n" .
|
|
"Nachricht:\n%s\n\n" .
|
|
"---\n" .
|
|
"Bitte antworten Sie direkt an %s.\n\n" .
|
|
"Diese E-Mail wurde automatisch gesendet.",
|
|
$job_title,
|
|
$job_location ? $job_location : 'Nicht angegeben',
|
|
$job_type ? $job_type : 'Nicht angegeben',
|
|
$applicant_name,
|
|
$applicant_email,
|
|
$applicant_message,
|
|
$applicant_email
|
|
);
|
|
|
|
// Set email headers
|
|
$headers = array( 'Content-Type: text/html; charset=UTF-8' );
|
|
|
|
// Convert plain text to HTML with line breaks
|
|
$html_body = nl2br( esc_html( $body ) );
|
|
|
|
// Send email
|
|
$sent = wp_mail( $provider_email, $subject, $html_body, $headers );
|
|
|
|
// Log if email fails
|
|
if ( ! $sent ) {
|
|
error_log(
|
|
sprintf(
|
|
'DDHH Job Manager: Failed to send application notification for job #%d "%s". Email may be disabled in Local WP environment.',
|
|
$job_id,
|
|
$job_title
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notify opted-in mentors when a job is published
|
|
*
|
|
* @param string $new_status New post status.
|
|
* @param string $old_status Old post status.
|
|
* @param WP_Post $post Post object.
|
|
*/
|
|
public static function notify_mentors_on_job_publish( $new_status, $old_status, $post ) {
|
|
// Only trigger on job_offer posts
|
|
if ( 'job_offer' !== $post->post_type ) {
|
|
return;
|
|
}
|
|
|
|
// Only send notification on initial publish (not updates to already published posts)
|
|
if ( 'publish' !== $new_status || 'publish' === $old_status ) {
|
|
return;
|
|
}
|
|
|
|
// Get opted-in mentors
|
|
$mentor_ids = DDHH_JM_User_Preferences::get_opted_in_mentors();
|
|
|
|
// Check if any mentors opted in
|
|
if ( empty( $mentor_ids ) ) {
|
|
error_log(
|
|
sprintf(
|
|
'DDHH Job Manager: No opted-in mentors to notify for job #%d "%s"',
|
|
$post->ID,
|
|
$post->post_title
|
|
)
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Schedule async batch notifications
|
|
$batch_count = DDHH_JM_Scheduler::schedule_mentor_notification_batch( $mentor_ids, $post->ID );
|
|
|
|
// Log success
|
|
error_log(
|
|
sprintf(
|
|
'DDHH Job Manager: Scheduled %d notification batches for job #%d "%s" to %d mentors',
|
|
$batch_count,
|
|
$post->ID,
|
|
$post->post_title,
|
|
count( $mentor_ids )
|
|
)
|
|
);
|
|
}
|
|
}
|