/**
  * Generate and store all the attendees information for a new order.
  */
 public function generate_tickets()
 {
     if (empty($_POST['tickets_process']) || empty($_POST['attendee']) || empty($_POST['product_id'])) {
         return;
     }
     $has_tickets = $post_id = false;
     /**
      * RSVP specific action fired just before a RSVP-driven attendee tickets for an order are generated
      *
      * @param $data post Parameters comes from RSVP Form
      */
     do_action('tribe_tickets_rsvp_before_order_processing', $_POST);
     $order_id = md5(time() . rand());
     $attendee_email = empty($_POST['attendee']['email']) ? null : sanitize_email($_POST['attendee']['email']);
     $attendee_email = is_email($attendee_email) ? $attendee_email : null;
     $attendee_full_name = empty($_POST['attendee']['full_name']) ? null : sanitize_text_field($_POST['attendee']['full_name']);
     $attendee_optout = empty($_POST['attendee']['optout']) ? false : (bool) $_POST['attendee']['optout'];
     if (empty($_POST['attendee']['order_status']) || !$this->tickets_view->is_valid_rsvp_option($_POST['attendee']['order_status'])) {
         $attendee_order_status = 'yes';
     } else {
         $attendee_order_status = $_POST['attendee']['order_status'];
     }
     if (!$attendee_email || !$attendee_full_name) {
         $url = get_permalink($post_id);
         $url = add_query_arg('rsvp_error', 1, $url);
         wp_redirect(esc_url_raw($url));
         tribe_exit();
     }
     $rsvp_options = $this->tickets_view->get_rsvp_options(null, false);
     // Iterate over each product
     foreach ((array) $_POST['product_id'] as $product_id) {
         $order_attendee_id = 0;
         // Get the event this tickets is for
         $post_id = get_post_meta($product_id, $this->event_key, true);
         if (empty($post_id)) {
             continue;
         }
         $ticket_type = $this->get_ticket($post_id, $product_id);
         // if there were no RSVP tickets for the product added to the cart, continue
         if (empty($_POST["quantity_{$product_id}"])) {
             continue;
         }
         // get the RSVP status `decrease_stock_by` value
         $status_stock_size = $rsvp_options[$attendee_order_status]['decrease_stock_by'];
         $ticket_qty = intval($_POST["quantity_{$product_id}"]);
         // to avoid tickets from not being created on a status stock size of 0
         // let's take the status stock size into account and create a number of tickets
         // at least equal to the number of tickets the user requested
         $ticket_qty = $status_stock_size < 1 ? $ticket_qty : $status_stock_size * $ticket_qty;
         $qty = max($ticket_qty, 0);
         // Throw an error if Qty is bigger then Remaining
         if ($ticket_type->managing_stock() && $qty > $ticket_type->remaining()) {
             $url = add_query_arg('rsvp_error', 2, get_permalink($post_id));
             wp_redirect(esc_url_raw($url));
             tribe_exit();
         }
         $has_tickets = true;
         /**
          * RSVP specific action fired just before a RSVP-driven attendee ticket for an event is generated
          *
          * @param $post_id ID of event
          * @param $ticket_type Ticket Type object for the product
          * @param $data post Parameters comes from RSVP Form
          */
         do_action('tribe_tickets_rsvp_before_attendee_ticket_creation', $post_id, $ticket_type, $_POST);
         // Iterate over all the amount of tickets purchased (for this product)
         for ($i = 0; $i < $qty; $i++) {
             $attendee = array('post_status' => 'publish', 'post_title' => $attendee_full_name . ' | ' . ($i + 1), 'post_type' => self::ATTENDEE_OBJECT, 'ping_status' => 'closed');
             // Insert individual ticket purchased
             $attendee_id = wp_insert_post($attendee);
             if ($status_stock_size > 0) {
                 $sales = (int) get_post_meta($product_id, 'total_sales', true);
                 update_post_meta($product_id, 'total_sales', ++$sales);
             }
             update_post_meta($attendee_id, self::ATTENDEE_PRODUCT_KEY, $product_id);
             update_post_meta($attendee_id, self::ATTENDEE_EVENT_KEY, $post_id);
             update_post_meta($attendee_id, self::ATTENDEE_RSVP_KEY, $attendee_order_status);
             update_post_meta($attendee_id, $this->security_code, $this->generate_security_code($attendee_id));
             update_post_meta($attendee_id, $this->order_key, $order_id);
             update_post_meta($attendee_id, self::ATTENDEE_OPTOUT_KEY, (bool) $attendee_optout);
             update_post_meta($attendee_id, $this->full_name, $attendee_full_name);
             update_post_meta($attendee_id, $this->email, $attendee_email);
             /**
              * RSVP specific action fired when a RSVP-driven attendee ticket for an event is generated
              *
              * @param $attendee_id ID of attendee ticket
              * @param $post_id ID of event
              * @param $order_id RSVP order ID
              * @param $product_id RSVP product ID
              */
             do_action('event_tickets_rsvp_attendee_created', $attendee_id, $post_id, $order_id);
             /**
              * Action fired when an RSVP attendee ticket is created
              *
              * @param $attendee_id ID of the attendee post
              * @param $post_id Event post ID
              * @param $product_id RSVP ticket post ID
              * @param $order_attendee_id Attendee # for order
              */
             do_action('event_tickets_rsvp_ticket_created', $attendee_id, $post_id, $product_id, $order_attendee_id);
             $this->record_attendee_user_id($attendee_id);
             $order_attendee_id++;
         }
         /**
          * Action fired when an RSVP has had attendee tickets generated for it
          *
          * @param $product_id RSVP ticket post ID
          * @param $order_id ID of the RSVP order
          * @param $qty Quantity ordered
          */
         do_action('event_tickets_rsvp_tickets_generated_for_product', $product_id, $order_id, $qty);
         // After Adding the Values we Update the Transient
         Tribe__Post_Transient::instance()->delete($post_id, Tribe__Tickets__Tickets::ATTENDEES_CACHE);
     }
     /**
      * Fires when an RSVP attendee tickets have been generated.
      *
      * @param int    $order_id              ID of the RSVP order
      * @param int    $post_id               ID of the post the order was placed for
      * @param string $attendee_order_status 'yes' if the user indicated they will attend
      */
     do_action('event_tickets_rsvp_tickets_generated', $order_id, $post_id, $attendee_order_status);
     $send_mail_stati = array('yes');
     /**
      * Filters whether a confirmation email should be sent or not for RSVP tickets.
      *
      * This applies to attendance and non attendance emails.
      *
      * @param bool $send_mail Defaults to `true`.
      */
     $send_mail = apply_filters('tribe_tickets_rsvp_send_mail', true);
     if ($send_mail) {
         /**
          * Filters the attendee order stati that should trigger an attendance confirmation.
          *
          * Any attendee order status not listed here will trigger a non attendance email.
          *
          * @param array  $send_mail_stati       An array of default stati triggering an attendance email.
          * @param int    $order_id              ID of the RSVP order
          * @param int    $post_id               ID of the post the order was placed for
          * @param string $attendee_order_status 'yes' if the user indicated they will attend
          */
         $send_mail_stati = apply_filters('tribe_tickets_rsvp_send_mail_stati', $send_mail_stati, $order_id, $post_id, $attendee_order_status);
         // No point sending tickets if their current intention is not to attend
         if ($has_tickets && in_array($attendee_order_status, $send_mail_stati)) {
             $this->send_tickets_email($order_id);
         } elseif ($has_tickets) {
             $this->send_non_attendance_confirmation($order_id, $post_id);
         }
     }
     // Redirect to the same page to prevent double purchase on refresh
     if (!empty($post_id)) {
         $url = get_permalink($post_id);
         $url = add_query_arg('rsvp_sent', 1, $url);
         wp_redirect(esc_url_raw($url));
         tribe_exit();
     }
 }