Restaurant Reservations - Version 2.5.2

Version Description

(2022-03-16) = - Updated nonces. - Fixes for conflicts with date range exceptions and regular scheduling rules. - Fix for Send Email feature not working when accessed via the Details area. - Fix for times not showing on days that had no specified open/close times and when max reservations was being used. - Added a warning above the time picker when there are no time slots left for the chosen day. - Fixed incorrect totals issue in export. - Updated the layout of the PDF export to separate bookings by date. - Added Time column to CSV export.

Download this release

Release Info

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

Code changes from version 2.5.1 to 2.5.2

assets/js/admin.js CHANGED
@@ -121,7 +121,7 @@ jQuery(document).ready(function ($) {
121
  });
122
 
123
  // Register clicks on action links
124
- $( '#rtb-bookings-table tr .actions' ).click( function(e) {
125
 
126
  var target = $(e.target);
127
  var action = target.data( 'action' );
@@ -141,6 +141,7 @@ jQuery(document).ready(function ($) {
141
  rtb_trash_booking( target.data( 'id' ), cell );
142
 
143
  } else if ( target.data( 'action' ) == 'email') {
 
144
  rtb_toggle_email_modal( true, target.data( 'id'), target.data( 'email' ), target.data( 'name' ) );
145
 
146
  } else if ( target.data( 'action' ) == 'ban') {
121
  });
122
 
123
  // Register clicks on action links
124
+ $( document ).on('click', '#rtb-bookings-table tr .actions, #rtb-details-modal .actions', function(e) {
125
 
126
  var target = $(e.target);
127
  var action = target.data( 'action' );
141
  rtb_trash_booking( target.data( 'id' ), cell );
142
 
143
  } else if ( target.data( 'action' ) == 'email') {
144
+ rtb_toggle_details_modal(false);
145
  rtb_toggle_email_modal( true, target.data( 'id'), target.data( 'email' ), target.data( 'name' ) );
146
 
147
  } else if ( target.data( 'action' ) == 'ban') {
assets/js/booking-form.js CHANGED
@@ -257,14 +257,40 @@ jQuery(document).ready(function ($) {
257
 
258
  var data = jQuery.param( params );
259
  jQuery.post( ajaxurl, data, function( response ) {
 
260
  if ( ! response ) {
 
261
  rtb_booking_form.timepicker.set( 'disable', true );
262
 
263
  return;
264
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
 
266
- var additional_valid_times = jQuery.parseJSON( response );
267
- var all_valid_times = valid_times.concat( additional_valid_times );
268
  rtb_booking_form.timepicker.set( 'disable', all_valid_times );
269
  });
270
  }
@@ -438,6 +464,7 @@ jQuery(document).ready(function ($) {
438
 
439
  if ( interval > 0 ) {
440
  hour--;
 
441
  interval = 60 - interval;
442
  }
443
 
@@ -811,6 +838,30 @@ function delayedPaymentHandler() {
811
  });
812
  }
813
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
814
  // Functions for the 'View Bookings' shortcode
815
  jQuery(document).ready(function ($) {
816
  jQuery('.rtb-view-bookings-form-date-selector').on('change', function() {
257
 
258
  var data = jQuery.param( params );
259
  jQuery.post( ajaxurl, data, function( response ) {
260
+
261
  if ( ! response ) {
262
+ displayFieldError( 'date', rtb_booking_form_js_localize.error['smthng-wrng-cntct-us'] );
263
  rtb_booking_form.timepicker.set( 'disable', true );
264
 
265
  return;
266
  }
267
+ else {
268
+ clearPrevFieldError( 'date' );
269
+ }
270
+
271
+ var additional_valid_times = jQuery.parseJSON( response );
272
+
273
+ // If today is all day open, only add one valid date/time rule
274
+ let outer_range = valid_times[0];
275
+ if(
276
+ additional_valid_times.length == 1
277
+ && additional_valid_times[0].from[0] == outer_range.from[0]
278
+ && additional_valid_times[0].from[1] == outer_range.from[1]
279
+ && additional_valid_times[0].to[0] == outer_range.to[0]
280
+ && additional_valid_times[0].to[1] == outer_range.to[1] ) {
281
+ var all_valid_times = [ additional_valid_times[0] ];
282
+ }
283
+ else {
284
+ var all_valid_times = valid_times.concat( additional_valid_times );
285
+ }
286
+
287
+ if( !Array.isArray( additional_valid_times ) || 1 > additional_valid_times.length ) {
288
+ displayFieldError( 'time', rtb_booking_form_js_localize.error['no-slots-available'] );
289
+ }
290
+ else {
291
+ clearPrevFieldError( 'time' );
292
+ }
293
 
 
 
294
  rtb_booking_form.timepicker.set( 'disable', all_valid_times );
295
  });
296
  }
464
 
465
  if ( interval > 0 ) {
466
  hour--;
467
+ // All day open does not work when date-time-range and current open time are exact same
468
  interval = 60 - interval;
469
  }
470
 
838
  });
839
  }
840
 
841
+ function displayFieldError( field, message ) {
842
+
843
+ const fieldSelector = '.'+field;
844
+ var fieldElm = jQuery('form.rtb-booking-form-form '+fieldSelector);
845
+
846
+ if( fieldElm.length ) {
847
+
848
+ clearPrevFieldError( field );
849
+
850
+ fieldElm.prepend(`
851
+ <div class="rtb-error">${message}</div>
852
+ `);
853
+ }
854
+ }
855
+
856
+ function clearPrevFieldError( field ) {
857
+ const fieldSelector = '.'+field;
858
+ var errorElms = jQuery('form.rtb-booking-form-form ' + fieldSelector + ' .rtb-error');
859
+
860
+ if( errorElms.length ) {
861
+ errorElms.each((idx, x) => x.remove());
862
+ }
863
+ }
864
+
865
  // Functions for the 'View Bookings' shortcode
866
  jQuery(document).ready(function ($) {
867
  jQuery('.rtb-view-bookings-form-date-selector').on('change', function() {
includes/AdminBookings.class.php CHANGED
@@ -191,7 +191,7 @@ class rtbAdminBookings {
191
  <input type="hidden" name="email" value="">
192
 
193
  <fieldset>
194
- <legend><?php _e( 'Send Email', 'retaurant-reservations' ); ?></legend>
195
 
196
  <div class="to">
197
  <label for="rtb-email-to"><?php _ex( 'To', 'Label next to the email address to which an email will be sent', 'restaurant-reservations' ); ?></label>
191
  <input type="hidden" name="email" value="">
192
 
193
  <fieldset>
194
+ <legend><?php _e( 'Send Email', 'restaurant-reservations' ); ?></legend>
195
 
196
  <div class="to">
197
  <label for="rtb-email-to"><?php _ex( 'To', 'Label next to the email address to which an email will be sent', 'restaurant-reservations' ); ?></label>
includes/Ajax.class.php CHANGED
@@ -240,6 +240,9 @@ if ( !class_exists( 'rtbAJAX' ) ) {
240
  $this->month = sanitize_text_field( $_POST['month'] );
241
  $this->day = sanitize_text_field( $_POST['day'] );
242
 
 
 
 
243
  $finalize_response = function ( $open_close_pair_list = array() ) {
244
 
245
  $valid_times = [];
@@ -249,9 +252,9 @@ if ( !class_exists( 'rtbAJAX' ) ) {
249
  foreach ( $open_close_pair_list as $pair ) {
250
 
251
  $valid_times[] = array(
252
- 'from' => $this->format_pickadate_time( $pair['from'] ),
253
- 'to' => $this->format_pickadate_time( $pair['to'] ),
254
- 'inverted' => true
255
  );
256
  }
257
  }
@@ -261,19 +264,64 @@ if ( !class_exists( 'rtbAJAX' ) ) {
261
  die();
262
  };
263
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  // Get opening/closing times for this particular day
265
  $hours = $this->get_opening_hours();
266
 
267
  // If the restaurant is closed that day
268
  // If Enable Max Reservation not set
269
- if ( ! $hours || ! $max_reservations_enabled ) {
270
- $finalize_response( $hours );
 
 
 
 
 
 
271
  }
272
 
273
  $location_slug = ! empty( $this->location ) ? $this->location->slug : false;
274
 
275
- $interval = $rtb_controller->settings->get_setting( 'time-interval' ) * 60;
276
-
277
  $dining_block_seconds = (int) $rtb_controller->settings->get_setting( 'rtb-dining-block-length' ) * 60;
278
 
279
  $min_party_size = (int) $rtb_controller->settings->get_setting( 'party-size-min' );
@@ -282,15 +330,7 @@ if ( !class_exists( 'rtbAJAX' ) ) {
282
 
283
  $max_people = (int) $rtb_controller->settings->get_setting( 'rtb-max-people-count', $location_slug );
284
 
285
- $all_possible_slots = [];
286
- foreach ( $hours as $pair ) {
287
- $all_possible_slots[] = $pair['from'];
288
- $next = $pair['from'] + $interval;
289
- while ( $next <= $pair['to'] ) {
290
- $all_possible_slots[] = $next;
291
- $next += $interval;
292
- }
293
- }
294
 
295
  // Get all current bookings sorted by date
296
  $args = array(
@@ -325,7 +365,7 @@ if ( !class_exists( 'rtbAJAX' ) ) {
325
  $all_bookings_by_slots = [];
326
  foreach ( $bookings as $key => $booking ) {
327
  // Convert booking date to seconds from UNIX
328
- $booking_time = strtotime($booking->date);
329
  if( ! array_key_exists( $booking_time, $all_bookings_by_slots ) ) {
330
  $all_bookings_by_slots[$booking_time] = [
331
  'total_bookings' => 0,
@@ -440,26 +480,9 @@ if ( !class_exists( 'rtbAJAX' ) ) {
440
  sort( $available_slots, SORT_NUMERIC );
441
 
442
  // consolidating timeslots to timeframes
443
- $timeframe = [];
444
- $available_slots_count = count( $available_slots );
445
- if( 0 < $available_slots_count ) {
446
 
447
- $current_pair = [ 'from' => $available_slots[ 0 ] ];
448
-
449
- for ( $i = 1; $i < $available_slots_count; $i++) {
450
- if( $available_slots[ $i ] - $available_slots[ $i - 1 ] !== $interval ) {
451
- $current_pair[ 'to' ] = $available_slots[ $i - 1 ];
452
- $timeframe[] = $current_pair;
453
-
454
- $current_pair = [ 'from' => $available_slots[ $i ] ];
455
- }
456
- }
457
-
458
- $current_pair[ 'to' ] = $available_slots[ $i - 1 ];
459
- $timeframe[] = $current_pair;
460
- }
461
-
462
- $finalize_response( $timeframe );
463
  }
464
 
465
  public function get_opening_hours() {
@@ -475,27 +498,30 @@ if ( !class_exists( 'rtbAJAX' ) ) {
475
  // Check if this date is an exception to the rules
476
  if ( $schedule_closed !== 'undefined' ) {
477
 
478
- $selected_date = ( new DateTime() )->setTime(0, 0, 2)->setDate( $this->year, $this->month, $this->day );
 
 
479
 
480
  foreach ( $schedule_closed as $ids => $closing ) {
481
  if( array_key_exists( 'date_range', $closing ) ) {
 
482
  $start = ! empty( $closing['date_range']['start'] )
483
  ? new DateTime( $closing['date_range']['start'], wp_timezone() )
484
  : new DateTime( 'now', wp_timezone() );
485
- $start.setTime(0, 0);
486
 
487
  $end = !empty( $closing['date_range']['end'] )
488
  ? new DateTime( $closing['date_range']['end'], wp_timezone() )
489
  : ( new DateTime( 'now', wp_timezone() ) )->add( new DateInterval( 'P10Y' ) );
490
- $end.setTime(23, 59, 58);
491
 
492
  if( $start < $selected_date && $selected_date < $end ) {
493
- $exception = $selected_date;
494
  }
495
  else {
496
  // Set anything to void this rule
497
- $exception = $selected_date;
498
- $exception.add( new DateInterval( 'P1Y' ) );
499
  }
500
  }
501
  else {
@@ -511,14 +537,20 @@ if ( !class_exists( 'rtbAJAX' ) ) {
511
 
512
  if ( $closing['time']['start'] !== 'undefined' ) {
513
  $open_time = ( new DateTime( $exception->format( 'Y-m-d' ) . ' ' . $closing['time']['start'], wp_timezone() ) )->format( 'U' );
514
- } else {
515
- $open_time = ( new DateTime( $exception->format( 'Y-m-d' ), wp_timezone() ) )->format('U'); // Start of the day
 
 
 
516
  }
517
 
518
  if ( $closing['time']['end'] !== 'undefined' ) {
519
  $close_time = ( new DateTime( $exception->format( 'Y-m-d' ) . ' ' . $closing['time']['end'], wp_timezone() ) )->format( 'U' );
520
- } else {
521
- $close_time = ( new DateTime( $exception->format( 'Y-m-d' ) . ' 23:59:59', wp_timezone() ) )->format( 'U' ); // End of the day
 
 
 
522
  }
523
 
524
  $open_time = $this->get_earliest_time( $open_time );
@@ -540,40 +572,39 @@ if ( !class_exists( 'rtbAJAX' ) ) {
540
 
541
  // Get any rules which apply to this weekday
542
  $day_of_week = strtolower(
543
- date( 'l', strtotime( $this->year . '-' . $this->month . '-' . $this->day . ' 1:00:00' ) )
544
  );
545
 
 
 
 
 
546
  foreach ( $schedule_open as $opening ) {
547
 
548
  if ( $opening['weekdays'] !== 'undefined' ) {
549
 
550
  foreach ( $opening['weekdays'] as $weekday => $value ) {
551
-
552
- if ( $weekday == $day_of_week ) {
553
 
554
- // Closed all day
555
- if ( ! isset($opening['time']) || $opening['time'] == 'undefined' ) {
556
-
557
- return false;
558
- }
559
 
560
- if ( $opening['time']['start'] !== 'undefined' ) {
561
 
562
- $open_time = strtotime( $this->year . '-' . $this->month . '-' . $this->day . ' ' . $opening['time']['start'] );
563
  }
564
  else {
565
 
566
- $open_time = strtotime( $this->year . '-' . $this->month . '-' . $this->day );
 
567
  }
568
 
569
- if ( $opening['time']['end'] !== 'undefined' ) {
570
 
571
- $close_time = strtotime( $this->year . '-' . $this->month . '-' . $this->day . ' ' . $opening['time']['end'] );
572
  }
573
  else {
574
 
575
  // End of the day
576
- $close_time = strtotime( $this->year . '-' . $this->month . '-' . $this->day . ' 23:59:59' );
577
  }
578
 
579
  $open_time = $this->get_earliest_time( $open_time );
@@ -588,27 +619,23 @@ if ( !class_exists( 'rtbAJAX' ) ) {
588
  }
589
 
590
  // Pass any valid times located
591
- if ( sizeOf( $valid_times ) >= 1 ) {
592
-
593
- return $valid_times;
594
- }
595
-
596
- return false;
597
  }
598
 
599
  public function get_earliest_time( $open_time ) {
600
  global $rtb_controller;
601
 
602
  $interval = $rtb_controller->settings->get_setting( 'time-interval' ) * 60;
603
-
604
- $timezone = wp_timezone();
605
- $offset = $timezone->getOffset( new DateTime );
 
606
 
607
  // adjust open time with respect to the current time of the day for upcoming timeslots
608
- $current_time = time() + $offset;
609
 
610
  // Only make adjustments for current day selections
611
- if ( date( 'y-m-d', strtotime( "{$this->year}-{$this->month}-{$this->day}" ) ) !== date( 'y-m-d', $current_time) ) {
612
  return $open_time;
613
  }
614
 
@@ -622,12 +649,12 @@ if ( !class_exists( 'rtbAJAX' ) ) {
622
 
623
  // adjust the open time for the Late Bookings option
624
  if ( is_numeric($late_bookings) && $late_bookings % 1 === 0 ) {
625
- $time_calc = time() + $offset + $late_bookings * 60;
626
  while ($time_calc > $open_time) {
627
  $open_time = $open_time + $interval;
628
  }
629
  }
630
-
631
  return $open_time;
632
  }
633
 
@@ -658,7 +685,7 @@ if ( !class_exists( 'rtbAJAX' ) ) {
658
  $hours = $this->get_opening_hours();
659
 
660
  // If the restaurant is closed that day, return false
661
- if ( ! $hours ) { die(); }
662
 
663
  // If no time is selected, return false
664
  if ( ! $this->time ) { die(); }
@@ -691,7 +718,9 @@ if ( !class_exists( 'rtbAJAX' ) ) {
691
  // Get all current bookings sorted by date
692
  $bookings = $query->get_bookings();
693
 
694
- $selected_date_time = strtotime($this->year . '-' . $this->month . '-' . $this->day . ' ' . $this->time);
 
 
695
  $selected_date_time_start = $selected_date_time - $dining_block_seconds;
696
  $selected_date_time_end = $selected_date_time + $dining_block_seconds;
697
  $party_sizes = [];
@@ -706,7 +735,7 @@ if ( !class_exists( 'rtbAJAX' ) ) {
706
  foreach ( $bookings as $key => $booking ) {
707
 
708
  // Convert booking date to seconds from UNIX
709
- $booking_time = strtotime($booking->date);
710
 
711
  // Ignore bookings outside of our time range
712
  if ($booking_time < $selected_date_time_start or $booking_time > $selected_date_time_end) { continue; }
@@ -764,7 +793,7 @@ if ( !class_exists( 'rtbAJAX' ) ) {
764
 
765
  if ( ! isset( $this->year ) or ! isset( $this->month ) or ! isset( $this->day ) or ! isset( $this->time ) ) { return false; }
766
 
767
- $datetime = strtotime( $this->year . '-' . $this->month . '-' . $this->day . ' ' . $this->time );
768
 
769
  $valid_tables = rtb_get_valid_tables( $datetime );
770
 
@@ -913,7 +942,8 @@ if ( !class_exists( 'rtbAJAX' ) ) {
913
  }
914
 
915
  public function format_pickadate_time( $time ) {
916
- return array( date( 'G', $time ), date( 'i', $time ) );
 
917
  }
918
  }
919
  }
240
  $this->month = sanitize_text_field( $_POST['month'] );
241
  $this->day = sanitize_text_field( $_POST['day'] );
242
 
243
+ $interval = $rtb_controller->settings->get_setting( 'time-interval' ) * 60;
244
+
245
+ // Helper functions
246
  $finalize_response = function ( $open_close_pair_list = array() ) {
247
 
248
  $valid_times = [];
252
  foreach ( $open_close_pair_list as $pair ) {
253
 
254
  $valid_times[] = array(
255
+ 'from' => $this->format_pickadate_time( $pair['from'] ),
256
+ 'to' => $this->format_pickadate_time( $pair['to'] ),
257
+ 'inverted' => true
258
  );
259
  }
260
  }
264
  die();
265
  };
266
 
267
+ $all_slots_for = function( $pairs ) use( $interval ) {
268
+ $all_possible_slots = [];
269
+
270
+ if( !is_array( $pairs ) ) return $pairs;
271
+
272
+ foreach ( $pairs as $pair ) {
273
+ $all_possible_slots[] = $pair['from'];
274
+ $next = $pair['from'] + $interval;
275
+ while ( $next <= $pair['to'] ) {
276
+ $all_possible_slots[] = $next;
277
+ $next += $interval;
278
+ }
279
+ }
280
+
281
+ return $all_possible_slots;
282
+ };
283
+
284
+ $consolidating_timeslots_to_timeframes = function( $slots ) use( $interval ) {
285
+ $timeframe = [];
286
+
287
+ $slots_count = count( $slots );
288
+ if( 0 < $slots_count ) {
289
+
290
+ $current_pair = [ 'from' => $slots[ 0 ] ];
291
+
292
+ for ( $i = 1; $i < $slots_count; $i++) {
293
+ if( $slots[ $i ] - $slots[ $i - 1 ] !== $interval ) {
294
+ $current_pair[ 'to' ] = $slots[ $i - 1 ];
295
+ $timeframe[] = $current_pair;
296
+
297
+ $current_pair = [ 'from' => $slots[ $i ] ];
298
+ }
299
+ }
300
+
301
+ $current_pair[ 'to' ] = $slots[ $i - 1 ];
302
+ $timeframe[] = $current_pair;
303
+ }
304
+
305
+ return $timeframe;
306
+ };
307
+
308
  // Get opening/closing times for this particular day
309
  $hours = $this->get_opening_hours();
310
 
311
  // If the restaurant is closed that day
312
  // If Enable Max Reservation not set
313
+ if ( 1 > count( $hours ) || ! $max_reservations_enabled ) {
314
+ $slots = $all_slots_for( $hours );
315
+
316
+ sort( $slots, SORT_NUMERIC );
317
+
318
+ $timeframes = $consolidating_timeslots_to_timeframes( $slots );
319
+
320
+ $finalize_response( $timeframes );
321
  }
322
 
323
  $location_slug = ! empty( $this->location ) ? $this->location->slug : false;
324
 
 
 
325
  $dining_block_seconds = (int) $rtb_controller->settings->get_setting( 'rtb-dining-block-length' ) * 60;
326
 
327
  $min_party_size = (int) $rtb_controller->settings->get_setting( 'party-size-min' );
330
 
331
  $max_people = (int) $rtb_controller->settings->get_setting( 'rtb-max-people-count', $location_slug );
332
 
333
+ $all_possible_slots = $all_slots_for( $hours );
 
 
 
 
 
 
 
 
334
 
335
  // Get all current bookings sorted by date
336
  $args = array(
365
  $all_bookings_by_slots = [];
366
  foreach ( $bookings as $key => $booking ) {
367
  // Convert booking date to seconds from UNIX
368
+ $booking_time = ( new DateTime( $booking->date , wp_timezone() ) )->format( 'U' );
369
  if( ! array_key_exists( $booking_time, $all_bookings_by_slots ) ) {
370
  $all_bookings_by_slots[$booking_time] = [
371
  'total_bookings' => 0,
480
  sort( $available_slots, SORT_NUMERIC );
481
 
482
  // consolidating timeslots to timeframes
483
+ $timeframes = $consolidating_timeslots_to_timeframes( $available_slots );
 
 
484
 
485
+ $finalize_response( $timeframes );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
486
  }
487
 
488
  public function get_opening_hours() {
498
  // Check if this date is an exception to the rules
499
  if ( $schedule_closed !== 'undefined' ) {
500
 
501
+ $selected_date = ( new DateTime('now', wp_timezone() ) )
502
+ ->setTime(0, 0, 2)
503
+ ->setDate( $this->year, $this->month, $this->day );
504
 
505
  foreach ( $schedule_closed as $ids => $closing ) {
506
  if( array_key_exists( 'date_range', $closing ) ) {
507
+
508
  $start = ! empty( $closing['date_range']['start'] )
509
  ? new DateTime( $closing['date_range']['start'], wp_timezone() )
510
  : new DateTime( 'now', wp_timezone() );
511
+ $start->setTime(0, 0);
512
 
513
  $end = !empty( $closing['date_range']['end'] )
514
  ? new DateTime( $closing['date_range']['end'], wp_timezone() )
515
  : ( new DateTime( 'now', wp_timezone() ) )->add( new DateInterval( 'P10Y' ) );
516
+ $end->setTime(23, 59, 58);
517
 
518
  if( $start < $selected_date && $selected_date < $end ) {
519
+ $exception = clone $selected_date;
520
  }
521
  else {
522
  // Set anything to void this rule
523
+ $exception = clone $selected_date;
524
+ $exception->add( new DateInterval( 'P1Y' ) );
525
  }
526
  }
527
  else {
537
 
538
  if ( $closing['time']['start'] !== 'undefined' ) {
539
  $open_time = ( new DateTime( $exception->format( 'Y-m-d' ) . ' ' . $closing['time']['start'], wp_timezone() ) )->format( 'U' );
540
+ }
541
+ else {
542
+
543
+ // Start of the day
544
+ $open_time = ( new DateTime( $exception->format( 'Y-m-d' ), wp_timezone() ) )->format('U');
545
  }
546
 
547
  if ( $closing['time']['end'] !== 'undefined' ) {
548
  $close_time = ( new DateTime( $exception->format( 'Y-m-d' ) . ' ' . $closing['time']['end'], wp_timezone() ) )->format( 'U' );
549
+ }
550
+ else {
551
+
552
+ // End of the day
553
+ $close_time = ( new DateTime( $exception->format( 'Y-m-d' ) . ' 23:59:59', wp_timezone() ) )->format( 'U' );
554
  }
555
 
556
  $open_time = $this->get_earliest_time( $open_time );
572
 
573
  // Get any rules which apply to this weekday
574
  $day_of_week = strtolower(
575
+ ( new DateTime( $this->year . '-' . $this->month . '-' . $this->day . ' 1:00:00', wp_timezone() ) )->format( 'l' )
576
  );
577
 
578
+ $selected_date = ( new DateTime('now', wp_timezone() ) )
579
+ ->setTime(0, 0, 2)
580
+ ->setDate( $this->year, $this->month, $this->day );
581
+
582
  foreach ( $schedule_open as $opening ) {
583
 
584
  if ( $opening['weekdays'] !== 'undefined' ) {
585
 
586
  foreach ( $opening['weekdays'] as $weekday => $value ) {
 
 
587
 
588
+ if ( $weekday == $day_of_week ) {
 
 
 
 
589
 
590
+ if ( isset( $opening['time'] ) && $opening['time']['start'] !== 'undefined' ) {
591
 
592
+ $open_time = ( new DateTime( $selected_date->format( 'Y-m-d' ) .' '. $opening['time']['start'], wp_timezone() ) )->format( 'U' );
593
  }
594
  else {
595
 
596
+ // Start of the day
597
+ $open_time = ( new DateTime( $selected_date->format( 'Y-m-d' ), wp_timezone() ) )->format('U');
598
  }
599
 
600
+ if ( isset( $opening['time'] ) && $opening['time']['end'] !== 'undefined' ) {
601
 
602
+ $close_time = ( new DateTime( $selected_date->format( 'Y-m-d' ) .' '. $opening['time']['end'], wp_timezone() ) )->format( 'U' );
603
  }
604
  else {
605
 
606
  // End of the day
607
+ $close_time = ( new DateTime( $selected_date->format( 'Y-m-d' ) . ' 23:59:59', wp_timezone() ) )->format( 'U' );
608
  }
609
 
610
  $open_time = $this->get_earliest_time( $open_time );
619
  }
620
 
621
  // Pass any valid times located
622
+ return $valid_times;
 
 
 
 
 
623
  }
624
 
625
  public function get_earliest_time( $open_time ) {
626
  global $rtb_controller;
627
 
628
  $interval = $rtb_controller->settings->get_setting( 'time-interval' ) * 60;
629
+
630
+ $selected_date = ( new DateTime('now', wp_timezone() ) )
631
+ ->setTime(0, 0, 2)
632
+ ->setDate( $this->year, $this->month, $this->day );
633
 
634
  // adjust open time with respect to the current time of the day for upcoming timeslots
635
+ $current_time = ( new DateTime( 'now', wp_timezone() ) )->format( 'U' );
636
 
637
  // Only make adjustments for current day selections
638
+ if ( $selected_date->format('Y-m-d') !== ( new DateTime( 'today', wp_timezone() ) )->format('Y-m-d') ) {
639
  return $open_time;
640
  }
641
 
649
 
650
  // adjust the open time for the Late Bookings option
651
  if ( is_numeric($late_bookings) && $late_bookings % 1 === 0 ) {
652
+ $time_calc = ( new DateTime( 'now', wp_timezone() ) )->format( 'U' ) + ( $late_bookings * 60 );
653
  while ($time_calc > $open_time) {
654
  $open_time = $open_time + $interval;
655
  }
656
  }
657
+
658
  return $open_time;
659
  }
660
 
685
  $hours = $this->get_opening_hours();
686
 
687
  // If the restaurant is closed that day, return false
688
+ if ( 1 > count( $hours ) ) { die(); }
689
 
690
  // If no time is selected, return false
691
  if ( ! $this->time ) { die(); }
718
  // Get all current bookings sorted by date
719
  $bookings = $query->get_bookings();
720
 
721
+ $tmzn = wp_timezone();
722
+
723
+ $selected_date_time = ( new DateTime( $this->year . '-' . $this->month . '-' . $this->day . ' ' . $this->time, $tmzn ) )->format( 'U' );
724
  $selected_date_time_start = $selected_date_time - $dining_block_seconds;
725
  $selected_date_time_end = $selected_date_time + $dining_block_seconds;
726
  $party_sizes = [];
735
  foreach ( $bookings as $key => $booking ) {
736
 
737
  // Convert booking date to seconds from UNIX
738
+ $booking_time = ( new DateTime( $booking->date, $tmzn ) )->format( 'U' );
739
 
740
  // Ignore bookings outside of our time range
741
  if ($booking_time < $selected_date_time_start or $booking_time > $selected_date_time_end) { continue; }
793
 
794
  if ( ! isset( $this->year ) or ! isset( $this->month ) or ! isset( $this->day ) or ! isset( $this->time ) ) { return false; }
795
 
796
+ $datetime = ( new DateTime( $this->year . '-' . $this->month . '-' . $this->day . ' ' . $this->time, wp_timezone() ) )->format( 'U' );
797
 
798
  $valid_tables = rtb_get_valid_tables( $datetime );
799
 
942
  }
943
 
944
  public function format_pickadate_time( $time ) {
945
+ $obj = ( new DateTime('now' ) )->setTimestamp( $time )->setTimezone( wp_timezone() );
946
+ return array( $obj->format( 'G' ), $obj->format( 'i' ) );
947
  }
948
  }
949
  }
includes/Booking.class.php CHANGED
@@ -385,7 +385,7 @@ class rtbBooking {
385
  ) {
386
 
387
  /**
388
- * We are checking the booking againt exceptions whihc consists blacklist and whitelist rules
389
  * - Any rule without time is a blacklist entry
390
  * - Any rule with time is a modified white entry
391
  * Thus consider the request as legit by default and terminate the loop when we hit first
@@ -499,7 +499,7 @@ class rtbBooking {
499
 
500
  // Too early
501
  if ( !empty( $rule['time']['start'] ) ) {
502
- $rule_start_time = new DateTime( $request->format( 'Y-m-d' ) . ' ' . $rule['time']['start'] );
503
  if ( $rule_start_time->format( 'U' ) <= $request->format( 'U' ) ) {
504
  $too_early = false;
505
  }
@@ -507,7 +507,7 @@ class rtbBooking {
507
 
508
  // Too late
509
  if ( !empty( $rule['time']['end'] ) ) {
510
- $rule_end_time = new DateTime( $request->format( 'Y-m-d' ) . ' ' . $rule['time']['end'] );
511
  if ( $rule_end_time->format( 'U' ) >= $request->format( 'U' ) ) {
512
  $too_late = false;
513
  }
@@ -908,8 +908,9 @@ class rtbBooking {
908
 
909
  $dining_block_seconds = (int) $rtb_controller->settings->get_setting( 'rtb-dining-block-length' ) * 60 - 1; // Take 1 second off, to avoid bookings that start or end exactly at the beginning of a booking block
910
 
911
- $after_time = strtotime($this->date) - $dining_block_seconds - (3600 * get_option( 'gmt_offset' ) );
912
- $before_time = strtotime($this->date) + $dining_block_seconds - (3600 * get_option( 'gmt_offset' ) );
 
913
 
914
  $args = array(
915
  'posts_per_page' => -1,
@@ -939,12 +940,14 @@ class rtbBooking {
939
  $query = new rtbQuery( $args );
940
  $query->prepare_args();
941
 
 
 
942
  $times = array();
943
  foreach ( $query->get_bookings() as $booking ) {
944
 
945
  if ( isset( $this->ID ) and $booking->ID == $this->ID ) { continue; }
946
 
947
- $times[] = strtotime( $booking->date );
948
  }
949
 
950
  sort( $times );
@@ -986,8 +989,9 @@ class rtbBooking {
986
 
987
  $dining_block_seconds = (int) $rtb_controller->settings->get_setting( 'rtb-dining-block-length' ) * 60 - 1; // Take 1 second off, to avoid bookings that start or end exactly at the beginning of a booking block
988
 
989
- $after_time = strtotime($this->date) - $dining_block_seconds - (3600 * get_option( 'gmt_offset' ) );
990
- $before_time = strtotime($this->date) + $dining_block_seconds - (3600 * get_option( 'gmt_offset' ) );
 
991
 
992
  $args = array(
993
  'posts_per_page' => -1,
@@ -1016,12 +1020,13 @@ class rtbBooking {
1016
  require_once( RTB_PLUGIN_DIR . '/includes/Query.class.php' );
1017
  $query = new rtbQuery( $args );
1018
 
 
1019
  $times = array();
1020
  foreach ( $query->get_bookings() as $booking ) {
1021
 
1022
  if ( isset( $this->ID ) and $booking->ID == $this->ID ) { continue; }
1023
 
1024
- $booking_time = strtotime( $booking->date );
1025
  if ( isset( $times[$booking_time] ) ) { $times[$booking_time] += intval( $booking->party ); }
1026
  else { $times[$booking_time] = (int) $booking->party; }
1027
  }
@@ -1117,7 +1122,8 @@ class rtbBooking {
1117
  // Get any rules which apply to this weekday
1118
  if ( $deposit_applicable != 'undefined' ) {
1119
 
1120
- $date_object = new DateTime( $this->date );
 
1121
 
1122
  $time = $date_object->format( 'U' );
1123
 
@@ -1139,20 +1145,20 @@ class rtbBooking {
1139
 
1140
  if ( $applicable['time']['start'] !== 'undefined' ) {
1141
 
1142
- $applicable_start_time = strtotime( $date_object->format( 'Y-m-d' ) . ' ' . $applicable['time']['start'] );
1143
  }
1144
  else {
1145
 
1146
- $applicable_start_time = strtotime( $date_object->format( 'Y-m-d' ) );
1147
  }
1148
 
1149
  if ( $applicable['time']['end'] !== 'undefined' ) {
1150
 
1151
- $applicable_end_time = strtotime( $date_object->format( 'Y-m-d' ) . ' ' . $applicable['time']['end'] );
1152
  }
1153
  else {
1154
  // End of the day
1155
- $applicable_end_time = strtotime( $date_object->format( 'Y-m-d' ) . ' 23:59:59' );
1156
  }
1157
 
1158
  if ( $time > $applicable_start_time and $time < $applicable_end_time ) {
@@ -1183,8 +1189,9 @@ class rtbBooking {
1183
 
1184
  $dining_block_seconds = (int) $rtb_controller->settings->get_setting( 'rtb-dining-block-length' ) * 60 - 1; // Take 1 second off, to avoid bookings that start or end exactly at the beginning of a booking block
1185
 
1186
- $after_time = strtotime($this->date) - $dining_block_seconds - (3600 * get_option( 'gmt_offset' ) );
1187
- $before_time = strtotime($this->date) + $dining_block_seconds - (3600 * get_option( 'gmt_offset' ) );
 
1188
 
1189
  $args = array(
1190
  'posts_per_page' => -1,
@@ -1199,9 +1206,10 @@ class rtbBooking {
1199
  $query = new rtbQuery( $args );
1200
  $query->prepare_args();
1201
 
 
1202
  $times = array();
1203
  foreach ( $query->get_bookings() as $booking ) {
1204
- $times[] = strtotime( $booking->date );
1205
  }
1206
 
1207
  sort( $times );
@@ -1235,8 +1243,9 @@ class rtbBooking {
1235
 
1236
  $dining_block_seconds = (int) $rtb_controller->settings->get_setting( 'rtb-dining-block-length' ) * 60 - 1; // Take 1 second off, to avoid bookings that start or end exactly at the beginning of a booking block
1237
 
1238
- $after_time = strtotime($this->date) - $dining_block_seconds - (3600 * get_option( 'gmt_offset' ) );
1239
- $before_time = strtotime($this->date) + $dining_block_seconds - (3600 * get_option( 'gmt_offset' ) );
 
1240
 
1241
  $args = array(
1242
  'posts_per_page' => -1,
@@ -1250,9 +1259,10 @@ class rtbBooking {
1250
  require_once( RTB_PLUGIN_DIR . '/includes/Query.class.php' );
1251
  $query = new rtbQuery( $args );
1252
 
 
1253
  $times = array();
1254
  foreach ( $query->get_bookings() as $booking ) {
1255
- $booking_time = strtotime( $booking->date );
1256
  if ( isset( $times[$booking_time] ) ) { $times[$booking_time] += $booking->party; }
1257
  else { $times[$booking_time] = $booking->party; }
1258
  }
385
  ) {
386
 
387
  /**
388
+ * We are checking the booking againt exceptions which consists blacklist and whitelist rules
389
  * - Any rule without time is a blacklist entry
390
  * - Any rule with time is a modified white entry
391
  * Thus consider the request as legit by default and terminate the loop when we hit first
499
 
500
  // Too early
501
  if ( !empty( $rule['time']['start'] ) ) {
502
+ $rule_start_time = new DateTime( $request->format( 'Y-m-d' ) . ' ' . $rule['time']['start'], wp_timezone() );
503
  if ( $rule_start_time->format( 'U' ) <= $request->format( 'U' ) ) {
504
  $too_early = false;
505
  }
507
 
508
  // Too late
509
  if ( !empty( $rule['time']['end'] ) ) {
510
+ $rule_end_time = new DateTime( $request->format( 'Y-m-d' ) . ' ' . $rule['time']['end'], wp_timezone() );
511
  if ( $rule_end_time->format( 'U' ) >= $request->format( 'U' ) ) {
512
  $too_late = false;
513
  }
908
 
909
  $dining_block_seconds = (int) $rtb_controller->settings->get_setting( 'rtb-dining-block-length' ) * 60 - 1; // Take 1 second off, to avoid bookings that start or end exactly at the beginning of a booking block
910
 
911
+ $tmp = ( new DateTime( $this->date, wp_timezone() ) )->format( 'U' );
912
+ $after_time = $tmp - $dining_block_seconds;
913
+ $before_time = $tmp + $dining_block_seconds;
914
 
915
  $args = array(
916
  'posts_per_page' => -1,
940
  $query = new rtbQuery( $args );
941
  $query->prepare_args();
942
 
943
+ $tmzn = wp_timezone();
944
+
945
  $times = array();
946
  foreach ( $query->get_bookings() as $booking ) {
947
 
948
  if ( isset( $this->ID ) and $booking->ID == $this->ID ) { continue; }
949
 
950
+ $times[] = ( new DateTime( $booking->date, $tmzn ) )->format( 'U' );
951
  }
952
 
953
  sort( $times );
989
 
990
  $dining_block_seconds = (int) $rtb_controller->settings->get_setting( 'rtb-dining-block-length' ) * 60 - 1; // Take 1 second off, to avoid bookings that start or end exactly at the beginning of a booking block
991
 
992
+ $tmp = ( new DateTime( $this->date, wp_timezone() ) )->format( 'U' );
993
+ $after_time = $tmp - $dining_block_seconds;
994
+ $before_time = $tmp + $dining_block_seconds;
995
 
996
  $args = array(
997
  'posts_per_page' => -1,
1020
  require_once( RTB_PLUGIN_DIR . '/includes/Query.class.php' );
1021
  $query = new rtbQuery( $args );
1022
 
1023
+ $tmzn = wp_timezone();
1024
  $times = array();
1025
  foreach ( $query->get_bookings() as $booking ) {
1026
 
1027
  if ( isset( $this->ID ) and $booking->ID == $this->ID ) { continue; }
1028
 
1029
+ $booking_time = (new DateTime( $booking->date, $tmzn ) )->format( 'U' );
1030
  if ( isset( $times[$booking_time] ) ) { $times[$booking_time] += intval( $booking->party ); }
1031
  else { $times[$booking_time] = (int) $booking->party; }
1032
  }
1122
  // Get any rules which apply to this weekday
1123
  if ( $deposit_applicable != 'undefined' ) {
1124
 
1125
+ $tmzn = wp_timezone();
1126
+ $date_object = new DateTime( $this->date, $tmzn );
1127
 
1128
  $time = $date_object->format( 'U' );
1129
 
1145
 
1146
  if ( $applicable['time']['start'] !== 'undefined' ) {
1147
 
1148
+ $applicable_start_time = ( new DateTime( $date_object->format( 'Y-m-d' ) . ' ' . $applicable['time']['start'], $tmzn ) )->format( 'U' );
1149
  }
1150
  else {
1151
 
1152
+ $applicable_start_time = ( new DateTime( $date_object->format( 'Y-m-d' ), $tmzn ) )->format( 'U' );
1153
  }
1154
 
1155
  if ( $applicable['time']['end'] !== 'undefined' ) {
1156
 
1157
+ $applicable_end_time = ( new DateTime( $date_object->format( 'Y-m-d' ) . ' ' . $applicable['time']['end'], $tmzn ) )->format( 'U' );
1158
  }
1159
  else {
1160
  // End of the day
1161
+ $applicable_end_time = ( new DateTime( $date_object->format( 'Y-m-d' ) . ' 23:59:59', $tmzn ) )->format( 'U' );
1162
  }
1163
 
1164
  if ( $time > $applicable_start_time and $time < $applicable_end_time ) {
1189
 
1190
  $dining_block_seconds = (int) $rtb_controller->settings->get_setting( 'rtb-dining-block-length' ) * 60 - 1; // Take 1 second off, to avoid bookings that start or end exactly at the beginning of a booking block
1191
 
1192
+ $tmp = (new DateTime( $this->date, wp_timezone() ) )->format( 'U' );
1193
+ $after_time = $tmp - $dining_block_seconds;
1194
+ $before_time = $tmp + $dining_block_seconds;
1195
 
1196
  $args = array(
1197
  'posts_per_page' => -1,
1206
  $query = new rtbQuery( $args );
1207
  $query->prepare_args();
1208
 
1209
+ $tmzn = wp_timezone();
1210
  $times = array();
1211
  foreach ( $query->get_bookings() as $booking ) {
1212
+ $times[] = (new DateTime( $booking->date, $tmzn ) )->format( "U" );
1213
  }
1214
 
1215
  sort( $times );
1243
 
1244
  $dining_block_seconds = (int) $rtb_controller->settings->get_setting( 'rtb-dining-block-length' ) * 60 - 1; // Take 1 second off, to avoid bookings that start or end exactly at the beginning of a booking block
1245
 
1246
+ $tmp = (new DateTime( $this->date, wp_timezone() ) )->format( 'U' );
1247
+ $after_time = $tmp - $dining_block_seconds;
1248
+ $before_time = $tmp + $dining_block_seconds;
1249
 
1250
  $args = array(
1251
  'posts_per_page' => -1,
1259
  require_once( RTB_PLUGIN_DIR . '/includes/Query.class.php' );
1260
  $query = new rtbQuery( $args );
1261
 
1262
+ $tmzn = wp_timezone();
1263
  $times = array();
1264
  foreach ( $query->get_bookings() as $booking ) {
1265
+ $booking_time = ( new DateTime( $booking->date, $tmzn ) )->format( 'U' );
1266
  if ( isset( $times[$booking_time] ) ) { $times[$booking_time] += $booking->party; }
1267
  else { $times[$booking_time] = $booking->party; }
1268
  }
includes/Export.CSV.class.php CHANGED
@@ -67,15 +67,17 @@ class ebfrtbExportCSV extends ebfrtbExport {
67
  * @since 0.1
68
  */
69
  public function export() {
70
-
71
  global $rtb_controller;
 
72
  $date_format = $rtb_controller->settings->get_setting( 'ebfrtb-csv-date-format' );
 
73
 
74
  // Compile bookings arrayarray headers
75
  $arr = apply_filters( 'ebfrtb_export_csv_booking_headers', array(
76
  array(
77
  'ID' => __( 'Booking ID', 'restaurant-reservations' ),
78
  'date' => __( 'Date', 'restaurant-reservations' ),
 
79
  'name' => __( 'Name', 'restaurant-reservations' ),
80
  'party' => __( 'Party', 'restaurant-reservations' ),
81
  'email' => __( 'Email', 'restaurant-reservations' ),
@@ -86,17 +88,20 @@ class ebfrtbExportCSV extends ebfrtbExport {
86
  )
87
  ) );
88
 
 
 
89
  // Compile bookings array
90
  foreach( $this->bookings as $booking ) {
91
  $arr[] = apply_filters( 'ebfrtb_export_csv_booking', array(
92
  'ID' => $booking->ID,
93
- 'date' => date_i18n( $date_format, strtotime( $booking->date ) ),
 
94
  'name' => $booking->name,
95
  'party' => $booking->party,
96
  'email' => $booking->email,
97
  'phone' => $booking->phone,
98
  'message' => str_replace( array( "\r\n", "\n", "\r", '<br />', '<br>', '<br/>' ), ' ', $booking->message ),
99
- 'date_submission' => date_i18n( $date_format, $booking->date_submission ),
100
  'status' => $booking->post_status,
101
  ), $booking );
102
  }
67
  * @since 0.1
68
  */
69
  public function export() {
 
70
  global $rtb_controller;
71
+
72
  $date_format = $rtb_controller->settings->get_setting( 'ebfrtb-csv-date-format' );
73
+ $time_format = get_option( 'time_format' );
74
 
75
  // Compile bookings arrayarray headers
76
  $arr = apply_filters( 'ebfrtb_export_csv_booking_headers', array(
77
  array(
78
  'ID' => __( 'Booking ID', 'restaurant-reservations' ),
79
  'date' => __( 'Date', 'restaurant-reservations' ),
80
+ 'time' => __( 'Time', 'restaurant-reservations' ),
81
  'name' => __( 'Name', 'restaurant-reservations' ),
82
  'party' => __( 'Party', 'restaurant-reservations' ),
83
  'email' => __( 'Email', 'restaurant-reservations' ),
88
  )
89
  ) );
90
 
91
+ $tmzn = wp_timezone();
92
+
93
  // Compile bookings array
94
  foreach( $this->bookings as $booking ) {
95
  $arr[] = apply_filters( 'ebfrtb_export_csv_booking', array(
96
  'ID' => $booking->ID,
97
+ 'date' => date_i18n( $date_format, ( new DateTime( $booking->date, $tmzn ) )->format( 'U' ) ),
98
+ 'time' => date_i18n( $time_format, ( new DateTime( $booking->date, $tmzn ) )->format( 'U' ) ),
99
  'name' => $booking->name,
100
  'party' => $booking->party,
101
  'email' => $booking->email,
102
  'phone' => $booking->phone,
103
  'message' => str_replace( array( "\r\n", "\n", "\r", '<br />', '<br>', '<br/>' ), ' ', $booking->message ),
104
+ 'date_submission' => date_i18n( $date_format . ' ' . $time_format, $booking->date_submission ),
105
  'status' => $booking->post_status,
106
  ), $booking );
107
  }
includes/Export.PDF.class.php CHANGED
@@ -44,6 +44,13 @@ class ebfrtbExportPDF extends ebfrtbExport {
44
  */
45
  public $query_args;
46
 
 
 
 
 
 
 
 
47
  /**
48
  * Insantiate the PDF export
49
  *
@@ -101,6 +108,8 @@ class ebfrtbExportPDF extends ebfrtbExport {
101
  */
102
  public function export() {
103
 
 
 
104
  if ( $this->lib === 'tcpdf' ) {
105
  $this->export_tcpdf();
106
 
@@ -326,5 +335,31 @@ class ebfrtbExportPDF extends ebfrtbExport {
326
  }
327
  }
328
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
  }
330
  } // endif
44
  */
45
  public $query_args;
46
 
47
+ /**
48
+ * The reservation and guest numbers by date
49
+ *
50
+ * @since 0.1
51
+ */
52
+ public $bookings_summary = array();
53
+
54
  /**
55
  * Insantiate the PDF export
56
  *
108
  */
109
  public function export() {
110
 
111
+ $this->create_bookings_summary();
112
+
113
  if ( $this->lib === 'tcpdf' ) {
114
  $this->export_tcpdf();
115
 
335
  }
336
  }
337
 
338
+ /**
339
+ * Calcualte the reservation and guests number by date
340
+ *
341
+ * @since 2.5.2
342
+ */
343
+ public function create_bookings_summary() {
344
+ global $rtb_controller;
345
+
346
+ foreach( $this->bookings as $booking ) {
347
+
348
+ $booking_date_idx = mysql2date( 'Y-m-d', $booking->date );
349
+
350
+ if ( ! isset( $this->bookings_summary[ $booking_date_idx ] ) ) {
351
+
352
+ $this->bookings_summary[ $booking_date_idx ] = array(
353
+ 'reservations' => 0,
354
+ 'seats' => 0
355
+ );
356
+ }
357
+
358
+ $this->bookings_summary[ $booking_date_idx ]['reservations']++;
359
+
360
+ $this->bookings_summary[ $booking_date_idx ]['seats'] += $booking->party;
361
+ }
362
+ }
363
+
364
  }
365
  } // endif
includes/Export.class.php CHANGED
@@ -110,7 +110,7 @@ abstract class ebfrtbExport {
110
  if ( $this->query_args['date_range'] === 'today' ) {
111
  return sprintf( _x( 'Bookings for %s', 'Subject for some export documents', 'restaurant-reservations' ), $date );
112
  } else {
113
- return sprintf( _x( "Bookings from %s", 'Subject for some export documents', 'restaurant-reservations' ), $date );
114
  }
115
  }
116
 
110
  if ( $this->query_args['date_range'] === 'today' ) {
111
  return sprintf( _x( 'Bookings for %s', 'Subject for some export documents', 'restaurant-reservations' ), $date );
112
  } else {
113
+ return sprintf( _x( "Bookings as of %s", 'Subject for some export documents', 'restaurant-reservations' ), $date );
114
  }
115
  }
116
 
includes/ExportHandler.class.php CHANGED
@@ -128,7 +128,12 @@ class rtbExportHandler {
128
  }
129
 
130
  // Prepare query args
131
- $query = new rtbQuery( array(), 'export' );
 
 
 
 
 
132
  $query->parse_request_args();
133
  $query->prepare_args();
134
  $query->args['posts_per_page'] = -1;
128
  }
129
 
130
  // Prepare query args
131
+ $args = array(
132
+ 'orderby' => 'date',
133
+ 'order' => 'ASC',
134
+ );
135
+
136
+ $query = new rtbQuery( $args, 'export' );
137
  $query->parse_request_args();
138
  $query->prepare_args();
139
  $query->args['posts_per_page'] = -1;
includes/Notifications.class.php CHANGED
@@ -143,7 +143,7 @@ class rtbNotifications {
143
  <?php $booking_object = new rtbBooking(); ?>
144
  <?php $booking_object->load_post( $booking ); ?>
145
  <tr>
146
- <td><?php echo date( 'H:i:s', strtotime( $booking_object->date ) ); ?></td>
147
  <td><?php echo $booking_object->party; ?></td>
148
  <td><?php echo $booking_object->name; ?></td>
149
  <td><?php echo $booking_object->email; ?></td>
@@ -243,6 +243,8 @@ class rtbNotifications {
243
  return;
244
  }
245
 
 
 
246
  $this->set_booking( $booking_post );
247
 
248
  $this->event( 'pending_to_confirmed' );
@@ -298,6 +300,22 @@ class rtbNotifications {
298
 
299
  }
300
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
  /**
302
  * Process notifications for an event
303
  * @since 0.0.1
143
  <?php $booking_object = new rtbBooking(); ?>
144
  <?php $booking_object->load_post( $booking ); ?>
145
  <tr>
146
+ <td><?php echo ( new DateTime( $booking_object->date ) )->format( 'H:i:s' ); ?></td>
147
  <td><?php echo $booking_object->party; ?></td>
148
  <td><?php echo $booking_object->name; ?></td>
149
  <td><?php echo $booking_object->email; ?></td>
243
  return;
244
  }
245
 
246
+ $this->clear_to_email( 'pending_to_confirmed' );
247
+
248
  $this->set_booking( $booking_post );
249
 
250
  $this->event( 'pending_to_confirmed' );
300
 
301
  }
302
 
303
+ /**
304
+ * Clear the 'to_email' property of the selected event notification
305
+ *
306
+ * @since 2.5.2
307
+ */
308
+ public function clear_to_email( $event ) {
309
+
310
+ foreach ( $this->notifications as $notification ) {
311
+
312
+ if ( $event == $notification->event ) {
313
+
314
+ $notification->to_email = '';
315
+ }
316
+ }
317
+ }
318
+
319
  /**
320
  * Process notifications for an event
321
  * @since 0.0.1
includes/PaymentGatewayStripe.class.php CHANGED
@@ -136,6 +136,8 @@ class rtbPaymentGatewayStripe implements rtbPaymentGateway {
136
  id='stripe-payment-form'
137
  data-booking_id='<?php echo esc_attr( $booking->ID ) ;?>'>
138
 
 
 
139
  <?php if( $SCA ) { ?>
140
 
141
  <div class='form-row'>
@@ -202,9 +204,24 @@ class rtbPaymentGatewayStripe implements rtbPaymentGateway {
202
  $booking_page = get_permalink();
203
  }
204
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  // load the stripe libraries
206
  require_once(RTB_PLUGIN_DIR . '/lib/stripe/init.php');
207
-
208
  // retrieve the token generated by stripe.js
209
  $token = sanitize_text_field( $_POST['stripeToken'] );
210
 
@@ -245,32 +262,30 @@ class rtbPaymentGatewayStripe implements rtbPaymentGateway {
245
  do_action( 'rtb_booking_paid', $booking );
246
 
247
  // redirect on successful payment
248
- $redirect = add_query_arg(
249
  array(
250
  'payment' => 'paid',
251
  'booking_id' => $booking_id
252
- ),
253
  $booking_page
254
  );
255
-
256
- } catch (Exception $e) {
257
-
258
- $booking->post_status = 'payment_failed';
259
- $booking->payment_failure_message = $e->getDeclineCode();
260
 
261
- $booking->insert_post_data();
 
 
 
262
 
263
  // redirect on failed payment
264
  $redirect = add_query_arg(
265
  array(
266
  'payment' => 'failed',
267
  'booking_id' => $booking_id,
268
- 'error_code' => urlencode( $e->getDeclineCode() )
269
  ),
270
  $booking_page
271
  );
272
  }
273
-
274
  // redirect back to our previous page with the added query variable
275
  wp_redirect($redirect); exit;
276
  }
@@ -354,7 +369,9 @@ class rtbPaymentGatewayStripe implements rtbPaymentGateway {
354
  'metadata' => $metadata
355
  ];
356
 
 
357
  if( $rtb_controller->settings->get_setting( 'rtb-stripe-hold' ) ) {
 
358
  $intentData['capture_method'] = 'manual';
359
  }
360
 
@@ -363,10 +380,6 @@ class rtbPaymentGatewayStripe implements rtbPaymentGateway {
363
  // Used this for verification of two step payment processing under SCA
364
  $booking->stripe_payment_intent_id = $intent->id;
365
 
366
- $booking->stripe_payment_hold_status = 'not-placed';
367
- if( $rtb_controller->settings->get_setting( 'rtb-stripe-hold' ) ) {
368
- $booking->stripe_payment_hold_status = 'hold-placed';
369
- }
370
  $booking->insert_post_data();
371
 
372
  $response(
136
  id='stripe-payment-form'
137
  data-booking_id='<?php echo esc_attr( $booking->ID ) ;?>'>
138
 
139
+ <?php wp_nonce_field( 'rtb-stripe-payment', 'nonce' ) ?>
140
+
141
  <?php if( $SCA ) { ?>
142
 
143
  <div class='form-row'>
204
  $booking_page = get_permalink();
205
  }
206
 
207
+ if ( !wp_verify_nonce( sanitize_text_field( $_POST['nonce'] ), 'rtb-stripe-payment' ) ) {
208
+ // Invalid request
209
+ $redirect = add_query_arg(
210
+ array(
211
+ 'payment' => 'failed',
212
+ 'booking_id' => $booking_id,
213
+ 'error_code' => urlencode( __( 'The request has been rejected because it does not appear to have come from this site.', 'restaurant-reservations' ) )
214
+ ),
215
+ $booking_page
216
+ );
217
+
218
+ // redirect back to our previous page with the added query variable
219
+ wp_redirect($redirect); exit;
220
+ }
221
+
222
  // load the stripe libraries
223
  require_once(RTB_PLUGIN_DIR . '/lib/stripe/init.php');
224
+
225
  // retrieve the token generated by stripe.js
226
  $token = sanitize_text_field( $_POST['stripeToken'] );
227
 
262
  do_action( 'rtb_booking_paid', $booking );
263
 
264
  // redirect on successful payment
265
+ $redirect = add_query_arg(
266
  array(
267
  'payment' => 'paid',
268
  'booking_id' => $booking_id
269
+ ),
270
  $booking_page
271
  );
 
 
 
 
 
272
 
273
+ }
274
+ catch ( Exception $ex ) {
275
+
276
+ $booking->payment_failed( $ex->getMessage() );
277
 
278
  // redirect on failed payment
279
  $redirect = add_query_arg(
280
  array(
281
  'payment' => 'failed',
282
  'booking_id' => $booking_id,
283
+ 'error_code' => urlencode( $ex->getMessage() )
284
  ),
285
  $booking_page
286
  );
287
  }
288
+
289
  // redirect back to our previous page with the added query variable
290
  wp_redirect($redirect); exit;
291
  }
369
  'metadata' => $metadata
370
  ];
371
 
372
+ $booking->stripe_payment_hold_status = 'not-placed';
373
  if( $rtb_controller->settings->get_setting( 'rtb-stripe-hold' ) ) {
374
+ $booking->stripe_payment_hold_status = 'hold-placed';
375
  $intentData['capture_method'] = 'manual';
376
  }
377
 
380
  // Used this for verification of two step payment processing under SCA
381
  $booking->stripe_payment_intent_id = $intent->id;
382
 
 
 
 
 
383
  $booking->insert_post_data();
384
 
385
  $response(
includes/Settings.class.php CHANGED
@@ -483,7 +483,7 @@ class rtbSettings {
483
  // Export defaults
484
  'ebfrtb-paper-size' => 'A4',
485
  'ebfrtb-pdf-lib' => 'mpdf',
486
- 'ebfrtb-csv-date-format' => get_option( 'date_format' ) . ' ' . get_option( 'time_format' ),
487
 
488
  'table-sections' => array(),
489
 
483
  // Export defaults
484
  'ebfrtb-paper-size' => 'A4',
485
  'ebfrtb-pdf-lib' => 'mpdf',
486
+ 'ebfrtb-csv-date-format' => get_option( 'date_format' ),
487
 
488
  'table-sections' => array(),
489
 
includes/template-functions.php CHANGED
@@ -416,7 +416,7 @@ function rtb_print_view_bookings_form( $args = array() ) {
416
  <?php else : ?><td><input type='checkbox' class='rtb-edit-view-booking' checked disabled /></td>
417
  <?php endif; ?>
418
  <?php } ?>
419
- <td><?php echo date('H:i:s', strtotime($booking_object->date)); ?></td>
420
  <td><?php echo $booking_object->party; ?></td>
421
  <td><?php echo $booking_object->name; ?></td>
422
  <td><?php echo $booking_object->email; ?></td>
@@ -575,16 +575,20 @@ function rtb_get_datepicker_rules( $location_slug = '' ) {
575
  if ( !empty( $rule['date'] ) ) {
576
  $date = new DateTime( $rule['date'], wp_timezone() );
577
  $formatted_rule = array( $date->format( 'Y' ), ( $date->format( 'n' ) - 1 ), $date->format( 'j' ) );
 
 
 
 
 
 
578
  }
579
  // Exception date ranges
580
- // If ranged expcetion has time portion, we do not want it to be disabled
581
- // and adding "inverted" will not work for range
582
- elseif ( !empty( $rule['date_range'] ) && empty( $rule['time'] ) ) {
583
  $start = !empty( $rule['date_range']['start'] )
584
  ? new DateTime( $rule['date_range']['start'] , wp_timezone() )
585
  : new DateTime( 'now', wp_timezone() );
586
- // If no end date set, disable for 1 year
587
- $end = !empty( $rule['date_range']['start'] )
588
  ? new DateTime( $rule['date_range']['end'], wp_timezone() )
589
  // Disable future dates for 10 years when no end date is given for exception
590
  : (new DateTime( 'now', wp_timezone() ) )->add( new DateInterval( 'P10Y' ) );
@@ -597,16 +601,16 @@ function rtb_get_datepicker_rules( $location_slug = '' ) {
597
  $end->format( 'Y' ), ( $end->format( 'n' ) - 1 ), $end->format( 'j' )
598
  )
599
  );
600
- }
601
 
602
- if( null != $formatted_rule ) {
603
- $disable_rules[] = empty( $rule['time'] )
604
  // Disable exception date that are closed all day
605
- ? $formatted_rule
606
  // Enable exception dates that have opening/closing times
607
- : array_merge( $formatted_rule, ['inverted'] );
608
  }
609
 
 
 
610
  }
611
  }
612
 
@@ -964,9 +968,9 @@ if ( ! function_exists( 'rtb_get_valid_tables') ) {
964
  function rtb_get_valid_tables( $datetime ) {
965
  global $rtb_controller;
966
 
967
- $request_time = is_int( $datetime) ? $datetime : strtotime( $datetime );
968
 
969
- if ( ! $request_time ) { return false; }
970
 
971
  $tables = $rtb_controller->settings->get_sorted_tables();
972
 
@@ -993,10 +997,12 @@ if ( ! function_exists( 'rtb_get_valid_tables') ) {
993
  $request_time_start = $request_time - $dining_block_seconds;
994
  $request_time_end = $request_time + $dining_block_seconds;
995
 
 
 
996
  foreach ( $bookings as $booking ) {
997
  if ( $booking->post_status == 'cancelled' ) { continue; }
998
 
999
- $booking_time = strtotime( $booking->date );
1000
 
1001
  if ( $booking_time < $request_time_start or $booking_time > $request_time_end ) { continue; }
1002
 
416
  <?php else : ?><td><input type='checkbox' class='rtb-edit-view-booking' checked disabled /></td>
417
  <?php endif; ?>
418
  <?php } ?>
419
+ <td><?php echo ( new DateTime( $booking_object->date, wp_timezone() ) )->format( 'H:i:s' ); ?></td>
420
  <td><?php echo $booking_object->party; ?></td>
421
  <td><?php echo $booking_object->name; ?></td>
422
  <td><?php echo $booking_object->email; ?></td>
575
  if ( !empty( $rule['date'] ) ) {
576
  $date = new DateTime( $rule['date'], wp_timezone() );
577
  $formatted_rule = array( $date->format( 'Y' ), ( $date->format( 'n' ) - 1 ), $date->format( 'j' ) );
578
+
579
+ $formatted_rule = empty( $rule['time'] )
580
+ // Disable exception date that are closed all day
581
+ ? $formatted_rule
582
+ // Enable exception dates that have opening/closing times
583
+ : array_merge( $formatted_rule, ['inverted'] );
584
  }
585
  // Exception date ranges
586
+ elseif ( !empty( $rule['date_range'] ) ) {
 
 
587
  $start = !empty( $rule['date_range']['start'] )
588
  ? new DateTime( $rule['date_range']['start'] , wp_timezone() )
589
  : new DateTime( 'now', wp_timezone() );
590
+
591
+ $end = !empty( $rule['date_range']['end'] )
592
  ? new DateTime( $rule['date_range']['end'], wp_timezone() )
593
  // Disable future dates for 10 years when no end date is given for exception
594
  : (new DateTime( 'now', wp_timezone() ) )->add( new DateInterval( 'P10Y' ) );
601
  $end->format( 'Y' ), ( $end->format( 'n' ) - 1 ), $end->format( 'j' )
602
  )
603
  );
 
604
 
605
+ $formatted_rule = empty( $rule['time'] )
 
606
  // Disable exception date that are closed all day
607
+ ? $formatted_rule
608
  // Enable exception dates that have opening/closing times
609
+ : array_merge( $formatted_rule, ['inverted' => true] );
610
  }
611
 
612
+ $disable_rules[] = $formatted_rule;
613
+
614
  }
615
  }
616
 
968
  function rtb_get_valid_tables( $datetime ) {
969
  global $rtb_controller;
970
 
971
+ $request_time = is_int( $datetime) ? $datetime : ( new DateTime( 'now', wp_timezone() ) )->setTimestamp( $datetime )->format( 'U' );
972
 
973
+ if ( ! $request_time ) { return array(); }
974
 
975
  $tables = $rtb_controller->settings->get_sorted_tables();
976
 
997
  $request_time_start = $request_time - $dining_block_seconds;
998
  $request_time_end = $request_time + $dining_block_seconds;
999
 
1000
+ $tmzn = wp_timezone();
1001
+
1002
  foreach ( $bookings as $booking ) {
1003
  if ( $booking->post_status == 'cancelled' ) { continue; }
1004
 
1005
+ $booking_time = ( new DateTime( $booking->date, $tmzn ) )->format( 'U' );
1006
 
1007
  if ( $booking_time < $request_time_start or $booking_time > $request_time_end ) { continue; }
1008
 
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: FiveStarPlugins
3
  Requires at Least: 4.4
4
  Tested Up To: 5.9
5
  Tags: reservation, reservations, restaurant reservations, reservation form, restaurant booking, restaurant reservation form, restaurant booking form, restaurant booking system, reservation system, online reservations, online restaurant booking, dinner reservations, restaurant form, gutenberg reservations, gutenberg restaurant reservations, gutenberg restaurant booking, mobile reservations, responsive reservations, table reservations, open table, book table, reserve table, easy reservations, simple reservations, quick restaurant reservations, custom reservation form, custom restaurant reservations
6
- Stable tag: 2.5.1
7
  License: GPLv3
8
  License URI:http://www.gnu.org/licenses/gpl-3.0.html
9
  Donate Link: https://www.etoilewebdesign.com/plugin-donations/
@@ -195,8 +195,19 @@ Find answers to even more questions in the [FAQ](http://doc.fivestarplugins.com/
195
  15. It also integrates with the Business Profile plugin to support booking for multiple locations.
196
  16. Access a short guide from your Plugins list to help you get started quickly.
197
 
 
198
  == Changelog ==
199
 
 
 
 
 
 
 
 
 
 
 
200
  = 2.5.1 (2022-03-07) =
201
  - Added the ability to set a date range for exceptions in the global booking schedule settings.
202
  - Fixed an issue in which the daily summary email was being sent to the email address specified for admin notifications and not the one specified for the daily summary email.
3
  Requires at Least: 4.4
4
  Tested Up To: 5.9
5
  Tags: reservation, reservations, restaurant reservations, reservation form, restaurant booking, restaurant reservation form, restaurant booking form, restaurant booking system, reservation system, online reservations, online restaurant booking, dinner reservations, restaurant form, gutenberg reservations, gutenberg restaurant reservations, gutenberg restaurant booking, mobile reservations, responsive reservations, table reservations, open table, book table, reserve table, easy reservations, simple reservations, quick restaurant reservations, custom reservation form, custom restaurant reservations
6
+ Stable tag: 2.5.2
7
  License: GPLv3
8
  License URI:http://www.gnu.org/licenses/gpl-3.0.html
9
  Donate Link: https://www.etoilewebdesign.com/plugin-donations/
195
  15. It also integrates with the Business Profile plugin to support booking for multiple locations.
196
  16. Access a short guide from your Plugins list to help you get started quickly.
197
 
198
+
199
  == Changelog ==
200
 
201
+ = 2.5.2 (2022-03-16) =
202
+ - Updated nonces.
203
+ - Fixes for conflicts with date range exceptions and regular scheduling rules.
204
+ - Fix for Send Email feature not working when accessed via the Details area.
205
+ - Fix for times not showing on days that had no specified open/close times and when max reservations was being used.
206
+ - Added a warning above the time picker when there are no time slots left for the chosen day.
207
+ - Fixed incorrect totals issue in export.
208
+ - Updated the layout of the PDF export to separate bookings by date.
209
+ - Added Time column to CSV export.
210
+
211
  = 2.5.1 (2022-03-07) =
212
  - Added the ability to set a date range for exceptions in the global booking schedule settings.
213
  - Fixed an issue in which the daily summary email was being sent to the email address specified for admin notifications and not the one specified for the daily summary email.
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.5.1
7
  * Author: FiveStarPlugins
8
  * Author URI: https://profiles.wordpress.org/fivestarplugins/
9
  * Text Domain: restaurant-reservations
@@ -39,7 +39,7 @@ class rtbInit {
39
  public function __construct() {
40
 
41
  // Common strings
42
- define( 'RTB_VERSION', '2.5.1' );
43
  define( 'RTB_PLUGIN_DIR', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
44
  define( 'RTB_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
45
  define( 'RTB_PLUGIN_FNAME', plugin_basename( __FILE__ ) );
@@ -525,7 +525,11 @@ class rtbInit {
525
  'guests' => __( 'guests', 'restaurant-reservations' ),
526
  'cancel' => __( 'Cancel', 'restaurant-reservations' ),
527
  'cancelled' => __( 'Cancelled', 'restaurant-reservations' ),
528
- 'deposit' => __( 'Deposit', 'restaurant-reservations' )
 
 
 
 
529
  )
530
  );
531
  }
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.5.2
7
  * Author: FiveStarPlugins
8
  * Author URI: https://profiles.wordpress.org/fivestarplugins/
9
  * Text Domain: restaurant-reservations
39
  public function __construct() {
40
 
41
  // Common strings
42
+ define( 'RTB_VERSION', '2.5.2' );
43
  define( 'RTB_PLUGIN_DIR', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
44
  define( 'RTB_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
45
  define( 'RTB_PLUGIN_FNAME', plugin_basename( __FILE__ ) );
525
  'guests' => __( 'guests', 'restaurant-reservations' ),
526
  'cancel' => __( 'Cancel', 'restaurant-reservations' ),
527
  'cancelled' => __( 'Cancelled', 'restaurant-reservations' ),
528
+ 'deposit' => __( 'Deposit', 'restaurant-reservations' ),
529
+ 'error' => array(
530
+ 'smthng-wrng-cntct-us' => __( 'Something went wrong. Please try agian and if issue persists, please contact us.', 'restaurant-reservations' ),
531
+ 'no-slots-available' => __( 'There are currently no times available for booking on your selected date.', 'restaurant-reservations' )
532
+ )
533
  )
534
  );
535
  }
templates/mpdf.php CHANGED
@@ -118,16 +118,23 @@
118
  <!-- Now the list of bookings begins -->
119
  <div class="bookings">
120
 
121
- <?php foreach( $bookings as $booking ) : ?>
122
- <?php $booking_date = apply_filters( 'get_the_date', mysql2date( get_option( 'date_format' ), $booking->date ) ); ?>
 
 
 
 
123
 
124
  <table class="booking-wrapper" cellspacing="0" cellpadding="0">
125
 
126
  <?php // Display the date if we've hit a new day ?>
127
  <?php // putting it under the table keeps it from being split in a page break ?>
128
- <?php if ( !isset( $current_date ) || $booking_date !== $current_date ) : ?>
129
- <tr class="date"><td><h1><?php echo esc_html( $booking_date ); ?></h1></td></tr>
130
- <?php $current_date = $booking_date; ?>
 
 
 
131
  <?php endif; ?>
132
 
133
  <tr>
118
  <!-- Now the list of bookings begins -->
119
  <div class="bookings">
120
 
121
+ <?php
122
+ global $rtb_controller;
123
+ foreach( $bookings as $booking ) :
124
+ $booking_date = apply_filters( 'get_the_date', mysql2date( $rtb_controller->settings->get_setting( 'ebfrtb-csv-date-format' ), $booking->date ) );
125
+ $summary_date_idx = mysql2date( 'Y-m-d', $booking->date );
126
+ ?>
127
 
128
  <table class="booking-wrapper" cellspacing="0" cellpadding="0">
129
 
130
  <?php // Display the date if we've hit a new day ?>
131
  <?php // putting it under the table keeps it from being split in a page break ?>
132
+ <?php if ( !isset( $current_date ) || $summary_date_idx !== $current_date ) : ?>
133
+ <tr class="date"><td>
134
+ <h1><?php echo esc_html( $booking_date ); ?></h1>
135
+ <h4><?php echo sprintf( __( ' %d reservation(s), %d guest(s)', 'restaurant-reservations' ), esc_html( $this->bookings_summary[ $summary_date_idx ]['reservations'] ), esc_html( $this->bookings_summary[ $summary_date_idx ]['seats'] ) ); ?></h4>
136
+ </td></tr>
137
+ <?php $current_date = $summary_date_idx; ?>
138
  <?php endif; ?>
139
 
140
  <tr>
templates/tcpdf.php CHANGED
@@ -28,13 +28,18 @@
28
 
29
  <div class="bookings">
30
 
31
- <?php foreach( $bookings as $booking ) : ?>
32
- <?php $booking_date = apply_filters( 'get_the_date', mysql2date( get_option( 'date_format' ), $booking->date ) ); ?>
 
 
 
 
33
 
34
  <?php // Display the date if we've hit a new day ?>
35
- <?php if ( !isset( $current_date ) || $booking_date !== $current_date ) : ?>
36
- <h1 class="date" style="vertical-align:middle;"><?php echo esc_html( $booking_date ); ?></h1>
37
- <?php $current_date = $booking_date; ?>
 
38
  <?php endif; ?>
39
 
40
  <table class="booking">
28
 
29
  <div class="bookings">
30
 
31
+ <?php
32
+ global $rtb_controller;
33
+ foreach( $bookings as $booking ) :
34
+ $booking_date = apply_filters( 'get_the_date', mysql2date( $rtb_controller->settings->get_setting( 'ebfrtb-csv-date-format' ), $booking->date ) );
35
+ $summary_date_idx = mysql2date( 'Y-m-d', $booking->date );
36
+ ?>
37
 
38
  <?php // Display the date if we've hit a new day ?>
39
+ <?php if ( !isset( $current_date ) || $summary_date_idx !== $current_date ) : ?>
40
+ <h1 class="date" style="vertical-align:middle;"><?php echo esc_html( $booking_date ); ?></h1>
41
+ <h4><?php echo sprintf( __( ' %d reservation(s), %d guest(s)', 'restaurant-reservations' ), esc_html( $this->bookings_summary[ $summary_date_idx ]['reservations'] ), esc_html( $this->bookings_summary[ $summary_date_idx ]['seats'] ) ); ?></h4>
42
+ <?php $current_date = $summary_date_idx; ?>
43
  <?php endif; ?>
44
 
45
  <table class="booking">