Restaurant Reservations - Version 2.1.5

Version Description

(2020-05-28) = - New option to enable a maximum number of seats at one time in the premium section

Download this release

Release Info

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

Code changes from version 2.1.4 to 2.1.5

assets/js/booking-form.js CHANGED
@@ -161,6 +161,13 @@ jQuery(document).ready(function ($) {
161
rtb_booking_form.datepicker.on( {
162
close: function() {
163
rtb_booking_form.update_timepicker_range();
164
}
165
});
166
}
@@ -418,6 +425,47 @@ jQuery(document).ready(function ($) {
418
return start_time;
419
};
420
421
422
rtb_booking_form.init();
423
});
161
rtb_booking_form.datepicker.on( {
162
close: function() {
163
rtb_booking_form.update_timepicker_range();
164
+ rtb_booking_form.update_party_size_select();
165
+ }
166
+ });
167
+
168
+ rtb_booking_form.timepicker.on( {
169
+ close: function() {
170
+ rtb_booking_form.update_party_size_select();
171
}
172
});
173
}
425
return start_time;
426
};
427
428
+ rtb_booking_form.update_party_size_select = function() {
429
+ if ( rtb_pickadate.enable_max_reservations && rtb_pickadate.max_people ) {
430
+ var partySelect = $('#rtb-party'),
431
+ selected_date = new Date( rtb_booking_form.datepicker.get( 'select', 'yyyy/mm/dd' ) ),
432
+ selected_date_year = selected_date.getFullYear(),
433
+ selected_date_month = selected_date.getMonth(),
434
+ selected_date_date = selected_date.getDate(),
435
+ selected_time = rtb_booking_form.timepicker.get('value');
436
+
437
+ if ( ! selected_time ) { return; }
438
+
439
+ selected_date_month = ('0' + (selected_date_month + 1)).slice(-2);
440
+ selected_date_date = ('0' + selected_date_date).slice(-2);
441
+
442
+ //reset party size
443
+ partySelect.prop("selectedIndex", 0).change();
444
+
445
+ var data = 'year=' + selected_date_year + '&month=' + selected_date_month + '&day=' + selected_date_date + '&time=' + selected_time + '&action=rtb_get_available_party_size';
446
+ jQuery.post( ajaxurl, data, function( response ) {
447
+ if ( ! response ) {
448
+ return;
449
+ }
450
+
451
+ response = jQuery.parseJSON(response);
452
+
453
+ var available_spots = response.available_spots;
454
+
455
+ partySelect.prop('disabled', false);
456
+
457
+ partySelect.find('> option').each(function() {
458
+ var that = $(this);
459
+ if (this.value > available_spots) {
460
+ that.prop('disabled', true);
461
+ } else {
462
+ that.prop('disabled', false);
463
+ }
464
+ });
465
+ });
466
+ }
467
+ }
468
+
469
470
rtb_booking_form.init();
471
});
includes/Ajax.class.php CHANGED
@@ -2,405 +2,531 @@
2
if ( !defined( 'ABSPATH' ) ) exit;
3
4
if ( !class_exists( 'rtbAJAX' ) ) {
5
- /**
6
- * Class to handle AJAX date interactions for Restaurant Reservations
7
- *
8
- * @since 2.0.0
9
- */
10
- class rtbAJAX {
11
-
12
/**
13
- * The year of the booking date we're getting timeslots for
14
* @since 2.0.0
15
*/
16
- public $year;
17
18
- /**
19
- * The month of the booking date we're getting timeslots for
20
- * @since 2.0.0
21
- */
22
- public $month;
23
24
- /**
25
- * The day of the booking date we're getting timeslots for
26
- * @since 2.0.0
27
- */
28
- public $day;
29
30
- public function __construct() {
31
32
- add_action( 'wp_ajax_rtb_get_available_time_slots', array( $this, 'get_time_slots' ) );
33
- add_action( 'wp_ajax_nopriv_rtb_get_available_time_slots', array( $this, 'get_time_slots' ) );
34
35
- add_action( 'wp_ajax_rtb_find_reservations', array( $this, 'get_reservations' ) );
36
- add_action( 'wp_ajax_nopriv_rtb_find_reservations', array( $this, 'get_reservations' ) );
37
38
- add_action( 'wp_ajax_rtb_cancel_reservations', array( $this, 'cancel_reservation' ) );
39
- add_action( 'wp_ajax_nopriv_rtb_cancel_reservations', array( $this, 'cancel_reservation' ) );
40
- }
41
42
- /**
43
- * Get reservations that are associated with the email address that was sent
44
- * @since 2.1.0
45
- */
46
- public function get_reservations() {
47
- global $wpdb;
48
49
- $email = isset($_POST['booking_email']) ? sanitize_email( $_POST['booking_email'] ) : '';
50
51
- if ( ! $email ) {
52
- wp_send_json_error(
53
- array(
54
- 'error' => 'noemail',
55
- 'msg' => __( 'The email you entered is not valid.', 'restaurant-reservations' ),
56
- )
57
- );
58
}
59
60
- require_once( RTB_PLUGIN_DIR . '/includes/Booking.class.php' );
61
62
- $bookings = array();
63
- $booking_ids = $wpdb->get_results($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_key='rtb' AND meta_value LIKE %s", '%' . $email . '%'));
64
- foreach ( $booking_ids as $booking_id ) {
65
- $booking = new rtbBooking();
66
- if ( $booking->load_post( $booking_id->post_id ) ) {
67
- if ( ( $booking->post_status == 'pending' or $booking->post_status == 'confirmed' ) and time() < strtotime( $booking->date ) ) {
68
- $bookings[] = array(
69
- 'ID' => $booking->ID,
70
- 'email' => $booking->email,
71
- 'datetime' => $booking->format_date( $booking->date ),
72
- 'party' => $booking->party
73
- );
74
}
75
}
76
- }
77
78
- if ( ! empty($bookings) ) {
79
- wp_send_json_success(
80
- array(
81
- 'bookings' => $bookings
82
- )
83
- );
84
- }
85
- else {
86
- wp_send_json_error(
87
- array(
88
- 'error' => 'nobookings',
89
- 'msg' => __( 'No bookings were found for the email address you entered.', 'restaurant-reservations' ),
90
- )
91
- );
92
- }
93
94
- die();
95
- }
96
97
- /**
98
- * Cancel a reservation based on its ID, with the email address used for confirmation
99
- * @since 2.1.0
100
- */
101
- public function cancel_reservation( $non_ajax = true ) {
102
- global $rtb_controller;
103
104
- $booking_id = isset($_REQUEST['booking_id']) ? absint( $_REQUEST['booking_id'] ) : '';
105
- $booking_email = isset($_REQUEST['booking_email']) ? sanitize_email( $_REQUEST['booking_email'] ) : '';
106
107
- require_once( RTB_PLUGIN_DIR . '/includes/Booking.class.php' );
108
109
- $success = false;
110
111
- $booking = new rtbBooking();
112
- if ( $booking->load_post( $booking_id ) ) {
113
- if ( $booking_email == $booking->email ) {
114
- wp_update_post( array( 'ID' => $booking->ID, 'post_status' => 'cancelled' ) );
115
116
- $success = true;
117
}
118
else {
119
wp_send_json_error(
120
array(
121
- 'error' => 'invalidemail',
122
'msg' => __( 'No booking matches the information that was sent.', 'restaurant-reservations' ),
123
)
124
);
125
}
126
- }
127
- else {
128
- wp_send_json_error(
129
- array(
130
- 'error' => 'invalidid',
131
- 'msg' => __( 'No booking matches the information that was sent.', 'restaurant-reservations' ),
132
- )
133
- );
134
- }
135
136
- if ( $ajax ) {
137
- if ( $success ) {
138
- wp_send_json_success(
139
array(
140
- 'booking_id' => $booking_id
141
- )
142
);
143
- }
144
145
- die();
146
}
147
- elseif ( $success ) {
148
- $booking_page_id = $rtb_controller->settings->get_setting( 'booking-page' );
149
- $booking_page_url = get_permalink( $booking_page_id );
150
-
151
- $cancelled_url = add_query_arg(
152
- array(
153
- 'bookingCancelled' => 'success'
154
- ),
155
- $booking_page_url
156
- );
157
158
- header( 'location:' . $cancelled_url );
159
- }
160
- }
161
162
- /**
163
- * Get available timeslots when "Max Reservations" is enabled
164
- * @since 2.0.0
165
- */
166
- public function get_time_slots() {
167
- global $rtb_controller;
168
169
- $max_reservations_setting = $rtb_controller->settings->get_setting( 'rtb-max-tables-count' );
170
- $max_reservations = substr( $max_reservations_setting, 0, strpos( $max_reservations_setting, '_' ) );
171
-
172
- $this->year = sanitize_text_field( $_POST['year'] );
173
- $this->month = sanitize_text_field( $_POST['month'] );
174
- $this->day = sanitize_text_field( $_POST['day'] );
175
-
176
- $dining_block_setting = $rtb_controller->settings->get_setting( 'rtb-dining-block-length' );
177
- $dining_block = substr( $dining_block_setting, 0, strpos( $dining_block_setting, '_' ) );
178
- $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
179
-
180
- // Get opening/closing times for this particular day
181
- $hours = $this->get_opening_hours();
182
-
183
- // If the restaurant is closed that day, return false
184
- if ( ! $hours ) { echo $hours; die(); }
185
-
186
- $args = array(
187
- 'posts_per_page' => -1,
188
- 'date_range' => 'dates',
189
- 'start_date' => $this->year . '-' . $this->month . '-' . $this->day,
190
- 'end_date' => $this->year . '-' . $this->month . '-' . $this->day
191
- );
192
-
193
- require_once( RTB_PLUGIN_DIR . '/includes/Query.class.php' );
194
- $query = new rtbQuery( $args );
195
- $query->prepare_args();
196
197
- // Get all current booking times in seconds from UNIX
198
- $times = array();
199
- foreach ( $query->get_bookings() as $booking ) {
200
- $times[] = strtotime( $booking->date );
201
- }
202
-
203
- sort( $times );
204
-
205
- // Go through all current booking times and figure out when we're at or above the max
206
- $blocked = false;
207
- $blocked_times = array();
208
- $current_times = array();
209
- if ($max_reservations != 'undefined' and $max_reservations != 0) {
210
- foreach ( $times as $key => $time ) {
211
- $current_times[] = $time;
212
213
- while ( sizeOf( $current_times ) > 0 and reset( $current_times ) < $time - $dining_block_seconds ) {
214
- //save the time to know when the blocking potentially ends
215
- $removed_time = reset( $current_times );
216
-
217
- // remove the expired time
218
- array_shift( $current_times );
219
220
- // remove the block if we've dropped below the max reservation count
221
- if ( $blocked and sizeOf( $current_times ) < $max_reservations ) {
222
- $blocked = false;
223
- $blocked_times[] = $removed_time + $dining_block_seconds;
224
- }
225
- }
226
227
- // Check if we're at or above the maximum number of reservations
228
- if ( ! $blocked and sizeOf( $current_times ) >= $max_reservations ) {
229
- $blocked = true;
230
- $blocked_times[] = $time - $dining_block_seconds;
231
- }
232
- }
233
- }
234
-
235
- if ( $blocked ) { $blocked_times[] = end( $current_times ) + $dining_block_seconds; }
236
-
237
- $combined_times = array_merge( $blocked_times, $hours );
238
- sort( $combined_times );
239
-
240
- //Go through all of times to determine when the restaurant is open and not blocked
241
- $open = false;
242
- $blocked = false;
243
- $valid_times = array();
244
- foreach ( $combined_times as $time ) {
245
- if ( in_array( $time, $blocked_times ) ) {
246
- if ( ! $blocked ) {
247
- $blocked = true;
248
- if ( $open ) {
249
- $valid_times[] = (object) array( 'from' => $this->format_pickadate_time( $open_time ), 'to' => $this->format_pickadate_time( $time ), 'inverted' => true );
250
}
251
}
252
- else {
253
- $blocked = false;
254
- if ( $open ) { $open_time = $time; }
255
}
256
}
257
- else {
258
- if ( ! $open ) {
259
- $open = true;
260
- if ( ! $blocked ) { $open_time = $time; }
261
}
262
else {
263
- $open = false;
264
- if ( ! $blocked ) { $valid_times[] = (object) array( 'from' => $this->format_pickadate_time( $open_time ), 'to' => $this->format_pickadate_time( $time ), 'inverted' => true ); }
265
}
266
}
267
}
268
-
269
- echo json_encode( $valid_times );
270
-
271
- die();
272
- }
273
274
- public function get_opening_hours() {
275
- global $rtb_controller;
276
277
- $schedule_closed = $rtb_controller->settings->get_setting( 'schedule-closed' );
278
279
- $valid_times = array();
280
281
- // Check if this date is an exception to the rules
282
- if ( $schedule_closed !== 'undefined' ) {
283
284
- foreach ( $schedule_closed as $closing ) {
285
- $time = strtotime( $closing['date'] );
286
287
- if ( date( 'Y', $time ) == $this->year &&
288
- date( 'm', $time ) == $this->month &&
289
- date( 'd', $time ) == $this->day
290
- ) {
291
292
- // Closed all day
293
- if ( $closing['time'] == 'undefined' ) {
294
- return false;
295
- }
296
297
- if ( $closing['time']['start'] !== 'undefined' ) {
298
- $open_time = strtotime( $closing['date'] . ' ' . $closing['time']['start'] );
299
- } else {
300
- $open_time = strtotime( $closing['date'] ); // Start of the day
301
- }
302
303
- if ( $closing['time']['end'] !== 'undefined' ) {
304
- $close_time = strtotime( $closing['date'] . ' ' . $closing['time']['end'] );
305
- } else {
306
- $close_time = strtotime( $closing['date'] . ' 23:59:59' ); // End of the day
307
- }
308
309
- $open_time = $this->get_earliest_time( $open_time );
310
311
- if ( $open_time < $close_time ) {
312
- $valid_times[] = $open_time;
313
- $valid_times[] = $close_time;
314
- }
315
- else {
316
- return false;
317
}
318
}
319
- }
320
321
- // Exit early if this date is an exception
322
- if ( isset( $open_time ) ) {
323
- return $valid_times;
324
}
325
- }
326
327
- $schedule_open = $rtb_controller->settings->get_setting( 'schedule-open' );
328
329
- // Get any rules which apply to this weekday
330
- if ( $schedule_open != 'undefined' ) {
331
332
- $day_of_week = strtolower( date( 'l', strtotime( $this->year . '-' . $this->month . '-' . $this->day . ' 1:00:00' ) ) );
333
334
- foreach ( $schedule_open as $opening ) {
335
336
- if ( $opening['weekdays'] !== 'undefined' ) {
337
- foreach ( $opening['weekdays'] as $weekday => $value ) {
338
- if ( $weekday == $day_of_week ) {
339
340
- // Closed all day
341
- if ( $opening->time == 'undefined' ) {
342
- return false;
343
- }
344
345
- if ( $opening['time']['start'] !== 'undefined' ) {
346
- $open_time = strtotime( $this->year . '-' . $this->month . '-' . $this->day . ' ' . $opening['time']['start'] );
347
- } else {
348
- $open_time = strtotime( $this->year . '-' . $this->month . '-' . $this->day );
349
- }
350
351
- if ( $opening['time']['end'] !== 'undefined' ) {
352
- $close_time = strtotime( $this->year . '-' . $this->month . '-' . $this->day . ' ' . $opening['time']['end'] );
353
- } else {
354
- $close_time = strtotime( $this->year . '-' . $this->month . '-' . $this->day . ' 23:59:59' ); // End of the day
355
- }
356
357
- $open_time = $this->get_earliest_time( $open_time );
358
359
- if ( $open_time < $close_time ) {
360
- $valid_times[] = $open_time;
361
- $valid_times[] = $close_time;
362
- }
363
- else {
364
- return false;
365
}
366
}
367
}
368
}
369
- }
370
371
- // Pass any valid times located
372
- if ( sizeOf( $valid_times ) >= 1 ) {
373
- return $valid_times;
374
}
375
}
376
377
- return false;
378
- }
379
380
- public function get_earliest_time( $open_time ) {
381
- global $rtb_controller;
382
383
- // Only make adjustments for current day selections
384
- if ( date( 'y-m-d', strtotime( $this->year . '-' . $this->month . '-' . $this->day ) ) !== date( 'y-m-d' ) ) {
385
return $open_time;
386
- }
387
388
- $late_bookings = ( is_admin() && current_user_can( 'manage_bookings' ) ) ? '' : $rtb_controller->settings->get_setting( 'late-bookings' );
389
390
- $open_time = time() > $open_time ? time() : $open_time;
391
392
- if ( $late_bookings === 'number' && $late_bookings % 1 === 0 ) {
393
- if ( time() + $late_bookings * 60 > $open_time ) {
394
- $open_time = time() + $late_bookings;
395
}
396
}
397
398
- return $open_time;
399
- }
400
-
401
- public function format_pickadate_time( $time ) {
402
- return array( date( 'G', $time ), date( 'i', $time ) );
403
}
404
- }
405
-
406
}
2
if ( !defined( 'ABSPATH' ) ) exit;
3
4
if ( !class_exists( 'rtbAJAX' ) ) {
5
/**
6
+ * Class to handle AJAX date interactions for Restaurant Reservations
7
+ *
8
* @since 2.0.0
9
*/
10
+ class rtbAJAX {
11
12
+ /**
13
+ * The year of the booking date we're getting timeslots for
14
+ * @since 2.0.0
15
+ */
16
+ public $year;
17
18
+ /**
19
+ * The month of the booking date we're getting timeslots for
20
+ * @since 2.0.0
21
+ */
22
+ public $month;
23
24
+ /**
25
+ * The day of the booking date we're getting timeslots for
26
+ * @since 2.0.0
27
+ */
28
+ public $day;
29
30
+ /**
31
+ * The time of the booking we're getting timeslots for
32
+ * @since 2.1.5
33
+ */
34
+ public $time;
35
36
+ public function __construct() {
37
38
+ add_action( 'wp_ajax_rtb_get_available_time_slots', array( $this, 'get_time_slots' ) );
39
+ add_action( 'wp_ajax_nopriv_rtb_get_available_time_slots', array( $this, 'get_time_slots' ) );
40
41
+ add_action( 'wp_ajax_rtb_find_reservations', array( $this, 'get_reservations' ) );
42
+ add_action( 'wp_ajax_nopriv_rtb_find_reservations', array( $this, 'get_reservations' ) );
43
44
+ add_action( 'wp_ajax_rtb_cancel_reservations', array( $this, 'cancel_reservation' ) );
45
+ add_action( 'wp_ajax_nopriv_rtb_cancel_reservations', array( $this, 'cancel_reservation' ) );
46
47
+ add_action( 'wp_ajax_rtb_get_available_party_size', array( $this, 'get_available_party_size' ) );
48
+ add_action( 'wp_ajax_nopriv_rtb_get_available_party_size', array( $this, 'get_available_party_size' ) );
49
}
50
51
+ /**
52
+ * Get reservations that are associated with the email address that was sent
53
+ * @since 2.1.0
54
+ */
55
+ public function get_reservations() {
56
+ global $wpdb;
57
58
+ $email = isset($_POST['booking_email']) ? sanitize_email( $_POST['booking_email'] ) : '';
59
+
60
+ if ( ! $email ) {
61
+ wp_send_json_error(
62
+ array(
63
+ 'error' => 'noemail',
64
+ 'msg' => __( 'The email you entered is not valid.', 'restaurant-reservations' ),
65
+ )
66
+ );
67
+ }
68
+
69
+ require_once( RTB_PLUGIN_DIR . '/includes/Booking.class.php' );
70
+
71
+ $bookings = array();
72
+ $booking_ids = $wpdb->get_results($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_key='rtb' AND meta_value LIKE %s", '%' . $email . '%'));
73
+ foreach ( $booking_ids as $booking_id ) {
74
+ $booking = new rtbBooking();
75
+ if ( $booking->load_post( $booking_id->post_id ) ) {
76
+ if ( ( $booking->post_status == 'pending' or $booking->post_status == 'confirmed' ) and time() < strtotime( $booking->date ) ) {
77
+ $bookings[] = array(
78
+ 'ID' => $booking->ID,
79
+ 'email' => $booking->email,
80
+ 'datetime' => $booking->format_date( $booking->date ),
81
+ 'party' => $booking->party
82
+ );
83
+ }
84
}
85
}
86
87
+ if ( ! empty($bookings) ) {
88
+ wp_send_json_success(
89
+ array(
90
+ 'bookings' => $bookings
91
+ )
92
+ );
93
+ }
94
+ else {
95
+ wp_send_json_error(
96
+ array(
97
+ 'error' => 'nobookings',
98
+ 'msg' => __( 'No bookings were found for the email address you entered.', 'restaurant-reservations' ),
99
+ )
100
+ );
101
+ }
102
103
+ die();
104
+ }
105
106
+ /**
107
+ * Cancel a reservation based on its ID, with the email address used for confirmation
108
+ * @since 2.1.0
109
+ */
110
+ public function cancel_reservation( $non_ajax = true ) {
111
+ global $rtb_controller;
112
113
+ $booking_id = isset($_REQUEST['booking_id']) ? absint( $_REQUEST['booking_id'] ) : '';
114
+ $booking_email = isset($_REQUEST['booking_email']) ? sanitize_email( $_REQUEST['booking_email'] ) : '';
115
116
+ require_once( RTB_PLUGIN_DIR . '/includes/Booking.class.php' );
117
118
+ $success = false;
119
120
+ $booking = new rtbBooking();
121
+ if ( $booking->load_post( $booking_id ) ) {
122
+ if ( $booking_email == $booking->email ) {
123
+ wp_update_post( array( 'ID' => $booking->ID, 'post_status' => 'cancelled' ) );
124
125
+ $success = true;
126
+ }
127
+ else {
128
+ wp_send_json_error(
129
+ array(
130
+ 'error' => 'invalidemail',
131
+ 'msg' => __( 'No booking matches the information that was sent.', 'restaurant-reservations' ),
132
+ )
133
+ );
134
+ }
135
}
136
else {
137
wp_send_json_error(
138
array(
139
+ 'error' => 'invalidid',
140
'msg' => __( 'No booking matches the information that was sent.', 'restaurant-reservations' ),
141
)
142
);
143
}
144
145
+ if ( $ajax ) {
146
+ if ( $success ) {
147
+ wp_send_json_success(
148
+ array(
149
+ 'booking_id' => $booking_id
150
+ )
151
+ );
152
+ }
153
+
154
+ die();
155
+ }
156
+ elseif ( $success ) {
157
+ $booking_page_id = $rtb_controller->settings->get_setting( 'booking-page' );
158
+ $booking_page_url = get_permalink( $booking_page_id );
159
+
160
+ $cancelled_url = add_query_arg(
161
array(
162
+ 'bookingCancelled' => 'success'
163
+ ),
164
+ $booking_page_url
165
);
166
167
+ header( 'location:' . $cancelled_url );
168
+ }
169
}
170
171
+ /**
172
+ * Get available timeslots when "Max Reservations" or "Max People" is enabled
173
+ * @since 2.0.0
174
+ */
175
+ public function get_time_slots() {
176
+ global $rtb_controller;
177
178
+ $max_reservations_setting = $rtb_controller->settings->get_setting( 'rtb-max-tables-count' );
179
+ $max_reservations = substr( $max_reservations_setting, 0, strpos( $max_reservations_setting, '_' ) );
180
181
+ $max_people_setting = $rtb_controller->settings->get_setting( 'rtb-max-people-count' );
182
+ $max_people = substr( $max_people_setting, 0, strpos( $max_people_setting, '_' ) );
183
184
+ $this->year = sanitize_text_field( $_POST['year'] );
185
+ $this->month = sanitize_text_field( $_POST['month'] );
186
+ $this->day = sanitize_text_field( $_POST['day'] );
187
188
+ $dining_block_setting = $rtb_controller->settings->get_setting( 'rtb-dining-block-length' );
189
+ $dining_block = substr( $dining_block_setting, 0, strpos( $dining_block_setting, '_' ) );
190
+ $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
191
+
192
+ // Get opening/closing times for this particular day
193
+ $hours = $this->get_opening_hours();
194
195
+ // var_dump($hours);
196
197
+ // If the restaurant is closed that day, return false
198
+ if ( ! $hours ) { echo $hours; die(); }
199
+
200
+ $args = array(
201
+ 'posts_per_page' => -1,
202
+ 'date_range' => 'dates',
203
+ 'start_date' => $this->year . '-' . $this->month . '-' . $this->day,
204
+ 'end_date' => $this->year . '-' . $this->month . '-' . $this->day
205
+ );
206
+
207
+ require_once( RTB_PLUGIN_DIR . '/includes/Query.class.php' );
208
+ $query = new rtbQuery( $args );
209
+ $query->prepare_args();
210
+
211
+ // Get all current bookings sorted by date
212
+ $bookings = $query->get_bookings();
213
+
214
+ // Go through all current booking times and figure out when we're at or above the max
215
+ $blocked = false;
216
+ $blocked_times = array();
217
+ $current_times = array();
218
+ $party_sizes = array();
219
+ if ($max_reservations != 'undefined' and $max_reservations != 0) {
220
+ foreach ( $bookings as $key => $booking ) {
221
+ // Convert booking date to seconds from UNIX
222
+ $booking_time = strtotime($booking->date);
223
+ $current_times[] = $booking_time;
224
+
225
+ while ( sizeOf( $current_times ) > 0 and reset( $current_times ) < $booking_time - $dining_block_seconds ) {
226
+ //save the time to know when the blocking potentially ends
227
+ $removed_time = reset( $current_times );
228
+
229
+ // remove the expired time
230
+ array_shift( $current_times );
231
+
232
+ // remove the block if we've dropped below the max reservation
233
+ if ( $blocked and sizeOf( $current_times ) < $max_reservations ) {
234
+ $blocked = false;
235
+ $blocked_times[] = $removed_time + $dining_block_seconds;
236
+ }
237
}
238
+
239
+ // Check if we're at or above the maximum number of reservations
240
+ if ( ! $blocked and sizeOf( $current_times ) >= $max_reservations ) {
241
+ $blocked = true;
242
+ $blocked_times[] = $booking_time - $dining_block_seconds;
243
+ }
244
}
245
+ } else if ( $max_people != 'undefined' and $max_people != 0 ) {
246
+ foreach ( $bookings as $key => $booking ) {
247
+ // Convert booking date to seconds from UNIX
248
+ $booking_time = strtotime($booking->date);
249
+ $current_times[] = $booking_time;
250
+ $party_sizes[] = (int) $booking->party;
251
+
252
+ while ( sizeOf( $current_times ) > 0 and reset( $current_times ) < $booking_time - $dining_block_seconds ) {
253
+ //save the time to know when the blocking potentially ends
254
+ $removed_time = reset( $current_times );
255
+
256
+ // remove the expired time and party size
257
+ array_shift( $current_times );
258
+ array_shift( $party_sizes );
259
+
260
+ // remove the block if we've dropped below the max people count
261
+ if ( $blocked and array_sum($party_sizes) < $max_people ) {
262
+ $blocked = false;
263
+ $blocked_times[] = $removed_time + $dining_block_seconds;
264
+ }
265
+ }
266
+
267
+ // Check if we're at or above the maximum number of people
268
+ if ( ! $blocked and array_sum($party_sizes) >= $max_people ) {
269
+ $blocked = true;
270
+ $blocked_times[] = $booking_time - $dining_block_seconds;
271
+ }
272
}
273
}
274
+
275
+ if ( $blocked ) { $blocked_times[] = end( $current_times ) + $dining_block_seconds; }
276
+
277
+ $combined_times = array_merge( $blocked_times, $hours );
278
+ sort( $combined_times );
279
+
280
+ //Go through all of times to determine when the restaurant is open and not blocked
281
+ $open = false;
282
+ $blocked = false;
283
+ $valid_times = array();
284
+ foreach ( $combined_times as $time ) {
285
+ if ( in_array( $time, $blocked_times ) ) {
286
+ if ( ! $blocked ) {
287
+ $blocked = true;
288
+ if ( $open ) {
289
+ $valid_times[] = (object) array( 'from' => $this->format_pickadate_time( $open_time ), 'to' => $this->format_pickadate_time( $time ), 'inverted' => true );
290
+ }
291
+ }
292
+ else {
293
+ $blocked = false;
294
+ if ( $open ) { $open_time = $time; }
295
+ }
296
}
297
else {
298
+ if ( ! $open ) {
299
+ $open = true;
300
+ if ( ! $blocked ) { $open_time = $time; }
301
+ }
302
+ else {
303
+ $open = false;
304
+ if ( ! $blocked ) { $valid_times[] = (object) array( 'from' => $this->format_pickadate_time( $open_time ), 'to' => $this->format_pickadate_time( $time ), 'inverted' => true ); }
305
+ }
306
}
307
}
308
+
309
+ echo json_encode( $valid_times );
310
+
311
+ die();
312
}
313
314
+ public function get_opening_hours() {
315
+ global $rtb_controller;
316
317
+ $schedule_closed = $rtb_controller->settings->get_setting( 'schedule-closed' );
318
319
+ $valid_times = array();
320
321
+ // Check if this date is an exception to the rules
322
+ if ( $schedule_closed !== 'undefined' ) {
323
324
+ foreach ( $schedule_closed as $closing ) {
325
+ $time = strtotime( $closing['date'] );
326
327
+ if ( date( 'Y', $time ) == $this->year &&
328
+ date( 'm', $time ) == $this->month &&
329
+ date( 'd', $time ) == $this->day
330
+ ) {
331
332
+ // Closed all day
333
+ if ( $closing['time'] == 'undefined' ) {
334
+ return false;
335
+ }
336
337
+ if ( $closing['time']['start'] !== 'undefined' ) {
338
+ $open_time = strtotime( $closing['date'] . ' ' . $closing['time']['start'] );
339
+ } else {
340
+ $open_time = strtotime( $closing['date'] ); // Start of the day
341
+ }
342
343
+ if ( $closing['time']['end'] !== 'undefined' ) {
344
+ $close_time = strtotime( $closing['date'] . ' ' . $closing['time']['end'] );
345
+ } else {
346
+ $close_time = strtotime( $closing['date'] . ' 23:59:59' ); // End of the day
347
+ }
348
349
+ $open_time = $this->get_earliest_time( $open_time );
350
351
+ if ( $open_time <= $close_time ) {
352
+ $valid_times[] = $open_time;
353
+ $valid_times[] = $close_time;
354
+ }
355
+ else {
356
+ return false;
357
+ }
358
}
359
}
360
361
+ // Exit early if this date is an exception
362
+ if ( isset( $open_time ) ) {
363
+ return $valid_times;
364
+ }
365
}
366
367
+ $schedule_open = $rtb_controller->settings->get_setting( 'schedule-open' );
368
369
+ // Get any rules which apply to this weekday
370
+ if ( $schedule_open != 'undefined' ) {
371
372
+ $day_of_week = strtolower( date( 'l', strtotime( $this->year . '-' . $this->month . '-' . $this->day . ' 1:00:00' ) ) );
373
374
+ foreach ( $schedule_open as $opening ) {
375
376
+ if ( $opening['weekdays'] !== 'undefined' ) {
377
+ foreach ( $opening['weekdays'] as $weekday => $value ) {
378
+ if ( $weekday == $day_of_week ) {
379
380
+ // Closed all day
381
+ if ( $opening->time == 'undefined' ) {
382
+ return false;
383
+ }
384
385
+ if ( $opening['time']['start'] !== 'undefined' ) {
386
+ $open_time = strtotime( $this->year . '-' . $this->month . '-' . $this->day . ' ' . $opening['time']['start'] );
387
+ } else {
388
+ $open_time = strtotime( $this->year . '-' . $this->month . '-' . $this->day );
389
+ }
390
391
+ if ( $opening['time']['end'] !== 'undefined' ) {
392
+ $close_time = strtotime( $this->year . '-' . $this->month . '-' . $this->day . ' ' . $opening['time']['end'] );
393
+ } else {
394
+ $close_time = strtotime( $this->year . '-' . $this->month . '-' . $this->day . ' 23:59:59' ); // End of the day
395
+ }
396
397
+ $open_time = $this->get_earliest_time( $open_time );
398
399
+ if ( $open_time <= $close_time ) {
400
+ $valid_times[] = $open_time;
401
+ $valid_times[] = $close_time;
402
+ }
403
+ else {
404
+ return false;
405
+ }
406
}
407
}
408
}
409
}
410
411
+ // Pass any valid times located
412
+ if ( sizeOf( $valid_times ) >= 1 ) {
413
+ return $valid_times;
414
+ }
415
}
416
+
417
+ return false;
418
}
419
420
+ public function get_earliest_time( $open_time ) {
421
+ global $rtb_controller;
422
+
423
+ // Only make adjustments for current day selections
424
+ if ( date( 'y-m-d', strtotime( $this->year . '-' . $this->month . '-' . $this->day ) ) !== date( 'y-m-d' ) ) {
425
+ return $open_time;
426
+ }
427
428
+ $late_bookings = ( is_admin() && current_user_can( 'manage_bookings' ) ) ? '' : $rtb_controller->settings->get_setting( 'late-bookings' );
429
+
430
+ $open_time = time() > $open_time ? time() : $open_time;
431
+
432
+ if ( $late_bookings === 'number' && $late_bookings % 1 === 0 ) {
433
+ if ( time() + $late_bookings * 60 > $open_time ) {
434
+ $open_time = time() + $late_bookings;
435
+ }
436
+ }
437
438
return $open_time;
439
+ }
440
+
441
+ /**
442
+ * Get number of seats remaining avilable to be booked
443
+ * @since 2.1.5
444
+ */
445
+ public function get_available_party_size() {
446
+ global $rtb_controller;
447
+
448
+ $max_people_setting = $rtb_controller->settings->get_setting( 'rtb-max-people-count' );
449
+ $max_people = substr( $max_people_setting, 0, strpos( $max_people_setting, '_' ) );
450
+
451
+ $this->year = sanitize_text_field( $_POST['year'] );
452
+ $this->month = sanitize_text_field( $_POST['month'] );
453
+ $this->day = sanitize_text_field( $_POST['day'] );
454
+ $this->time = sanitize_text_field( $_POST['time'] );
455
+
456
+ $dining_block_setting = $rtb_controller->settings->get_setting( 'rtb-dining-block-length' );
457
+ $dining_block = substr( $dining_block_setting, 0, strpos( $dining_block_setting, '_' ) );
458
+ $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
459
+
460
+ // Get opening/closing times for this particular day
461
+ $hours = $this->get_opening_hours();
462
+
463
+ // If the restaurant is closed that day, return false
464
+ if ( ! $hours ) { die(); }
465
466
+ // If no time is selected, return false
467
+ if ( ! $this->time ) { die(); }
468
+
469
+ $args = array(
470
+ 'posts_per_page' => -1,
471
+ 'date_range' => 'dates',
472
+ 'start_date' => $this->year . '-' . $this->month . '-' . $this->day,
473
+ 'end_date' => $this->year . '-' . $this->month . '-' . $this->day
474
+ );
475
+
476
+ require_once( RTB_PLUGIN_DIR . '/includes/Query.class.php' );
477
+ $query = new rtbQuery( $args );
478
+ $query->prepare_args();
479
+
480
+ // Get all current bookings sorted by date
481
+ $bookings = $query->get_bookings();
482
+
483
+ $selected_date_time = strtotime($this->year . '-' . $this->month . '-' . $this->day . ' ' . $this->time);
484
+ $selected_date_time_start = $selected_date_time - $dining_block_seconds;
485
+ $selected_date_time_end = $selected_date_time + $dining_block_seconds;
486
+ $party_sizes = [];
487
+
488
+ if ($max_people != 'undefined' and $max_people != 0) {
489
+
490
+ $max_time_size = 0;
491
+ $current_times = array();
492
+ $party_sizes = array();
493
+
494
+ // Go through all current booking and collect the total party size
495
+ foreach ( $bookings as $key => $booking ) {
496
+
497
+ // Convert booking date to seconds from UNIX
498
+ $booking_time = strtotime($booking->date);
499
+
500
+ // Ignore bookings outside of our time range
501
+ if ($booking_time < $selected_date_time_start or $booking_time > $selected_date_time_end) { continue; }
502
+
503
+ $current_times[] = $booking_time;
504
+ $party_sizes[] = (int) $booking->party;
505
+
506
+ while ( sizeOf( $current_times ) > 0 and reset( $current_times ) < $booking_time - $dining_block_seconds ) {
507
+ //save the time to know when the blocking potentially ends
508
+ $removed_time = reset( $current_times );
509
+
510
+ // remove the expired time and party size
511
+ array_shift( $current_times );
512
+ array_shift( $party_sizes );
513
+ }
514
+
515
+ $max_time_size = max( $max_time_size, array_sum( $party_sizes ) );
516
+ }
517
518
+ $response = (object) array( 'available_spots' => $max_people - $max_time_size);
519
520
+ echo json_encode($response);
521
+
522
+ die();
523
+ } else {
524
+ return false;
525
}
526
}
527
528
+ public function format_pickadate_time( $time ) {
529
+ return array( date( 'G', $time ), date( 'i', $time ) );
530
+ }
531
}
532
}
includes/InstallationWalkthrough.class.php CHANGED
@@ -162,9 +162,9 @@ class rtbInstallationWalkthrough {
162
<p><?php _e('Thanks for choosing the Five-Star Restaurant Reservations! The following will help you get started with the setup of your reservations system by creating your reservations page, setting times when bookings are allowed as well as configuring a few key options.', 'restaurant-reservations'); ?></p>
163
</div>
164
<?php } ?>
165
-
166
<div class='rtb-welcome-screen-box rtb-welcome-screen-reservations_page rtb-welcome-screen-open' data-screen='reservations_page'>
167
- <h2><?php _e('1. Add a Reservations Page', 'restaurant-reservations'); ?></h2>
168
<div class='rtb-welcome-screen-box-content'>
169
<p><?php _e('You can create a dedicated reservations booking page below, or skip this step and add your reservations to a page you\'ve already created manually.', 'restaurant-reservations'); ?></p>
170
<div class='rtb-welcome-screen-menu-page'>
@@ -175,9 +175,9 @@ class rtbInstallationWalkthrough {
175
<div class='clear'></div>
176
</div>
177
</div>
178
-
179
<div class='rtb-welcome-screen-box rtb-welcome-screen-schedule_open' data-screen='schedule_open'>
180
- <h2><?php _e('2. Create Booking Schedule', 'restaurant-reservations'); ?></h2>
181
<div class='rtb-welcome-screen-box-content'>
182
<p><?php _e('Choose what times each week your restaurant is available to book reservations.', 'restaurant-reservations'); ?></p>
183
<div class='rtb-welcome-screen-created-schedule-open'>
@@ -197,7 +197,7 @@ class rtbInstallationWalkthrough {
197
</div>
198
199
<div class='rtb-welcome-screen-box rtb-welcome-screen-options' data-screen='options'>
200
- <h2><?php _e('3. Set Key Options', 'restaurant-reservations'); ?></h2>
201
<div class='rtb-welcome-screen-box-content'>
202
<p><?php _e('Set a min/max party size for bookings, choose how early and late bookings can be made, and pick the time interval between different booking options.', 'restaurant-reservations'); ?></p>
203
<div class='rtb-welcome-screen-option'>
162
<p><?php _e('Thanks for choosing the Five-Star Restaurant Reservations! The following will help you get started with the setup of your reservations system by creating your reservations page, setting times when bookings are allowed as well as configuring a few key options.', 'restaurant-reservations'); ?></p>
163
</div>
164
<?php } ?>
165
+ <?php if (!isset($_GET['exclude'])) { ?>
166
<div class='rtb-welcome-screen-box rtb-welcome-screen-reservations_page rtb-welcome-screen-open' data-screen='reservations_page'>
167
+ <h2><?php _e('Add a Reservations Page', 'restaurant-reservations'); ?></h2>
168
<div class='rtb-welcome-screen-box-content'>
169
<p><?php _e('You can create a dedicated reservations booking page below, or skip this step and add your reservations to a page you\'ve already created manually.', 'restaurant-reservations'); ?></p>
170
<div class='rtb-welcome-screen-menu-page'>
175
<div class='clear'></div>
176
</div>
177
</div>
178
+ <?php } ?>
179
<div class='rtb-welcome-screen-box rtb-welcome-screen-schedule_open' data-screen='schedule_open'>
180
+ <h2><?php echo (isset($_GET['exclude']) ? '1.' : '2.') . __(' Create Booking Schedule', 'restaurant-reservations'); ?></h2>
181
<div class='rtb-welcome-screen-box-content'>
182
<p><?php _e('Choose what times each week your restaurant is available to book reservations.', 'restaurant-reservations'); ?></p>
183
<div class='rtb-welcome-screen-created-schedule-open'>
197
</div>
198
199
<div class='rtb-welcome-screen-box rtb-welcome-screen-options' data-screen='options'>
200
+ <h2><?php echo (isset($_GET['exclude']) ? '2.' : '3.') . __(' Set Key Options', 'restaurant-reservations'); ?></h2>
201
<div class='rtb-welcome-screen-box-content'>
202
<p><?php _e('Set a min/max party size for bookings, choose how early and late bookings can be made, and pick the time interval between different booking options.', 'restaurant-reservations'); ?></p>
203
<div class='rtb-welcome-screen-option'>
includes/Settings.class.php CHANGED
@@ -1256,6 +1256,20 @@ If you were not the one to cancel this booking, please contact us.
1256
)
1257
);
1258
1259
$sap->add_setting(
1260
'rtb-settings',
1261
'rtb-table-seat-assignments',
1256
)
1257
);
1258
1259
+ $sap->add_setting(
1260
+ 'rtb-settings',
1261
+ 'rtb-table-seat-assignments',
1262
+ 'count',
1263
+ array(
1264
+ 'id' => 'rtb-max-people-count',
1265
+ 'title' => __( 'Max People', 'restaurant-reservations' ),
1266
+ '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' ),
1267
+ 'min_value' => 1,
1268
+ 'max_value' => 100,
1269
+ 'increment' => 1
1270
+ )
1271
+ );
1272
+
1273
$sap->add_setting(
1274
'rtb-settings',
1275
'rtb-table-seat-assignments',
includes/template-functions.php CHANGED
@@ -690,18 +690,19 @@ function rtb_enqueue_assets() {
690
apply_filters(
691
'rtb_pickadate_args',
692
array(
693
- 'date_format' => rtb_esc_js( $rtb_controller->settings->get_setting( 'date-format' ) ),
694
- 'time_format' => rtb_esc_js( $rtb_controller->settings->get_setting( 'time-format' ) ),
695
- 'disable_dates' => rtb_get_datepicker_rules(),
696
- 'schedule_open' => $rtb_controller->settings->get_setting( 'schedule-open' ),
697
- 'schedule_closed' => $rtb_controller->settings->get_setting( 'schedule-closed' ),
698
- 'early_bookings' => is_admin() && current_user_can( 'manage_bookings' ) ? '' : $rtb_controller->settings->get_setting( 'early-bookings' ),
699
- 'late_bookings' => is_admin() && current_user_can( 'manage_bookings' ) ? '' : $rtb_controller->settings->get_setting( 'late-bookings' ),
700
- 'enable_max_reservations' => is_admin() && current_user_can( 'manage_bookings' ) ? false : $rtb_controller->settings->get_setting( 'rtb-enable-max-tables' ),
701
- 'date_onload' => $rtb_controller->settings->get_setting( 'date-onload' ),
702
- 'time_interval' => $rtb_controller->settings->get_setting( 'time-interval' ),
703
- 'first_day' => $rtb_controller->settings->get_setting( 'week-start' ),
704
- 'allow_past' => is_admin() && current_user_can( 'manage_bookings' ),
705
)
706
)
707
);
@@ -1118,4 +1119,4 @@ if ( !function_exists('rtb_esc_js') ) {
1118
1119
return preg_replace( '/[^a-zA-Z ,.-:\/]/', '', $value );
1120
}
1121
- }
690
apply_filters(
691
'rtb_pickadate_args',
692
array(
693
+ 'date_format' => rtb_esc_js( $rtb_controller->settings->get_setting( 'date-format' ) ),
694
+ 'time_format' => rtb_esc_js( $rtb_controller->settings->get_setting( 'time-format' ) ),
695
+ 'disable_dates' => rtb_get_datepicker_rules(),
696
+ 'schedule_open' => $rtb_controller->settings->get_setting( 'schedule-open' ),
697
+ 'schedule_closed' => $rtb_controller->settings->get_setting( 'schedule-closed' ),
698
+ 'early_bookings' => is_admin() && current_user_can( 'manage_bookings' ) ? '' : $rtb_controller->settings->get_setting( 'early-bookings' ),
699
+ 'late_bookings' => is_admin() && current_user_can( 'manage_bookings' ) ? '' : $rtb_controller->settings->get_setting( 'late-bookings' ),
700
+ 'enable_max_reservations' => is_admin() && current_user_can( 'manage_bookings' ) ? false : $rtb_controller->settings->get_setting( 'rtb-enable-max-tables' ),
701
+ 'max_people' => is_admin() && current_user_can( 'manage_bookings' ) ? 100 : $rtb_controller->settings->get_setting( 'rtb-max-people-count' ),
702
+ 'date_onload' => $rtb_controller->settings->get_setting( 'date-onload' ),
703
+ 'time_interval' => $rtb_controller->settings->get_setting( 'time-interval' ),
704
+ 'first_day' => $rtb_controller->settings->get_setting( 'week-start' ),
705
+ 'allow_past' => is_admin() && current_user_can( 'manage_bookings' ),
706
)
707
)
708
);
1119
1120
return preg_replace( '/[^a-zA-Z ,.-:\/]/', '', $value );
1121
}
1122
+ }
lib/simple-admin-pages/classes/AdminPageSetting.Scheduler.class.php CHANGED
@@ -123,7 +123,7 @@ class sapAdminPageSettingScheduler_2_2_0 extends sapAdminPageSetting_2_2_0 {
123
'delete' => null, // _x( 'Delete rule', 'Delete a scheduling rule', 'textdomain' ),
124
'delete_schedule' => null, // __( 'Delete scheduling rule', 'textdomain' ),
125
'never' => null, // _x( 'Never', 'Brief default description of a scheduling rule when no weekdays or weeks are included in the rule', 'textdomain' ),
126
- 'weekly_always' => null, // _x( 'Every day', 'Brief default description of a scheduling rule when all the weekdays/weeks are included in the rule', 'textdomain' ),
127
'monthly_weekdays' => null, // _x( '%s on the %s week of the month', 'Brief default description of a scheduling rule when some weekdays are included on only some weeks of the month. %s should be left alone and will be replaced by a comma-separated list of days and weeks in the following format: M, T, W on the first, second week of the month', 'textdomain' ),
128
'monthly_weeks' => null, // _x( '%s week of the month', 'Brief default description of a scheduling rule when some weeks of the month are included but all or no weekdays are selected. %s should be left alone and will be replaced by a comma-separated list of weeks in the following format: First, second week of the month', 'textdomain' ),
129
'all_day' => null, // _x( 'All day', 'Brief default description of a scheduling rule when no times are set', 'textdomain' ),
@@ -650,7 +650,7 @@ class sapAdminPageSettingScheduler_2_2_0 extends sapAdminPageSetting_2_2_0 {
650
if ( !is_array( $values ) || !count( $values ) ) {
651
return $output;
652
}
653
-
654
foreach ( $values as $i => $rule ) {
655
656
if ( !empty( $rule['weekdays'] ) ) {
123
'delete' => null, // _x( 'Delete rule', 'Delete a scheduling rule', 'textdomain' ),
124
'delete_schedule' => null, // __( 'Delete scheduling rule', 'textdomain' ),
125
'never' => null, // _x( 'Never', 'Brief default description of a scheduling rule when no weekdays or weeks are included in the rule', 'textdomain' ),
126
+ 'weekly_always' => null, // _x( 'Every day', 'Brief default description of a scheduling rule when all the weekdays/weeks are included in the rule', 'textdomain' ),
127
'monthly_weekdays' => null, // _x( '%s on the %s week of the month', 'Brief default description of a scheduling rule when some weekdays are included on only some weeks of the month. %s should be left alone and will be replaced by a comma-separated list of days and weeks in the following format: M, T, W on the first, second week of the month', 'textdomain' ),
128
'monthly_weeks' => null, // _x( '%s week of the month', 'Brief default description of a scheduling rule when some weeks of the month are included but all or no weekdays are selected. %s should be left alone and will be replaced by a comma-separated list of weeks in the following format: First, second week of the month', 'textdomain' ),
129
'all_day' => null, // _x( 'All day', 'Brief default description of a scheduling rule when no times are set', 'textdomain' ),
650
if ( !is_array( $values ) || !count( $values ) ) {
651
return $output;
652
}
653
+
654
foreach ( $values as $i => $rule ) {
655
656
if ( !empty( $rule['weekdays'] ) ) {
readme.txt CHANGED
@@ -184,6 +184,9 @@ Find answers to even more questions in the [FAQ](http://doc.fivestarplugins.com/
184
185
== Changelog ==
186
187
= 2.1.4 (2020-05-26) =
188
- Correcting calculation error for "per guest" deposits in ultimate version.
189
184
185
== Changelog ==
186
187
+ = 2.1.5 (2020-05-28) =
188
+ - New option to enable a maximum number of seats at one time in the premium section
189
+
190
= 2.1.4 (2020-05-26) =
191
- Correcting calculation error for "per guest" deposits in ultimate version.
192
restaurant-reservations.php CHANGED
@@ -3,7 +3,7 @@
3
* Plugin Name: Five Star Restaurant Reservations
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.4
7
* Author: FiveStarPlugins
8
* Author URI: https://profiles.wordpress.org/fivestarplugins/
9
* Text Domain: restaurant-reservations
3
* Plugin Name: Five Star Restaurant Reservations
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.5
7
* Author: FiveStarPlugins
8
* Author URI: https://profiles.wordpress.org/fivestarplugins/
9
* Text Domain: restaurant-reservations