# Trainer Profile Custom Post Type - Developer Implementation Guide ## Overview This document provides implementation specifications for creating a custom "Trainer Profile" post type to extend WordPress user functionality beyond the limitations of the standard User post type. This replaces the current user meta field approach with a proper custom post type for better data management, public directory compatibility, and Gutenberg integration. ## Core Requirements ### Data Architecture #### Synchronized Fields (User ↔ Trainer Profile) These fields must be kept in sync between wp_users and trainer_profile posts: - `first_name` (user) ↔ `trainer_first_name` (profile meta) - `last_name` (user) ↔ `trainer_last_name` (profile meta) - `display_name` (user) ↔ `trainer_display_name` (profile meta) #### Trainer Profile Exclusive Fields Move these from user meta to trainer_profile post meta: - `linkedin_profile_url` - `personal_accreditation` - `biographical_info` - `training_audience` - `training_formats` - `training_locations` - `training_resources` - `annual_revenue_target` - `application_details` - `date_certified` - `certification_type` - `certification_status` - `trainer_city` - `trainer_state` - `trainer_country` - `business_type` (taxonomy term, same as "Organizer Category" from CSV) - `latitude` (auto-generated from address) - `longitude` (auto-generated from address) #### Relationship Mapping - Store `user_id` in trainer_profile post meta - Store `trainer_profile_id` in user meta - Enforce 1:1 relationship ### Custom Post Type Configuration ```php register_post_type('trainer_profile', [ 'labels' => [ 'name' => 'Trainer Profiles', 'singular_name' => 'Trainer Profile', 'edit_item' => 'Edit Trainer Profile' ], 'public' => true, 'publicly_queryable' => true, 'show_ui' => true, 'show_in_rest' => true, 'capability_type' => 'post', 'supports' => ['title', 'editor', 'custom-fields', 'thumbnail'], 'has_archive' => true, 'rewrite' => ['slug' => 'trainers'] ]); ``` ### Permission System #### Edit Permissions - Profile owners can edit their own trainer_profile - Users with `hvac_master_trainer` role can edit all trainer_profiles - Restrict editing of email, password, username, latitude, longitude fields #### Implementation Pattern ```php function trainer_profile_edit_permissions($caps, $cap, $user_id, $args) { if (!in_array($cap, ['edit_post', 'delete_post'])) { return $caps; } $post_id = $args[0]; $post = get_post($post_id); if (!$post || $post->post_type !== 'trainer_profile') { return $caps; } $profile_user_id = get_post_meta($post_id, 'user_id', true); // Allow profile owner or master trainers if ($user_id == $profile_user_id || user_can($user_id, 'hvac_master_trainer')) { return ['exist']; } return $caps; } add_filter('map_meta_cap', 'trainer_profile_edit_permissions', 10, 4); ``` ## Implementation Components ### Core Classes to Create #### HVAC_Trainer_Profile_Manager Primary manager class using singleton pattern: - Handle trainer_profile CRUD operations - Manage user-profile relationships - Coordinate data synchronization - Auto-create profiles for new trainers #### HVAC_Profile_Sync_Handler Handle bidirectional synchronization: - Sync shared fields between user and profile - Prevent infinite loops during updates - Handle bulk sync operations - Conflict resolution #### HVAC_Geocoding_Service Google Maps API integration: - Geocode addresses to coordinates - Cache results to avoid API rate limits - Handle API errors gracefully - Store geocoding status and timestamps ### Required WordPress Hooks ```php // Profile creation/updates add_action('save_post_trainer_profile', 'sync_profile_to_user'); add_action('profile_update', 'sync_user_to_profile'); add_action('add_user_role', 'maybe_create_trainer_profile'); // Geocoding triggers add_action('updated_post_meta', 'maybe_trigger_geocoding'); add_action('added_post_meta', 'maybe_trigger_geocoding'); // Admin integration add_action('admin_menu', 'add_trainer_profile_settings'); ``` ### Settings Integration Add Google Maps API configuration to existing HVAC plugin settings: - API Key field (password type, encrypted storage) - Enable/disable geocoding toggle - Rate limit configuration - Cache duration settings Access via: WordPress Admin → HVAC Settings → API Configuration ## Page Template Updates ### /trainer/profile/ Page Refactor **File**: `templates/page-trainer-profile.php` Requirements: - Primary focus on trainer_profile fields (not user fields) - Include password change section at bottom - Use AJAX form submission with validation - Follow existing page template patterns - Include breadcrumb navigation #### Password Change Section - Current Password (required) - New Password (strength validation) - Confirm New Password (match validation) - Separate form section with independent submission ### /master-trainer/trainer-profile/edit Page **File**: `templates/page-master-trainer-profile-edit.php` Requirements: - Allow editing all trainer_profile fields except restricted ones - Restricted fields: email, password, username, latitude, longitude - User selection dropdown with search functionality - Permission validation before access - Audit logging for changes made - "View Public Profile" preview link ### Master Dashboard Updates Update the "Trainer Performance Analytics" table: - Make trainer names clickable links - Link to `/master-trainer/trainer-profile/edit?user_id={id}` - Maintain existing sorting and filtering functionality ## Data Migration Strategy ### CSV Import Migration Create migration function to: 1. For each existing user with trainer role 2. Create corresponding trainer_profile post 3. Migrate relevant fields from user meta to post meta 4. Set business_type taxonomy term 5. Establish user-profile relationship 6. Trigger initial geocoding 7. Clean up old user meta fields ### Migration Script Requirements ```php function migrate_users_to_trainer_profiles() { // Get all users with trainer roles $trainers = get_users(['role__in' => ['hvac_trainer', 'hvac_master_trainer']]); foreach ($trainers as $user) { // Create trainer_profile post // Migrate user meta to post meta // Set up relationships // Trigger geocoding // Clean up old meta } } ``` ## Geocoding Implementation ### Google Maps API Integration - Use Google Maps Geocoding API - Store API key in WordPress options (encrypted) - Implement rate limiting and caching - Handle API errors and fallbacks ### Geocoding Triggers Monitor these meta fields for changes: - `trainer_city` - `trainer_state` - `trainer_country` ### Geocoding Logic ```php function geocode_trainer_address($post_id) { $city = get_post_meta($post_id, 'trainer_city', true); $state = get_post_meta($post_id, 'trainer_state', true); $country = get_post_meta($post_id, 'trainer_country', true); $address = implode(', ', array_filter([$city, $state, $country])); if (empty($address)) return; // Check cache first $cache_key = 'geocode_' . md5($address); $cached = get_transient($cache_key); if ($cached !== false) { update_post_meta($post_id, 'latitude', $cached['lat']); update_post_meta($post_id, 'longitude', $cached['lng']); return; } // Make API call $api_key = get_option('hvac_google_maps_api_key'); $url = "https://maps.googleapis.com/maps/api/geocode/json"; $response = wp_remote_get($url . '?' . http_build_query([ 'address' => $address, 'key' => $api_key ])); // Process response and update coordinates // Cache results for 24 hours // Log errors appropriately } ``` ## Form Implementation ### Trainer Profile Edit Form Structure #### Form Sections 1. **Personal Information** - First Name, Last Name, Display Name (synced fields) - LinkedIn Profile URL - Personal Accreditation 2. **Professional Details** - Biographical Info (WordPress editor) - Training Audience (multi-select) - Training Formats (checkboxes) - Training Locations (textarea) 3. **Business Information** - Business Type (dropdown from taxonomy) - Annual Revenue Target (number input) - Training Resources (textarea) 4. **Certification Details** - Date Certified (date picker) - Certification Type (dropdown) - Certification Status (conditional editing) 5. **Location Information** - Trainer City/State/Country - Coordinates (readonly, auto-populated) 6. **Password Change** (separate section) - Current Password - New Password - Confirm New Password ### Form Validation Requirements #### Client-side (JavaScript) - Required field validation - Email format checking - Password strength requirements - Real-time feedback #### Server-side (PHP) - Sanitize all inputs using WordPress functions - Verify user permissions - Validate data formats - Check for required fields ## Security Considerations ### Input Sanitization ```php // Text fields $value = sanitize_text_field($_POST['field_name']); // URLs $url = esc_url_raw($_POST['url_field']); // Rich text $content = wp_kses_post($_POST['content_field']); // Email $email = sanitize_email($_POST['email_field']); ``` ### Permission Validation - Verify nonces on all form submissions - Check user capabilities before operations - Validate user owns profile or has master trainer role - Log permission violations ### API Security - Store Google Maps API key encrypted - Implement rate limiting for geocoding - Log API errors without exposing keys - Validate all API responses ## Testing Requirements ### Unit Tests - Profile creation and updates - Data synchronization accuracy - Geocoding functionality - Permission validation ### Integration Tests - CSV migration process - Form submission workflows - Master trainer operations - Public directory compatibility ### Manual Testing - Test all form fields and validations - Verify geocoding triggers correctly - Check master trainer permissions - Test mobile responsiveness - Verify Gutenberg compatibility ## Deployment Process ### Pre-Deployment 1. Run `bin/pre-deployment-check.sh` 2. Backup existing user meta data 3. Test migration script on staging 4. Configure Google Maps API key ### Deployment Steps 1. Deploy via `scripts/deploy.sh staging` 2. Run data migration script 3. Verify trainer profile creation 4. Test geocoding functionality 5. Validate permissions across roles ### Post-Deployment Verification 1. Run `scripts/verify-plugin-fixes.sh` 2. Check error logs for issues 3. Test public directory functionality 4. Verify form submissions work 5. Test master trainer features ## File Structure ``` includes/ ├── class-hvac-trainer-profile-manager.php ├── class-hvac-profile-sync-handler.php ├── class-hvac-geocoding-service.php └── class-hvac-trainer-profile-settings.php templates/ ├── page-trainer-profile.php (updated) └── page-master-trainer-profile-edit.php (new) assets/js/ ├── trainer-profile-edit.js └── master-trainer-profile-edit.js assets/css/ ├── trainer-profile.css └── master-trainer-profile.css ``` ## Performance Considerations - Cache geocoding results for 24 hours minimum - Use lazy loading for coordinates display - Implement batch processing for bulk operations - Add database indexes on relationship fields - Optimize queries to avoid N+1 problems ## Error Handling - Log geocoding API failures with appropriate detail - Handle data synchronization conflicts gracefully - Provide user-friendly error messages - Implement retry logic for transient failures - Monitor and alert on critical errors This implementation maintains consistency with existing HVAC plugin patterns while providing the enhanced functionality needed for trainer profile management and public directory compatibility.