init_hooks(); } /** * Initialize hooks */ private function init_hooks() { add_action('init', [$this, 'register_page']); add_action('wp_enqueue_scripts', [$this, 'enqueue_assets']); add_filter('body_class', [$this, 'add_body_classes']); add_shortcode('hvac_find_trainer', [$this, 'render_shortcode']); add_shortcode('hvac_trainer_directory', [$this, 'render_directory_shortcode']); // AJAX handlers add_action('wp_ajax_hvac_get_trainer_upcoming_events', [$this, 'ajax_get_upcoming_events']); add_action('wp_ajax_nopriv_hvac_get_trainer_upcoming_events', [$this, 'ajax_get_upcoming_events']); } /** * Register the Find a Trainer page */ public function register_page() { // Check if page exists $page = get_page_by_path($this->page_slug); if (!$page) { $this->create_page(); } } /** * Create the Find a Trainer page */ private function create_page() { $page_content = $this->get_page_content(); $page_data = [ 'post_title' => 'Find a Trainer', 'post_name' => $this->page_slug, 'post_content' => $page_content, 'post_status' => 'publish', 'post_type' => 'page', 'post_author' => 1, 'meta_input' => [ '_wp_page_template' => 'default', 'ast-site-content-layout' => 'page-builder', 'site-post-title' => 'disabled', 'site-sidebar-layout' => 'no-sidebar', 'ast-main-header-display' => 'enabled', 'ast-hfb-above-header-display' => 'disabled', 'ast-hfb-below-header-display' => 'disabled', 'ast-featured-img' => 'disabled' ] ]; $page_id = wp_insert_post($page_data); if ($page_id && !is_wp_error($page_id)) { update_option('hvac_find_trainer_page_id', $page_id); } } /** * Get the page content with Gutenberg blocks */ private function get_page_content() { return '

Find certified HVAC trainers in your area. Use the interactive map and filters below to discover trainers who match your specific needs. Click on any trainer to view their profile and contact them directly.

[display-map id="5872"]
Filters:
[hvac_trainer_directory]

Are you an HVAC Trainer that wants to be listed in our directory?

'; } /** * Enqueue assets for the Find a Trainer page */ public function enqueue_assets() { if (!$this->is_find_trainer_page()) { return; } // Enqueue CSS wp_enqueue_style( 'hvac-find-trainer', HVAC_PLUGIN_URL . 'assets/css/find-trainer.css', ['astra-theme-css'], HVAC_VERSION ); // Enqueue JavaScript wp_enqueue_script( 'hvac-find-trainer', HVAC_PLUGIN_URL . 'assets/js/find-trainer.js', ['jquery'], HVAC_VERSION, true ); // Localize script wp_localize_script('hvac-find-trainer', 'hvac_find_trainer', [ 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('hvac_find_trainer'), 'map_id' => '5872', 'messages' => [ 'loading' => __('Loading...', 'hvac'), 'error' => __('An error occurred. Please try again.', 'hvac'), 'no_results' => __('No trainers found matching your criteria.', 'hvac'), 'form_error' => __('Please check the form and try again.', 'hvac'), 'form_success' => __('Your message has been sent! Check your inbox for more details.', 'hvac') ] ]); } /** * Add body classes for the Find a Trainer page */ public function add_body_classes($classes) { if ($this->is_find_trainer_page()) { $classes[] = 'hvac-find-trainer-page'; $classes[] = 'hvac-full-width'; } return $classes; } /** * Check if current page is the Find a Trainer page */ private function is_find_trainer_page() { return is_page($this->page_slug) || is_page(get_option('hvac_find_trainer_page_id')); } /** * Render the main shortcode */ public function render_shortcode($atts) { $atts = shortcode_atts([ 'show_map' => true, 'show_filters' => true, 'show_directory' => true ], $atts); ob_start(); ?>
render_filters(); ?>
render_directory(); ?>
12, 'columns' => 2 ], $atts); ob_start(); $this->render_directory($atts); return ob_get_clean(); } /** * Render filter controls */ private function render_filters() { ?>
Filters:
12, 'columns' => 2 ]; $args = wp_parse_args($args, $defaults); // Get trainers $query_args = [ 'post_type' => 'trainer_profile', 'posts_per_page' => $args['per_page'], 'post_status' => 'publish', 'meta_query' => [ [ 'key' => 'is_public_profile', 'value' => '1', 'compare' => '=' ] ] ]; $trainers = new WP_Query($query_args); ?>
have_posts()) : ?> have_posts()) : $trainers->the_post(); ?> render_trainer_card(get_the_ID()); ?>

max_num_pages > 1) : ?>
$trainers->max_num_pages, 'current' => max(1, get_query_var('paged')), 'prev_text' => '« Previous', 'next_text' => 'Next »' ]); ?>
<?php echo esc_attr($trainer_name); ?>

,

'trainer_profile', 'posts_per_page' => -1, 'post_status' => 'publish', 'meta_query' => [ [ 'key' => 'is_public_profile', 'value' => '1', 'compare' => '=' ], [ 'key' => 'latitude', 'compare' => 'EXISTS' ], [ 'key' => 'longitude', 'compare' => 'EXISTS' ] ] ]; $trainers = new WP_Query($args); if ($trainers->have_posts()) { while ($trainers->have_posts()) { $trainers->the_post(); $profile_id = get_the_ID(); $markers[] = $this->format_marker_data($profile_id); } } wp_reset_postdata(); return $markers; } /** * Format marker data for a trainer */ private function format_marker_data($profile_id) { $user_id = get_post_meta($profile_id, 'user_id', true); $trainer_name = get_post_meta($profile_id, 'trainer_display_name', true); $city = get_post_meta($profile_id, 'trainer_city', true); $state = get_post_meta($profile_id, 'trainer_state', true); $lat = get_post_meta($profile_id, 'latitude', true); $lng = get_post_meta($profile_id, 'longitude', true); $certification = get_post_meta($profile_id, 'certification_type', true); $business_types = wp_get_post_terms($profile_id, 'business_type', ['fields' => 'names']); return [ 'id' => $profile_id, 'title' => $trainer_name, 'lat' => floatval($lat), 'lng' => floatval($lng), 'content' => $this->generate_marker_content($profile_id), 'data' => [ 'trainer_id' => $user_id, 'profile_id' => $profile_id, 'certification' => $certification, 'business_type' => $business_types, 'state' => $state, 'city' => $city ] ]; } /** * Generate marker popup content */ private function generate_marker_content($profile_id) { $trainer_name = get_post_meta($profile_id, 'trainer_display_name', true); $city = get_post_meta($profile_id, 'trainer_city', true); $state = get_post_meta($profile_id, 'trainer_state', true); return sprintf( '

%s

%s, %s

', $profile_id, esc_html($trainer_name), esc_html($city), esc_html($state), $profile_id ); } /** * AJAX handler for getting trainer upcoming events */ public function ajax_get_upcoming_events() { // Verify nonce if (!wp_verify_nonce($_POST['nonce'], 'hvac_find_trainer')) { wp_send_json_error('Invalid nonce'); } $profile_id = intval($_POST['profile_id']); if (!$profile_id) { wp_send_json_error('Invalid profile ID'); } // Get the user ID from the profile $user_id = get_post_meta($profile_id, 'user_id', true); if (!$user_id) { wp_send_json_error('No user found for this profile'); } $upcoming_events = []; // Get upcoming events using the fixed query if (function_exists('tribe_get_events')) { $events = tribe_get_events([ 'author' => $user_id, 'posts_per_page' => 5, 'ends_after' => 'now', 'orderby' => 'event_date', 'order' => 'ASC' ]); foreach ($events as $event) { $upcoming_events[] = [ 'title' => $event->post_title, 'date' => tribe_get_start_date($event->ID, false, 'M j, Y'), 'url' => get_permalink($event->ID) ]; } } wp_send_json_success([ 'events' => $upcoming_events, 'count' => count($upcoming_events) ]); } }