upskill-event-manager/includes/class-hvac-approval-workflow.php
bengizmo a58ea1603c fix: Resolve duplicate initialization and jQuery selector errors
- Implement singleton pattern for HVAC_Enhanced_Settings to prevent duplicate initialization
- Fix jQuery selector error by checking for valid hash selectors before using $(href)
- Add default email templates with professional copy for trainer notifications
- Update plugin version to 1.0.1 for cache busting
- Remove duplicate Enhanced Settings initialization from HVAC_Community_Events
- Add force cache refresh suffix to admin scripts

This resolves the duplicate content issue on email templates page and fixes
JavaScript errors in the admin interface.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-28 17:58:39 -03:00

423 lines
No EOL
17 KiB
PHP

<?php
/**
* HVAC Community Events - Approval Workflow
*
* Handles trainer approval workflow and email notifications
*
* @package HVAC_Community_Events
* @since 1.0.0
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class HVAC_Approval_Workflow
*
* Manages the trainer approval process including email notifications
*/
class HVAC_Approval_Workflow {
/**
* Constructor
*/
public function __construct() {
// Hook into trainer status changes
add_action( 'hvac_trainer_status_changed', array( $this, 'handle_status_change' ), 10, 3 );
// Add query variable for approval token
add_filter( 'query_vars', array( $this, 'add_query_vars' ) );
// Handle approval URL visits
add_action( 'template_redirect', array( $this, 'handle_approval_request' ), 5 );
// Add AJAX handlers for bulk updates
add_action( 'wp_ajax_hvac_bulk_update_trainer_status', array( $this, 'ajax_bulk_update_status' ) );
}
/**
* Add query variables for approval
*/
public function add_query_vars( $vars ) {
$vars[] = 'hvac_approve_trainer';
$vars[] = 'hvac_approval_token';
return $vars;
}
/**
* Handle trainer status changes
*
* @param int $user_id User ID
* @param string $new_status New status
* @param string $old_status Old status
*/
public function handle_status_change( $user_id, $new_status, $old_status ) {
// Send appropriate notifications based on status change
if ( $new_status === HVAC_Trainer_Status::STATUS_APPROVED && $old_status === HVAC_Trainer_Status::STATUS_PENDING ) {
$this->send_approval_notification( $user_id );
} elseif ( $new_status === HVAC_Trainer_Status::STATUS_DISABLED ) {
$this->send_disabled_notification( $user_id );
}
}
/**
* Send new registration notification to admins
*
* @param int $user_id User ID
* @param array $registration_data Registration form data
*/
public function send_new_registration_notification( $user_id, $registration_data ) {
$user = get_userdata( $user_id );
if ( ! $user ) {
return false;
}
// Get notification emails
$options = get_option( 'hvac_ce_options', array() );
$notification_emails = isset( $options['notification_emails'] ) ? $options['notification_emails'] : get_option( 'admin_email' );
// Convert comma-separated list to array
if ( is_string( $notification_emails ) ) {
$notification_emails = array_map( 'trim', explode( ',', $notification_emails ) );
}
// Generate approval token
$approval_token = $this->generate_approval_token( $user_id );
update_user_meta( $user_id, 'hvac_approval_token', $approval_token );
// Build approval URL
$approval_url = add_query_arg( array(
'hvac_approve_trainer' => $user_id,
'hvac_approval_token' => $approval_token,
), home_url( '/master-trainer/dashboard/' ) );
// Get email template
$template = $this->get_email_template( 'new_registration' );
// Replace placeholders
$replacements = array(
'{trainer_name}' => $user->display_name,
'{trainer_email}' => $user->user_email,
'{business_name}' => get_user_meta( $user_id, 'business_name', true ),
'{business_phone}' => get_user_meta( $user_id, 'business_phone', true ),
'{business_email}' => get_user_meta( $user_id, 'business_email', true ),
'{registration_date}' => date( 'F j, Y', strtotime( $user->user_registered ) ),
'{application_details}' => get_user_meta( $user_id, 'application_details', true ),
'{approval_url}' => $approval_url,
'{website_name}' => get_bloginfo( 'name' ),
'{website_url}' => home_url(),
);
$subject = str_replace( array_keys( $replacements ), array_values( $replacements ), $template['subject'] );
$message = str_replace( array_keys( $replacements ), array_values( $replacements ), $template['body'] );
// Send emails
$headers = array( 'Content-Type: text/html; charset=UTF-8' );
foreach ( $notification_emails as $email ) {
wp_mail( $email, $subject, $message, $headers );
}
return true;
}
/**
* Send approval notification to trainer
*
* @param int $user_id User ID
*/
public function send_approval_notification( $user_id ) {
$user = get_userdata( $user_id );
if ( ! $user ) {
return false;
}
// Get email template
$template = $this->get_email_template( 'account_approved' );
// Replace placeholders
$replacements = array(
'{trainer_name}' => $user->display_name,
'{trainer_email}' => $user->user_email,
'{business_name}' => get_user_meta( $user_id, 'business_name', true ),
'{dashboard_url}' => home_url( '/trainer/dashboard/' ),
'{login_url}' => home_url( '/community-login/' ),
'{website_name}' => get_bloginfo( 'name' ),
'{website_url}' => home_url(),
'{current_date}' => date( 'F j, Y' ),
);
$subject = str_replace( array_keys( $replacements ), array_values( $replacements ), $template['subject'] );
$message = str_replace( array_keys( $replacements ), array_values( $replacements ), $template['body'] );
// Send email
$headers = array( 'Content-Type: text/html; charset=UTF-8' );
return wp_mail( $user->user_email, $subject, $message, $headers );
}
/**
* Send disabled notification to trainer
*
* @param int $user_id User ID
*/
public function send_disabled_notification( $user_id ) {
$user = get_userdata( $user_id );
if ( ! $user ) {
return false;
}
// Get email template
$template = $this->get_email_template( 'account_disabled' );
// Replace placeholders
$replacements = array(
'{trainer_name}' => $user->display_name,
'{trainer_email}' => $user->user_email,
'{business_name}' => get_user_meta( $user_id, 'business_name', true ),
'{support_email}' => get_option( 'admin_email' ),
'{website_name}' => get_bloginfo( 'name' ),
'{website_url}' => home_url(),
'{current_date}' => date( 'F j, Y' ),
);
$subject = str_replace( array_keys( $replacements ), array_values( $replacements ), $template['subject'] );
$message = str_replace( array_keys( $replacements ), array_values( $replacements ), $template['body'] );
// Send email
$headers = array( 'Content-Type: text/html; charset=UTF-8' );
return wp_mail( $user->user_email, $subject, $message, $headers );
}
/**
* Get email template
*
* @param string $template_key Template key
* @return array Template data with subject and body
*/
private function get_email_template( $template_key ) {
$options = get_option( 'hvac_ce_email_templates', array() );
// Default templates
$defaults = array(
'new_registration' => array(
'subject' => 'New HVAC Trainer Registration - {trainer_name}',
'body' => '
<h2>New Trainer Registration Pending Approval</h2>
<p>A new HVAC trainer has registered and is awaiting approval.</p>
<h3>Trainer Details:</h3>
<ul>
<li><strong>Name:</strong> {trainer_name}</li>
<li><strong>Email:</strong> {trainer_email}</li>
<li><strong>Business:</strong> {business_name}</li>
<li><strong>Phone:</strong> {business_phone}</li>
<li><strong>Business Email:</strong> {business_email}</li>
<li><strong>Registration Date:</strong> {registration_date}</li>
</ul>
<h3>Application Details:</h3>
<p>{application_details}</p>
<p><a href="{approval_url}" style="display: inline-block; padding: 10px 20px; background: #0073aa; color: white; text-decoration: none; border-radius: 4px;">Approve This Trainer</a></p>
<p>Or copy this link: {approval_url}</p>
',
),
'account_approved' => array(
'subject' => 'Your HVAC Trainer Account Has Been Approved!',
'body' => '
<h2>Welcome to {website_name}!</h2>
<p>Dear {trainer_name},</p>
<p>Great news! Your HVAC trainer account has been approved and you now have full access to create and manage training events.</p>
<h3>What You Can Do Now:</h3>
<ul>
<li>Create and manage training events</li>
<li>Access your trainer dashboard</li>
<li>Generate certificates for attendees</li>
<li>Communicate with your attendees</li>
<li>View analytics and reports</li>
</ul>
<h3>Getting Started:</h3>
<ol>
<li><a href="{login_url}">Log in to your account</a></li>
<li>Visit your <a href="{dashboard_url}">Trainer Dashboard</a></li>
<li>Click "Create New Event" to post your first training event</li>
<li>Share your event with your network to maximize attendance</li>
</ol>
<p>If you have any questions or need assistance, please don\'t hesitate to reach out to our support team.</p>
<p>We\'re excited to have you as part of our training community!</p>
<p>Best regards,<br>
The {website_name} Team</p>
',
),
'account_disabled' => array(
'subject' => 'Your HVAC Trainer Account Has Been Disabled',
'body' => '
<h2>Account Status Update</h2>
<p>Dear {trainer_name},</p>
<p>We regret to inform you that your HVAC trainer account on {website_name} has been disabled.</p>
<p>Your account may have been disabled for one of the following reasons:</p>
<ul>
<li>Violation of our terms of service or community guidelines</li>
<li>Extended period of inactivity</li>
<li>Incomplete or inaccurate information</li>
<li>Quality concerns or complaints</li>
</ul>
<p>If you believe this action was taken in error or would like to discuss reactivating your account, please contact our support team at <a href="mailto:{support_email}">{support_email}</a>.</p>
<p>We appreciate your understanding.</p>
<p>Sincerely,<br>
The {website_name} Team</p>
',
),
);
// Return custom template if exists, otherwise default
if ( isset( $options[$template_key] ) ) {
return $options[$template_key];
}
return isset( $defaults[$template_key] ) ? $defaults[$template_key] : array( 'subject' => '', 'body' => '' );
}
/**
* Generate approval token
*
* @param int $user_id User ID
* @return string Token
*/
private function generate_approval_token( $user_id ) {
return wp_hash( $user_id . time() . wp_rand() );
}
/**
* Handle approval request from email link
*/
public function handle_approval_request() {
$user_id = get_query_var( 'hvac_approve_trainer' );
$token = get_query_var( 'hvac_approval_token' );
if ( ! $user_id || ! $token ) {
return;
}
// Verify token
$stored_token = get_user_meta( $user_id, 'hvac_approval_token', true );
if ( $token !== $stored_token ) {
wp_die( __( 'Invalid approval token.', 'hvac-community-events' ) );
}
// Check if user is logged in
if ( ! is_user_logged_in() ) {
// Store approval request in session/transient
set_transient( 'hvac_pending_approval_' . $token, $user_id, HOUR_IN_SECONDS );
// Redirect to login with return URL
$login_url = add_query_arg( array(
'redirect_to' => urlencode( add_query_arg( array(
'hvac_approve_trainer' => $user_id,
'hvac_approval_token' => $token,
), home_url( '/master-trainer/dashboard/' ) ) ),
), home_url( '/community-login/' ) );
wp_redirect( $login_url );
exit;
}
// Check if current user can approve trainers
if ( ! current_user_can( 'view_master_dashboard' ) && ! current_user_can( 'manage_options' ) ) {
wp_die( __( 'You do not have permission to approve trainers.', 'hvac-community-events' ) );
}
// Approve the trainer
if ( ! class_exists( 'HVAC_Trainer_Status' ) ) {
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-trainer-status.php';
}
$result = HVAC_Trainer_Status::set_trainer_status( $user_id, HVAC_Trainer_Status::STATUS_APPROVED );
if ( $result ) {
// Delete the token
delete_user_meta( $user_id, 'hvac_approval_token' );
// Get trainer info for message
$trainer = get_userdata( $user_id );
$message = sprintf(
__( 'Trainer %s with email %s has been approved!', 'hvac-community-events' ),
$trainer->display_name,
$trainer->user_email
);
// Store success message in transient
set_transient( 'hvac_approval_message', $message, 30 );
}
// Redirect to master dashboard
wp_redirect( home_url( '/master-trainer/dashboard/' ) );
exit;
}
/**
* AJAX handler for bulk status updates
*/
public function ajax_bulk_update_status() {
// Check nonce
if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'hvac_master_dashboard_nonce' ) ) {
wp_die( 'Security check failed' );
}
// Check permissions
if ( ! current_user_can( 'view_master_dashboard' ) && ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( array( 'message' => 'Insufficient permissions' ) );
}
// Get parameters
$user_ids = isset( $_POST['user_ids'] ) ? array_map( 'intval', $_POST['user_ids'] ) : array();
$new_status = isset( $_POST['status'] ) ? sanitize_text_field( $_POST['status'] ) : '';
if ( empty( $user_ids ) || empty( $new_status ) ) {
wp_send_json_error( array( 'message' => 'Missing required parameters' ) );
}
// Load status class
if ( ! class_exists( 'HVAC_Trainer_Status' ) ) {
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-trainer-status.php';
}
// Perform bulk update
$results = HVAC_Trainer_Status::bulk_update_status( $user_ids, $new_status );
if ( $results['success'] > 0 ) {
wp_send_json_success( array(
'message' => sprintf(
__( 'Successfully updated %d trainer(s). %d failed.', 'hvac-community-events' ),
$results['success'],
$results['failed']
),
'results' => $results,
) );
} else {
wp_send_json_error( array(
'message' => __( 'Failed to update trainer statuses.', 'hvac-community-events' ),
'results' => $results,
) );
}
}
}