user_id = $user_id; } /** * Get the total number of events created by the trainer. * * @return int */ public function get_total_events_count() : int { $args = array( 'post_type' => Tribe__Events__Main::POSTTYPE, // 'author' => $this->user_id, // Query by organizer instead 'post_status' => array( 'publish', 'future', 'draft', 'pending', 'private' ), 'posts_per_page' => -1, 'fields' => 'ids', // Only need the count // Restore organizer query 'meta_key' => '_EventOrganizerID', 'meta_value' => $this->user_id, 'meta_compare' => '=', // Explicitly set compare 'meta_type' => 'NUMERIC', // Specify numeric comparison ); $query = new WP_Query( $args ); return (int) $query->found_posts; } /** * Get the number of upcoming events for the trainer. * * @return int */ public function get_upcoming_events_count() : int { $today = date( 'Y-m-d H:i:s' ); $args = array( 'post_type' => Tribe__Events__Main::POSTTYPE, // 'author' => $this->user_id, // Query by organizer instead 'post_status' => array( 'publish', 'future' ), // Only published or scheduled future events 'posts_per_page' => -1, 'fields' => 'ids', // Only need the count 'meta_query' => array( 'relation' => 'AND', // Combine organizer and date query array( 'key' => '_EventOrganizerID', 'value' => $this->user_id, 'compare' => '=', 'type' => 'NUMERIC', // Specify numeric comparison ), array( 'key' => '_EventStartDate', 'value' => $today, 'compare' => '>=', 'type' => 'DATETIME', ), ), 'orderby' => 'event_date', 'order' => 'ASC', ); $query = new WP_Query( $args ); return (int) $query->found_posts; } /** * Get the number of past events for the trainer. * * @return int */ public function get_past_events_count() : int { $today = date( 'Y-m-d H:i:s' ); $args = array( 'post_type' => Tribe__Events__Main::POSTTYPE, // 'author' => $this->user_id, // Query by organizer instead 'post_status' => array( 'publish', 'private' ), // Count published or private past events 'posts_per_page' => -1, 'fields' => 'ids', // Only need the count 'meta_query' => array( 'relation' => 'AND', // Combine organizer and date query array( 'key' => '_EventOrganizerID', 'value' => $this->user_id, 'compare' => '=', 'type' => 'NUMERIC', // Specify numeric comparison ), array( 'key' => '_EventEndDate', // Use end date to determine if it's truly past 'value' => $today, 'compare' => '<', 'type' => 'DATETIME', ), ), ); $query = new WP_Query( $args ); return (int) $query->found_posts; } /** * Get the total number of tickets sold across all the trainer's events. * * @return int */ public function get_total_tickets_sold() : int { $total_tickets = 0; $args = array( 'post_type' => Tribe__Events__Main::POSTTYPE, // 'author' => $this->user_id, // Query by organizer instead 'post_status' => array( 'publish', 'future', 'draft', 'pending', 'private' ), // Include all statuses for historical data 'posts_per_page' => -1, 'fields' => 'ids', // Only need the IDs 'meta_key' => '_EventOrganizerID', 'meta_value' => $this->user_id, 'meta_compare' => '=', // Explicitly set compare 'meta_type' => 'NUMERIC', // Specify numeric comparison 'meta_compare' => '=', // Explicitly set compare 'meta_type' => 'NUMERIC', // Specify numeric comparison ); $event_ids = get_posts( $args ); if ( ! empty( $event_ids ) ) { foreach ( $event_ids as $event_id ) { // Event Tickets Plus often stores sold count in '_tribe_tickets_sold' meta $sold = get_post_meta( $event_id, '_tribe_tickets_sold', true ); if ( is_numeric( $sold ) ) { $total_tickets += (int) $sold; } // Fallback or alternative check if needed (e.g., querying attendee posts) // Depending on the exact ticket plugin setup, this might need adjustment. } } return $total_tickets; } /** * Get the total revenue generated across all the trainer's events. * * @return float */ public function get_total_revenue() : float { $total_revenue = 0.0; $args = array( 'post_type' => Tribe__Events__Main::POSTTYPE, // 'author' => $this->user_id, // Query by organizer instead 'post_status' => array( 'publish', 'future', 'draft', 'pending', 'private' ), // Include all statuses for historical data 'posts_per_page' => -1, 'fields' => 'ids', // Only need the IDs 'meta_key' => '_EventOrganizerID', 'meta_value' => $this->user_id, ); $event_ids = get_posts( $args ); if ( ! empty( $event_ids ) ) { foreach ( $event_ids as $event_id ) { // Event Tickets Plus often stores total revenue in '_tribe_revenue_total' meta $revenue = get_post_meta( $event_id, '_tribe_revenue_total', true ); if ( is_numeric( $revenue ) ) { $total_revenue += (float) $revenue; } // Depending on the exact ticket plugin setup, this might need adjustment. } } return $total_revenue; } /** * Get the annual revenue target set by the trainer. * * @return float|null Returns the target as a float, or null if not set. */ public function get_annual_revenue_target() : ?float { $target = get_user_meta( $this->user_id, 'annual_revenue_target', true ); return ! empty( $target ) && is_numeric( $target ) ? (float) $target : null; } /** * Get the data needed for the events table on the dashboard. * * @param string $filter_status The status to filter events by ('all', 'publish', 'future', 'draft', 'pending', 'private'). Defaults to 'all'. * @return array An array of event data arrays/objects, each containing keys like: id, status, name, link, date, organizer, capacity, sold, revenue. */ public function get_events_table_data( string $filter_status = 'all' ) : array { $events_data = []; $valid_statuses = array( 'publish', 'future', 'draft', 'pending', 'private' ); $post_status = ( 'all' === $filter_status || ! in_array( $filter_status, $valid_statuses, true ) ) ? $valid_statuses : array( $filter_status ); $args = array( 'post_type' => Tribe__Events__Main::POSTTYPE, // 'author' => $this->user_id, // Query by organizer instead 'post_status' => $post_status, 'posts_per_page' => -1, 'meta_query' => array( // Use meta_query for organizer filtering array( 'key' => '_EventOrganizerID', 'value' => $this->user_id, 'compare' => '=', 'type' => 'NUMERIC', // Specify numeric comparison ), ), 'orderby' => 'meta_value', // Order by start date 'meta_key' => '_EventStartDate', // Specify the meta key for ordering 'order' => 'DESC', // Show most recent first ); $query = new WP_Query( $args ); if ( $query->have_posts() ) { while ( $query->have_posts() ) { $query->the_post(); $event_id = get_the_ID(); // Get Capacity - Sum capacity of all tickets for this event $total_capacity = 0; if ( function_exists( 'tribe_get_tickets' ) ) { $tickets = tribe_get_tickets( $event_id ); if ( $tickets ) { foreach ( $tickets as $ticket ) { $capacity = $ticket->capacity(); // -1 often means unlimited capacity for Tribe Tickets if ( $capacity === -1 ) { $total_capacity = -1; // Mark as unlimited break; // No need to sum further if one is unlimited } if ( is_numeric( $capacity ) ) { $total_capacity += $capacity; } } } } $sold = get_post_meta( $event_id, '_tribe_tickets_sold', true ); $revenue = get_post_meta( $event_id, '_tribe_revenue_total', true ); $events_data[] = array( 'id' => $event_id, 'status' => get_post_status( $event_id ), 'name' => get_the_title(), // Return raw data instead of calling TEC functions here 'link' => get_permalink( $event_id ), // Use standard WP permalink 'start_date_ts' => strtotime( get_post_meta( $event_id, '_EventStartDate', true ) ), // Return timestamp 'organizer_id' => (int) get_post_meta( $event_id, '_EventOrganizerID', true ), // Return organizer ID 'capacity' => ( $total_capacity === -1 ) ? 'Unlimited' : (int) $total_capacity, 'sold' => is_numeric( $sold ) ? (int) $sold : 0, 'revenue' => is_numeric( $revenue ) ? (float) $revenue : 0.0, ); } wp_reset_postdata(); // Restore original Post Data } return $events_data; } } // End class HVAC_Dashboard_Data