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)
- '. implode('
- ', $EM_Booking->get_errors()).'
';
}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;
}
}
?>