event_id = $data->event_id; $sql = "SELECT * FROM ". EM_BOOKINGS_TABLE ." WHERE event_id ='{$this->event_id}'"; $bookings = $wpdb->get_results($sql, ARRAY_A); foreach ($bookings as $booking){ $this->bookings[] = new EM_Booking($booking); } $this->spaces = $this->get_spaces(); }elseif( is_array($data) ){ foreach( $data as $EM_Booking ){ if( get_class($EM_Booking) == 'EM_Booking'){ $this->bookings[] = $EM_Booking; } } } } /** * Add a booking into this event (or add spaces if person already booked this), checking that there's enough space for the event * @param EM_Booking $EM_Booking * @return boolean */ function add( $EM_Booking ){ global $wpdb,$EM_Mailer; if ( $this->get_available_spaces() >= $EM_Booking->get_spaces(true) ) { //Save the booking $email = false; if( !get_option('dbem_bookings_approval') && $EM_Booking->booking_status < 2 ){ $EM_Booking->booking_status = 1; } $result = $EM_Booking->save(false); if($result){ //Success $this->bookings[] = $EM_Booking; $email = $EM_Booking->email(); if( get_option('dbem_bookings_approval') == 1 && $EM_Booking->booking_status == 0){ $this->feedback_message = get_option('dbem_booking_feedback_pending'); }else{ $this->feedback_message = get_option('dbem_booking_feedback'); } if(!$email){ $this->feedback_message .= ' '.get_option('dbem_booking_feedback_nomail'); if( current_user_can('activate_plugins') ){ if( count($EM_Booking->get_errors()) > 0 ){ $this->feedback_message .= '
Errors: (only admins see this message)
'; }else{ $this->feedback_message .= '
No errors returned by mailer (only admins see this message)'; } } } return true; }else{ //Failure $this->errors[] = "".get_option('dbem_booking_feedback_error')."
". implode('
', $EM_Booking->errors); } } else { $this->add_error(get_option('dbem_booking_feedback_full')); } return apply_filters('em_bookings_add', false, $EM_Booking); } /** * Get POST data and create a booking for each ticket requested. If successful, a booking object is returned, false if not. * @return false|object */ function add_from_post(){ $EM_Booking = new EM_booking(); $result = $EM_Booking->get_post(); if($result){ $result = $this->add($EM_Booking); if($result){ $result = $EM_Booking; } $this->feedback_message = sprintf(__('%s created.','dbem'),__('Booking','dbem')); }else{ $this->errors = array_merge($this->errors, $EM_Booking->errors); } return apply_filters('em_bookings_add_from_post',$result,$EM_Booking,$this); } /** * Smart event locator, saves a database read if possible. Note that if an event doesn't exist, a blank object will be created to prevent duplicates. */ function get_event(){ global $EM_Event; if( is_object($EM_Event) && $EM_Event->event_id == $this->event_id ){ return $EM_Event; }else{ if( is_numeric($this->event_id) && $this->event_id > 0 ){ return new EM_Event($this->event_id, 'event_id'); }elseif( count($this->bookings) > 0 ){ foreach($this->bookings as $EM_Booking){ /* @var $EM_Booking EM_Booking */ return new EM_Event($EM_Booking->event_id, 'event_id'); } } } return new EM_Event($this->event_id); } /** * Retrieve and save the bookings belonging to instance. If called again will return cached version, set $force_reload to true to create a new EM_Tickets object. * @param boolean $force_reload * @return EM_Tickets */ function get_tickets( $force_reload = false ){ if( !is_object($this->tickets) || $force_reload ){ $this->tickets = new EM_Tickets($this->event_id); }else{ $this->tickets->event_id = $this->event_id; } return apply_filters('em_bookings_get_tickets', $this->tickets, $this); } /** * Returns EM_Tickets object with available tickets * @return EM_Tickets */ function get_available_tickets(){ $tickets = array(); $timesamp = current_time('timestamp'); foreach ($this->get_tickets() as $EM_Ticket){ /* @var EM_Ticket $EM_Ticket */ if( $EM_Ticket->is_available() ){ //within time range if( $EM_Ticket->get_available_spaces() > 0 ){ $tickets[] = $EM_Ticket; } } } $EM_Tickets = new EM_Tickets($tickets); return apply_filters('em_bookings_get_tickets', $EM_Tickets, $this); } function get_user_list(){ $users = array(); foreach( $this->get_bookings()->bookings as $EM_Booking ){ $users[$EM_Booking->person->ID] = $EM_Booking->person; } return $users; } /** * does this ticket exist? * @return bool */ function ticket_exists($ticket_id){ $EM_Tickets = $this->get_tickets(); foreach( $EM_Tickets->tickets as $EM_Ticket){ if($EM_Ticket->ticket_id == $ticket_id){ return apply_filters('em_bookings_ticket_exists',true, $EM_Ticket, $this); } } return apply_filters('em_bookings_ticket_exists',false, false,$this); } /** * Delete bookings on this id * @return boolean */ function delete(){ global $wpdb; $booking_ids = array(); //get the booking ids tied to this event foreach( $this->bookings as $EM_Booking ){ $booking_ids[] = $EM_Booking->booking_id; } $result_tickets = true; $result = true; if( count($booking_ids) > 0 ){ //Delete bookings and ticket bookings $result_tickets = $wpdb->query("DELETE FROM ". EM_TICKETS_BOOKINGS_TABLE ." WHERE booking_id IN (".implode(',',$booking_ids).");"); $result = $wpdb->query("DELETE FROM ".EM_BOOKINGS_TABLE." WHERE event_id IN (".implode(',',$booking_ids).")"); } return ($result !== false && $result_tickets !== false); } /** * Will approve all supplied booking ids, which must be in the form of a numeric array or a single number. * @param array|int $booking_ids * @return boolean */ function approve( $booking_ids ){ $this->set_status(1, $booking_ids); return false; } /** * Will reject all supplied booking ids, which must be in the form of a numeric array or a single number. * @param array|int $booking_ids * @return boolean */ function reject( $booking_ids ){ return $this->set_status(2, $booking_ids); } /** * Will unapprove all supplied booking ids, which must be in the form of a numeric array or a single number. * @param array|int $booking_ids * @return boolean */ function unapprove( $booking_ids ){ return $this->set_status(0, $booking_ids); } /** * @param int $status * @param array|int $booking_ids * @return bool */ function set_status($status, $booking_ids){ //FIXME status should work with instantiated object //FIXME there is a vulnerability where any user can approve/reject bookings if they know the ID if( $this->array_is_numeric($booking_ids) ){ //Get all the bookings $results = array(); $mails = array(); foreach( $booking_ids as $booking_id ){ $EM_Booking = new EM_Booking($booking_id); if( !$EM_Booking->can_manage() ){ $this->feedback_message = __('Bookings %s. Mails Sent.', 'dbem'); return false; } $results[] = $EM_Booking->set_status($status); } if( !in_array('false',$results) ){ $this->feedback_message = __('Bookings %s. Mails Sent.', 'dbem'); return true; }else{ //TODO Better error handling needed if some bookings fail approval/failure $this->feedback_message = __('An error occurred.', 'dbem'); return false; } }elseif( is_numeric($booking_ids) || is_object($booking_ids) ){ $EM_Booking = ( is_object($booking_ids) && get_class($booking_ids) == 'EM_Booking') ? $booking_ids : new EM_Booking($booking_ids); $result = $EM_Booking->set_status($status); $this->feedback_message = $EM_Booking->feedback_message; return $result; } return false; } /** * Get the total number of spaces this event has. This will show the lower value of event global spaces limit or total ticket spaces. Setting $force_refresh to true will recheck spaces, even if previously done so. * @param boolean $force_refresh * @return int */ function get_spaces( $force_refresh=false ){ if($force_refresh || $this->spaces == 0){ $this->spaces = $this->get_tickets()->get_spaces(); } return apply_filters('em_booking_get_spaces',$this->spaces,$this); } /** * Returns number of available spaces for this event. If approval of bookings is on, will include pending bookings depending on em option. * @return int */ function get_available_spaces(){ $available_spaces = $this->get_spaces() - $this->get_booked_spaces(); return apply_filters('em_booking_get_available_spaces', $available_spaces, $this); } /** * Returns number of booked spaces for this event. If approval of bookings is on, will return number of booked confirmed spaces. * @return int */ function get_booked_spaces($force_refresh = false){ $booked_spaces = 0; $EM_Bookings = $this->get_bookings(true); $reserved_pending = get_option('dbem_bookings_approval_reserved'); $auto_approval = get_option('dbem_bookings_approval'); foreach ( $EM_Bookings->bookings as $EM_Booking ){ //never show cancelled status, nor pending if approvals required if( $EM_Booking->booking_status == 1 || ((!$auto_approval || $reserved_pending) && $EM_Booking->booking_status == 0) ){ $booked_spaces += $EM_Booking->get_spaces($force_refresh); } } return $booked_spaces; } /** * Gets number of pending spaces awaiting approval. Will return 0 if booking approval is not enabled. * @return int */ function get_pending_spaces(){ if( get_option('dbem_bookings_approval') == 0 ){ return 0; } $pending = 0; foreach ( $this->bookings as $booking ){ if($booking->booking_status == 0){ $pending += $booking->get_spaces(); } } return apply_filters('em_bookings_get_pending_spaces', $pending, $this); } /** * Gets number of bookings (not spaces). If booking approval is enabled, only the number of approved bookings will be shown. * @return EM_Bookings */ function get_bookings( $all_bookings = false ){ $confirmed = array(); foreach ( $this->bookings as $booking ){ if( $booking->booking_status == 1 || (get_option('dbem_bookings_approval') == 0 && $booking->booking_status == 0) || $all_bookings ){ $confirmed[] = $booking; } } $EM_Bookings = new EM_Bookings($confirmed); return $EM_Bookings; } /** * Get pending bookings. If booking approval is disabled, will return no bookings. * @return EM_Bookings */ function get_pending_bookings(){ if( get_option('dbem_bookings_approval') == 0 ){ return array(); } $pending = array(); foreach ( $this->bookings as $booking ){ if($booking->booking_status == 0){ $pending[] = $booking; } } $EM_Bookings = new EM_Bookings($pending); return $EM_Bookings; } /** * Get rejected bookings. If booking approval is disabled, will return no bookings. * @return array EM_Bookings */ function get_rejected_bookings(){ $rejected = array(); foreach ( $this->bookings as $booking ){ if($booking->booking_status == 2){ $rejected[] = $booking; } } $EM_Bookings = new EM_Bookings($rejected); return $EM_Bookings; } /** * Get cancelled bookings. * @return array EM_Booking */ function get_cancelled_bookings(){ $cancelled = array(); foreach ( $this->bookings as $booking ){ if($booking->booking_status == 3){ $cancelled[] = $booking; } } $EM_Bookings = new EM_Bookings($cancelled); return $EM_Bookings; } /** * Checks if a person with similar details has booked for this before * @param $person_id * @return EM_Booking */ function find_previous_booking($EM_Booking){ //First see if we have a similar person on record that's making this booking $EM_Booking->person->load_similar(); //If person exists on record, see if they've booked this event before, if so return the booking. if( is_numeric($EM_Booking->person->ID) && $EM_Booking->person->ID > 0 ){ $EM_Booking->person_id = $EM_Booking->person->ID; foreach ($this->bookings as $booking){ if( $booking->person_id == $EM_Booking->person->ID ){ return $booking; } } } return false; } /** * Checks to see if user has a booking for this event * @param unknown_type $user_id */ function has_booking( $user_id = false ){ if( $user_id === false ){ $user_id = get_current_user_id(); } if( is_numeric($user_id) && $user_id > 0 ){ foreach ($this->bookings as $EM_Booking){ if( $EM_Booking->person->ID == $user_id && $EM_Booking->booking_status != 3 ){ return apply_filters('em_bookings_has_booking', $EM_Booking, $this); } } } return apply_filters('em_bookings_has_booking', false, $this); } /** * Get bookings that match the array of arguments passed. * @return array * @static */ function get( $args = array(), $count = false ){ global $wpdb,$current_user; $bookings_table = EM_BOOKINGS_TABLE; $events_table = EM_EVENTS_TABLE; $locations_table = EM_LOCATIONS_TABLE; //Quick version, we can accept an array of IDs, which is easy to retrieve if( self::array_is_numeric($args) ){ //Array of numbers, assume they are event IDs to retreive //We can just get all the events here and return them $sql = " SELECT * FROM $bookings_table b LEFT JOIN $events_table e ON e.event_id=b.event_id WHERE booking_id".implode(" OR booking_id=", $args); $results = $wpdb->get_results(apply_filters('em_bookings_get_sql',$sql),ARRAY_A); $bookings = array(); foreach($results as $result){ $bookings[] = new EM_Booking($result); } return $bookings; //We return all the bookings matched as an EM_Booking array. } //We assume it's either an empty array or array of search arguments to merge with defaults $args = self::get_default_search($args); $limit = ( $args['limit'] && is_numeric($args['limit'])) ? "LIMIT {$args['limit']}" : ''; $offset = ( $limit != "" && is_numeric($args['offset']) ) ? "OFFSET {$args['offset']}" : ''; //Get the default conditions $conditions = self::build_sql_conditions($args); //Put it all together $where = ( count($conditions) > 0 ) ? " WHERE " . implode ( " AND ", $conditions ):''; //Get ordering instructions $EM_Booking = new EM_Booking(); $accepted_fields = $EM_Booking->get_fields(true); $orderby = self::build_sql_orderby($args, $accepted_fields); //Now, build orderby sql $orderby_sql = ( count($orderby) > 0 ) ? 'ORDER BY '. implode(', ', $orderby) : ''; //Selector $selectors = ( $count ) ? 'COUNT(*)':'*'; //Create the SQL statement and execute $sql = " SELECT $selectors FROM $bookings_table LEFT JOIN $events_table ON {$events_table}.event_id={$bookings_table}.event_id LEFT JOIN $locations_table ON {$locations_table}.location_id={$events_table}.location_id $where $orderby_sql $limit $offset "; //If we're only counting results, return the number of results if( $count ){ return apply_filters('em_bookings_get_count', $wpdb->get_var($sql), $args); } $results = $wpdb->get_results( apply_filters('em_events_get_sql',$sql, $args), ARRAY_A); //If we want results directly in an array, why not have a shortcut here? if( $args['array'] == true ){ return $results; } //Make returned results EM_Booking objects $results = (is_array($results)) ? $results:array(); $bookings = array(); foreach ( $results as $booking ){ $bookings[] = new EM_Booking($booking); } $EM_Bookings = new EM_Bookings($bookings); return apply_filters('em_bookings_get', $EM_Bookings); } function count( $args = array() ){ return self::get($args, true); } //List of patients in the patient database, that a user can choose and go on to edit any previous treatment data, or add a new admission. function export_csv() { global $EM_Event; if($EM_Event->event_id != $this->event_id ){ $event = $this->get_event(); $event_name = $event->name; }else{ $event_name = $EM_Event->name; } // The name of the file on the user's pc $file_name = sanitize_title($event_name). "-bookings.csv"; header("Content-Type: application/octet-stream"); header("Content-Disposition: Attachment; filename=$file_name"); em_locate_template('templates/csv-event-bookings.php', true); exit(); } /* Overrides EM_Object method to apply a filter to result * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_conditions() */ function build_sql_conditions( $args = array() ){ $conditions = apply_filters( 'em_bookings_build_sql_conditions', parent::build_sql_conditions($args), $args ); if( is_numeric($args['status']) ){ $conditions['status'] = 'booking_status='.$args['status']; }elseif( is_array($args['status']) && count($args['status']) > 0 ){ $conditions['status'] = 'booking_status IN ('.implode(',',$args['status']).')'; }elseif( !is_array($args['status']) && preg_match('/^([0-9],?)+$/', $args['status']) ){ $conditions['status'] = 'booking_status IN ('.$args['status'].')'; } if( is_numeric($args['person']) && current_user_can('manage_others_bookings') ){ $conditions['person'] = EM_BOOKINGS_TABLE.'.person_id='.$args['person']; } return apply_filters('em_bookings_build_sql_conditions', $conditions, $args); } /* Overrides EM_Object method to apply a filter to result * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_orderby() */ function build_sql_orderby( $args, $accepted_fields, $default_order = 'ASC' ){ return apply_filters( 'em_bookings_build_sql_orderby', parent::build_sql_orderby($args, $accepted_fields, get_option('dbem_events_default_order')), $args, $accepted_fields, $default_order ); } /* * Adds custom Events search defaults * @param array $array * @return array * @uses EM_Object#get_default_search() */ function get_default_search( $array = array() ){ $defaults = array( 'status' => false, 'person' => true //to add later, search by person's bookings... ); if( true || is_admin() ){ //figure out default owning permissions if( !current_user_can('edit_others_events') ){ $defaults['owner'] = get_current_user_id(); }else{ $defaults['owner'] = false; } } return apply_filters('em_bookings_get_default_search', parent::get_default_search($defaults,$array), $array, $defaults); } //Iterator Implementation public function rewind(){ reset($this->bookings); } public function current(){ $var = current($this->bookings); return $var; } public function key(){ $var = key($this->bookings); return $var; } public function next(){ $var = next($this->bookings); return $var; } public function valid(){ $key = key($this->bookings); $var = ($key !== NULL && $key !== FALSE); return $var; } } ?>