upskill-event-manager/includes/class-hvac-venue-categories.php
ben ca928bfffb feat: Staging email filter, venue geocoding, MapGeo improvements, trainers overview
Accumulated changes from previous sessions (Feb 9-20):
- Staging email filter to prevent test emails reaching real users
- Version bump to 2.2.0 in plugin header
- Venue geocoding enhancements and batch processing
- Find Training page improvements (tab content, map data)
- MapGeo integration hardening for Find a Trainer
- Master trainers overview table improvements
- AJAX handler additions for venue categories
- SVG marker icon tweaks (trainer, venue)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 13:50:51 -04:00

289 lines
9.6 KiB
PHP

<?php
/**
* Venue Categories - Taxonomy Registration for Training Labs
*
* Registers custom taxonomies for TEC venues:
* - venue_type: Training lab types (e.g., "measureQuick Approved Training Lab")
* - venue_equipment: Equipment available at venues
* - venue_amenities: Amenities available at venues
*
* @package HVAC_Community_Events
* @since 2.3.0
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* Class HVAC_Venue_Categories
*
* Manages venue taxonomies for categorizing training labs.
*/
class HVAC_Venue_Categories {
/**
* Singleton instance
*
* @var HVAC_Venue_Categories|null
*/
private static ?self $instance = null;
/**
* Get singleton instance
*
* @return HVAC_Venue_Categories
*/
public static function instance(): self {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor
*/
private function __construct() {
// If init has already fired (we're being initialized late), register immediately
// This handles the case where the class is instantiated during 'init' priority >= 5
if (did_action('init')) {
$this->register_taxonomies();
$this->create_default_terms();
} else {
add_action('init', [$this, 'register_taxonomies'], 5);
add_action('init', [$this, 'create_default_terms'], 10);
}
}
/**
* Register venue taxonomies
*/
public function register_taxonomies(): void {
// Venue Type taxonomy (e.g., "measureQuick Approved Training Lab")
register_taxonomy('venue_type', 'tribe_venue', [
'labels' => [
'name' => __('Venue Types', 'hvac-community-events'),
'singular_name' => __('Venue Type', 'hvac-community-events'),
'search_items' => __('Search Venue Types', 'hvac-community-events'),
'all_items' => __('All Venue Types', 'hvac-community-events'),
'parent_item' => __('Parent Venue Type', 'hvac-community-events'),
'parent_item_colon' => __('Parent Venue Type:', 'hvac-community-events'),
'edit_item' => __('Edit Venue Type', 'hvac-community-events'),
'update_item' => __('Update Venue Type', 'hvac-community-events'),
'add_new_item' => __('Add New Venue Type', 'hvac-community-events'),
'new_item_name' => __('New Venue Type Name', 'hvac-community-events'),
'menu_name' => __('Venue Types', 'hvac-community-events'),
],
'hierarchical' => true,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'show_admin_column' => true,
'show_in_rest' => true,
'query_var' => true,
'rewrite' => ['slug' => 'venue-type'],
]);
// Venue Equipment taxonomy
register_taxonomy('venue_equipment', 'tribe_venue', [
'labels' => [
'name' => __('Equipment', 'hvac-community-events'),
'singular_name' => __('Equipment', 'hvac-community-events'),
'search_items' => __('Search Equipment', 'hvac-community-events'),
'all_items' => __('All Equipment', 'hvac-community-events'),
'parent_item' => __('Parent Equipment', 'hvac-community-events'),
'parent_item_colon' => __('Parent Equipment:', 'hvac-community-events'),
'edit_item' => __('Edit Equipment', 'hvac-community-events'),
'update_item' => __('Update Equipment', 'hvac-community-events'),
'add_new_item' => __('Add New Equipment', 'hvac-community-events'),
'new_item_name' => __('New Equipment Name', 'hvac-community-events'),
'menu_name' => __('Equipment', 'hvac-community-events'),
],
'hierarchical' => true,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'show_admin_column' => true,
'show_in_rest' => true,
'query_var' => true,
'rewrite' => ['slug' => 'venue-equipment'],
]);
// Venue Amenities taxonomy
register_taxonomy('venue_amenities', 'tribe_venue', [
'labels' => [
'name' => __('Amenities', 'hvac-community-events'),
'singular_name' => __('Amenity', 'hvac-community-events'),
'search_items' => __('Search Amenities', 'hvac-community-events'),
'all_items' => __('All Amenities', 'hvac-community-events'),
'parent_item' => __('Parent Amenity', 'hvac-community-events'),
'parent_item_colon' => __('Parent Amenity:', 'hvac-community-events'),
'edit_item' => __('Edit Amenity', 'hvac-community-events'),
'update_item' => __('Update Amenity', 'hvac-community-events'),
'add_new_item' => __('Add New Amenity', 'hvac-community-events'),
'new_item_name' => __('New Amenity Name', 'hvac-community-events'),
'menu_name' => __('Amenities', 'hvac-community-events'),
],
'hierarchical' => true,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'show_admin_column' => true,
'show_in_rest' => true,
'query_var' => true,
'rewrite' => ['slug' => 'venue-amenities'],
]);
}
/**
* Create default taxonomy terms
*/
public function create_default_terms(): void {
// Only run once
if (get_option('hvac_venue_categories_initialized')) {
return;
}
// Venue Types
$venue_types = [
'measureQuick Approved Training Lab' => 'mq-approved-lab',
];
foreach ($venue_types as $name => $slug) {
if (!term_exists($slug, 'venue_type')) {
wp_insert_term($name, 'venue_type', ['slug' => $slug]);
}
}
// Equipment
$equipment = [
'Furnace',
'Heat Pump',
'Air Conditioner',
'Mini-Split',
'Boiler',
'Gas Meter',
'TrueFlow Grid',
'Flow Hood',
];
foreach ($equipment as $name) {
$slug = sanitize_title($name);
if (!term_exists($slug, 'venue_equipment')) {
wp_insert_term($name, 'venue_equipment', ['slug' => $slug]);
}
}
// Amenities
$amenities = [
'Coffee',
'Water',
'Tea',
'Soda',
'Snacks',
'Projector',
'Whiteboard',
'WiFi',
'Parking',
'Vending Machines',
];
foreach ($amenities as $name) {
$slug = sanitize_title($name);
if (!term_exists($slug, 'venue_amenities')) {
wp_insert_term($name, 'venue_amenities', ['slug' => $slug]);
}
}
update_option('hvac_venue_categories_initialized', true);
}
/**
* Get venues by type
*
* @param string $type_slug Type slug (e.g., 'mq-approved-lab')
* @return array Venue IDs
*/
public function get_venues_by_type(string $type_slug): array {
$query = new WP_Query([
'post_type' => 'tribe_venue',
'posts_per_page' => -1,
'post_status' => 'publish',
'fields' => 'ids',
'tax_query' => [
[
'taxonomy' => 'venue_type',
'field' => 'slug',
'terms' => $type_slug,
],
],
]);
return $query->posts;
}
/**
* Check if venue is an approved training lab
*
* @param int $venue_id Venue post ID
* @return bool
*/
public function is_approved_training_lab(int $venue_id): bool {
return has_term('mq-approved-lab', 'venue_type', $venue_id);
}
/**
* Get venue equipment
*
* @param int $venue_id Venue post ID
* @return array Equipment names
*/
public function get_venue_equipment(int $venue_id): array {
$terms = wp_get_post_terms($venue_id, 'venue_equipment', ['fields' => 'names']);
return is_wp_error($terms) ? [] : $terms;
}
/**
* Get venue amenities
*
* @param int $venue_id Venue post ID
* @return array Amenity names
*/
public function get_venue_amenities(int $venue_id): array {
$terms = wp_get_post_terms($venue_id, 'venue_amenities', ['fields' => 'names']);
return is_wp_error($terms) ? [] : $terms;
}
/**
* Set venue as approved training lab
*
* @param int $venue_id Venue post ID
* @return bool|WP_Error
*/
public function set_as_approved_lab(int $venue_id) {
return wp_set_post_terms($venue_id, ['mq-approved-lab'], 'venue_type', false);
}
/**
* Set venue equipment
*
* @param int $venue_id Venue post ID
* @param array $equipment Equipment slugs or names
* @return bool|WP_Error
*/
public function set_venue_equipment(int $venue_id, array $equipment) {
return wp_set_post_terms($venue_id, $equipment, 'venue_equipment', false);
}
/**
* Set venue amenities
*
* @param int $venue_id Venue post ID
* @param array $amenities Amenity slugs or names
* @return bool|WP_Error
*/
public function set_venue_amenities(int $venue_id, array $amenities) {
return wp_set_post_terms($venue_id, $amenities, 'venue_amenities', false);
}
}