Restaurant Reservations - Version 2.1.20

Version Description

(2020-08-31) = - It now shows the section label for combined tables. - It now disallows bookings with the exact same information (date, time, party, name, email & phone), to prevent duplicate bookings when the page is refreshed. - Update to prevent overbooking (allowing more reservations than the set maximum) that was sometimes occurring if multiple people had the booking form open at the same time.

Download this release

Release Info

Developer Rustaurius
Plugin Icon 128x128 Restaurant Reservations
Version 2.1.20
Comparing to
See all releases

Code changes from version 2.1.19 to 2.1.20

includes/Ajax.class.php CHANGED
@@ -593,7 +593,9 @@ if ( !class_exists( 'rtbAJAX' ) ) {
593
 
594
  $combination = $this->get_combinations_chain( $tables, $valid_tables, $valid_table, $tables[ $valid_table ]->max_people, $this->party );
595
 
596
- if ( $combination ) { $possible_combinations[] = $combination; }
 
 
597
  }
598
 
599
  $return_tables = $this->format_tables( $possible_combinations );
@@ -678,15 +680,33 @@ if ( !class_exists( 'rtbAJAX' ) ) {
678
  $table_values['numbers'] .= ( strlen( $table_values['numbers'] ) ? ', ' : '' ) . $table->number;
679
  $table_values['min_people'] += $table->min_people;
680
  $table_values['max_people'] += $table->max_people;
 
 
681
  }
682
  }
683
 
684
- $formatted_tables[ $table_values['numbers'] ] = $table_values['numbers'] . ' - (min. ' . $table_values['min_people'] . '/max. ' . $table_values['max_people'] . ')';
 
 
685
  }
686
 
687
  return $formatted_tables;
688
  }
689
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
690
  public function format_pickadate_time( $time ) {
691
  return array( date( 'G', $time ), date( 'i', $time ) );
692
  }
593
 
594
  $combination = $this->get_combinations_chain( $tables, $valid_tables, $valid_table, $tables[ $valid_table ]->max_people, $this->party );
595
 
596
+ if ( $combination ) {
597
+ $possible_combinations[] = $combination;
598
+ }
599
  }
600
 
601
  $return_tables = $this->format_tables( $possible_combinations );
680
  $table_values['numbers'] .= ( strlen( $table_values['numbers'] ) ? ', ' : '' ) . $table->number;
681
  $table_values['min_people'] += $table->min_people;
682
  $table_values['max_people'] += $table->max_people;
683
+
684
+ if ( ! isset( $section_name ) ) { $section_name = $this->get_section_name( $table->section ); }
685
  }
686
  }
687
 
688
+ $formatted_tables[ $table_values['numbers'] ] = $table_values['numbers'] . ' - ' . $section_name . ' (min. ' . $table_values['min_people'] . '/max. ' . $table_values['max_people'] . ')';
689
+
690
+ unset( $section_name );
691
  }
692
 
693
  return $formatted_tables;
694
  }
695
 
696
+ public function get_section_name( $section_id ) {
697
+ global $rtb_controller;
698
+
699
+ $sections = json_decode( html_entity_decode( $rtb_controller->settings->get_setting( 'rtb-table-sections' ) ) ); update_option("EWD_Debugging", print_r( $sections, true ) );
700
+ $sections = is_array( $sections ) ? $sections : array();
701
+
702
+ foreach ( $sections as $section ) {
703
+
704
+ if ( $section->section_id == $section_id ) { return $section->name; }
705
+ }
706
+
707
+ return false;
708
+ }
709
+
710
  public function format_pickadate_time( $time ) {
711
  return array( date( 'G', $time ), date( 'i', $time ) );
712
  }
includes/Booking.class.php CHANGED
@@ -567,7 +567,7 @@ class rtbBooking {
567
  $this->validation_errors[] = array(
568
  'field' => 'date',
569
  'post_variable' => $ip,
570
- 'message' => __( 'Your booking has been rejected. Please call us if you would like to make a booking.', 'restaurant-reservations' ),
571
  );
572
  } elseif ( empty( $this->ip ) ) {
573
  $this->ip = sanitize_text_field( $ip );
@@ -575,6 +575,33 @@ class rtbBooking {
575
  } elseif ( empty( $this->ip ) ) {
576
  $this->ip = sanitize_text_field( $_SERVER['REMOTE_ADDR'] );
577
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
578
 
579
  do_action( 'rtb_validate_booking_submission', $this );
580
 
@@ -710,6 +737,157 @@ class rtbBooking {
710
  return $this->table == array_intersect( $this->table, $valid_tables );
711
  }
712
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
713
  /**
714
  * Check whether the number of reservations occurring at the same time is below the threshold
715
  * where reservations get automatically confirmed
@@ -722,7 +900,7 @@ class rtbBooking {
722
  $max_reservations_setting = $rtb_controller->settings->get_setting( 'auto-confirm-max-reservations' );
723
  $max_reservations = substr( $max_reservations_setting, 0, strpos( $max_reservations_setting, '_' ) );
724
 
725
- if ($max_reservations == 'undefined' or $max_reservations <= 1) { return false; }
726
 
727
  $dining_block_setting = $rtb_controller->settings->get_setting( 'rtb-dining-block-length' );
728
  $dining_block = substr( $dining_block_setting, 0, strpos( $dining_block_setting, '_' ) );
@@ -776,7 +954,7 @@ class rtbBooking {
776
  $max_seats_setting = $rtb_controller->settings->get_setting( 'auto-confirm-max-seats' );
777
  $max_seats = substr( $max_seats_setting, 0, strpos( $max_seats_setting, '_' ) );
778
 
779
- if ($max_seats == 'undefined' or $max_seats <= 1 or $this->party >= $max_seats) { return false; }
780
 
781
  $dining_block_setting = $rtb_controller->settings->get_setting( 'rtb-dining-block-length' );
782
  $dining_block = substr( $dining_block_setting, 0, strpos( $dining_block_setting, '_' ) );
567
  $this->validation_errors[] = array(
568
  'field' => 'date',
569
  'post_variable' => $ip,
570
+ 'message' => __( 'Your booking has been rejected. Please call us if you would like to make a booking.', 'restaurant-reservations' ),
571
  );
572
  } elseif ( empty( $this->ip ) ) {
573
  $this->ip = sanitize_text_field( $ip );
575
  } elseif ( empty( $this->ip ) ) {
576
  $this->ip = sanitize_text_field( $_SERVER['REMOTE_ADDR'] );
577
  }
578
+
579
+ // Check to make sure that the maximum number of reservations has not already been made
580
+ if ( ! $this->is_under_max_reservations() ){
581
+ $this->validation_errors[] = array(
582
+ 'field' => 'time',
583
+ 'error_msg' => 'maximum reservations exceeded',
584
+ 'message' => __( 'The maximum number of reservations for that timeslot has been reached. Please select a different timeslot.', 'restaurant-reservations' ),
585
+ );
586
+ }
587
+
588
+ // Check to make sure that the maximum number of seats has not already been made
589
+ if ( ! $this->is_under_max_seats() ){
590
+ $this->validation_errors[] = array(
591
+ 'field' => 'time',
592
+ 'error_msg' => 'maximum seats exceeded',
593
+ 'message' => __( 'With your party, the maximum number of seats for that timeslot would be exceeded. Please select a different timeslot or reduce your party size.', 'restaurant-reservations' ),
594
+ );
595
+ }
596
+
597
+ // Check if there is a booking already made with the exact same information, to prevent double bookings on refresh
598
+ if ( $this->is_duplicate_booking() ){
599
+ $this->validation_errors[] = array(
600
+ 'field' => 'date',
601
+ 'error_msg' => 'duplicate booking',
602
+ 'message' => __( 'Your booking and personal information exactly matches another booking. If this was not caused by refreshing the page, please call us to make a booking.', 'restaurant-reservations' ),
603
+ );
604
+ }
605
 
606
  do_action( 'rtb_validate_booking_submission', $this );
607
 
737
  return $this->table == array_intersect( $this->table, $valid_tables );
738
  }
739
 
740
+ /**
741
+ * Check if this booking would put the restaurant over the maximum, if set
742
+ *
743
+ * @return bool
744
+ * @since 2.1.20
745
+ */
746
+ public function is_under_max_reservations() {
747
+ global $rtb_controller;
748
+
749
+ $max_reservations_enabled = $rtb_controller->settings->get_setting( 'rtb-enable-max-tables' );
750
+
751
+ if ( ! $max_reservations_enabled ) { return true; }
752
+
753
+ $max_reservations_setting = $rtb_controller->settings->get_setting( 'rtb-max-tables-count' );
754
+ $max_reservations = substr( $max_reservations_setting, 0, strpos( $max_reservations_setting, '_' ) );
755
+
756
+ if ($max_reservations == 'undefined' or ! $max_reservations ) { return true; }
757
+
758
+ $dining_block_setting = $rtb_controller->settings->get_setting( 'rtb-dining-block-length' );
759
+ $dining_block = substr( $dining_block_setting, 0, strpos( $dining_block_setting, '_' ) );
760
+ $dining_block_seconds = ( $dining_block * 60 - 1 ); // Take 1 second off, to avoid bookings that start or end exactly at the beginning of a booking block
761
+
762
+ $after_time = strtotime($this->date) - $dining_block_seconds - (3600 * get_option( 'gmt_offset' ) );
763
+ $before_time = strtotime($this->date) + $dining_block_seconds - (3600 * get_option( 'gmt_offset' ) );
764
+
765
+ $args = array(
766
+ 'posts_per_page' => -1,
767
+ 'date_query' => array(
768
+ 'before' => date( 'c', $before_time ),
769
+ 'after' => date( 'c', $after_time )
770
+ )
771
+ );
772
+
773
+ require_once( RTB_PLUGIN_DIR . '/includes/Query.class.php' );
774
+ $query = new rtbQuery( $args );
775
+ $query->prepare_args();
776
+
777
+ $times = array();
778
+ foreach ( $query->get_bookings() as $booking ) {
779
+ $times[] = strtotime( $booking->date );
780
+ }
781
+
782
+ sort( $times );
783
+
784
+ $accept_reservation = true;
785
+ $current_times = array();
786
+ foreach ( $times as $time ) {
787
+ $current_times[] = $time;
788
+
789
+ if ( reset( $current_times ) < ($time - $dining_block_seconds) ) { array_shift( $current_times ); }
790
+
791
+ // Check if we go above the max confirmation number
792
+ if ( sizeOf( $current_times ) + 1 > $max_reservations ) { $accept_reservation = false; break; }
793
+ }
794
+
795
+ return $accept_reservation;
796
+ }
797
+
798
+ /**
799
+ * Check if this booking would put the restaurant over the maximum number of people, if set
800
+ *
801
+ * @return bool
802
+ * @since 2.1.20
803
+ */
804
+ public function is_under_max_seats() {
805
+ global $rtb_controller;
806
+
807
+ $max_reservations_enabled = $rtb_controller->settings->get_setting( 'rtb-enable-max-tables' );
808
+
809
+ if ( ! $max_reservations_enabled ) { return true; }
810
+
811
+ $max_seats_setting = $rtb_controller->settings->get_setting( 'rtb-max-people-count' );
812
+ $max_seats = substr( $max_seats_setting, 0, strpos( $max_seats_setting, '_' ) );
813
+
814
+ if ( $max_seats == 'undefined' or ! $max_seats ) { return true; }
815
+ if ( $this->party > $max_seats ) { return false; }
816
+
817
+ $dining_block_setting = $rtb_controller->settings->get_setting( 'rtb-dining-block-length' );
818
+ $dining_block = substr( $dining_block_setting, 0, strpos( $dining_block_setting, '_' ) );
819
+ $dining_block_seconds = ( $dining_block * 60 - 1 ); // Take 1 second off, to avoid bookings that start or end exactly at the beginning of a booking block
820
+
821
+ $after_time = strtotime($this->date) - $dining_block_seconds - (3600 * get_option( 'gmt_offset' ) );
822
+ $before_time = strtotime($this->date) + $dining_block_seconds - (3600 * get_option( 'gmt_offset' ) );
823
+
824
+ $args = array(
825
+ 'posts_per_page' => -1,
826
+ 'date_query' => array(
827
+ 'before' => date( 'c', $before_time ),
828
+ 'after' => date( 'c', $after_time )
829
+ )
830
+ );
831
+
832
+ require_once( RTB_PLUGIN_DIR . '/includes/Query.class.php' );
833
+ $query = new rtbQuery( $args );
834
+
835
+ $times = array();
836
+ foreach ( $query->get_bookings() as $booking ) {
837
+ $booking_time = strtotime( $booking->date );
838
+ if ( isset( $times[$booking_time] ) ) { $times[$booking_time] += $booking->party; }
839
+ else { $times[$booking_time] = $booking->party; }
840
+ }
841
+
842
+ ksort( $times );
843
+
844
+ $accept_reservation = true;
845
+ $current_seats = array();
846
+ foreach ( $times as $time => $seats ) {
847
+ $current_seats[$time] = $seats;
848
+
849
+ reset( $current_seats );
850
+
851
+ if ( key ( $current_seats ) < $time - $dining_block_seconds ) { array_shift( $current_seats ); }
852
+
853
+ // Check if adding the current party puts us above the max confirmation number
854
+ if ( array_sum( $current_seats ) + $this->party > $max_seats ) { $accept_reservation = false; break; }
855
+ }
856
+
857
+ return $accept_reservation;
858
+
859
+ }
860
+
861
+ /**
862
+ * Check if the information in a booking exactly matches another booking
863
+ *
864
+ * @return bool
865
+ * @since 2.1.20
866
+ */
867
+ public function is_duplicate_booking() {
868
+ global $wpdb;
869
+
870
+ $booking_result = $wpdb->get_row( $wpdb->prepare(
871
+ "SELECT ID FROM $wpdb->posts WHERE post_type=%s AND post_date=%s AND post_title=%s",
872
+ RTB_BOOKING_POST_TYPE,
873
+ $this->date,
874
+ $this->name
875
+ ) );
876
+
877
+ if ( $booking_result ) {
878
+
879
+ $meta = get_post_meta( $booking_result->ID, 'rtb', true );
880
+ $meta = is_array( $meta ) ? $meta : array();
881
+
882
+ if ( $this->party = $meta['party'] and $this->email = $meta['email'] and $this->phone = $meta['phone'] ) {
883
+
884
+ return true;
885
+ }
886
+ }
887
+
888
+ return false;
889
+ }
890
+
891
  /**
892
  * Check whether the number of reservations occurring at the same time is below the threshold
893
  * where reservations get automatically confirmed
900
  $max_reservations_setting = $rtb_controller->settings->get_setting( 'auto-confirm-max-reservations' );
901
  $max_reservations = substr( $max_reservations_setting, 0, strpos( $max_reservations_setting, '_' ) );
902
 
903
+ if ( $max_reservations == 'undefined' or $max_reservations <= 1 ) { return false; }
904
 
905
  $dining_block_setting = $rtb_controller->settings->get_setting( 'rtb-dining-block-length' );
906
  $dining_block = substr( $dining_block_setting, 0, strpos( $dining_block_setting, '_' ) );
954
  $max_seats_setting = $rtb_controller->settings->get_setting( 'auto-confirm-max-seats' );
955
  $max_seats = substr( $max_seats_setting, 0, strpos( $max_seats_setting, '_' ) );
956
 
957
+ if ( $max_seats == 'undefined' or $max_seats <= 1 or $this->party >= $max_seats ) { return false; }
958
 
959
  $dining_block_setting = $rtb_controller->settings->get_setting( 'rtb-dining-block-length' );
960
  $dining_block = substr( $dining_block_setting, 0, strpos( $dining_block_setting, '_' ) );
includes/Settings.class.php CHANGED
@@ -1354,7 +1354,7 @@ If you were not the one to cancel this booking, please contact us.
1354
  array(
1355
  'id' => 'rtb-max-people-count',
1356
  'title' => __( 'Max People', 'restaurant-reservations' ),
1357
- 'description' => __( 'How many people, if enabled above, should be allowed to be present in the restaurant at the same time? Set dining block length setting above to change how long a meal typically lasts. Will be ignored if max reservations is set.', 'restaurant-reservations' ),
1358
  'min_value' => 1,
1359
  'max_value' => 100,
1360
  'increment' => 1
1354
  array(
1355
  'id' => 'rtb-max-people-count',
1356
  'title' => __( 'Max People', 'restaurant-reservations' ),
1357
+ 'description' => __( 'How many people, if enabled above, should be allowed to be present in the restaurant at the same time? Set dining block length setting above to change how long a meal typically lasts. May not work correctly if max reservations is set.', 'restaurant-reservations' ),
1358
  'min_value' => 1,
1359
  'max_value' => 100,
1360
  'increment' => 1
readme.txt CHANGED
@@ -196,6 +196,11 @@ Find answers to even more questions in the [FAQ](http://doc.fivestarplugins.com/
196
 
197
  == Changelog ==
198
 
 
 
 
 
 
199
  = 2.1.19 (2020-08-20) =
200
  - Fixed issue with booking edit panel that was making it so, if there was only one table available, it wouldn't save correctly if you tried to change the booking status.
201
  - Generated a new .pot file.
196
 
197
  == Changelog ==
198
 
199
+ = 2.1.20 (2020-08-31) =
200
+ - It now shows the section label for combined tables.
201
+ - It now disallows bookings with the exact same information (date, time, party, name, email & phone), to prevent duplicate bookings when the page is refreshed.
202
+ - Update to prevent overbooking (allowing more reservations than the set maximum) that was sometimes occurring if multiple people had the booking form open at the same time.
203
+
204
  = 2.1.19 (2020-08-20) =
205
  - Fixed issue with booking edit panel that was making it so, if there was only one table available, it wouldn't save correctly if you tried to change the booking status.
206
  - Generated a new .pot file.
restaurant-reservations.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Five Star Restaurant Reservations - WordPress Booking Plugin
4
  * Plugin URI: http://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/
5
  * Description: Restaurant reservations made easy. Accept bookings online. Quickly confirm or reject reservations, send email notifications, set booking times and more.
6
- * Version: 2.1.19
7
  * Author: FiveStarPlugins
8
  * Author URI: https://profiles.wordpress.org/fivestarplugins/
9
  * Text Domain: restaurant-reservations
3
  * Plugin Name: Five Star Restaurant Reservations - WordPress Booking Plugin
4
  * Plugin URI: http://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/
5
  * Description: Restaurant reservations made easy. Accept bookings online. Quickly confirm or reject reservations, send email notifications, set booking times and more.
6
+ * Version: 2.1.20
7
  * Author: FiveStarPlugins
8
  * Author URI: https://profiles.wordpress.org/fivestarplugins/
9
  * Text Domain: restaurant-reservations