Advertisement
Guest User

booking.php

a guest
Nov 28th, 2016
279
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 47.18 KB | None | 0 0
  1. <?php
  2. /**
  3.  * gets a booking in a more db-friendly manner, allows hooking into booking object right after instantiation
  4.  * @param mixed $id
  5.  * @param mixed $search_by
  6.  * @return EM_Booking
  7.  */
  8. function em_get_booking($id = false) {
  9.     global $EM_Booking;
  10.     //check if it's not already global so we don't instantiate again
  11.     if( is_object($EM_Booking) && get_class($EM_Booking) == 'EM_Booking' ){
  12.         if( is_object($id) && $EM_Booking->booking_id == $id->booking_id ){
  13.             return apply_filters('em_get_booking', $EM_Booking);
  14.         }else{
  15.             if( is_numeric($id) && $EM_Booking->booking_id == $id ){
  16.                 return apply_filters('em_get_booking', $EM_Booking);
  17.             }elseif( is_array($id) && !empty($id['booking_id']) && $EM_Booking->booking_id == $id['booking_id'] ){
  18.                 return apply_filters('em_get_booking', $EM_Booking);
  19.             }
  20.         }
  21.     }
  22.     if( is_object($id) && get_class($id) == 'EM_Booking' ){
  23.         return apply_filters('em_get_booking', $id);
  24.     }else{
  25.         return apply_filters('em_get_booking', new EM_Booking($id));
  26.     }
  27. }
  28. /**
  29.  * Contains all information and relevant functions surrounding a single booking made with Events Manager
  30.  */
  31. class EM_Booking extends EM_Object{
  32.     //DB Fields
  33.     var $booking_id;
  34.     var $event_id;
  35.     var $person_id;
  36.     var $booking_price = null;
  37.     var $booking_spaces;
  38.     var $booking_comment;
  39.     var $booking_status = false;
  40.     var $booking_tax_rate = null;
  41.     var $booking_taxes = null;
  42.     var $booking_meta = array();
  43.     var $fields = array(
  44.         'booking_id' => array('name'=>'id','type'=>'%d'),
  45.         'event_id' => array('name'=>'event_id','type'=>'%d'),
  46.         'person_id' => array('name'=>'person_id','type'=>'%d'),
  47.         'booking_price' => array('name'=>'price','type'=>'%f'),
  48.         'booking_spaces' => array('name'=>'spaces','type'=>'%d'),
  49.         'booking_comment' => array('name'=>'comment','type'=>'%s'),
  50.         'booking_status' => array('name'=>'status','type'=>'%d'),
  51.         'booking_tax_rate' => array('name'=>'tax_rate','type'=>'%f','null'=>1),
  52.         'booking_taxes' => array('name'=>'taxes','type'=>'%f','null'=>1),
  53.         'booking_meta' => array('name'=>'meta','type'=>'%s')
  54.     );
  55.     //Other Vars
  56.     /**
  57.      * array of notes by admins on this booking. loaded from em_meta table in construct
  58.      * @var array
  59.      */
  60.     var $notes;
  61.     var $timestamp;
  62.     var $person;
  63.     var $required_fields = array('booking_id', 'event_id', 'person_id', 'booking_spaces');
  64.     var $feedback_message = "";
  65.     var $errors = array();
  66.     /**
  67.      * when using EM_Booking::email_send(), this number is updated with sent emails
  68.      * @var int
  69.      */
  70.     var $mails_sent = 0;
  71.     /**
  72.      * Contains an array of custom fields for a booking. This is loaded from em_meta, where the booking_custom name contains arrays of data.
  73.      * @var array
  74.      */
  75.     var $custom = array();
  76.     /**
  77.      * If saved in this instance, you can see what previous approval status was.
  78.      * @var int
  79.      */
  80.     var $previous_status = false;
  81.     /**
  82.      * The booking approval status number corresponds to a state in this array.
  83.      * @var unknown_type
  84.      */
  85.     var $status_array = array();
  86.     /**
  87.      * @var EM_Tickets
  88.      */
  89.     var $tickets;
  90.     /**
  91.      * @var EM_Event
  92.      */
  93.     var $event;
  94.     /**
  95.      * @var EM_Tickets_Bookings
  96.      */
  97.     var $tickets_bookings;
  98.     /**
  99.      * If set to true, this booking can be managed by any logged in user.
  100.      * @var EM_Tickets_Bookings
  101.      */
  102.     var $manage_override;
  103.    
  104.     /**
  105.      * Creates booking object and retreives booking data (default is a blank booking object). Accepts either array of booking data (from db) or a booking id.
  106.      * @param mixed $booking_data
  107.      * @return null
  108.      */
  109.     function __construct( $booking_data = false ){
  110.         //Get the person for this booking
  111.         global $wpdb;
  112.         if( $booking_data !== false ){
  113.             //Load booking data
  114.             $booking = array();
  115.             if( is_array($booking_data) ){
  116.                 $booking = $booking_data;
  117.             }elseif( is_numeric($booking_data) ){
  118.                 //Retreiving from the database
  119.                 $sql = "SELECT * FROM ". EM_BOOKINGS_TABLE ." WHERE booking_id ='$booking_data'";
  120.                 $booking = $wpdb->get_row($sql, ARRAY_A);
  121.             }
  122.             //booking meta
  123.             $booking['booking_meta'] = (!empty($booking['booking_meta'])) ? maybe_unserialize($booking['booking_meta']):array();
  124.             //Save into the object
  125.             $this->to_object($booking);
  126.             $this->previous_status = $this->booking_status;
  127.             $this->get_person();
  128.             $this->timestamp = !empty($booking['booking_date']) ? strtotime($booking['booking_date'], current_time('timestamp')):false;
  129.         }
  130.         //Do it here so things appear in the po file.
  131.         $this->status_array = array(
  132.             0 => __('Pending','events-manager'),
  133.             1 => __('Approved','events-manager'),
  134.             2 => __('Rejected','events-manager'),
  135.             3 => __('Cancelled','events-manager'),
  136.             4 => __('Awaiting Online Payment','events-manager'),
  137.             5 => __('Awaiting Payment','events-manager')
  138.         );
  139.         $this->compat_keys(); //depricating in 6.0
  140.         //do some legacy checking here for bookings made prior to 5.4, due to how taxes are calculated
  141.         $this->get_tax_rate();
  142.         if( !empty($this->legacy_tax_rate) ){
  143.             //reset booking_price, it'll be recalculated later (if you're using this property directly, don't, use $this->get_price())
  144.             $this->booking_price = $this->booking_taxes = null;
  145.         }
  146.         do_action('em_booking', $this, $booking_data);
  147.     }
  148.    
  149.     function get_notes(){
  150.         global $wpdb;
  151.         if( !is_array($this->notes) && !empty($this->booking_id) ){
  152.             $notes = $wpdb->get_results("SELECT * FROM ". EM_META_TABLE ." WHERE meta_key='booking-note' AND object_id ='{$this->booking_id}'", ARRAY_A);
  153.             $this->notes = array();
  154.             foreach($notes as $note){
  155.                 $this->notes[] = unserialize($note['meta_value']);
  156.             }
  157.         }elseif( empty($this->booking_id) ){
  158.             $this->notes = array();
  159.         }
  160.         return $this->notes;
  161.     }
  162.    
  163.     /**
  164.      * Saves the booking into the database, whether a new or existing booking
  165.      * @param $mail whether or not to email the user and contact people
  166.      * @return boolean
  167.      */
  168.     function save($mail = true){
  169.         global $wpdb;
  170.         $table = EM_BOOKINGS_TABLE;
  171.         do_action('em_booking_save_pre',$this);
  172.         if( $this->can_manage() ){
  173.             //update prices, spaces, person_id
  174.             $this->get_spaces(true);
  175.             $this->calculate_price();
  176.             $this->person_id = (empty($this->person_id)) ? $this->get_person()->ID : $this->person_id;         
  177.             //Step 1. Save the booking
  178.             $data = $this->to_array();
  179.             $data['booking_meta'] = serialize($data['booking_meta']);
  180.             //update or save
  181.             if($this->booking_id != ''){
  182.                 $update = true;
  183.                 $where = array( 'booking_id' => $this->booking_id );  
  184.                 $result = $wpdb->update($table, $data, $where, $this->get_types($data));
  185.                 $result = ($result !== false);
  186.                 $this->feedback_message = __('Changes saved','events-manager');
  187.             }else{
  188.                 $update = false;
  189.                 $data_types = $this->get_types($data);
  190.                 $data['booking_date'] = current_time('mysql');
  191.                 $data_types[] = '%s';
  192.                 $result = $wpdb->insert($table, $data, $data_types);
  193.                 $this->booking_id = $wpdb->insert_id;  
  194.                 $this->feedback_message = __('Your booking has been recorded','events-manager');
  195.             }
  196.             //Step 2. Insert ticket bookings for this booking id if no errors so far
  197.             if( $result === false ){
  198.                 $this->feedback_message = __('There was a problem saving the booking.', 'events-manager');
  199.                 $this->errors[] = __('There was a problem saving the booking.', 'events-manager');
  200.             }else{
  201.                 $tickets_bookings_result = $this->get_tickets_bookings()->save();
  202.                 if( !$tickets_bookings_result ){
  203.                     if( !$update ){
  204.                         //delete the booking and tickets, instead of a transaction
  205.                         $this->delete();
  206.                     }
  207.                     $this->errors[] = __('There was a problem saving the booking.', 'events-manager');
  208.                     $this->add_error( $this->get_tickets_bookings()->get_errors() );
  209.                 }
  210.             }
  211.             //Step 3. email if necessary
  212.             if ( count($this->errors) == 0  && $mail ) {
  213.                 $this->email();
  214.             }
  215.             $this->compat_keys();
  216.             return apply_filters('em_booking_save', ( count($this->errors) == 0 ), $this);
  217.         }else{
  218.             $this->feedback_message = __('There was a problem saving the booking.', 'events-manager');
  219.             if( !$this->can_manage() ){
  220.                 $this->add_error(sprintf(__('You cannot manage this %s.', 'events-manager'),__('Booking','events-manager')));
  221.             }
  222.         }
  223.         return apply_filters('em_booking_save', false, $this);
  224.     }
  225.    
  226.     /**
  227.      * Load an record into this object by passing an associative array of table criterie to search for.
  228.      * Returns boolean depending on whether a record is found or not.
  229.      * @param $search
  230.      * @return boolean
  231.      */
  232.     function get($search) {
  233.         global $wpdb;
  234.         $conds = array();
  235.         foreach($search as $key => $value) {
  236.             if( array_key_exists($key, $this->fields) ){
  237.                 $value = esc_sql($value);
  238.                 $conds[] = "`$key`='$value'";
  239.             }
  240.         }
  241.         $sql = "SELECT * FROM ". $wpdb->EM_BOOKINGS_TABLE ." WHERE " . implode(' AND ', $conds) ;
  242.         $result = $wpdb->get_row($sql, ARRAY_A);
  243.         if($result){
  244.             $this->to_object($result);
  245.             $this->person = new EM_Person($this->person_id);
  246.             return true;   
  247.         }else{
  248.             return false;
  249.         }
  250.     }
  251.    
  252.     /**
  253.      * Get posted data and save it into the object (not db)
  254.      * @return boolean
  255.      */
  256.     function get_post( $override_availability = false ){
  257.         $this->tickets_bookings = new EM_Tickets_Bookings($this->booking_id);
  258.         do_action('em_booking_get_post_pre',$this);
  259.         $result = array();
  260.         $this->event_id = $_REQUEST['event_id'];
  261.         if( isset($_REQUEST['em_tickets']) && is_array($_REQUEST['em_tickets']) && ($_REQUEST['em_tickets'] || $override_availability) ){
  262.             foreach( $_REQUEST['em_tickets'] as $ticket_id => $values){
  263.                 //make sure ticket exists
  264.                 if( !empty($values['spaces']) || $override_availability ){
  265.                     $args = array('ticket_id'=>$ticket_id, 'ticket_booking_spaces'=>$values['spaces'], 'booking_id'=>$this->booking_id);
  266.                     if($this->get_event()->get_bookings()->ticket_exists($ticket_id)){
  267.                             $EM_Ticket_Booking = new EM_Ticket_Booking($args);
  268.                             $EM_Ticket_Booking->booking = $this;
  269.                             if( !$this->tickets_bookings->add( $EM_Ticket_Booking, $override_availability ) ){
  270.                                 $this->add_error($this->tickets_bookings->get_errors());
  271.                             }
  272.                     }else{
  273.                         $this->errors[]=__('You are trying to book a non-existent ticket for this event.','events-manager');
  274.                     }
  275.                 }
  276.             }
  277.             $this->booking_comment = (!empty($_REQUEST['booking_comment'])) ? wp_kses_data(wp_unslash($_REQUEST['booking_comment'])):'';
  278.             //allow editing of tax rate
  279.             if( !empty($this->booking_id) && $this->can_manage() ){
  280.                 $this->booking_tax_rate = (!empty($_REQUEST['booking_tax_rate']) && is_numeric($_REQUEST['booking_tax_rate'])) ? $_REQUEST['booking_tax_rate']:$this->booking_tax_rate;
  281.             }
  282.             //recalculate spaces/price
  283.             $this->get_spaces(true);
  284.             $this->calculate_price();
  285.             //get person
  286.             $this->get_person();
  287.             //re-run compatiblity keys function
  288.             $this->compat_keys(); //depricating in 6.0
  289.         }
  290.         return apply_filters('em_booking_get_post',count($this->errors) == 0,$this);
  291.     }
  292.    
  293.     function validate( $override_availability = false ){
  294.         //step 1, basic info
  295.         $basic = (
  296.             (empty($this->event_id) || is_numeric($this->event_id)) &&
  297.             (empty($this->person_id) || is_numeric($this->person_id)) &&
  298.             is_numeric($this->booking_spaces) && $this->booking_spaces > 0
  299.         );
  300.         //give some errors in step 1
  301.         if( $this->booking_spaces == 0 ){
  302.             $this->add_error(get_option('dbem_booking_feedback_min_space'));
  303.         }
  304.         //step 2, tickets bookings info
  305.         if( count($this->get_tickets_bookings()) > 0 ){
  306.             $ticket_validation = array();
  307.             foreach($this->get_tickets_bookings()->tickets_bookings as $EM_Ticket_Booking){ /* @var $EM_Ticket_Booking EM_Ticket_Booking */
  308.                 if ( !$EM_Ticket_Booking->validate() ){
  309.                     $ticket_validation[] = false;
  310.                     $result = $basic && !in_array(false,$ticket_validation);
  311.                 }
  312.                 $this->errors = array_merge($this->errors, $EM_Ticket_Booking->get_errors());
  313.             }
  314.             $result = $basic && !in_array(false,$ticket_validation);
  315.         }else{
  316.             $result = false;
  317.         }
  318.         //is there enough space overall?
  319.         if( !$override_availability && $this->get_event()->get_bookings()->get_available_spaces() < $this->get_spaces() ){
  320.             $result = false;
  321.             $this->add_error(get_option('dbem_booking_feedback_full'));
  322.         }
  323.         //can we book this amount of spaces at once?
  324.         if( $this->get_event()->event_rsvp_spaces > 0 && $this->get_spaces() > $this->get_event()->event_rsvp_spaces ){
  325.             $result = false;
  326.             $this->add_error( sprintf(get_option('dbem_booking_feedback_spaces_limit'), $this->get_event()->event_rsvp_spaces));           
  327.         }
  328.         return apply_filters('em_booking_validate',$result,$this);
  329.     }
  330.    
  331.     /**
  332.      * Get the total number of spaces booked in THIS booking. Seting $force_refresh to true will recheck spaces, even if previously done so.
  333.      * @param unknown_type $force_refresh
  334.      * @return mixed
  335.      */
  336.     function get_spaces( $force_refresh=false ){
  337.         if($this->booking_spaces == 0 || $force_refresh == true ){
  338.             $this->booking_spaces = $this->get_tickets_bookings()->get_spaces($force_refresh);
  339.         }
  340.         return apply_filters('em_booking_get_spaces',$this->booking_spaces,$this);
  341.     }
  342.    
  343.     /* Price Calculations */
  344.    
  345.     /**
  346.      * Gets the total price for this whole booking, including any discounts, taxes, and any other additional items. In other words, what the person has to pay or has supposedly paid.
  347.      * This price shouldn't change once established, unless there's any alteration to the booking itself that'd affect the price, such as a change in ticket numbers, discount, etc.
  348.      * @param boolean $format
  349.      * @return double|string
  350.      */
  351.     function get_price( $format = false, $format_depricated = null ){
  352.         if( $format_depricated !== null ) $format = $format_depricated; //support for old parameters, will be depricated soon
  353.         //recalculate price here only if price is not actually set
  354.         if( $this->booking_price === null ){
  355.             $this->calculate_price();
  356.             $this->booking_price = apply_filters('em_booking_get_price', $this->booking_price, $this);
  357.         }
  358.         //return booking_price, formatted or not
  359.         if($format){
  360.             return $this->format_price($this->booking_price);
  361.         }
  362.         return round($this->booking_price,2);
  363.     }
  364.    
  365.     /**
  366.      * Total of tickets without taxes, discounts or any other modification. No filter given here for that very reason!
  367.      * @param boolean $format
  368.      * @return double|string
  369.      */
  370.     function get_price_base( $format = false ){
  371.         $price = $this->get_tickets_bookings()->get_price();
  372.         if($format){
  373.             return $this->format_price($price);
  374.         }
  375.         return $price;
  376.     }
  377.    
  378.     function get_price_pre_taxes( $format = false ){
  379.         $price = $base_price = $this->get_price_base();
  380.         //apply pre-tax discounts
  381.         $price -= $this->get_price_discounts_amount('pre', $price);
  382.         if( $price < 0 ){ $price = 0; } //no negative prices
  383.         //return amount of taxes applied, formatted or not
  384.         if( $format ) return $this->format_price($price);
  385.         return $price;
  386.     }
  387.    
  388.     /**
  389.      * Gets price AFTER taxes and post-tax discounts have also been added
  390.      * @param boolean $format
  391.      * @return double|string
  392.      */
  393.     function get_price_post_taxes( $format = false ){
  394.         //get price before taxes
  395.         $price = $this->get_price_pre_taxes();
  396.         //add taxes to price
  397.         if( $this->get_tax_rate() > 0 ){
  398.             $this->booking_taxes = $price * ($this->get_tax_rate()/100); //calculate and save tax amount
  399.             $price += $this->booking_taxes; //add taxes
  400.             $this->taxes_applied = true;
  401.         }
  402.         //apply post-tax discounts
  403.         $price -= $this->get_price_discounts_amount('post', $price);
  404.         if( $price < 0 ){ $price = 0; } //no negative prices
  405.         //return amount of taxes applied, formatted or not
  406.         if( $format ) return $this->format_price($price);
  407.         return $price;
  408.     }
  409.    
  410.     /**
  411.      * Get amount of taxes applied to this booking price.
  412.      * @param boolean $format
  413.      * @return double|string
  414.      */
  415.     function get_price_taxes( $format=false ){
  416.         if( $this->booking_taxes !== null ){
  417.             $this->booking_taxes; //taxes already calculated
  418.         }else{
  419.             $this->calculate_price(); //recalculate price and taxes
  420.         }
  421.         //return amount of taxes applied, formatted or not
  422.         if( $format ){
  423.             return $this->format_price($this->booking_taxes);
  424.         }
  425.         return $this->booking_taxes;
  426.     }
  427.    
  428.     function get_price_discount(){
  429.        
  430.     }
  431.    
  432.     /**
  433.      * Calculates (or recalculates) the price of this booking including taxes, discounts etc., saves it to the booking_price property and writes to relevant properties booking_meta variables
  434.      * @return double
  435.      */
  436.     function calculate_price(){
  437.         //reset price and taxes calculations
  438.         $this->booking_price = $this->booking_taxes = null;
  439.         //get post-tax price and save it to booking_price
  440.         $this->booking_price = apply_filters('em_booking_calculate_price', $this->get_price_post_taxes(), $this);
  441.         return $this->booking_price;
  442.     }
  443.    
  444.     /*
  445.      * Gets tax rate of booking
  446.      * @see EM_Object::get_tax_rate()
  447.      * @return double
  448.      */
  449.     function get_tax_rate(){
  450.         if( $this->booking_tax_rate === null ){
  451.             //booking not saved or tax never defined
  452.             if( !empty($this->booking_id) && get_option('dbem_legacy_bookings_tax', 'x') !== 'x'){ //even if 0 if defined as tax rate we still use it, delete the option entirely to stop
  453.                 //no tax applied yet to an existing booking, or tax possibly applied (but handled separately in EM_Tickets_Bookings but in legacy < v5.4
  454.                 //sort out MultiSite nuances
  455.                 if( EM_MS_GLOBAL && $this->get_event()->blog_id != get_current_blog_id() ){
  456.                     //MultiSite AND Global tables enabled AND this event belongs to another blog - get settings for blog that published the event
  457.                     $this->booking_tax_rate = get_blog_option($this->get_event()->blog_id, 'dbem_legacy_bookings_tax');
  458.                 }else{
  459.                     //get booking from current site, whether or not we're in MultiSite
  460.                     $this->booking_tax_rate = get_option('dbem_legacy_bookings_tax');
  461.                 }
  462.                 $this->legacy_tax_rate = true;
  463.             }else{
  464.                 //first time we're applying tax rate
  465.                 $this->booking_tax_rate = $this->get_event()->get_tax_rate();
  466.             }
  467.         }
  468.         return $this->booking_tax_rate;
  469.     }
  470.    
  471.     /**
  472.      * Returns an array of discounts to be applied to a booking. Here is an example of an array item that is expected:
  473.      * array('name' => 'Name of Discount', 'type'=>'% or #', 'amount'=> 0.00, 'desc' => 'Comments about discount', 'tax'=>'pre/post', 'data' => 'any info for hooks to use' );
  474.      * About the array keys:
  475.      * type - $ means a fixed amount of discount, % means a percentage off the base price
  476.      * amount - if type is a percentage, it is written as a number from 0-100, e.g. 10 = 10%
  477.      * tax - 'pre' means discount is applied before tax, 'post' means after tax
  478.      * data - any data to be stored that can be used by actions/filters
  479.      * @return array
  480.      */
  481.     function get_price_discounts(){
  482.         $discounts = array();
  483.         if( !empty($this->booking_meta['discounts']) && is_array($this->booking_meta['discounts']) ){
  484.             $discounts = $this->booking_meta['discounts'];
  485.         }
  486.         return apply_filters('em_booking_get_price_discounts', $discounts, $this);
  487.     }
  488.    
  489.     function get_price_discounts_amount( $pre_or_post = 'pre', $price = false ){
  490.         $discounts = $this->get_price_discounts_summary($pre_or_post, $price);
  491.         $discount_amount = 0;
  492.         foreach($discounts as $discount){
  493.             $discount_amount += $discount['amount_discounted'];
  494.         }
  495.         return $discount_amount;
  496.     }
  497.  
  498.     function get_price_discounts_summary( $pre_or_post = 'pre', $price = false ){
  499.         $discounts=  $this->get_price_discounts();
  500.         $discount_summary = array();
  501.         if( $price === false ){
  502.             $price = $this->get_price_base();
  503.             if( $pre_or_post == 'post' ) $price = $this->get_price_pre_taxes() + $this->get_price_taxes();
  504.         }
  505.         foreach($discounts as $discount){
  506.             $discount_amount = 0;
  507.             if( !empty($discount['amount']) ){
  508.                 if( !empty($discount['tax']) && $discount['tax'] == $pre_or_post ){
  509.                     if( !empty($discount['type']) ){
  510.                         $discount_summary_item = array('name' => $discount['name'], 'desc' => $discount['desc'], 'discount'=>'0', 'amount_discounted'=>0);
  511.                         if( $discount['type'] == '%' ){ //discount by percentage
  512.                             $discount_summary_item['amount_discounted'] = round($price * ($discount['amount']/100),2);
  513.                             $discount_summary_item['amount'] = $this->format_price($discount_summary_item['amount_discounted']);
  514.                             $discount_summary_item['discount'] = number_format($discount['amount'],2).'%';
  515.                             $discount_summary[] = $discount_summary_item;
  516.                         }elseif( $discount['type'] == '#' ){ //discount by amount
  517.                             $discount_summary_item['amount_discounted'] = round($discount['amount'],2);
  518.                             $discount_summary_item['amount'] = $this->format_price($discount_summary_item['amount_discounted']);
  519.                             $discount_summary_item['discount'] = $this->format_price($discount['amount']);
  520.                             $discount_summary[] = $discount_summary_item;
  521.                         }
  522.                     }
  523.                 }
  524.             }
  525.         }
  526.         return $discount_summary;
  527.     }
  528.    
  529.     /**
  530.      * When generating totals at the bottom of a booking, this creates a useful array for displaying the summary in a meaningful way.
  531.      */
  532.     function get_price_summary_array(){
  533.         $summary = array();
  534.         //get base price of bookings
  535.         $summary['total_base'] = $this->get_price_base();
  536.         //get discounts
  537.         //apply pre-tax discounts
  538.         $summary['discounts_pre_tax'] = $this->get_price_discounts_summary('pre');
  539.         //add taxes to price
  540.         $summary['taxes'] = array('rate'=> 0, 'amount'=> 0);
  541.         if( $this->get_price_taxes() > 0 ){
  542.             $summary['taxes'] = array('rate'=> number_format($this->get_tax_rate(),2, get_option('dbem_bookings_currency_decimal_point'), get_option('dbem_bookings_currency_thousands_sep')).'%', 'amount'=> $this->get_price_taxes(true));
  543.         }
  544.         //apply post-tax discounts
  545.         $summary['discounts_post_tax'] = $this->get_price_discounts_summary('post');
  546.         //final price
  547.         $summary['total'] =  $this->get_price(true);
  548.         return $summary;
  549.     }
  550.    
  551.     /* Get Objects linked to booking */
  552.    
  553.     /**
  554.      * Gets the event this booking belongs to and saves a refernece in the event property
  555.      * @return EM_Event
  556.      */
  557.     function get_event(){
  558.         global $EM_Event;
  559.         if( is_object($this->event) && get_class($this->event)=='EM_Event' && $this->event->event_id == $this->event_id ){
  560.             return $this->event;
  561.         }elseif( is_object($EM_Event) && ( (is_object($this->event) && $this->event->event_id == $this->event_id) || empty($this->booking_id)) ){
  562.             $this->event = $EM_Event;
  563.         }else{
  564.             $this->event = new EM_Event($this->event_id, 'event_id');
  565.         }
  566.         return apply_filters('em_booking_get_event',$this->event, $this);
  567.     }
  568.    
  569.     /**
  570.      * Gets the ticket object this booking belongs to, saves a reference in ticket property
  571.      * @return EM_Tickets
  572.      */
  573.     function get_tickets(){
  574.         if( is_object($this->tickets) && get_class($this->tickets)=='EM_Tickets' ){
  575.             return apply_filters('em_booking_get_tickets', $this->tickets, $this);
  576.         }else{
  577.             $this->tickets = new EM_Tickets($this);
  578.         }
  579.         return apply_filters('em_booking_get_tickets', $this->tickets, $this);
  580.     }
  581.    
  582.     /**
  583.      * Gets the ticket object this booking belongs to, saves a reference in ticket property
  584.      * @return EM_Tickets_Bookings
  585.      */
  586.     function get_tickets_bookings(){
  587.         global $wpdb;
  588.         if( !is_object($this->tickets_bookings) || get_class($this->tickets_bookings)!='EM_Tickets_Bookings'){
  589.             $this->tickets_bookings = new EM_Tickets_Bookings($this);
  590.         }
  591.         return apply_filters('em_booking_get_tickets_bookings', $this->tickets_bookings, $this);
  592.     }
  593.    
  594.     /**
  595.      * @return EM_Person
  596.      */
  597.     function get_person(){
  598.         global $EM_Person;
  599.         if( is_object($this->person) && get_class($this->person)=='EM_Person' && ($this->person->ID == $this->person_id || empty($this->person_id) ) ){
  600.             //This person is already included, so don't do anything
  601.         }elseif( is_object($EM_Person) && ($EM_Person->ID === $this->person_id || $this->booking_id == '') ){
  602.             $this->person = $EM_Person;
  603.             $this->person_id = $this->person->ID;
  604.         }elseif( is_numeric($this->person_id) ){
  605.             $this->person = new EM_Person($this->person_id);
  606.         }else{
  607.             $this->person = new EM_Person(0);
  608.             $this->person_id = $this->person->ID;
  609.         }
  610.         //if this user is the parent user of disabled registrations, replace user details here:
  611.         if( get_option('dbem_bookings_registration_disable') && $this->person->ID == get_option('dbem_bookings_registration_user') && (empty($this->person->loaded_no_user) || $this->person->loaded_no_user != $this->booking_id) ){
  612.             //override any registration data into the person objet
  613.             if( !empty($this->booking_meta['registration']) ){
  614.                 foreach($this->booking_meta['registration'] as $key => $value){
  615.                     $this->person->$key = $value;
  616.                 }
  617.             }
  618.             $this->person->user_email = ( !empty($this->booking_meta['registration']['user_email']) ) ? $this->booking_meta['registration']['user_email']:$this->person->user_email;
  619.             //if a full name is given, overwrite the first/last name values IF they are also not defined
  620.             if( !empty($this->booking_meta['registration']['user_name']) ){
  621.                 if( !empty($this->booking_meta['registration']['first_name']) ){
  622.                     //first name is defined, so we remove it from full name in case we need the rest for surname
  623.                     $last_name = trim(str_replace($this->booking_meta['registration']['first_name'], '', $this->booking_meta['registration']['user_name']));
  624.                     //if last name isn't defined, provide the rest of the name minus the first name we just removed
  625.                     if( empty($this->booking_meta['registration']['last_name']) ){
  626.                         $this->booking_meta['registration']['last_name'] = $last_name;
  627.                     }
  628.                 }else{
  629.                     //no first name defined, check for last name and act accordingly
  630.                     if( !empty($this->booking_meta['registration']['last_name']) ){
  631.                         //we do opposite of above, remove last name from full name and use the rest as first name
  632.                         $first_name = trim(str_replace($this->booking_meta['registration']['last_name'], '', $this->booking_meta['registration']['user_name']));
  633.                         $this->booking_meta['registration']['first_name'] = $first_name;
  634.                     }else{
  635.                         //no defined first or last name, so we use the name and take first string for first name, second part for surname
  636.                         $name_string = explode(' ',$this->booking_meta['registration']['user_name']);
  637.                         $this->booking_meta['registration']['first_name'] = array_shift($name_string);
  638.                         $this->booking_meta['registration']['last_name'] = implode(' ', $name_string);
  639.                     }
  640.                 }
  641.             }
  642.             $this->person->user_firstname = ( !empty($this->booking_meta['registration']['first_name']) ) ? $this->booking_meta['registration']['first_name']:__('Guest User','events-manager');
  643.             $this->person->first_name = $this->person->user_firstname;
  644.             $this->person->user_lastname = ( !empty($this->booking_meta['registration']['last_name']) ) ? $this->booking_meta['registration']['last_name']:'';
  645.             $this->person->last_name = $this->person->user_lastname;
  646.             $this->person->phone = ( !empty($this->booking_meta['registration']['dbem_phone']) ) ? $this->booking_meta['registration']['dbem_phone']:__('Not Supplied','events-manager');
  647.             //build display name
  648.             $full_name = $this->person->user_firstname  . " " . $this->person->user_lastname ;
  649.             $full_name = trim($full_name);
  650.             $display_name = ( empty($full_name) ) ? __('Guest User','events-manager'):$full_name;
  651.             $this->person->display_name = $display_name;
  652.             $this->person->loaded_no_user = $this->booking_id;
  653.         }
  654.         return apply_filters('em_booking_get_person', $this->person, $this);
  655.     }
  656.    
  657.     /**
  658.      * Gets personal information from the $_REQUEST array and saves it to the $EM_Booking->booking_meta['registration'] array
  659.      * @return boolean
  660.      */
  661.     function get_person_post(){
  662.         $user_data = array();
  663.         $registration = true;
  664.         if( empty($this->booking_meta['registration']) ) $this->booking_meta['registration'] = array();
  665.         // Check the e-mail address
  666.         $user_email = trim(wp_unslash($_REQUEST['user_email'])); //apostrophes will not be allowed otherwise
  667.         if ( $user_email == '' ) {
  668.             $registration = false;
  669.             $this->add_error(__( '<strong>ERROR</strong>: Please type your e-mail address.', 'events-manager') );
  670.         } elseif ( !is_email( $user_email ) ) {
  671.             $registration = false;
  672.             $this->add_error( __( '<strong>ERROR</strong>: The email address isn&#8217;t correct.', 'events-manager') );
  673.         }elseif(email_exists( $user_email ) && !get_option('dbem_bookings_registration_disable_user_emails') ){
  674.             $registration = false;
  675.             $this->add_error( get_option('dbem_booking_feedback_email_exists') );
  676.         }else{
  677.             $user_data['user_email'] = $user_email;
  678.         }
  679.         //Check the user name
  680.         if( !empty($_REQUEST['user_name']) ){
  681.             //split full name up and save full, first and last names
  682.             $user_data['user_name'] = wp_kses(wp_unslash($_REQUEST['user_name']), array());
  683.             $name_string = explode(' ',$user_data['user_name']);
  684.             $user_data['first_name'] = array_shift($name_string);
  685.             $user_data['last_name'] = implode(' ', $name_string);
  686.         }else{
  687.             //Check the first/last name
  688.             $name_string = array();
  689.             if( !empty($_REQUEST['first_name']) ){
  690.                 $user_data['first_name'] = $name_string[] = wp_kses(wp_unslash($_REQUEST['first_name']), array());
  691.             }
  692.             if( !empty($_REQUEST['last_name']) ){
  693.                 $user_data['last_name'] = $name_string[] = wp_kses(wp_unslash($_REQUEST['last_name']), array());
  694.             }
  695.             if( !empty($name_string) ) $user_data['user_name'] = implode(' ', $name_string);
  696.         }
  697.         //Save full name
  698.         if( !empty($user_data['first_name']) || !empty($user_data['last_name']) )
  699.         //Check the phone
  700.         if( !empty($_REQUEST['dbem_phone']) ){
  701.             $user_data['dbem_phone'] = wp_kses(wp_unslash($_REQUEST['dbem_phone']), array());
  702.         }
  703.         //Add booking meta
  704.         if( $registration ){
  705.             $this->booking_meta['registration'] = array_merge($this->booking_meta['registration'], $user_data); //in case someone else added stuff
  706.         }
  707.         $registration = apply_filters('em_booking_get_person_post', $registration, $this);
  708.         if( $registration ){
  709.             $this->feedback_message = __('Personal details have successfully been modified.', 'events-manager');
  710.         }
  711.         return $registration;
  712.     }
  713.    
  714.     /**
  715.      * Displays a form containing user fields, used in no-user booking mode for editing guest users within a booking
  716.      * @return string
  717.      */
  718.     function get_person_editor(){
  719.         ob_start();
  720.         $name = $this->get_person()->get_name();
  721.         $email = $this->get_person()->user_email;
  722.         $phone = ($this->get_person()->phone != __('Not Supplied','events-manager')) ? $this->get_person()->phone:'';
  723.         if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'booking_modify_person' ){
  724.             $name = !empty($_REQUEST['user_name']) ? $_REQUEST['user_name']:$name;
  725.             $email = !empty($_REQUEST['user_email']) ? $_REQUEST['user_email']:$email;
  726.             $phone = !empty($_REQUEST['dbem_phone']) ? $_REQUEST['dbem_phone']:$phone;
  727.         }
  728.         ?>
  729.         <table class="em-form-fields">
  730.             <tr><th><?php _e('Name','events-manager'); ?> : </th><td><input type="text" name="user_name" value="<?php echo esc_attr($name); ?>" /></td></tr>
  731.             <tr><th><?php _e('Email','events-manager'); ?> : </th><td><input type="text" name="user_email" value="<?php echo esc_attr($email); ?>" /></td></tr>
  732.             <tr><th><?php _e('Phone','events-manager'); ?> : </th><td><input type="text" name="dbem_phone" value="<?php echo esc_attr($phone); ?>" /></td></tr>
  733.         </table>
  734.         <?php
  735.         return apply_filters('em_booking_get_person_editor', ob_get_clean(), $this);
  736.     }
  737.  
  738.     /**
  739.      * Returns a string representation of the booking's status
  740.      * @return string
  741.      */
  742.     function get_status(){
  743.         $status = ($this->booking_status == 0 && !get_option('dbem_bookings_approval') ) ? 1:$this->booking_status;
  744.         return apply_filters('em_booking_get_status', $this->status_array[$status], $this);
  745.     }
  746.    
  747.     /**
  748.      * I wonder what this does....
  749.      * @return boolean
  750.      */
  751.     function delete(){
  752.         global $wpdb;
  753.         $result = false;
  754.         if( $this->can_manage('manage_bookings','manage_others_bookings') ){
  755.             $sql = $wpdb->prepare("DELETE FROM ". EM_BOOKINGS_TABLE . " WHERE booking_id=%d", $this->booking_id);
  756.             $result = $wpdb->query( $sql );
  757.             if( $result !== false ){
  758.                 //delete the tickets too
  759.                 $this->get_tickets_bookings()->delete();
  760.                 $this->previous_status = $this->booking_status;
  761.                 $this->booking_status = false;
  762.                 $this->feedback_message = sprintf(__('%s deleted', 'events-manager'), __('Booking','events-manager'));
  763.                 $wpdb->delete( EM_META_TABLE, array('meta_key'=>'booking-note', 'object_id' => $this->booking_id), array('%s','%d'));
  764.             }else{
  765.                 $this->add_error(sprintf(__('%s could not be deleted', 'events-manager'), __('Booking','events-manager')));
  766.             }
  767.         }
  768.         do_action('em_bookings_deleted', $result, array($this->booking_id));
  769.         return apply_filters('em_booking_delete',( $result !== false ), $this);
  770.     }
  771.    
  772.     function cancel($email = true){
  773.         if( $this->person->ID == get_current_user_id() ){
  774.             $this->manage_override = true; //normally, users can't manage a bookiing, only event owners, so we allow them to mod their booking status in this case only.
  775.         }
  776.         return $this->set_status(3, $email);
  777.     }
  778.    
  779.     /**
  780.      * Approve a booking.
  781.      * @return bool
  782.      */
  783.     function approve($email = true, $ignore_spaces = false){
  784.         return $this->set_status(1, $email, $ignore_spaces);
  785.     }  
  786.     /**
  787.      * Reject a booking and save
  788.      * @return bool
  789.      */
  790.     function reject($email = true){
  791.         return $this->set_status(2, $email);
  792.     }  
  793.     /**
  794.      * Unapprove a booking.
  795.      * @return bool
  796.      */
  797.     function unapprove($email = true){
  798.         return $this->set_status(0, $email);
  799.     }
  800.    
  801.     /**
  802.      * Change the status of the booking. This will save to the Database too.
  803.      * @param int $status
  804.      * @return boolean
  805.      */
  806.     function set_status($status, $email = true, $ignore_spaces = false){
  807.         global $wpdb;
  808.         $action_string = strtolower($this->status_array[$status]);
  809.         //if we're approving we can't approve a booking if spaces are full, so check before it's approved.
  810.         if(!$ignore_spaces && $status == 1){
  811.             if( !$this->is_reserved() && $this->get_event()->get_bookings()->get_available_spaces() < $this->get_spaces() && !get_option('dbem_bookings_approval_overbooking') ){
  812.                 $this->feedback_message = sprintf(__('Not approved, spaces full.','events-manager'), $action_string);
  813.                 $this->add_error($this->feedback_message);
  814.                 return apply_filters('em_booking_set_status', false, $this);
  815.             }
  816.         }
  817.         $this->previous_status = $this->booking_status;
  818.         $this->booking_status = $status;
  819.         $result = $wpdb->query($wpdb->prepare('UPDATE '.EM_BOOKINGS_TABLE.' SET booking_status=%d WHERE booking_id=%d', array($status, $this->booking_id)));
  820.         if($result !== false){
  821.             $this->feedback_message = sprintf(__('Booking %s.','events-manager'), $action_string);
  822.             if( $email ){
  823.                 if( $this->email() ){
  824.                     if( $this->mails_sent > 0 ){
  825.                         $this->feedback_message .= " ".__('Email Sent.','events-manager');
  826.                     }
  827.                 }else{
  828.                     //extra errors may be logged by email() in EM_Object
  829.                     $this->feedback_message .= ' <span style="color:red">'.__('ERROR : Email Not Sent.','events-manager').'</span>';
  830.                     $this->add_error(__('ERROR : Email Not Sent.','events-manager'));
  831.                 }
  832.             }
  833.         }else{
  834.             //errors should be logged by save()
  835.             $this->feedback_message = sprintf(__('Booking could not be %s.','events-manager'), $action_string);
  836.             $this->add_error(sprintf(__('Booking could not be %s.','events-manager'), $action_string));
  837.             $result =  false;
  838.         }
  839.         return apply_filters('em_booking_set_status', $result, $this);
  840.     }
  841.    
  842.     /**
  843.      * Returns true if booking is reserving a space at this event, whether confirmed or not
  844.      */
  845.     function is_reserved(){
  846.         $result = false;
  847.         if( $this->booking_status == 0 && get_option('dbem_bookings_approval_reserved') ){
  848.             $result = true;
  849.         }elseif( $this->booking_status == 0 && !get_option('dbem_bookings_approval') ){
  850.             $result = true;
  851.         }elseif( $this->booking_status == 1 ){
  852.             $result = true;
  853.         }
  854.         return apply_filters('em_booking_is_reserved', $result, $this);
  855.     }
  856.    
  857.     /**
  858.      * Returns true if booking is either pending or reserved but not confirmed (which is assumed pending)
  859.      */
  860.     function is_pending(){
  861.         $result = ($this->is_reserved() || $this->booking_status == 0) && $this->booking_status != 1;
  862.         return apply_filters('em_booking_is_pending', $result, $this);
  863.     }
  864.    
  865.     /**
  866.      * Add a booking note to this booking. returns wpdb result or false if use can't manage this event.
  867.      * @param string $note
  868.      * @return mixed
  869.      */
  870.     function add_note( $note_text ){
  871.         global $wpdb;
  872.         if( $this->can_manage() ){
  873.             $this->get_notes();
  874.             $note = array('author'=>get_current_user_id(),'note'=>$note_text,'timestamp'=>current_time('timestamp'));
  875.             $this->notes[] = wp_kses_data($note);
  876.             $this->feedback_message = __('Booking note successfully added.','events-manager');
  877.             return $wpdb->insert(EM_META_TABLE, array('object_id'=>$this->booking_id, 'meta_key'=>'booking-note', 'meta_value'=> serialize($note)),array('%d','%s','%s'));
  878.         }
  879.         return false;
  880.     }
  881.  
  882.     function get_admin_url(){
  883.         if( get_option('dbem_edit_bookings_page') && (!is_admin() || !empty($_REQUEST['is_public'])) ){
  884.             $my_bookings_page = get_permalink(get_option('dbem_edit_bookings_page'));
  885.             $bookings_link = em_add_get_params($my_bookings_page, array('event_id'=>$this->event_id, 'booking_id'=>$this->booking_id), false);
  886.         }else{
  887.             if( $this->get_event()->blog_id != get_current_blog_id() ){
  888.                 $bookings_link = get_admin_url($this->get_event()->blog_id, 'edit.php?post_type='.EM_POST_TYPE_EVENT."&page=events-manager-bookings&event_id=".$this->event_id."&booking_id=".$this->booking_id);
  889.             }else{
  890.                 $bookings_link = EM_ADMIN_URL. "&page=events-manager-bookings&event_id=".$this->event_id."&booking_id=".$this->booking_id;
  891.             }
  892.         }
  893.         return apply_filters('em_booking_get_bookings_url', $bookings_link, $this);
  894.     }
  895.    
  896.     function output($format, $target="html") {
  897.         preg_match_all("/(#@?_?[A-Za-z0-9]+)({([^}]+)})?/", $format, $placeholders);
  898.         foreach( $this->get_tickets() as $EM_Ticket){ /* @var $EM_Ticket EM_Ticket */ break; } //Get first ticket for single ticket placeholders
  899.         $output_string = $format;
  900.         $replaces = array();
  901.         foreach($placeholders[1] as $key => $result) {
  902.             $replace = '';
  903.             $full_result = $placeholders[0][$key];     
  904.             switch( $result ){
  905.                 case '#_BOOKINGID':
  906.                     $replace = $this->booking_id;
  907.                     break;
  908.                 case '#_RESPNAME' : //deprecated
  909.                 case '#_BOOKINGNAME':
  910.                     $replace = $this->get_person()->get_name();
  911.                     break;
  912.                 case '#_RESPEMAIL' : //deprecated
  913.                 case '#_BOOKINGEMAIL':
  914.                     $replace = $this->get_person()->user_email;
  915.                     break;
  916.                 case '#_RESPPHONE' : //deprecated
  917.                 case '#_BOOKINGPHONE':
  918.                     $replace = $this->get_person()->phone;
  919.                     break;
  920.                 case '#_BOOKINGSPACES':
  921.                     $replace = $this->get_spaces();
  922.                     break;
  923.                 case '#_BOOKINGDATE':
  924.                     $replace = ( $this->timestamp ) ? date_i18n(get_option('dbem_date_format'), $this->timestamp):'n/a';
  925.                     break;
  926.                 case '#_BOOKINGTIME':
  927.                     $replace = ( $this->timestamp ) ? date_i18n(get_option('dbem_time_format'), $this->timestamp):'n/a';
  928.                     break;
  929.                 case '#_BOOKINGDATETIME':
  930.                     $replace = ( $this->timestamp ) ? date_i18n(get_option('dbem_date_format').' '.get_option('dbem_time_format'), $this->timestamp):'n/a';
  931.                     break;
  932.                 case '#_BOOKINGLISTURL':
  933.                     $replace = em_get_my_bookings_url();
  934.                     break;
  935.                 case '#_COMMENT' : //deprecated
  936.                 case '#_BOOKINGCOMMENT':
  937.                     $replace = $this->booking_comment;
  938.                     break;
  939.                     $replace = $this->get_price(true); //if there's tax, it'll be added here
  940.                     break;
  941.                 case '#_BOOKINGPRICEWITHOUTTAX':
  942.                     $replace = $this->format_price($this->get_price() - $this->get_price_taxes());
  943.                     break;
  944.                 case '#_BOOKINGPRICETAX':
  945.                     $replace = $this->get_price_taxes(true);
  946.                     break;
  947.                 case '#_BOOKINGPRICEWITHTAX':
  948.                 case '#_BOOKINGPRICE':
  949.                     $replace = $this->get_price(true);
  950.                     break;
  951.                 case '#_BOOKINGTICKETNAME':
  952.                     $replace = $EM_Ticket->name;
  953.                     break;
  954.                 case '#_BOOKINGTICKETDESCRIPTION':
  955.                     $replace = $EM_Ticket->description;
  956.                     break;
  957.                 case '#_BOOKINGTICKETPRICEWITHTAX':
  958.                     $replace = $this->format_price( $EM_Ticket->get_price_without_tax() * (1+$this->get_tax_rate()/100) );
  959.                     break;
  960.                 case '#_BOOKINGTICKETPRICEWITHOUTTAX':
  961.                     $replace = $EM_Ticket->get_price_without_tax(true);
  962.                     break;
  963.                 case '#_BOOKINGTICKETTAX':
  964.                     $replace = $this->format_price( $EM_Ticket->get_price_without_tax() * ($this->get_tax_rate()/100) );
  965.                     break;
  966.                 case '#_BOOKINGTICKETPRICE':
  967.                     $replace = $EM_Ticket->get_price(true);
  968.                     break;
  969.                 case '#_BOOKINGTICKETS':
  970.                     ob_start();
  971.                     em_locate_template('emails/bookingtickets.php', true, array('EM_Booking'=>$this));
  972.                     $replace = ob_get_clean();
  973.                     break;
  974.                 case '#_BOOKINGSUMMARY':
  975.                     ob_start();
  976.                     em_locate_template('emails/bookingsummary.php', true, array('EM_Booking'=>$this));
  977.                     $replace = ob_get_clean();
  978.                     break;
  979.                 default:
  980.                     $replace = $full_result;
  981.                     break;
  982.             }
  983.             $replaces[$full_result] = apply_filters('em_booking_output_placeholder', $replace, $this, $full_result, $target);
  984.         }
  985.         //sort out replacements so that during replacements shorter placeholders don't overwrite longer varieties.
  986.         krsort($replaces);
  987.         foreach($replaces as $full_result => $replacement){
  988.             $output_string = str_replace($full_result, $replacement , $output_string );
  989.         }
  990.         //run event output too, since this is never run from within events and will not infinitely loop
  991.         $EM_Event = apply_filters('em_booking_output_event', $this->get_event(), $this); //allows us to override the booking event info if it belongs to a parent or translation
  992.         $output_string = $EM_Event->output($output_string, $target);
  993.         return apply_filters('em_booking_output', $output_string, $this, $format, $target);
  994.     }
  995.    
  996.     /**
  997.      * @param EM_Booking $EM_Booking
  998.      * @param EM_Event $event
  999.      * @return boolean
  1000.      */
  1001.     function email( $email_admin = true, $force_resend = false, $email_attendee = true ){
  1002.         global $EM_Mailer;
  1003.         $result = true;
  1004.         $this->mails_sent = 0;
  1005.        
  1006.         //FIXME ticket logic needed
  1007.         $EM_Event = $this->get_event(); //We NEED event details here.
  1008.         $EM_Event->get_bookings(true); //refresh all bookings
  1009.        
  1010.         //Make sure event matches booking, and that booking used to be approved.
  1011.         if( $this->booking_status !== $this->previous_status || $force_resend ){
  1012.             //messages can be overridden just before being sent
  1013.             $msg = $this->email_messages();
  1014.             $output_type = get_option('dbem_smtp_html') ? 'html':'email';
  1015.  
  1016.             //Send user (booker) emails
  1017.             if( !empty($msg['user']['subject']) && $email_attendee ){
  1018.                 $msg['user']['subject'] = $this->output($msg['user']['subject'], 'raw');
  1019.                 $msg['user']['body'] = $this->output($msg['user']['body'], $output_type);
  1020.                 //Send to the person booking
  1021.                 if( !$this->email_send( $msg['user']['subject'], $msg['user']['body'], $this->get_person()->user_email) ){
  1022.                     $result = false;
  1023.                 }else{
  1024.                     $this->mails_sent++;
  1025.                 }
  1026.             }
  1027.            
  1028.             //Send admin/contact emails if this isn't the event owner or an events admin
  1029.             if( $email_admin && !empty($msg['admin']['subject']) ){ //emails won't be sent if admin is logged in unless they book themselves
  1030.                 //get admin emails that need to be notified, hook here to add extra admin emails
  1031.                 $admin_emails = str_replace(' ','',get_option('dbem_bookings_notify_admin'));
  1032.                 $admin_emails = apply_filters('em_booking_admin_emails', explode(',', $admin_emails), $this); //supply emails as array
  1033.                 if( get_option('dbem_bookings_contact_email') == 1 && !empty($EM_Event->get_contact()->user_email) ){
  1034.                     //add event owner contact email to list of admin emails
  1035.                     $admin_emails[] = $EM_Event->get_contact()->user_email;
  1036.                 }
  1037.                 foreach($admin_emails as $key => $email){ if( !is_email($email) ) unset($admin_emails[$key]); } //remove bad emails
  1038.                 //proceed to email admins if need be
  1039.                 if( !empty($admin_emails) ){
  1040.                     //Only gets sent if this is a pending booking, unless approvals are disabled.
  1041.                     $msg['admin']['subject'] = $this->output($msg['admin']['subject'],'raw');
  1042.                     $msg['admin']['body'] = $this->output($msg['admin']['body'], $output_type);
  1043.                     //email admins
  1044.                         if( !$this->email_send( $msg['admin']['subject'], $msg['admin']['body'], $admin_emails) && current_user_can('manage_options') ){
  1045.                             $this->errors[] = __('Confirmation email could not be sent to admin. Registrant should have gotten their email (only admin see this warning).','events-manager');
  1046.                             $result = false;
  1047.                         }else{
  1048.                             $this->mails_sent++;
  1049.                         }
  1050.                 }
  1051.             }
  1052.         }
  1053.         return $result;
  1054.         //TODO need error checking for booking mail send
  1055.     }  
  1056.    
  1057.     function email_messages(){
  1058.         $msg = array( 'user'=> array('subject'=>'', 'body'=>''), 'admin'=> array('subject'=>'', 'body'=>'')); //blank msg template         
  1059.         //admin messages won't change whether pending or already approved
  1060.         switch( $this->booking_status ){
  1061.             case 0:
  1062.             case 5: //TODO remove offline status from here and move to pro
  1063.                 $msg['user']['subject'] = get_option('dbem_bookings_email_pending_subject');
  1064.                 $msg['user']['body'] = get_option('dbem_bookings_email_pending_body');
  1065.                 //admins should get something (if set to)
  1066.                 $msg['admin']['subject'] = get_option('dbem_bookings_contact_email_pending_subject');
  1067.                 $msg['admin']['body'] = get_option('dbem_bookings_contact_email_pending_body');
  1068.                 break;
  1069.             case 1:
  1070.                 $msg['user']['subject'] = get_option('dbem_bookings_email_confirmed_subject');
  1071.                 $msg['user']['body'] = get_option('dbem_bookings_email_confirmed_body');
  1072.                 //admins should get something (if set to)
  1073.                 $msg['admin']['subject'] = get_option('dbem_bookings_contact_email_confirmed_subject');
  1074.                 $msg['admin']['body'] = get_option('dbem_bookings_contact_email_confirmed_body');
  1075.                 break;
  1076.             case 2:
  1077.                 $msg['user']['subject'] = get_option('dbem_bookings_email_rejected_subject');
  1078.                 $msg['user']['body'] = get_option('dbem_bookings_email_rejected_body');
  1079.                 //admins should get something (if set to)
  1080.                 $msg['admin']['subject'] = get_option('dbem_bookings_contact_email_rejected_subject');
  1081.                 $msg['admin']['body'] = get_option('dbem_bookings_contact_email_rejected_body');
  1082.                 break;
  1083.             case 3:
  1084.                 $msg['user']['subject'] = get_option('dbem_bookings_email_cancelled_subject');
  1085.                 $msg['user']['body'] = get_option('dbem_bookings_email_cancelled_body');
  1086.                 //admins should get something (if set to)
  1087.                 $msg['admin']['subject'] = get_option('dbem_bookings_contact_email_cancelled_subject');
  1088.                 $msg['admin']['body'] = get_option('dbem_bookings_contact_email_cancelled_body');
  1089.                 break;
  1090.         }
  1091.         return apply_filters('em_booking_email_messages', $msg, $this);
  1092.     }
  1093.    
  1094.     /**
  1095.      * Can the user manage this event?
  1096.      */
  1097.     function can_manage( $owner_capability = false, $admin_capability = false, $user_to_check = false ){
  1098.         return $this->get_event()->can_manage('manage_bookings','manage_others_bookings') || empty($this->booking_id) || !empty($this->manage_override);
  1099.     }
  1100.    
  1101.     /**
  1102.      * Returns this object in the form of an array
  1103.      * @return array
  1104.      */
  1105.     function to_array($person = false){
  1106.         $booking = array();
  1107.         //Core Data
  1108.         $booking = parent::to_array();
  1109.         //Person Data
  1110.         if($person && is_object($this->person)){
  1111.             $person = $this->person->to_array();
  1112.             $booking = array_merge($booking, $person);
  1113.         }
  1114.         return $booking;
  1115.     }
  1116. }
  1117. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement