upskill-event-manager/includes/class-hvac-shortcodes.php
Ben c3e7fe9140 feat: comprehensive HVAC plugin development framework and modernization
## Major Enhancements

### 🏗️ Architecture & Infrastructure
- Implement comprehensive Docker testing infrastructure with hermetic environment
- Add Forgejo Actions CI/CD pipeline for automated deployments
- Create Page Object Model (POM) testing architecture reducing test duplication by 90%
- Establish security-first development patterns with input validation and output escaping

### 🧪 Testing Framework Modernization
- Migrate 146+ tests from 80 duplicate files to centralized architecture
- Add comprehensive E2E test suites for all user roles and workflows
- Implement WordPress error detection with automatic site health monitoring
- Create robust browser lifecycle management with proper cleanup

### 📚 Documentation & Guides
- Add comprehensive development best practices guide
- Create detailed administrator setup documentation
- Establish user guides for trainers and master trainers
- Document security incident reports and migration guides

### 🔧 Core Plugin Features
- Enhance trainer profile management with certification system
- Improve find trainer functionality with advanced filtering
- Strengthen master trainer area with content management
- Add comprehensive venue and organizer management

### 🛡️ Security & Reliability
- Implement security-first patterns throughout codebase
- Add comprehensive input validation and output escaping
- Create secure credential management system
- Establish proper WordPress role-based access control

### 🎯 WordPress Integration
- Strengthen singleton pattern implementation across all classes
- Enhance template hierarchy with proper WordPress integration
- Improve page manager with hierarchical URL structure
- Add comprehensive shortcode and menu system

### 🔍 Developer Experience
- Add extensive debugging and troubleshooting tools
- Create comprehensive test data seeding scripts
- Implement proper error handling and logging
- Establish consistent code patterns and standards

### 📊 Performance & Optimization
- Optimize database queries and caching strategies
- Improve asset loading and script management
- Enhance template rendering performance
- Streamline user experience across all interfaces

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-29 11:26:10 -03:00

789 lines
No EOL
29 KiB
PHP

<?php
/**
* HVAC Shortcodes Manager
*
* Centralized management of all plugin shortcodes
*
* @package HVAC_Community_Events
* @since 2.0.0
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* HVAC_Shortcodes class
*/
class HVAC_Shortcodes {
/**
* Instance
*
* @var HVAC_Shortcodes
*/
private static $instance = null;
/**
* Registered shortcodes
*
* @var array
*/
private $shortcodes = array();
/**
* Get instance
*
* @return HVAC_Shortcodes
*/
public static function instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor
*/
private function __construct() {
$this->define_shortcodes();
$this->register_shortcodes();
}
/**
* Define all plugin shortcodes
*
* @return void
*/
private function define_shortcodes() {
$this->shortcodes = array(
// Dashboard shortcodes
'hvac_dashboard' => array(
'callback' => array($this, 'render_dashboard'),
'description' => 'Trainer dashboard'
),
'hvac_master_dashboard' => array(
'callback' => array($this, 'render_master_dashboard'),
'description' => 'Master trainer dashboard'
),
// Event management shortcodes
// DISABLED - Using TEC Community Events 5.x instead
// 'hvac_manage_event' => array(
// 'callback' => array($this, 'render_manage_event'),
// 'description' => 'Event management form'
// ),
// 'hvac_create_event' => array(
// 'callback' => array($this, 'render_create_event'),
// 'description' => 'Create new event with REST API'
// ),
// NOTE: hvac_edit_event is handled by HVAC_Edit_Event_Shortcode class - ALSO DISABLED
// to avoid registration conflicts
'hvac_event_summary' => array(
'callback' => array($this, 'render_event_summary'),
'description' => 'Event summary page'
),
// Authentication shortcodes
'hvac_community_login' => array(
'callback' => array($this, 'render_login'),
'description' => 'Community login form'
),
'hvac_trainer_registration' => array(
'callback' => array($this, 'render_registration'),
'description' => 'Trainer registration form'
),
'hvac_edit_profile' => array(
'callback' => array($this, 'render_edit_profile'),
'description' => 'Edit trainer profile form'
),
// Profile shortcodes
'hvac_trainer_profile' => array(
'callback' => array($this, 'render_trainer_profile'),
'description' => 'Trainer profile page'
),
// Certificate shortcodes
'hvac_certificate_reports' => array(
'callback' => array($this, 'render_certificate_reports'),
'description' => 'Certificate reports page'
),
'hvac_generate_certificates' => array(
'callback' => array($this, 'render_generate_certificates'),
'description' => 'Certificate generation page'
),
// Communication shortcodes
'hvac_email_attendees' => array(
'callback' => array($this, 'render_email_attendees'),
'description' => 'Email attendees interface'
),
'hvac_communication_templates' => array(
'callback' => array($this, 'render_communication_templates'),
'description' => 'Communication templates management'
),
'hvac_communication_schedules' => array(
'callback' => array($this, 'render_communication_schedules'),
'description' => 'Communication schedules management'
),
// Venue shortcodes
'hvac_trainer_venues_list' => array(
'callback' => array($this, 'render_venues_list'),
'description' => 'Trainer venues listing page'
),
'hvac_trainer_venue_manage' => array(
'callback' => array($this, 'render_venue_manage'),
'description' => 'Trainer venue management page'
),
// Organizer shortcodes - Handled by HVAC_Organizers class
'hvac_trainer_organizers_list' => array(
'callback' => array($this, 'render_organizers_list'),
'description' => 'Trainer organizers listing page'
),
'hvac_trainer_organizer_manage' => array(
'callback' => array($this, 'render_organizer_manage'),
'description' => 'Trainer organizer management page'
),
// Profile shortcodes - additional ones beyond hvac_trainer_profile
'hvac_trainer_profile_view' => array(
'callback' => array($this, 'render_trainer_profile_view'),
'description' => 'Trainer profile view page'
),
'hvac_trainer_profile_edit' => array(
'callback' => array($this, 'render_trainer_profile_edit'),
'description' => 'Trainer profile edit page'
),
// Admin shortcodes
'hvac_google_sheets' => array(
'callback' => array($this, 'render_google_sheets_admin'),
'description' => 'Google Sheets integration admin'
),
);
// Allow filtering of shortcode definitions
$this->shortcodes = apply_filters('hvac_shortcode_definitions', $this->shortcodes);
}
/**
* Register all shortcodes
*
* @return void
*/
private function register_shortcodes() {
foreach ($this->shortcodes as $tag => $config) {
add_shortcode($tag, $config['callback']);
}
// Log registration
HVAC_Logger::info('Registered ' . count($this->shortcodes) . ' shortcodes', 'Shortcodes');
}
/**
* Get registered shortcodes
*
* @return array
*/
public function get_shortcodes() {
return $this->shortcodes;
}
/**
* Check if shortcode is registered
*
* @param string $tag Shortcode tag
* @return bool
*/
public function is_registered($tag) {
return isset($this->shortcodes[$tag]);
}
// ========================================
// Shortcode Render Methods
// ========================================
/**
* Render dashboard shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_dashboard($atts = array()) {
// Add debug comment to verify this method is being called
$debug = '<!-- HVAC_Shortcodes::render_dashboard called -->';
// Use the HVAC_Community_Events instance method
if (class_exists('HVAC_Community_Events')) {
$hvac = HVAC_Community_Events::get_instance();
if (method_exists($hvac, 'render_dashboard')) {
return $debug . $hvac->render_dashboard();
}
}
// Fallback if class not available
if (!is_user_logged_in()) {
return $debug . '<p>' . __('Please log in to view the dashboard.', 'hvac-community-events') . '</p>';
}
// Include the dashboard template
ob_start();
include HVAC_PLUGIN_DIR . 'templates/template-hvac-dashboard.php';
return ob_get_clean();
}
/**
* Render master dashboard shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_master_dashboard($atts = array()) {
// Add debug comment to verify this method is being called
$debug = '<!-- HVAC_Shortcodes::render_master_dashboard called -->';
// Use the HVAC_Community_Events instance method
if (class_exists('HVAC_Community_Events')) {
$hvac = HVAC_Community_Events::get_instance();
if (method_exists($hvac, 'render_master_dashboard')) {
return $debug . $hvac->render_master_dashboard();
}
}
// Fallback if class not available
if (!is_user_logged_in()) {
return $debug . '<p>' . __('Please log in to view the master dashboard.', 'hvac-community-events') . '</p>';
}
$user = wp_get_current_user();
if (!in_array('hvac_master_trainer', $user->roles) && !current_user_can('manage_options')) {
return $debug . '<div class="hvac-error">' . __('You do not have permission to view the master dashboard. This dashboard is only available to Master Trainers and Administrators.', 'hvac-community-events') . '</div>';
}
// Include the master dashboard template
ob_start();
include HVAC_PLUGIN_DIR . 'templates/template-hvac-master-dashboard.php';
return ob_get_clean();
}
/**
* Render manage event shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_manage_event($atts = array()) {
// The manage event page uses The Events Calendar Community Events shortcode
if (!shortcode_exists('tribe_community_events')) {
return '<p>' . __('Event management requires The Events Calendar Community Events add-on.', 'hvac-community-events') . '</p>';
}
// Get event ID from URL parameter to determine if we're creating or editing
$event_id = isset($_GET['event_id']) ? intval($_GET['event_id']) : null;
if ($event_id && $event_id > 0) {
// Editing existing event - use edit_event view with event ID
// This is the proper TEC way to edit events with full field population
return do_shortcode('[tribe_community_events view="edit_event" id="' . $event_id . '"]');
} else {
// Creating new event - use submission_form view
return do_shortcode('[tribe_community_events view="submission_form"]');
}
}
/**
* Render create event shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_create_event($atts = array()) {
// Check permissions
if (!is_user_logged_in()) {
return '<p>' . __('Please log in to create events.', 'hvac-community-events') . '</p>';
}
if (!current_user_can('hvac_trainer') && !current_user_can('hvac_master_trainer') && !current_user_can('manage_options')) {
return '<p>' . __('You must be a trainer to create events.', 'hvac-community-events') . '</p>';
}
// Start output buffering
ob_start();
?>
<div class="hvac-create-event-wrapper">
<?php
// Display trainer navigation menu
if (class_exists('HVAC_Menu_System')) {
echo '<div class="hvac-navigation-wrapper">';
HVAC_Menu_System::instance()->render_trainer_menu();
echo '</div>';
}
// Display breadcrumbs
if (class_exists('HVAC_Breadcrumbs')) {
echo '<div class="hvac-breadcrumbs-wrapper">';
HVAC_Breadcrumbs::instance()->render();
echo '</div>';
}
?>
<h1>Create New Event</h1>
<div class="hvac-form-notice">
<p>Create your event with full control over all fields including excerpt, categories, and tags.</p>
</div>
<div class="hvac-page-content">
<?php
// Check if TEC Community Events is active
if (shortcode_exists('tribe_community_events')) {
// Always show the submission form for creating new events
echo do_shortcode('[tribe_community_events view="submission_form"]');
} else {
echo '<p>' . __('Event management requires The Events Calendar Community Events add-on.', 'hvac-community-events') . '</p>';
}
?>
</div>
<script>
// Load form field injector if TEC form is empty
jQuery(document).ready(function($) {
console.log('[Create Event Shortcode] Checking form fields...');
// First load the form field injector
$.getScript('<?php echo HVAC_PLUGIN_URL; ?>assets/js/hvac-tec-form-fields-injector.js')
.done(function() {
console.log('[Create Event Shortcode] Form field injector loaded');
})
.fail(function() {
console.error('[Create Event Shortcode] Failed to load form field injector');
});
// Then load REST API enhancement
setTimeout(function() {
// Check if REST API script is loaded
if (typeof window.HVACRestEventSubmission !== 'undefined') {
console.log('[Create Event Shortcode] REST API script already loaded');
HVACRestEventSubmission.init();
} else {
console.log('[Create Event Shortcode] Loading REST API script dynamically...');
$.getScript('<?php echo HVAC_PLUGIN_URL; ?>assets/js/hvac-rest-api-event-submission.js')
.done(function() {
console.log('[Create Event Shortcode] REST API script loaded successfully');
if (typeof HVACRestEventSubmission !== 'undefined') {
HVACRestEventSubmission.init();
console.log('[Create Event Shortcode] REST API initialized for create mode');
}
})
.fail(function() {
console.error('[Create Event Shortcode] Failed to load REST API script');
});
}
}, 1000);
});
</script>
</div>
<style>
.hvac-create-event-wrapper {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.hvac-create-event-wrapper h1 {
color: #1a1a1a;
font-size: 28px;
margin-bottom: 20px;
}
.hvac-form-notice {
background: #f0f7ff;
border: 1px solid #0073aa;
border-radius: 4px;
padding: 12px;
margin-bottom: 20px;
}
.hvac-form-notice p {
margin: 0;
color: #0073aa;
}
.hvac-navigation-wrapper {
margin-bottom: 20px;
}
.hvac-breadcrumbs-wrapper {
margin-bottom: 15px;
}
</style>
<?php
return ob_get_clean();
}
// NOTE: render_edit_event method removed - handled by HVAC_Edit_Event_Shortcode class
/**
* Render event summary shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_event_summary($atts = array()) {
if (!class_exists('HVAC_Event_Summary')) {
return '<p>' . __('Event summary functionality not available.', 'hvac-community-events') . '</p>';
}
$event_summary = new HVAC_Event_Summary();
return $event_summary->render_summary($atts);
}
/**
* Render login shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_login($atts = array()) {
if (!class_exists('\\HVAC_Community_Events\\Community\\Login_Handler')) {
return '<p>' . __('Login functionality not available.', 'hvac-community-events') . '</p>';
}
$login_handler = new \HVAC_Community_Events\Community\Login_Handler();
return $login_handler->render_login_form($atts);
}
/**
* Render registration shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_registration($atts = array()) {
// Dependencies are loaded during plugin initialization - no need for conditional require_once
if (!class_exists('HVAC_Registration')) {
return '<p>' . __('Registration functionality not available.', 'hvac-community-events') . '</p>';
}
$registration = new HVAC_Registration();
return $registration->render_registration_form($atts);
}
/**
* Render edit profile shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_edit_profile($atts = array()) {
if (!class_exists('HVAC_Registration')) {
return '<p>' . __('Profile editing functionality not available.', 'hvac-community-events') . '</p>';
}
$registration = new HVAC_Registration();
return $registration->render_edit_profile_form($atts);
}
/**
* Render trainer profile shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_trainer_profile($atts = array()) {
if (!class_exists('HVAC_Trainer_Profile')) {
return '<p>' . __('Profile functionality not available.', 'hvac-community-events') . '</p>';
}
$trainer_profile = new HVAC_Trainer_Profile();
return $trainer_profile->render_profile($atts);
}
/**
* Render certificate reports shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_certificate_reports($atts = array()) {
// Check permissions
if (!is_user_logged_in()) {
return '<p>' . __('Please log in to view certificate reports.', 'hvac-community-events') . '</p>';
}
// Allow trainers, master trainers, or WordPress admins
if (!current_user_can('hvac_trainer') && !current_user_can('hvac_master_trainer') && !current_user_can('manage_options')) {
return '<p>' . __('You must be a trainer to access this page.', 'hvac-community-events') . '</p>';
}
// Use output buffering to capture template output properly
ob_start();
// Set flag to prevent template from echoing directly
define('HVAC_SHORTCODE_CONTEXT', true);
include HVAC_PLUGIN_DIR . 'templates/certificates/certificate-reports-content.php';
$content = ob_get_clean();
// Return the content for embedding in the WordPress template
return $content;
}
/**
* Render generate certificates shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_generate_certificates($atts = array()) {
// Check permissions
if (!is_user_logged_in()) {
return '<p>' . __('Please log in to generate certificates.', 'hvac-community-events') . '</p>';
}
// Allow trainers, master trainers, or WordPress admins
if (!current_user_can('hvac_trainer') && !current_user_can('hvac_master_trainer') && !current_user_can('manage_options')) {
return '<p>' . __('You must be a trainer to access this page.', 'hvac-community-events') . '</p>';
}
// Include the generate certificates content template
ob_start();
include HVAC_PLUGIN_DIR . 'templates/certificates/generate-certificates-content.php';
return ob_get_clean();
}
/**
* Render email attendees shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_email_attendees($atts = array()) {
// Check if user has appropriate permissions
// Allow trainers, master trainers, or WordPress admins
if (!current_user_can('hvac_trainer') && !current_user_can('hvac_master_trainer') && !current_user_can('manage_options')) {
return '<p>' . __('You must be a trainer to access this page.', 'hvac-community-events') . '</p>';
}
ob_start();
include HVAC_PLUGIN_DIR . 'templates/email-attendees.php';
return ob_get_clean();
}
/**
* Render communication templates shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_communication_templates($atts = array()) {
if (!class_exists('HVAC_Trainer_Communication_Templates')) {
return '<p>' . __('Communication templates functionality not available.', 'hvac-community-events') . '</p>';
}
// Use the new trainer communication templates class for read-only access
return HVAC_Trainer_Communication_Templates::instance()->render_templates_interface();
}
/**
* Render communication schedules shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_communication_schedules($atts = array()) {
if (!class_exists('HVAC_Communication_Scheduler')) {
return '<p>' . __('Communication scheduler functionality not available.', 'hvac-community-events') . '</p>';
}
// Check permissions
if (!current_user_can('edit_tribe_events') && !current_user_can('manage_options')) {
return '<p>' . __('You do not have permission to access this page.', 'hvac-community-events') . '</p>';
}
$scheduler = hvac_communication_scheduler();
ob_start();
$scheduler->render_schedules_page();
return ob_get_clean();
}
/**
* Render Google Sheets admin shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_google_sheets_admin($atts = array()) {
if (!class_exists('HVAC_Google_Sheets_Admin')) {
return '<p>' . __('Google Sheets functionality not available.', 'hvac-community-events') . '</p>';
}
// Check permissions
if (!current_user_can('manage_options') && !current_user_can('view_all_trainer_data')) {
return '<p>' . __('You do not have permission to access this page.', 'hvac-community-events') . '</p>';
}
$google_sheets = new HVAC_Google_Sheets_Admin();
ob_start();
$google_sheets->render_admin_page();
return ob_get_clean();
}
/**
* Render venues list shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_venues_list($atts = array()) {
// Check permissions
if (!is_user_logged_in()) {
return '<p>' . __('Please log in to view venues.', 'hvac-community-events') . '</p>';
}
// Allow trainers, master trainers, or WordPress admins
if (!current_user_can('hvac_trainer') && !current_user_can('hvac_master_trainer') && !current_user_can('manage_options')) {
return '<p>' . __('You must be a trainer to access this page.', 'hvac-community-events') . '</p>';
}
if (!class_exists('HVAC_Venues')) {
return '<p>' . __('Venues functionality not available.', 'hvac-community-events') . '</p>';
}
return HVAC_Venues::instance()->render_venues_list($atts);
}
/**
* Render venue manage shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_venue_manage($atts = array()) {
// Check permissions
if (!is_user_logged_in()) {
return '<p>' . __('Please log in to manage venues.', 'hvac-community-events') . '</p>';
}
// Allow trainers, master trainers, or WordPress admins
if (!current_user_can('hvac_trainer') && !current_user_can('hvac_master_trainer') && !current_user_can('manage_options')) {
return '<p>' . __('You must be a trainer to access this page.', 'hvac-community-events') . '</p>';
}
if (!class_exists('HVAC_Venues')) {
return '<p>' . __('Venues functionality not available.', 'hvac-community-events') . '</p>';
}
return HVAC_Venues::instance()->render_venue_manage($atts);
}
/**
* Render organizers list shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_organizers_list($atts = array()) {
// Check permissions
if (!is_user_logged_in()) {
return '<p>' . __('Please log in to view organizers.', 'hvac-community-events') . '</p>';
}
// Allow trainers, master trainers, or WordPress admins
if (!current_user_can('hvac_trainer') && !current_user_can('hvac_master_trainer') && !current_user_can('manage_options')) {
return '<p>' . __('You must be a trainer to access this page.', 'hvac-community-events') . '</p>';
}
if (!class_exists('HVAC_Organizers')) {
return '<p>' . __('Organizers functionality not available.', 'hvac-community-events') . '</p>';
}
$organizers = HVAC_Organizers::instance();
return $organizers->render_organizers_list($atts);
}
/**
* Render organizer manage shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_organizer_manage($atts = array()) {
// Check permissions
if (!is_user_logged_in()) {
return '<p>' . __('Please log in to manage organizers.', 'hvac-community-events') . '</p>';
}
// Allow trainers, master trainers, or WordPress admins
if (!current_user_can('hvac_trainer') && !current_user_can('hvac_master_trainer') && !current_user_can('manage_options')) {
return '<p>' . __('You must be a trainer to access this page.', 'hvac-community-events') . '</p>';
}
if (!class_exists('HVAC_Organizers')) {
return '<p>' . __('Organizers functionality not available.', 'hvac-community-events') . '</p>';
}
$organizers = HVAC_Organizers::instance();
return $organizers->render_organizer_manage($atts);
}
/**
* Render trainer profile view shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_trainer_profile_view($atts = array()) {
// Check permissions
if (!is_user_logged_in()) {
return '<p>' . __('Please log in to view your profile.', 'hvac-community-events') . '</p>';
}
// Allow trainers, master trainers, or WordPress admins
if (!current_user_can('hvac_trainer') && !current_user_can('hvac_master_trainer') && !current_user_can('manage_options')) {
return '<p>' . __('You must be a trainer to access this page.', 'hvac-community-events') . '</p>';
}
if (!class_exists('HVAC_Trainer_Profile_Manager')) {
return '<p>' . __('Profile functionality not available.', 'hvac-community-events') . '</p>';
}
$profile_manager = HVAC_Trainer_Profile_Manager::get_instance();
return $profile_manager->render_profile_view($atts);
}
/**
* Render trainer profile edit shortcode
*
* @param array $atts Shortcode attributes
* @return string
*/
public function render_trainer_profile_edit($atts = array()) {
// Check permissions
if (!is_user_logged_in()) {
return '<p>' . __('Please log in to edit your profile.', 'hvac-community-events') . '</p>';
}
// Allow trainers, master trainers, or WordPress admins
if (!current_user_can('hvac_trainer') && !current_user_can('hvac_master_trainer') && !current_user_can('manage_options')) {
return '<p>' . __('You must be a trainer to access this page.', 'hvac-community-events') . '</p>';
}
if (!class_exists('HVAC_Trainer_Profile_Manager')) {
return '<p>' . __('Profile functionality not available.', 'hvac-community-events') . '</p>';
}
$profile_manager = HVAC_Trainer_Profile_Manager::get_instance();
return $profile_manager->render_profile_edit($atts);
}
}