🚨 CRITICAL: Fixed deployment blockers by adding missing core directories: **Community System (CRITICAL)** - includes/community/ - Login_Handler and all community classes - templates/community/ - Community login forms **Certificate System (CRITICAL)** - includes/certificates/ - 8+ certificate classes and handlers - templates/certificates/ - Certificate reports and generation templates **Core Individual Classes (CRITICAL)** - includes/class-hvac-event-summary.php - includes/class-hvac-trainer-profile-manager.php - includes/class-hvac-master-dashboard-data.php - Plus 40+ other individual HVAC classes **Major Feature Systems (HIGH)** - includes/database/ - Training leads database tables - includes/find-trainer/ - Find trainer directory and MapGeo integration - includes/google-sheets/ - Google Sheets integration system - includes/zoho/ - Complete Zoho CRM integration - includes/communication/ - Communication templates system **Template Infrastructure** - templates/attendee/, templates/email-attendees/ - templates/event-summary/, templates/status/ - templates/template-parts/ - Shared template components **Impact:** - 70+ files added covering 10+ missing directories - Resolves ALL deployment blockers and feature breakdowns - Plugin activation should now work correctly - Multi-machine deployment fully supported 🔧 Generated with Claude Code Co-Authored-By: Ben Reed <ben@tealmaker.com>
		
			
				
	
	
		
			343 lines
		
	
	
		
			No EOL
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			343 lines
		
	
	
		
			No EOL
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * Handles data retrieval for the Order Summary page.
 | |
|  * Follows the pattern of HVAC_Event_Summary_Data.
 | |
|  */
 | |
| 
 | |
| if ( ! defined( 'ABSPATH' ) ) {
 | |
|     exit; // Exit if accessed directly
 | |
| }
 | |
| 
 | |
| class HVAC_Order_Summary_Data {
 | |
| 
 | |
|     /**
 | |
|      * The ID of the order.
 | |
|      *
 | |
|      * @var int|null
 | |
|      */
 | |
|     private $order_id = null;
 | |
| 
 | |
|     /**
 | |
|      * The order object (could be WooCommerce, RSVP, etc.).
 | |
|      *
 | |
|      * @var object|null
 | |
|      */
 | |
|     private $order_object = null;
 | |
|     
 | |
|     /**
 | |
|      * Array of event IDs associated with this order
 | |
|      * 
 | |
|      * @var array
 | |
|      */
 | |
|     private $event_ids = [];
 | |
| 
 | |
|     /**
 | |
|      * Constructor.
 | |
|      *
 | |
|      * @param int $order_id The ID of the order to retrieve data for.
 | |
|      */
 | |
|     public function __construct( $order_id ) {
 | |
|         $this->order_id = absint( $order_id );
 | |
|         $this->order_object = $this->load_order_object( $this->order_id );
 | |
|         
 | |
|         // Load associated events
 | |
|         if ($this->is_valid_order()) {
 | |
|             $this->event_ids = $this->get_associated_events();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Load the order object based on the order ID.
 | |
|      *
 | |
|      * @param int $order_id
 | |
|      * @return object|null
 | |
|      */
 | |
|     private function load_order_object( $order_id ) {
 | |
|         // WooCommerce order
 | |
|         if ( class_exists( 'WC_Order' ) && function_exists( 'wc_get_order' ) ) {
 | |
|             $order = wc_get_order( $order_id );
 | |
|             if ( $order ) {
 | |
|                 return $order;
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         // Event Tickets RSVP/Tribe order (fallback)
 | |
|         if ( class_exists( 'Tribe__Tickets__RSVP' ) ) {
 | |
|             // Implementation depends on how RSVP orders are stored
 | |
|             // This is a placeholder for potential RSVP orders
 | |
|         }
 | |
|         
 | |
|         // Add additional logic for other ticket providers if needed
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Check if the order is valid.
 | |
|      *
 | |
|      * @return bool
 | |
|      */
 | |
|     public function is_valid_order() {
 | |
|         return ! is_null( $this->order_object );
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Check if the current user has permission to view this order.
 | |
|      * Users can only view orders for events they created.
 | |
|      * 
 | |
|      * @return bool
 | |
|      */
 | |
|     public function user_can_view_order() {
 | |
|         // User must be logged in
 | |
|         if (!is_user_logged_in()) {
 | |
|             return false;
 | |
|         }
 | |
|         
 | |
|         // Order must be valid
 | |
|         if (!$this->is_valid_order()) {
 | |
|             return false;
 | |
|         }
 | |
|         
 | |
|         // Admin users can view all orders
 | |
|         if (current_user_can('manage_options')) {
 | |
|             return true;
 | |
|         }
 | |
|         
 | |
|         // Get the current user ID
 | |
|         $current_user_id = get_current_user_id();
 | |
|         
 | |
|         // Check if the user is the author of any of the events in this order
 | |
|         foreach ($this->event_ids as $event_id) {
 | |
|             $event = get_post($event_id);
 | |
|             if ($event && $event->post_author == $current_user_id) {
 | |
|                 return true;
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         return false;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get event IDs associated with this order.
 | |
|      * 
 | |
|      * @return array Array of event IDs
 | |
|      */
 | |
|     public function get_associated_events() {
 | |
|         $event_ids = [];
 | |
|         
 | |
|         // Get attendees for this order
 | |
|         $attendees = [];
 | |
|         if (function_exists('tribe_tickets_get_order_attendees')) {
 | |
|             $attendees = tribe_tickets_get_order_attendees($this->order_id);
 | |
|         }
 | |
|         
 | |
|         // Extract event IDs from attendees
 | |
|         foreach ($attendees as $attendee) {
 | |
|             if (isset($attendee['event_id'])) {
 | |
|                 $event_ids[] = absint($attendee['event_id']);
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         return array_unique($event_ids);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get basic order details.
 | |
|      *
 | |
|      * @return array|null
 | |
|      */
 | |
|     public function get_order_details() {
 | |
|         if ( ! $this->is_valid_order() ) {
 | |
|             return null;
 | |
|         }
 | |
| 
 | |
|         $details = [
 | |
|             'order_id'      => $this->order_id,
 | |
|             'order_number'  => null,
 | |
|             'purchaser_name'=> null,
 | |
|             'purchaser_email'=> null,
 | |
|             'purchase_date' => null,
 | |
|             'total_price'   => null,
 | |
|             'status'        => null,
 | |
|             'tickets'       => [],
 | |
|             'events'        => [],
 | |
|             'billing_address' => null,
 | |
|             'payment_method' => null,
 | |
|             'organization'  => null,
 | |
|         ];
 | |
| 
 | |
|         // WooCommerce order details
 | |
|         if ( $this->order_object instanceof WC_Order ) {
 | |
|             $details['order_number']   = $this->order_object->get_order_number();
 | |
|             $details['purchaser_name'] = $this->order_object->get_billing_first_name() . ' ' . $this->order_object->get_billing_last_name();
 | |
|             $details['purchaser_email']= $this->order_object->get_billing_email();
 | |
|             $details['purchase_date']  = $this->order_object->get_date_created() ? $this->order_object->get_date_created()->date( 'Y-m-d H:i:s' ) : null;
 | |
|             $details['total_price']    = $this->order_object->get_formatted_order_total();
 | |
|             $details['status']         = $this->order_object->get_status();
 | |
|             $details['tickets']        = $this->get_order_tickets();
 | |
|             $details['events']         = $this->get_event_details();
 | |
|             
 | |
|             // Get billing address
 | |
|             $address_parts = [
 | |
|                 $this->order_object->get_billing_address_1(),
 | |
|                 $this->order_object->get_billing_address_2(),
 | |
|                 $this->order_object->get_billing_city(),
 | |
|                 $this->order_object->get_billing_state(),
 | |
|                 $this->order_object->get_billing_postcode(),
 | |
|                 $this->order_object->get_billing_country()
 | |
|             ];
 | |
|             
 | |
|             // Filter out empty address parts and join
 | |
|             $address_parts = array_filter($address_parts);
 | |
|             $details['billing_address'] = implode(', ', $address_parts);
 | |
|             
 | |
|             // Get payment method
 | |
|             $details['payment_method'] = $this->order_object->get_payment_method_title();
 | |
|             
 | |
|             // Get organization (company name)
 | |
|             $details['organization'] = $this->order_object->get_billing_company();
 | |
|         }
 | |
| 
 | |
|         // Add additional providers here if needed
 | |
| 
 | |
|         return $details;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get ticket/attendee information for the order.
 | |
|      *
 | |
|      * @return array
 | |
|      */
 | |
|     public function get_order_tickets() {
 | |
|         $tickets = [];
 | |
| 
 | |
|         // WooCommerce + Event Tickets Plus
 | |
|         if ( $this->order_object instanceof WC_Order && function_exists( 'tribe_tickets_get_order_attendees' ) ) {
 | |
|             $order_id = $this->order_id;
 | |
|             $attendees = tribe_tickets_get_order_attendees( $order_id );
 | |
| 
 | |
|             foreach ( $attendees as $attendee ) {
 | |
|                 $event_id = $attendee['event_id'] ?? null;
 | |
|                 $event_title = '';
 | |
|                 
 | |
|                 if ($event_id) {
 | |
|                     $event_title = get_the_title($event_id);
 | |
|                 }
 | |
|                 
 | |
|                 $tickets[] = [
 | |
|                     'attendee_id'    => $attendee['attendee_id'] ?? null,
 | |
|                     'ticket_type'    => $attendee['ticket_name'] ?? null,
 | |
|                     'ticket_type_id' => $attendee['product_id'] ?? null,
 | |
|                     'attendee_name'  => $attendee['holder_name'] ?? null,
 | |
|                     'attendee_email' => $attendee['holder_email'] ?? null,
 | |
|                     'security_code'  => $attendee['security_code'] ?? null,
 | |
|                     'checked_in'     => isset( $attendee['check_in'] ) ? (bool) $attendee['check_in'] : false,
 | |
|                     'event_id'       => $event_id,
 | |
|                     'event_title'    => $event_title,
 | |
|                     'price'          => $attendee['price'] ?? $attendee['price_paid'] ?? null,
 | |
|                     'additional_fields' => $this->get_attendee_additional_fields($attendee),
 | |
|                 ];
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // Add additional providers here if needed
 | |
| 
 | |
|         return $tickets;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get details of events associated with this order.
 | |
|      * 
 | |
|      * @return array
 | |
|      */
 | |
|     public function get_event_details() {
 | |
|         $events = [];
 | |
|         
 | |
|         foreach ($this->event_ids as $event_id) {
 | |
|             $event = get_post($event_id);
 | |
|             if (!$event) {
 | |
|                 continue;
 | |
|             }
 | |
|             
 | |
|             $event_data = [
 | |
|                 'id' => $event_id,
 | |
|                 'title' => $event->post_title,
 | |
|                 'permalink' => get_permalink($event_id),
 | |
|                 'start_date' => null,
 | |
|                 'end_date' => null,
 | |
|                 'venue' => null,
 | |
|             ];
 | |
|             
 | |
|             // Add Event Calendar specific data if available
 | |
|             if (function_exists('tribe_get_start_date')) {
 | |
|                 $event_data['start_date'] = tribe_get_start_date($event_id, false);
 | |
|                 $event_data['end_date'] = tribe_get_end_date($event_id, false);
 | |
|                 
 | |
|                 if (function_exists('tribe_get_venue')) {
 | |
|                     $event_data['venue'] = tribe_get_venue($event_id);
 | |
|                 }
 | |
|             }
 | |
|             
 | |
|             $events[] = $event_data;
 | |
|         }
 | |
|         
 | |
|         return $events;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get additional fields for an attendee.
 | |
|      * These could be custom fields collected during checkout.
 | |
|      * 
 | |
|      * @param array $attendee The attendee data
 | |
|      * @return array
 | |
|      */
 | |
|     private function get_attendee_additional_fields($attendee) {
 | |
|         $additional_fields = [];
 | |
|         
 | |
|         // Check for meta data stored with the attendee
 | |
|         if (isset($attendee['attendee_meta']) && is_array($attendee['attendee_meta'])) {
 | |
|             foreach ($attendee['attendee_meta'] as $key => $value) {
 | |
|                 // Skip internal or empty fields
 | |
|                 if (strpos($key, '_') === 0 || empty($value)) {
 | |
|                     continue;
 | |
|                 }
 | |
|                 
 | |
|                 // Format field name for display
 | |
|                 $field_name = ucwords(str_replace(['_', '-'], ' ', $key));
 | |
|                 
 | |
|                 $additional_fields[$key] = [
 | |
|                     'label' => $field_name,
 | |
|                     'value' => $value
 | |
|                 ];
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         return $additional_fields;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get order notes.
 | |
|      * 
 | |
|      * @return array
 | |
|      */
 | |
|     public function get_order_notes() {
 | |
|         $notes = [];
 | |
|         
 | |
|         if ($this->order_object instanceof WC_Order && function_exists('wc_get_order_notes')) {
 | |
|             $raw_notes = wc_get_order_notes([
 | |
|                 'order_id' => $this->order_id,
 | |
|                 'type' => 'customer',
 | |
|             ]);
 | |
|             
 | |
|             foreach ($raw_notes as $note) {
 | |
|                 $notes[] = [
 | |
|                     'id' => $note->id,
 | |
|                     'content' => $note->content,
 | |
|                     'date' => $note->date_created->date('Y-m-d H:i:s'),
 | |
|                     'author' => $note->added_by,
 | |
|                 ];
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         return $notes;
 | |
|     }
 | |
| } |