upskill-event-manager/includes/class-hvac-access-control.php
bengizmo f0edd05369 feat: Implement trainer approval workflow with status management
- Add trainer status system (pending, approved, active, inactive, disabled)
- Create access control system based on trainer status
- Refactor Master Dashboard with enhanced trainer table
  - Add status column and filtering
  - Implement search and pagination
  - Add bulk status update functionality
- Create status pages for pending and disabled trainers
- Implement approval workflow with email notifications
- Add email template management to settings page
- Include comprehensive test suite (unit, integration, E2E)

This allows Master Trainers to manage trainer accounts, approve new registrations,
and control access based on account status. Trainers must be approved before
accessing dashboard features.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-28 12:38:34 -03:00

264 lines
No EOL
7.9 KiB
PHP

<?php
/**
* HVAC Community Events - Access Control
*
* Handles page access restrictions based on trainer status
*
* @package HVAC_Community_Events
* @since 1.0.0
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class HVAC_Access_Control
*
* Manages access control for trainer pages based on account status
*/
class HVAC_Access_Control {
/**
* Pages that require authentication but no specific status
*/
private static $public_pages = array(
'trainer/registration',
'registration-pending',
'community-login',
'training-login',
'trainer-account-pending',
'trainer-account-disabled',
);
/**
* Pages that require trainer to be active or inactive
*/
private static $trainer_pages = array(
'trainer/dashboard',
'trainer/event/manage',
'trainer/generate-certificates',
'trainer/certificate-reports',
'trainer/event-summary',
'trainer/email-attendees',
'trainer/communication-templates',
'edit-profile',
);
/**
* Constructor
*/
public function __construct() {
// Hook into template_redirect for access control
add_action( 'template_redirect', array( $this, 'check_page_access' ), 10 );
}
/**
* Check page access based on user status
*/
public function check_page_access() {
// Get current page path
$current_path = trim( parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH ), '/' );
// Check if this is a public page
if ( $this->is_public_page( $current_path ) ) {
return;
}
// Check if this is a trainer page
if ( $this->is_trainer_page( $current_path ) ) {
$this->check_trainer_access( $current_path );
}
}
/**
* Check if current page is public
*
* @param string $path Current page path
* @return bool
*/
private function is_public_page( $path ) {
foreach ( self::$public_pages as $public_page ) {
if ( $path === $public_page || strpos( $path, $public_page ) === 0 ) {
return true;
}
}
return false;
}
/**
* Check if current page is a trainer page
*
* @param string $path Current page path
* @return bool
*/
private function is_trainer_page( $path ) {
foreach ( self::$trainer_pages as $trainer_page ) {
if ( $path === $trainer_page || strpos( $path, $trainer_page ) === 0 ) {
return true;
}
}
// Also check for pages that start with 'trainer/'
if ( strpos( $path, 'trainer/' ) === 0 ) {
return true;
}
return false;
}
/**
* Check trainer access to protected pages
*
* @param string $path Current page path
*/
private function check_trainer_access( $path ) {
// First check if user is logged in
if ( ! is_user_logged_in() ) {
wp_safe_redirect( home_url( '/community-login/' ) );
exit;
}
$user_id = get_current_user_id();
$user = wp_get_current_user();
// Allow administrators full access
if ( current_user_can( 'manage_options' ) ) {
return;
}
// Check if user has trainer role
if ( ! in_array( 'hvac_trainer', $user->roles ) && ! in_array( 'hvac_master_trainer', $user->roles ) ) {
// Not a trainer, show access denied
$this->show_access_denied();
return;
}
// Get trainer status
if ( ! class_exists( 'HVAC_Trainer_Status' ) ) {
require_once HVAC_CE_PLUGIN_DIR . 'includes/class-hvac-trainer-status.php';
}
$status = HVAC_Trainer_Status::get_trainer_status( $user_id );
// Handle based on status
switch ( $status ) {
case HVAC_Trainer_Status::STATUS_PENDING:
// Redirect to pending page
if ( $path !== 'trainer-account-pending' && strpos( $path, 'trainer-account-pending' ) !== 0 ) {
wp_safe_redirect( home_url( '/trainer-account-pending/' ) );
exit;
}
break;
case HVAC_Trainer_Status::STATUS_DISABLED:
// Redirect to disabled page
if ( $path !== 'trainer-account-disabled' && strpos( $path, 'trainer-account-disabled' ) !== 0 ) {
wp_safe_redirect( home_url( '/trainer-account-disabled/' ) );
exit;
}
break;
case HVAC_Trainer_Status::STATUS_APPROVED:
case HVAC_Trainer_Status::STATUS_ACTIVE:
case HVAC_Trainer_Status::STATUS_INACTIVE:
// Allow access
break;
default:
// Unknown status, treat as pending
wp_safe_redirect( home_url( '/trainer-account-pending/' ) );
exit;
}
}
/**
* Show access denied page
*/
private function show_access_denied() {
get_header();
?>
<style>
.hvac-access-denied {
max-width: 600px;
margin: 60px auto;
padding: 40px;
text-align: center;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.hvac-access-denied h1 {
color: #d63638;
margin-bottom: 20px;
}
.hvac-access-denied p {
margin-bottom: 15px;
color: #666;
line-height: 1.6;
}
.hvac-access-denied .button {
background: #0073aa;
color: white;
padding: 12px 24px;
text-decoration: none;
border-radius: 4px;
display: inline-block;
margin-top: 20px;
}
.hvac-access-denied .button:hover {
background: #005a87;
color: white;
}
</style>
<div class="content-area primary ast-container">
<main class="site-main">
<div class="hvac-access-denied">
<h1><?php _e( 'Access Denied', 'hvac-community-events' ); ?></h1>
<p><?php _e( 'You do not have permission to access this page.', 'hvac-community-events' ); ?></p>
<p><?php _e( 'If you believe this is an error, please contact an administrator.', 'hvac-community-events' ); ?></p>
<a href="<?php echo esc_url( home_url() ); ?>" class="button"><?php _e( 'Return to Home', 'hvac-community-events' ); ?></a>
</div>
</main>
</div>
<?php
get_footer();
exit;
}
/**
* Add custom pages that require specific access
*
* @param string $page Page path
* @param string $type 'public' or 'trainer'
*/
public static function add_custom_page( $page, $type = 'trainer' ) {
if ( $type === 'public' ) {
self::$public_pages[] = $page;
} else {
self::$trainer_pages[] = $page;
}
}
/**
* Remove a page from access control
*
* @param string $page Page path
* @param string $type 'public' or 'trainer'
*/
public static function remove_custom_page( $page, $type = 'trainer' ) {
if ( $type === 'public' ) {
$key = array_search( $page, self::$public_pages );
if ( $key !== false ) {
unset( self::$public_pages[$key] );
}
} else {
$key = array_search( $page, self::$trainer_pages );
if ( $key !== false ) {
unset( self::$trainer_pages[$key] );
}
}
}
}