upskill-event-manager/includes/class-hvac-master-menu-system.php
Ben a74c273b1d feat: complete master trainer area audit and implementation
Systematic audit and implementation of missing Master Trainer functionality
with comprehensive WordPress best practices and security implementation.

## Features Implemented
- Master Events Overview (/master-trainer/events/) - KPI dashboard with filtering
- Import/Export Data Management (/master-trainer/import-export/) - CSV operations
- Communication Templates (/trainer/communication-templates/) - Professional templates
- Enhanced Announcements (/master-trainer/announcements/) - Dynamic shortcode integration
- Pending Approvals System (/master-trainer/pending-approvals/) - Workflow management

## Navigation & UX Improvements
- Removed redundant Events link from top-level navigation menu
- Reorganized administrative functions under Tools dropdown
- Enhanced navigation clarity and professional appearance
- Full responsive design with accessibility compliance

## Architecture & Security
- 5 new singleton manager classes following WordPress patterns
- Comprehensive role-based access control (hvac_master_trainer)
- Complete security implementation (nonces, sanitization, escaping)
- Performance optimizations with transient caching and conditional loading
- Professional error handling and user feedback systems

## Files Added (16 new files)
- 4 manager classes: Import/Export, Events Overview, Pending Approvals, Communication Templates
- 4 CSS files with responsive design and accessibility features
- 4 JavaScript files with AJAX functionality and error handling
- 2 new templates: Import/Export, Pending Approvals
- 2 enhanced templates: Events Overview, Communication Templates

## Files Modified (14 files)
- Core system integration in Plugin, Page Manager, Scripts/Styles classes
- Navigation system cleanup in Master Menu System
- Enhanced access control and role management
- Template updates for dynamic content integration

## Testing & Deployment
- Comprehensive testing with Playwright automation
- Successful staging deployment and verification
- All 5 missing pages now fully functional
- Navigation improvements verified working

Resolves master trainer area audit requirements with production-ready implementation.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-23 09:56:42 -03:00

383 lines
No EOL
13 KiB
PHP

<?php
/**
* HVAC Master Trainer Menu System
*
* Handles navigation menus specifically for master trainer pages
*
* @package HVAC_Community_Events
* @since 1.0.0
*/
if (!defined('ABSPATH')) {
exit;
}
class HVAC_Master_Menu_System {
/**
* Instance of this class
*
* @var HVAC_Master_Menu_System
*/
private static $instance = null;
/**
* Get instance of this class
*
* @return HVAC_Master_Menu_System
*/
public static function instance() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor
*/
private function __construct() {
// No auto-init hooks - will be called manually on master pages
}
/**
* Check if current page is a master trainer page
*
* @return bool
*/
public function is_master_trainer_page() {
$current_url = $_SERVER['REQUEST_URI'];
// List of master trainer page patterns
$master_pages = array(
'/master-trainer/master-dashboard/',
'/master-trainer/events/',
'/master-trainer/announcements/',
'/master-trainer/edit-trainer-profile/',
'/master-trainer/communication-templates/',
'/master-trainer/google-sheets/',
'/master-trainer/trainers/',
'/master-trainer/pending-approvals/',
'/master-trainer/trainer-stats/',
'/master-trainer/import-export/'
);
foreach ($master_pages as $page) {
if (strpos($current_url, $page) !== false) {
return true;
}
}
return false;
}
/**
* Render master trainer navigation menu
*/
public function render_master_menu() {
// Check if user has master trainer permissions
$user = wp_get_current_user();
if (!in_array('hvac_master_trainer', $user->roles) && !current_user_can('manage_options')) {
return;
}
$menu_items = $this->get_master_menu_structure();
echo '<div class="hvac-trainer-menu-wrapper">';
echo '<nav class="hvac-trainer-nav" role="navigation">';
// Add hamburger button for mobile
echo '<button class="hvac-hamburger-menu" id="hvac-hamburger-menu" aria-label="Toggle menu" aria-expanded="false">';
echo '<span class="hvac-hamburger-line"></span>';
echo '<span class="hvac-hamburger-line"></span>';
echo '<span class="hvac-hamburger-line"></span>';
echo '</button>';
echo '<ul class="hvac-trainer-menu" id="hvac-trainer-menu">';
foreach ($menu_items as $item) {
$this->render_menu_item($item);
}
echo '</ul>';
echo '</nav>';
echo '</div>';
}
/**
* Get master trainer menu structure
* Simplified to 5 essential items following UX best practices
*/
private function get_master_menu_structure() {
// Define simplified menu structure (5 primary items max)
$menu = array(
// Dashboard - Primary landing page
array(
'title' => esc_html__('Dashboard', 'hvac-community-events'),
'url' => home_url('/master-trainer/master-dashboard/'),
'icon' => 'dashicons-dashboard',
'cap' => 'hvac_master_trainer'
),
// Trainers - Core management function
array(
'title' => esc_html__('Trainers', 'hvac-community-events'),
'url' => home_url('/master-trainer/trainers/'),
'icon' => 'dashicons-groups',
'cap' => 'hvac_master_trainer',
'children' => array(
array(
'title' => esc_html__('All Trainers', 'hvac-community-events'),
'url' => home_url('/master-trainer/trainers/'),
'icon' => 'dashicons-list-view',
'cap' => 'hvac_master_trainer'
),
array(
'title' => esc_html__('Pending Approvals', 'hvac-community-events'),
'url' => home_url('/master-trainer/pending-approvals/'),
'icon' => 'dashicons-clock',
'cap' => 'approve_trainers'
)
)
),
// Tools - Administrative functions
array(
'title' => esc_html__('Tools', 'hvac-community-events'),
'url' => home_url('/master-trainer/communication-templates/'),
'icon' => 'dashicons-admin-tools',
'cap' => 'manage_communication_templates',
'children' => array(
array(
'title' => esc_html__('Google Sheets', 'hvac-community-events'),
'url' => home_url('/master-trainer/google-sheets/'),
'icon' => 'dashicons-media-spreadsheet',
'cap' => 'manage_google_sheets_integration'
),
array(
'title' => esc_html__('Communication Templates', 'hvac-community-events'),
'url' => home_url('/master-trainer/communication-templates/'),
'icon' => 'dashicons-email',
'cap' => 'manage_communication_templates'
),
array(
'title' => esc_html__('Announcements', 'hvac-community-events'),
'url' => home_url('/master-trainer/announcements/'),
'icon' => 'dashicons-megaphone',
'cap' => 'manage_announcements'
),
array(
'title' => esc_html__('Import/Export', 'hvac-community-events'),
'url' => home_url('/master-trainer/import-export/'),
'icon' => 'dashicons-database-import',
'cap' => 'import_export_data'
)
)
),
// Account - User options
array(
'title' => esc_html__('Account', 'hvac-community-events'),
'url' => '#',
'icon' => 'dashicons-admin-users',
'cap' => 'read',
'children' => array(
array(
'title' => esc_html__('Trainer Dashboard', 'hvac-community-events'),
'url' => home_url('/trainer/dashboard/'),
'icon' => 'dashicons-dashboard',
'cap' => 'read'
),
array(
'title' => esc_html__('Logout', 'hvac-community-events'),
'url' => wp_logout_url(home_url('/training-login/')),
'icon' => 'dashicons-exit',
'cap' => 'read',
'class' => 'menu-item-logout'
)
)
),
// Help - Documentation
array(
'title' => esc_html__('Help', 'hvac-community-events'),
'url' => home_url('/trainer/documentation/'),
'icon' => 'dashicons-editor-help',
'cap' => 'read',
'class' => 'hvac-help-menu-item'
)
);
// Allow other plugins to modify menu
$menu = apply_filters('hvac_master_menu_items', $menu);
// Filter menu items by user capabilities
$menu = $this->filter_menu_by_capabilities($menu);
return $menu;
}
/**
* Filter menu items by user capabilities
* Removes items the current user cannot access
*
* @param array $menu_items Menu items array
* @return array Filtered menu items
*/
private function filter_menu_by_capabilities($menu_items) {
$filtered_menu = array();
foreach ($menu_items as $item) {
// Check if user has capability for this item
$required_cap = isset($item['cap']) ? $item['cap'] : 'hvac_master_trainer';
// Handle role names vs capabilities properly
$user = wp_get_current_user();
$has_access = false;
if ($required_cap === 'hvac_master_trainer') {
$has_access = in_array('hvac_master_trainer', (array) $user->roles, true) || current_user_can('manage_options');
} else {
$has_access = current_user_can($required_cap);
}
if (!$has_access) {
continue; // Skip this item
}
// Filter children if they exist
if (isset($item['children']) && is_array($item['children'])) {
$filtered_children = array();
foreach ($item['children'] as $child) {
$child_cap = isset($child['cap']) ? $child['cap'] : 'hvac_master_trainer';
// Handle role names vs capabilities properly for children too
$has_child_access = false;
if ($child_cap === 'hvac_master_trainer') {
$has_child_access = in_array('hvac_master_trainer', (array) $user->roles, true) || current_user_can('manage_options');
} else {
$has_child_access = current_user_can($child_cap);
}
if ($has_child_access) {
$filtered_children[] = $child;
}
}
// Only include parent if it has accessible children or is directly accessible
if (!empty($filtered_children)) {
$item['children'] = $filtered_children;
$filtered_menu[] = $item;
} elseif (!isset($item['children']) || empty($item['children'])) {
// Include parent items without children
$filtered_menu[] = $item;
}
} else {
// Include items without children
$filtered_menu[] = $item;
}
}
return $filtered_menu;
}
/**
* Render a single menu item
*
* @param array $item Menu item configuration
*/
private function render_menu_item($item) {
$has_children = !empty($item['children']);
$current_url = $_SERVER['REQUEST_URI'];
// Check if this item or any of its children are active
$is_active = $this->is_menu_item_active($item, $current_url);
$li_classes = array('menu-item');
if ($is_active) {
$li_classes[] = 'current-menu-item';
}
if ($has_children) {
$li_classes[] = 'has-children';
}
if (!empty($item['class'])) {
$li_classes[] = $item['class'];
}
echo '<li class="' . implode(' ', $li_classes) . '">';
// Main link
$link_attrs = array(
'href="' . esc_url($item['url']) . '"'
);
if ($has_children) {
$link_attrs[] = 'aria-haspopup="true"';
$link_attrs[] = 'aria-expanded="false"';
}
echo '<a ' . implode(' ', $link_attrs) . '>';
if (!empty($item['icon'])) {
echo '<span class="dashicons ' . esc_attr($item['icon']) . '"></span>';
}
echo '<span class="menu-title">' . esc_html($item['title']) . '</span>';
if ($has_children) {
echo '<span class="menu-toggle" aria-hidden="true"></span>';
}
echo '</a>';
// Children
if ($has_children) {
echo '<ul class="sub-menu">';
foreach ($item['children'] as $child) {
$this->render_menu_item($child);
}
echo '</ul>';
}
echo '</li>';
}
/**
* Check if menu item is active
*
* @param array $item Menu item
* @param string $current_url Current URL
* @return bool
*/
private function is_menu_item_active($item, $current_url) {
// Clean URLs for comparison
$item_path = parse_url($item['url'], PHP_URL_PATH);
$current_path = parse_url($current_url, PHP_URL_PATH);
// Check exact match
if ($item_path === $current_path) {
return true;
}
// Check if current URL starts with item URL (for parent items)
if (!empty($item_path) && $item_path !== '/' && strpos($current_path, $item_path) === 0) {
return true;
}
// Check children
if (!empty($item['children'])) {
foreach ($item['children'] as $child) {
if ($this->is_menu_item_active($child, $current_url)) {
return true;
}
}
}
return false;
}
}
// Initialize the class
HVAC_Master_Menu_System::instance();