## 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>
15 KiB
15 KiB
Organizer Management System Documentation
Version: 2.0.0
Last Updated: August 28, 2025
Component: HVAC_Organizers
Status: ✅ Production Ready
Table of Contents
- Overview
- Features
- User Interface
- Technical Architecture
- Logo Management
- Database Schema
- API Reference
- Security Considerations
- Troubleshooting
Overview
The Organizer Management System enables trainers to create and manage organizations that host training events. This system integrates seamlessly with The Events Calendar (TEC) and provides professional branding capabilities through logo uploads and headquarters tracking.
Key Benefits
- Professional Branding: Logo upload for organization identity
- Headquarters Tracking: Document organization locations
- Contact Management: Centralized contact information
- Event Association: Link organizations to multiple events
- TEC Integration: Native organizer support in events
Features
Core Functionality
1. Organizer Directory (/trainer/organizer/list/)
- Searchable Listing: Find organizers by name
- Logo Display: Visual organization identification
- Contact Information: Email and phone at a glance
- Headquarters Location: City, state, country display
- Quick Actions: Edit buttons for management
- Pagination: 20 organizers per page
2. Organizer Management (/trainer/organizer/manage/)
- Create Organizations: Complete profile creation
- Edit Profiles: Update all organization details
- Logo Upload: Professional branding support
- Delete Organizations: Safe removal with checks
- Rich Profiles: Comprehensive information fields
Data Fields
Organization Information
- Organization Name (Required)
- Description: Detailed organization information
- Logo: Upload organization branding (JPG, PNG, GIF, WebP)
Headquarters Location
- City (Required)
- State/Province (Required)
- Country (Required): Selected from supported countries
Contact Information
- Phone Number: Organization telephone
- Email Address: Contact email
- Website URL: Organization website
Advanced Features
Logo Management
- Upload Support: JPG, PNG, GIF, WebP formats
- Size Limit: 5MB maximum file size
- Recommended: 300x300px for best display
- Fallback: Letter-based placeholder when no logo
- Media Library: Integration with WordPress media
Access Control
- Role-Based: Master trainers see all, trainers see own
- Edit Permissions: Only organizer creators can edit
- Delete Protection: Check for event associations
User Interface
Organizer List Page
┌─────────────────────────────────────────────────┐
│ Training Organizers [Add New Organizer] │
├─────────────────────────────────────────────────┤
│ [Search: ___________] [Search] [Clear] │
├─────────────────────────────────────────────────┤
│ Logo │ Name │ HQ │ Contact │ Website │ Actions │
├──────┼──────┼────┼─────────┼─────────┼─────────┤
│ [◼] │ ACME │NYC │email@ │[Visit] │ [Edit] │
│ │ Corp │USA │555-0123 │ │ │
└─────────────────────────────────────────────────┘
Organizer Management Form
┌─────────────────────────────────────────────────┐
│ Create New Organizer / Edit Organizer │
├─────────────────────────────────────────────────┤
│ Organization Logo │
│ ┌─────────┐ │
│ │ [Logo] │ [Upload Logo] [Remove Logo] │
│ └─────────┘ Recommended: 300x300px, Max: 5MB │
│ │
│ Organization Information │
│ ├─ Organization Name: [____________] * │
│ └─ Description: [__________________] │
│ │
│ Headquarters Location │
│ ├─ City: [__________] * │
│ ├─ State/Province: [_______] * │
│ └─ Country: [United States ▼] * │
│ │
│ Contact Information │
│ ├─ Phone: [___________] │
│ ├─ Email: [___________] │
│ └─ Website: [_________] │
│ │
│ [Save Organizer] [Cancel] [Delete] │
└─────────────────────────────────────────────────┘
Technical Architecture
Class Structure
class HVAC_Organizers {
// Singleton pattern
private static $instance = null;
public static function instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
// Core methods
public function render_organizers_list()
public function render_organizer_manage()
public function ajax_save_organizer()
public function ajax_delete_organizer()
public function ajax_upload_org_logo()
}
File Structure
includes/
├── class-hvac-organizers.php # Main organizer class
assets/
├── css/
│ └── hvac-organizers.css # Organizer styles
└── js/
└── hvac-organizers.js # Organizer JavaScript
templates/
├── page-trainer-organizer-list.php # List template
└── page-trainer-organizer-manage.php # Manage template
AJAX Endpoints
Save Organizer
- Action:
wp_ajax_hvac_save_organizer - Nonce:
hvac_organizers_nonce - Parameters: Organization data fields
- Response: Success/error with organizer ID
Delete Organizer
- Action:
wp_ajax_hvac_delete_organizer - Nonce:
hvac_organizers_nonce - Parameters:
organizer_id - Response: Success/error message
Upload Logo
- Action:
wp_ajax_hvac_upload_org_logo - Nonce:
hvac_organizers_nonce - Parameters:
org_logofile - Response: Attachment ID and URL
Logo Management
Upload Process
// JavaScript implementation
var formData = new FormData();
formData.append('org_logo', fileInput.files[0]);
formData.append('action', 'hvac_upload_org_logo');
formData.append('nonce', hvacOrganizers.nonce);
jQuery.ajax({
url: hvacOrganizers.ajax_url,
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(response) {
if (response.success) {
// Update logo display
updateLogoDisplay(response.data.url);
// Store attachment ID
$('#org_logo_id').val(response.data.attachment_id);
}
}
});
File Validation
// Server-side validation
$allowed_types = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp'];
$max_size = 5 * 1024 * 1024; // 5MB
// Check file type
$file_type = wp_check_filetype($_FILES['org_logo']['name']);
if (!in_array($file_type['type'], $allowed_types)) {
wp_send_json_error('Invalid file type');
}
// Check file size
if ($_FILES['org_logo']['size'] > $max_size) {
wp_send_json_error('File too large. Maximum size is 5MB.');
}
WordPress Media Integration
// Handle upload through WordPress media
require_once(ABSPATH . 'wp-admin/includes/media.php');
$attachment_id = media_handle_upload('org_logo', 0);
// Set as post thumbnail
set_post_thumbnail($organizer_id, $attachment_id);
Database Schema
Post Type
- Type:
tribe_organizer - Status:
publish - Author: Current user ID
Post Meta Fields
_OrganizerPhone -- Phone number
_OrganizerEmail -- Email address
_OrganizerWebsite -- Website URL
_hvac_headquarters_city -- HQ city
_hvac_headquarters_state -- HQ state/province
_hvac_headquarters_country -- HQ country
_thumbnail_id -- Logo attachment ID
User Meta
organizer_id -- Primary organizer for user
API Reference
PHP Functions
Creating an Organizer
// Using TEC function
$organizer_id = tribe_create_organizer([
'Organizer' => 'ACME Corporation',
'Description' => 'Leading HVAC training organization',
'Phone' => '555-0123',
'Email' => 'contact@acme.com',
'Website' => 'https://acme.com'
]);
// Add headquarters information
update_post_meta($organizer_id, '_hvac_headquarters_city', 'New York');
update_post_meta($organizer_id, '_hvac_headquarters_state', 'NY');
update_post_meta($organizer_id, '_hvac_headquarters_country', 'United States');
Retrieving Organizers
// Get all organizers
$organizers = get_posts([
'post_type' => 'tribe_organizer',
'posts_per_page' => -1,
'post_status' => 'publish'
]);
// Get user's organizers
$user_organizers = get_posts([
'post_type' => 'tribe_organizer',
'author' => get_current_user_id(),
'posts_per_page' => -1
]);
// Get organizer details
$organizer = get_post($organizer_id);
$phone = get_post_meta($organizer_id, '_OrganizerPhone', true);
$logo_id = get_post_thumbnail_id($organizer_id);
Updating an Organizer
// Using TEC function
tribe_update_organizer($organizer_id, [
'Organizer' => 'Updated Name',
'Email' => 'newemail@acme.com'
]);
// Update headquarters
update_post_meta($organizer_id, '_hvac_headquarters_city', 'Boston');
// Update logo
set_post_thumbnail($organizer_id, $new_logo_id);
JavaScript Functions
Save Organizer via AJAX
jQuery.ajax({
url: hvacOrganizers.ajax_url,
type: 'POST',
data: {
action: 'hvac_save_organizer',
nonce: hvacOrganizers.nonce,
org_name: 'ACME Corporation',
org_description: 'Description',
hq_city: 'New York',
hq_state: 'NY',
hq_country: 'United States',
org_phone: '555-0123',
org_email: 'contact@acme.com',
org_website: 'https://acme.com',
org_logo_id: 123
},
success: function(response) {
if (response.success) {
console.log('Organizer saved:', response.data.organizer_id);
}
}
});
Security Considerations
Access Control Matrix
| Action | Trainer | Master Trainer | Admin |
|---|---|---|---|
| View All | No | Yes | Yes |
| View Own | Yes | Yes | Yes |
| Create | Yes | Yes | Yes |
| Edit Own | Yes | Yes | Yes |
| Edit Any | No | No | Yes |
| Delete Own | Yes | Yes | Yes |
| Delete Any | No | No | Yes |
Data Validation
// Input sanitization
$org_name = sanitize_text_field($_POST['org_name']);
$org_email = sanitize_email($_POST['org_email']);
$org_website = esc_url_raw($_POST['org_website']);
$org_description = wp_kses_post($_POST['org_description']);
File Upload Security
// Validate file upload
if (!is_uploaded_file($_FILES['org_logo']['tmp_name'])) {
wp_send_json_error('Security error: Invalid file upload.');
}
// Check MIME type
$file_info = wp_check_filetype_and_ext(
$_FILES['org_logo']['tmp_name'],
$_FILES['org_logo']['name']
);
if (!$file_info['type']) {
wp_send_json_error('Invalid file type.');
}
Nonce Verification
// All actions require nonce
check_ajax_referer('hvac_organizers_nonce', 'nonce');
Troubleshooting
Common Issues
Logo Not Uploading
Problem: Logo upload fails
Solutions:
- Check file size (max 5MB)
- Verify file type (JPG, PNG, GIF, WebP)
- Check upload directory permissions
# Fix permissions
chmod 755 wp-content/uploads
Cannot Delete Organizer
Problem: Delete button doesn't work
Solution: Organizer is being used by events
// Check for events using organizer
$events = get_posts([
'post_type' => 'tribe_events',
'meta_key' => '_EventOrganizerID',
'meta_value' => $organizer_id
]);
if (!empty($events)) {
// Cannot delete - organizer in use
}
Organizer Not in Event Dropdown
Problem: Created organizer missing from event creation
Solution: Check post status
// Ensure organizer is published
wp_update_post([
'ID' => $organizer_id,
'post_status' => 'publish'
]);
Error Messages
| Error | Meaning | Solution |
|---|---|---|
| "Unauthorized" | User not logged in or wrong role | Check user authentication |
| "Invalid file type" | Wrong image format | Use JPG, PNG, GIF, or WebP |
| "File too large" | Exceeds 5MB limit | Reduce file size |
| "Cannot delete organizer" | In use by events | Remove from events first |
| "Organization name required" | Missing required field | Provide organization name |
Best Practices
Performance Optimization
- Image Optimization: Compress logos before upload
- Caching: Organizer queries are cached
- Lazy Loading: Logos load on scroll
- Pagination: Large lists are paginated
User Experience
- Visual Feedback: Loading indicators during upload
- Error Handling: Clear error messages
- Placeholder Images: Letter-based when no logo
- Responsive Design: Mobile-optimized interface
Development Guidelines
- Singleton Pattern: Use
HVAC_Organizers::instance() - WordPress APIs: Use native functions when available
- Security First: Always validate and sanitize
- Media Library: Leverage WordPress media handling
Integration with Events
Event Creation
// Organizers automatically available in TEC
// Dropdown populated with published organizers
Multiple Organizers
// Events can have multiple organizers
$event_organizers = tribe_get_organizer_ids($event_id);
Display on Event Pages
// Organizer information displayed automatically
// Logo, name, contact info shown on event details
Future Enhancements
Planned Features
- Bulk Import: CSV organizer upload
- Social Media: Social profile links
- Certifications: Organization credentials
- Branch Offices: Multiple locations
- Team Members: Staff directory
- Event History: Past events by organizer
- Rating System: Trainer feedback
API Extensions
- REST API: Full CRUD operations
- GraphQL: Query support
- Webhooks: Organization updates
- Third-party Integration: CRM systems
UI Improvements
- Drag-and-drop: Logo upload
- Rich Text Editor: Enhanced descriptions
- Map Integration: HQ location display
- Quick Edit: Inline editing
For additional support, see TROUBLESHOOTING.md or contact the development team.