cache_group); if ($cached !== false && empty($filters)) { return $cached; } // Get approved user IDs $approved_user_ids = $this->get_approved_user_ids(); if (empty($approved_user_ids)) { return []; } // Build query args $query_args = [ 'post_type' => 'trainer_profile', 'posts_per_page' => -1, 'post_status' => 'publish', 'meta_query' => [ 'relation' => 'AND', [ 'key' => 'is_public_profile', 'value' => '1', 'compare' => '=' ], [ 'key' => 'user_id', 'value' => $approved_user_ids, 'compare' => 'IN' ], [ 'key' => 'latitude', 'compare' => 'EXISTS' ], [ 'key' => 'longitude', 'compare' => 'EXISTS' ], [ 'key' => 'latitude', 'value' => '', 'compare' => '!=' ], [ 'key' => 'longitude', 'value' => '', 'compare' => '!=' ] ] ]; // Add state filter if (!empty($filters['state'])) { $query_args['meta_query'][] = [ 'key' => 'trainer_state', 'value' => sanitize_text_field($filters['state']), 'compare' => '=' ]; } // Add search filter if (!empty($filters['search'])) { $search = sanitize_text_field($filters['search']); $query_args['meta_query'][] = [ 'relation' => 'OR', [ 'key' => 'trainer_display_name', 'value' => $search, 'compare' => 'LIKE' ], [ 'key' => 'trainer_city', 'value' => $search, 'compare' => 'LIKE' ], [ 'key' => 'company_name', 'value' => $search, 'compare' => 'LIKE' ] ]; } $query = new WP_Query($query_args); $markers = []; if ($query->have_posts()) { while ($query->have_posts()) { $query->the_post(); $profile_id = get_the_ID(); $marker = $this->format_trainer_marker($profile_id); // Apply certification filter if (!empty($filters['certification'])) { $cert_match = false; foreach ($marker['certifications'] as $cert) { if (stripos($cert, $filters['certification']) !== false) { $cert_match = true; break; } } if (!$cert_match) { continue; } } // Apply proximity filter if (!empty($filters['lat']) && !empty($filters['lng']) && !empty($filters['radius'])) { $distance = $this->calculate_distance( $filters['lat'], $filters['lng'], $marker['lat'], $marker['lng'] ); if ($distance > $filters['radius']) { continue; } $marker['distance'] = round($distance, 1); } $markers[] = $marker; } } wp_reset_postdata(); // Sort by distance if proximity search if (!empty($filters['lat']) && !empty($filters['lng'])) { usort($markers, function($a, $b) { return ($a['distance'] ?? 0) <=> ($b['distance'] ?? 0); }); } // Cache if no filters if (empty($filters)) { wp_cache_set($cache_key, $markers, $this->cache_group, $this->cache_expiration); } return $markers; } /** * Get venue markers for map * * Filters to show only measureQuick Approved Training Labs. * * @param array $filters Optional filters * @return array Venue markers data */ public function get_venue_markers(array $filters = []): array { // Check if TEC is active if (!function_exists('tribe_get_venue')) { return []; } // Generate cache key $cache_key = 'venues_approved_labs_' . md5(serialize($filters)); $cached = wp_cache_get($cache_key, $this->cache_group); if ($cached !== false && empty($filters)) { return $cached; } // Build query args - filter for approved training labs only $query_args = [ 'post_type' => 'tribe_venue', 'posts_per_page' => -1, 'post_status' => 'publish', // Only show venues tagged as measureQuick Approved Training Labs 'tax_query' => [ [ 'taxonomy' => 'venue_type', 'field' => 'slug', 'terms' => 'mq-approved-lab', ], ], 'meta_query' => [ 'relation' => 'AND', [ 'relation' => 'OR', // Check for our custom venue coordinates [ 'key' => 'venue_latitude', 'compare' => 'EXISTS' ], // Also check TEC's built-in coordinates [ 'key' => '_VenueLat', 'compare' => 'EXISTS' ] ] ] ]; // Add state filter if (!empty($filters['state'])) { $query_args['meta_query'][] = [ 'relation' => 'OR', [ 'key' => '_VenueStateProvince', 'value' => sanitize_text_field($filters['state']), 'compare' => '=' ], [ 'key' => '_VenueState', 'value' => sanitize_text_field($filters['state']), 'compare' => '=' ] ]; } // Add search filter if (!empty($filters['search'])) { $query_args['s'] = sanitize_text_field($filters['search']); } $query = new WP_Query($query_args); $markers = []; if ($query->have_posts()) { while ($query->have_posts()) { $query->the_post(); $venue_id = get_the_ID(); $marker = $this->format_venue_marker($venue_id); // Skip venues without valid coordinates if (empty($marker['lat']) || empty($marker['lng'])) { continue; } // Apply proximity filter if (!empty($filters['lat']) && !empty($filters['lng']) && !empty($filters['radius'])) { $distance = $this->calculate_distance( $filters['lat'], $filters['lng'], $marker['lat'], $marker['lng'] ); if ($distance > $filters['radius']) { continue; } $marker['distance'] = round($distance, 1); } $markers[] = $marker; } } wp_reset_postdata(); // Sort by distance if proximity search if (!empty($filters['lat']) && !empty($filters['lng'])) { usort($markers, function($a, $b) { return ($a['distance'] ?? 0) <=> ($b['distance'] ?? 0); }); } // Cache if no filters if (empty($filters)) { wp_cache_set($cache_key, $markers, $this->cache_group, $this->cache_expiration); } return $markers; } /** * Format trainer data for map marker * * @param int $profile_id Trainer profile post ID * @return array Formatted marker data */ private function format_trainer_marker(int $profile_id): array { $user_id = get_post_meta($profile_id, 'user_id', true); $lat = get_post_meta($profile_id, 'latitude', true); $lng = get_post_meta($profile_id, 'longitude', true); // Get certifications $certifications = $this->get_trainer_certifications($profile_id, $user_id); // Determine if this is a champion (not a trainer offering public training) $is_champion = in_array('Certified measureQuick Champion', $certifications, true); // Get event count (cached) $event_count = get_post_meta($profile_id, 'cached_event_count', true); if (empty($event_count)) { $event_count = 0; } return [ 'id' => $profile_id, 'type' => 'trainer', 'is_champion' => $is_champion, 'lat' => floatval($lat), 'lng' => floatval($lng), 'name' => get_post_meta($profile_id, 'trainer_display_name', true), 'city' => $is_champion ? '' : get_post_meta($profile_id, 'trainer_city', true), 'state' => get_post_meta($profile_id, 'trainer_state', true), 'certifications' => $certifications, 'certification' => !empty($certifications) ? $certifications[0] : '', 'image' => get_post_meta($profile_id, 'profile_image_url', true), 'profile_id' => $profile_id, 'user_id' => intval($user_id), 'event_count' => intval($event_count) ]; } /** * Format venue data for map marker * * @param int $venue_id Venue post ID * @return array Formatted marker data */ private function format_venue_marker(int $venue_id): array { // Try our custom coordinates first, then TEC's $lat = get_post_meta($venue_id, 'venue_latitude', true); $lng = get_post_meta($venue_id, 'venue_longitude', true); if (empty($lat) || empty($lng)) { $lat = get_post_meta($venue_id, '_VenueLat', true); $lng = get_post_meta($venue_id, '_VenueLng', true); } // Get venue details from TEC $city = get_post_meta($venue_id, '_VenueCity', true); $state = get_post_meta($venue_id, '_VenueStateProvince', true) ?: get_post_meta($venue_id, '_VenueState', true); $address = get_post_meta($venue_id, '_VenueAddress', true); // Count upcoming events at this venue $upcoming_events_count = $this->count_venue_upcoming_events($venue_id); return [ 'id' => $venue_id, 'type' => 'venue', 'lat' => floatval($lat), 'lng' => floatval($lng), 'name' => html_entity_decode(get_the_title($venue_id), ENT_QUOTES, 'UTF-8'), 'address' => $address, 'city' => $city, 'state' => $state, 'upcoming_events' => $upcoming_events_count ]; } /** * Get trainer certifications * * @param int $profile_id Profile post ID * @param int $user_id User ID * @return array List of certification names */ private function get_trainer_certifications(int $profile_id, int $user_id): array { $certifications = []; // Try new certification system if (class_exists('HVAC_Trainer_Certification_Manager')) { $cert_manager = HVAC_Trainer_Certification_Manager::instance(); $trainer_certs = $cert_manager->get_trainer_certifications($user_id); foreach ($trainer_certs as $cert) { $cert_type = get_post_meta($cert->ID, 'certification_type', true); $status = get_post_meta($cert->ID, 'status', true) ?: 'active'; $expiration = get_post_meta($cert->ID, 'expiration_date', true); // Only include active, non-expired certifications $is_expired = $expiration && strtotime($expiration) < time(); if ($status === 'active' && !$is_expired && !empty($cert_type)) { $certifications[] = $cert_type; } } } // Fallback to legacy certification if (empty($certifications)) { $legacy = get_post_meta($profile_id, 'certification_type', true); if (!empty($legacy)) { $certifications[] = $legacy; } } return array_unique($certifications); } /** * Count upcoming events at a venue * * @param int $venue_id Venue post ID * @return int Number of upcoming events */ private function count_venue_upcoming_events(int $venue_id): int { if (!function_exists('tribe_get_events')) { return 0; } $events = tribe_get_events([ 'eventDisplay' => 'upcoming', 'posts_per_page' => -1, 'venue' => $venue_id, 'fields' => 'ids' ]); return is_array($events) ? count($events) : 0; } /** * Get full trainer profile for modal * * @param int $profile_id Profile post ID * @return array|null Trainer data or null if not found */ public function get_trainer_full_profile(int $profile_id): ?array { $profile = get_post($profile_id); if (!$profile || $profile->post_type !== 'trainer_profile') { return null; } $user_id = get_post_meta($profile_id, 'user_id', true); // Get basic marker data $data = $this->format_trainer_marker($profile_id); // Add additional details for modal $data['company'] = get_post_meta($profile_id, 'company_name', true); $data['bio'] = get_post_meta($profile_id, 'trainer_bio', true); $data['training_formats'] = $this->get_meta_array($profile_id, 'training_formats'); $data['training_locations'] = $this->get_meta_array($profile_id, 'training_locations'); // Get upcoming events $data['upcoming_events'] = $this->get_trainer_upcoming_events($user_id); return $data; } /** * Get full venue info * * @param int $venue_id Venue post ID * @return array|null Venue data or null if not found */ public function get_venue_full_info(int $venue_id): ?array { $venue = get_post($venue_id); if (!$venue || $venue->post_type !== 'tribe_venue') { return null; } $data = $this->format_venue_marker($venue_id); // Add additional details $data['zip'] = get_post_meta($venue_id, '_VenueZip', true); $data['country'] = get_post_meta($venue_id, '_VenueCountry', true); $data['phone'] = get_post_meta($venue_id, '_VenuePhone', true); $data['website'] = get_post_meta($venue_id, '_VenueURL', true); $data['description'] = $venue->post_content; $data['capacity'] = get_post_meta($venue_id, '_VenueCapacity', true); // Get equipment and amenities taxonomies $equipment = wp_get_post_terms($venue_id, 'venue_equipment', ['fields' => 'names']); $data['equipment'] = is_wp_error($equipment) ? [] : $equipment; $amenities = wp_get_post_terms($venue_id, 'venue_amenities', ['fields' => 'names']); $data['amenities'] = is_wp_error($amenities) ? [] : $amenities; // Get POC (Point of Contact) information $data['poc_user_id'] = get_post_meta($venue_id, '_venue_poc_user_id', true); $data['poc_name'] = get_post_meta($venue_id, '_venue_poc_name', true); $data['poc_email'] = get_post_meta($venue_id, '_venue_poc_email', true); // If no POC meta, use post author as fallback if (empty($data['poc_user_id'])) { $data['poc_user_id'] = $venue->post_author; $author = get_userdata($venue->post_author); if ($author) { $data['poc_name'] = $author->display_name; $data['poc_email'] = $author->user_email; } } // Get upcoming events list if (function_exists('tribe_get_events')) { $events = tribe_get_events([ 'eventDisplay' => 'upcoming', 'posts_per_page' => 5, 'venue' => $venue_id ]); $data['events'] = []; foreach ($events as $event) { $data['events'][] = [ 'id' => $event->ID, 'title' => html_entity_decode($event->post_title, ENT_QUOTES, 'UTF-8'), 'date' => tribe_get_start_date($event->ID, false, 'M j, Y'), 'url' => get_permalink($event->ID) ]; } } return $data; } /** * Get trainer's upcoming events * * @param int $user_id User ID * @param int $limit Maximum events to return * @return array Upcoming events */ private function get_trainer_upcoming_events(int $user_id, int $limit = 5): array { if (!function_exists('tribe_get_events')) { return []; } $events = tribe_get_events([ 'author' => $user_id, 'eventDisplay' => 'upcoming', 'posts_per_page' => $limit ]); $formatted = []; foreach ($events as $event) { $formatted[] = [ 'id' => $event->ID, 'title' => html_entity_decode($event->post_title, ENT_QUOTES, 'UTF-8'), 'date' => tribe_get_start_date($event->ID, false, 'M j, Y'), 'url' => get_permalink($event->ID) ]; } return $formatted; } /** * Get approved user IDs for filtering trainer profiles * * @return array User IDs */ private function get_approved_user_ids(): array { $user_query = new WP_User_Query([ 'meta_query' => [ [ 'key' => 'account_status', 'value' => ['approved', 'active', 'inactive'], 'compare' => 'IN' ] ], 'fields' => 'ID' ]); return $user_query->get_results(); } /** * Get meta value as array (handles comma-separated or serialized) * * @param int $post_id Post ID * @param string $meta_key Meta key * @return array Values */ private function get_meta_array(int $post_id, string $meta_key): array { $value = get_post_meta($post_id, $meta_key, true); if (empty($value)) { return []; } if (is_array($value)) { return $value; } // Handle comma-separated if (strpos($value, ',') !== false) { return array_map('trim', explode(',', $value)); } return [$value]; } /** * Calculate distance between two coordinates using Haversine formula * * @param float $lat1 First latitude * @param float $lng1 First longitude * @param float $lat2 Second latitude * @param float $lng2 Second longitude * @return float Distance in kilometers */ private function calculate_distance(float $lat1, float $lng1, float $lat2, float $lng2): float { $earth_radius = 6371; // km $lat1_rad = deg2rad($lat1); $lat2_rad = deg2rad($lat2); $delta_lat = deg2rad($lat2 - $lat1); $delta_lng = deg2rad($lng2 - $lng1); $a = sin($delta_lat / 2) * sin($delta_lat / 2) + cos($lat1_rad) * cos($lat2_rad) * sin($delta_lng / 2) * sin($delta_lng / 2); $c = 2 * atan2(sqrt($a), sqrt(1 - $a)); return $earth_radius * $c; } /** * Get unique state options from trainers * * @return array State options */ public function get_state_options(): array { // Check cache first $cache_key = 'filter_state_options'; $cached = wp_cache_get($cache_key, $this->cache_group); if ($cached !== false) { return $cached; } global $wpdb; $states = $wpdb->get_col(" SELECT DISTINCT pm.meta_value FROM {$wpdb->postmeta} pm INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id WHERE pm.meta_key = 'trainer_state' AND p.post_type = 'trainer_profile' AND p.post_status = 'publish' AND pm.meta_value != '' ORDER BY pm.meta_value ASC "); $states = array_filter($states); // Cache for 1 hour wp_cache_set($cache_key, $states, $this->cache_group, $this->cache_expiration); return $states; } /** * Get certification type options * * @return array Certification options */ public function get_certification_options(): array { // Check cache first $cache_key = 'filter_certification_options'; $cached = wp_cache_get($cache_key, $this->cache_group); if ($cached !== false) { return $cached; } global $wpdb; $certs = $wpdb->get_col(" SELECT DISTINCT pm.meta_value FROM {$wpdb->postmeta} pm INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id WHERE pm.meta_key = 'certification_type' AND p.post_type = 'trainer_profile' AND p.post_status = 'publish' AND pm.meta_value != '' ORDER BY pm.meta_value ASC "); $certs = array_filter($certs); // Cache for 1 hour wp_cache_set($cache_key, $certs, $this->cache_group, $this->cache_expiration); return $certs; } /** * Get training format options * * @return array Training format options */ public function get_training_format_options(): array { // Check cache first $cache_key = 'filter_format_options'; $cached = wp_cache_get($cache_key, $this->cache_group); if ($cached !== false) { return $cached; } global $wpdb; $formats_raw = $wpdb->get_col(" SELECT DISTINCT pm.meta_value FROM {$wpdb->postmeta} pm INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id WHERE pm.meta_key = 'training_formats' AND p.post_type = 'trainer_profile' AND p.post_status = 'publish' AND pm.meta_value != '' "); // Process comma-separated values $formats = []; foreach ($formats_raw as $format_string) { if (empty($format_string)) continue; $individual = array_map('trim', explode(',', $format_string)); $formats = array_merge($formats, $individual); } $formats = array_unique(array_filter($formats)); sort($formats); // Cache for 1 hour wp_cache_set($cache_key, $formats, $this->cache_group, $this->cache_expiration); return $formats; } /** * Get event markers for map * * @param array $filters Optional filters (state, search, lat/lng/radius, include_past) * @return array Event markers data */ public function get_event_markers(array $filters = []): array { // Check if TEC is active if (!function_exists('tribe_get_events')) { return []; } // Generate cache key $cache_key = 'events_' . md5(serialize($filters)); $cached = wp_cache_get($cache_key, $this->cache_group); if ($cached !== false && empty($filters)) { return $cached; } // Determine if we need to filter by venue first $venue_ids = null; if (!empty($filters['state']) || !empty($filters['search']) || (!empty($filters['lat']) && !empty($filters['lng']) && !empty($filters['radius']))) { $venue_ids = $this->get_venue_ids_by_filters($filters); // If venue filters are active but no matching venues found, return empty if (!empty($filters['state']) && empty($venue_ids)) { return []; } } // Build event query args $include_past = !empty($filters['include_past']); $event_args = [ 'posts_per_page' => 100, 'post_status' => 'publish', 'orderby' => 'event_date', 'order' => 'ASC', ]; if ($include_past) { // Custom date range: past 6 months to future 1 year $event_args['eventDisplay'] = 'custom'; $event_args['start_date'] = date('Y-m-d', strtotime('-6 months')); $event_args['end_date'] = date('Y-m-d', strtotime('+1 year')); } else { // Default: upcoming and ongoing events only $event_args['eventDisplay'] = 'list'; } // Apply venue filter if we have filtered venue IDs if ($venue_ids !== null && !empty($venue_ids)) { $event_args['venue'] = $venue_ids; } $events = tribe_get_events($event_args); $markers = []; // Batch load meta for performance if (!empty($events)) { $event_ids = wp_list_pluck($events, 'ID'); update_postmeta_cache($event_ids); } foreach ($events as $event) { $marker = $this->format_event_marker($event); // Skip events without valid coordinates if (empty($marker) || empty($marker['lat']) || empty($marker['lng'])) { continue; } // Apply search filter to event title and venue if (!empty($filters['search'])) { $search = strtolower($filters['search']); $title_match = stripos($marker['title'], $search) !== false; $venue_match = stripos($marker['venue_name'] ?? '', $search) !== false; $city_match = stripos($marker['venue_city'] ?? '', $search) !== false; if (!$title_match && !$venue_match && !$city_match) { continue; } } // Apply proximity filter if (!empty($filters['lat']) && !empty($filters['lng']) && !empty($filters['radius'])) { $distance = $this->calculate_distance( $filters['lat'], $filters['lng'], $marker['lat'], $marker['lng'] ); if ($distance > $filters['radius']) { continue; } $marker['distance'] = round($distance, 1); } $markers[] = $marker; } // Sort by distance if proximity search, otherwise by date if (!empty($filters['lat']) && !empty($filters['lng'])) { usort($markers, function($a, $b) { return ($a['distance'] ?? 0) <=> ($b['distance'] ?? 0); }); } // Cache if no filters if (empty($filters)) { wp_cache_set($cache_key, $markers, $this->cache_group, $this->cache_expiration); } return $markers; } /** * Format event data for map marker * * @param WP_Post $event Event post object * @return array|null Formatted marker data or null if invalid */ private function format_event_marker(WP_Post $event): ?array { // Get venue ID $venue_id = get_post_meta($event->ID, '_EventVenueID', true); // Skip events without venue if (empty($venue_id)) { return null; } // Check if event should show on map $show_map = get_post_meta($event->ID, '_EventShowMap', true); if ($show_map === 'false' || $show_map === '0') { // Virtual-only event with no map display return null; } // Get venue coordinates $lat = get_post_meta($venue_id, 'venue_latitude', true); $lng = get_post_meta($venue_id, 'venue_longitude', true); if (empty($lat) || empty($lng)) { $lat = get_post_meta($venue_id, '_VenueLat', true); $lng = get_post_meta($venue_id, '_VenueLng', true); } // Skip if no coordinates if (empty($lat) || empty($lng)) { return null; } // Get venue details $venue_name = get_the_title($venue_id); $venue_city = get_post_meta($venue_id, '_VenueCity', true); $venue_state = get_post_meta($venue_id, '_VenueStateProvince', true) ?: get_post_meta($venue_id, '_VenueState', true); // Get event dates $start_date = tribe_get_start_date($event->ID, false, 'M j, Y'); $end_date = tribe_get_end_date($event->ID, false, 'M j, Y'); $start_time = tribe_get_start_date($event->ID, false, 'g:i A'); $is_all_day = tribe_event_is_all_day($event->ID); // Determine if past event $event_end = tribe_get_end_date($event->ID, false, 'U'); $is_past = $event_end < time(); // Get cost $cost = tribe_get_formatted_cost($event->ID); if (empty($cost)) { $cost = 'Free'; } // Get excerpt (sanitized) $excerpt = wp_strip_all_tags($event->post_content); $excerpt = wp_trim_words($excerpt, 20, '...'); return [ 'id' => $event->ID, 'type' => 'event', 'lat' => floatval($lat), 'lng' => floatval($lng), 'title' => esc_html(html_entity_decode(get_the_title($event->ID), ENT_QUOTES, 'UTF-8')), 'excerpt' => $excerpt, 'start_date' => $start_date, 'end_date' => $end_date, 'start_time' => $is_all_day ? '' : $start_time, 'is_all_day' => $is_all_day, 'venue_id' => intval($venue_id), 'venue_name' => esc_html(html_entity_decode($venue_name, ENT_QUOTES, 'UTF-8')), 'venue_city' => $venue_city, 'venue_state' => $venue_state, 'cost' => $cost, 'url' => esc_url(get_permalink($event->ID)), 'is_past' => $is_past ]; } /** * Get venue IDs matching filters (for event filtering) * * @param array $filters Filters (state, search, lat/lng/radius) * @return array Matching venue IDs */ private function get_venue_ids_by_filters(array $filters): array { if (!function_exists('tribe_get_venue')) { return []; } $query_args = [ 'post_type' => 'tribe_venue', 'posts_per_page' => -1, 'post_status' => 'publish', 'fields' => 'ids', 'meta_query' => [ 'relation' => 'AND', ] ]; // Add state filter if (!empty($filters['state'])) { $query_args['meta_query'][] = [ 'relation' => 'OR', [ 'key' => '_VenueStateProvince', 'value' => sanitize_text_field($filters['state']), 'compare' => '=' ], [ 'key' => '_VenueState', 'value' => sanitize_text_field($filters['state']), 'compare' => '=' ] ]; } // Add search filter (venue name or city) if (!empty($filters['search'])) { $query_args['meta_query'][] = [ 'relation' => 'OR', [ 'key' => '_VenueCity', 'value' => sanitize_text_field($filters['search']), 'compare' => 'LIKE' ] ]; // Also search by venue name $query_args['s'] = sanitize_text_field($filters['search']); } $query = new WP_Query($query_args); $venue_ids = $query->posts; // Apply proximity filter if needed if (!empty($filters['lat']) && !empty($filters['lng']) && !empty($filters['radius']) && !empty($venue_ids)) { $filtered_ids = []; foreach ($venue_ids as $venue_id) { $lat = get_post_meta($venue_id, 'venue_latitude', true) ?: get_post_meta($venue_id, '_VenueLat', true); $lng = get_post_meta($venue_id, 'venue_longitude', true) ?: get_post_meta($venue_id, '_VenueLng', true); if (!empty($lat) && !empty($lng)) { $distance = $this->calculate_distance( $filters['lat'], $filters['lng'], floatval($lat), floatval($lng) ); if ($distance <= $filters['radius']) { $filtered_ids[] = $venue_id; } } } $venue_ids = $filtered_ids; } return $venue_ids; } /** * Clear event cache */ public function clear_event_cache(): void { if (function_exists('wp_cache_delete_group')) { wp_cache_delete_group($this->cache_group); } else { wp_cache_flush(); } } /** * Clear trainer cache */ public function clear_trainer_cache(): void { if (function_exists('wp_cache_delete_group')) { wp_cache_delete_group($this->cache_group); } else { wp_cache_flush(); } } /** * Clear venue cache */ public function clear_venue_cache(): void { if (function_exists('wp_cache_delete_group')) { wp_cache_delete_group($this->cache_group); } else { wp_cache_flush(); } } }