Restaurant Reservations - Version 2.3.0

Version Description

(2021-08-23) = - Updated the payment gateway option, so you can now offer PayPal and Stripe at the same time (your customers can choose which to use). - Fixed issue with Early Bookings feature were the X day option was calculating using hours instead of days. - Fixed an issue in which, if there was only one valid time slot left, it would sometimes not display as available. - Fixed an issue in which, if your set timezone was on a different day than UTC (e.g. near midnight), it would sometimes show the incorrect hours as available. - Fixed an issue loading the customizer for the email templates. - Fixed an issue causing the reservation reminder and late arrival notifications to still send if no time interval was specified. - Fixed an issue in which the red badge would still show beside the Bookings WP admin menu item even if there were no pending bookings.

Download this release

Release Info

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

Code changes from version 2.2.12 to 2.3.0

assets/css/admin.css CHANGED
@@ -2707,3 +2707,7 @@ NEW DATE SELETION FILTERS
2707
  color: #555;
2708
  }
2709
 
 
 
 
 
2707
  color: #555;
2708
  }
2709
 
2710
+
2711
+ .bookings_page_rtb-settings .wrap h1 {
2712
+ width: 100%;
2713
+ }
assets/js/stripe-payment.js CHANGED
@@ -144,7 +144,13 @@ jQuery(document).ready(function($) {
144
  result = JSON.parse(result);
145
 
146
  if(true == result.success) {
147
- window.location = window.location.origin + window.location.pathname + result.urlParams;
 
 
 
 
 
 
148
  }
149
  });
150
  });
144
  result = JSON.parse(result);
145
 
146
  if(true == result.success) {
147
+ var url = new URL(window.location.pathname, window.location.origin);
148
+
149
+ for(const [key, value] of Object.entries(result.urlParams)) {
150
+ url.searchParams.append(key, value);
151
+ }
152
+
153
+ window.location = url.href;
154
  }
155
  });
156
  });
includes/Ajax.class.php CHANGED
@@ -55,12 +55,6 @@ if ( !class_exists( 'rtbAJAX' ) ) {
55
 
56
  add_action( 'wp_ajax_rtb_get_available_tables', array( $this, 'get_available_tables' ) );
57
  add_action( 'wp_ajax_nopriv_rtb_get_available_tables', array( $this, 'get_available_tables' ) );
58
-
59
- add_action( 'wp_ajax_rtb_stripe_get_intent', array( $this, 'create_stripe_pmtIntnt' ) );
60
- add_action( 'wp_ajax_nopriv_rtb_stripe_get_intent', array( $this, 'create_stripe_pmtIntnt' ) );
61
-
62
- add_action( 'wp_ajax_rtb_stripe_pmt_succeed', array( $this, 'stripe_sca_succeed' ) );
63
- add_action( 'wp_ajax_nopriv_rtb_stripe_pmt_succeed', array( $this, 'stripe_sca_succeed' ) );
64
  }
65
 
66
  /**
@@ -304,7 +298,7 @@ if ( !class_exists( 'rtbAJAX' ) ) {
304
  ];
305
  }
306
  $all_bookings_by_slots[$booking_time]['total_bookings']++;
307
- $all_bookings_by_slots[$booking_time]['total_guest'] += $booking->party;
308
 
309
  /**
310
  * Expanding bookings
@@ -324,7 +318,7 @@ if ( !class_exists( 'rtbAJAX' ) ) {
324
  }
325
  $all_bookings_by_slots[$next]['overlapped'] = true;
326
  $all_bookings_by_slots[$next]['total_bookings']++;
327
- $all_bookings_by_slots[$next]['total_guest'] += $booking->party;
328
  $next += $interval;
329
  }
330
  }
@@ -412,7 +406,7 @@ if ( !class_exists( 'rtbAJAX' ) ) {
412
  // consolidating timeslots to timeframes
413
  $timeframe = [];
414
  $available_slots_count = count( $available_slots );
415
- if( 1 < $available_slots_count ) {
416
 
417
  $current_pair = [ 'from' => $available_slots[ 0 ] ];
418
 
@@ -543,13 +537,6 @@ if ( !class_exists( 'rtbAJAX' ) ) {
543
  public function get_earliest_time( $open_time ) {
544
  global $rtb_controller;
545
 
546
- // Only make adjustments for current day selections
547
- if ( date( 'y-m-d', strtotime( $this->year . '-' . $this->month . '-' . $this->day ) ) !== date( 'y-m-d' ) ) {
548
- return $open_time;
549
- }
550
-
551
- $late_bookings = ( is_admin() && current_user_can( 'manage_bookings' ) ) ? '' : $rtb_controller->settings->get_setting( 'late-bookings' );
552
-
553
  $interval = $rtb_controller->settings->get_setting( 'time-interval' ) * 60;
554
 
555
  $timezone = wp_timezone();
@@ -557,6 +544,14 @@ if ( !class_exists( 'rtbAJAX' ) ) {
557
 
558
  // adjust open time with respect to the current time of the day for upcoming timeslots
559
  $current_time = time() + $offset;
 
 
 
 
 
 
 
 
560
  if( $current_time > $open_time ) {
561
  while( $current_time > $open_time ) {
562
  $open_time += $interval;
@@ -835,158 +830,5 @@ if ( !class_exists( 'rtbAJAX' ) ) {
835
  public function format_pickadate_time( $time ) {
836
  return array( date( 'G', $time ), date( 'i', $time ) );
837
  }
838
-
839
- /**
840
- * Create Stripe payment intent for reservation deposits
841
- * @since 2.2.8
842
- */
843
- function create_stripe_pmtIntnt()
844
- {
845
- global $rtb_controller;
846
-
847
- $response = function ($success, $msg, $data = []) {
848
- echo json_encode(
849
- array_merge(
850
- [
851
- 'success' => $success,
852
- 'message' => $msg
853
- ],
854
- $data
855
- )
856
- );
857
-
858
- exit(0);
859
- };
860
-
861
- if( ! array_key_exists('booking_id', $_POST) ) {
862
- $response(false, 'Invalid booking.');
863
- }
864
-
865
- require_once( RTB_PLUGIN_DIR . '/includes/Booking.class.php' );
866
- $booking = new rtbBooking();
867
- $booking->load_post( $_POST['booking_id'] );
868
-
869
- $payment_amount = "JPY" != $rtb_controller->settings->get_setting( 'rtb-currency' )
870
- ? $booking->calculate_deposit() * 100
871
- : $booking->calculate_deposit();
872
-
873
- // load the stripe libraries
874
- require_once(RTB_PLUGIN_DIR . '/lib/stripe/init.php');
875
-
876
- $stripe_secret = 'test' == $rtb_controller->settings->get_setting( 'rtb-stripe-mode' )
877
- ? $rtb_controller->settings->get_setting( 'rtb-stripe-test-secret' )
878
- : $rtb_controller->settings->get_setting( 'rtb-stripe-live-secret' );
879
-
880
- try {
881
- \Stripe\Stripe::setApiKey( $stripe_secret );
882
-
883
- // $customer = \Stripe\Customer::create([
884
- // 'email' => $booking->email,
885
- // 'name' => $booking->name
886
- // ]);
887
-
888
- // $booking->stripe_customer_id = $customer->id;
889
- // $booking->insert_post_data();
890
-
891
- $metadata = array_filter([
892
- 'Booking ID' => $booking->ID,
893
- 'Email' => $booking->email,
894
- 'Name' => $booking->name,
895
- 'Date' => $booking->date,
896
- 'Party' => $booking->party
897
- ]);
898
-
899
- if( is_array( $booking->table ) && ! empty( $booking->table ) ) {
900
- $metadata['Table'] = implode('+', $booking->table);
901
- }
902
-
903
- $desc = implode(', ', $metadata );
904
- $stmt_desc = substr( implode( ';', $metadata ), 0, 22 );
905
-
906
- $intent = \Stripe\PaymentIntent::create([
907
- 'amount' => $payment_amount,
908
- 'currency' => $rtb_controller->settings->get_setting( 'rtb-currency' ),
909
- 'payment_method_types' => ['card'],
910
- 'receipt_email' => $booking->email,
911
- 'description' => apply_filters( 'rtb-stripe-payment-desc', $desc ),
912
- 'statement_descriptor' => apply_filters( 'rtb-stripe-payment-stmnt-desc', $stmt_desc ),
913
- 'metadata' => $metadata
914
- ]);
915
-
916
- $response(
917
- true,
918
- 'Payment Intent generated succsssfully',
919
- [
920
- 'clientSecret' => $intent->client_secret,
921
- 'name' => $booking->name,
922
- 'email' => $booking->email,
923
- ]
924
- );
925
- }
926
- catch(Exception $ex) {
927
- $response( false, 'Please try again.', ['error' => $ex->getError()] );
928
- }
929
- }
930
-
931
- /**
932
- * Stripe SCA payment success for reservation deposits
933
- * @since 2.2.8
934
- */
935
- public function stripe_sca_succeed()
936
- {
937
- global $rtb_controller;
938
-
939
- $response = function ($success = false, $urlParams = '') {
940
- echo json_encode([
941
- 'success' => $success,
942
- 'urlParams' => $urlParams
943
- ]);
944
-
945
- exit(0);
946
- };
947
-
948
- $success = false;
949
- $urlParams = '';
950
-
951
- if( ! array_key_exists('booking_id', $_POST) ) {
952
- $response();
953
- }
954
-
955
- require_once( RTB_PLUGIN_DIR . '/includes/Booking.class.php' );
956
- $booking = new rtbBooking();
957
- $booking->load_post( $_POST['booking_id'] );
958
-
959
- if( array_key_exists('success', $_POST) && 'false' != $_POST['success'] ) {
960
-
961
- $booking->deposit = "JPY" != $rtb_controller->settings->get_setting( 'rtb-currency' )
962
- ? $_POST['payment_amount'] / 100
963
- : $_POST['payment_amount'];
964
-
965
- $booking->receipt_id = $_POST['payment_id'];
966
- $booking->determine_status( true );
967
-
968
- do_action( 'rtb_booking_paid', $booking );
969
-
970
- // urlParams on successful payment
971
- $success = true;
972
- $urlParams = add_query_arg(
973
- array(
974
- 'payment' => 'paid',
975
- 'booking_id' => $booking->ID
976
- ),
977
- $booking_page
978
- );
979
-
980
- }
981
- else {
982
- $booking->post_status = 'payment_failed';
983
- $booking->payment_failure_message = ! empty( $_POST['message'] )
984
- ? $_POST['message'] : '';
985
- }
986
-
987
- $booking->insert_post_data();
988
-
989
- $response($success, $urlParams);
990
- }
991
  }
992
  }
55
 
56
  add_action( 'wp_ajax_rtb_get_available_tables', array( $this, 'get_available_tables' ) );
57
  add_action( 'wp_ajax_nopriv_rtb_get_available_tables', array( $this, 'get_available_tables' ) );
 
 
 
 
 
 
58
  }
59
 
60
  /**
298
  ];
299
  }
300
  $all_bookings_by_slots[$booking_time]['total_bookings']++;
301
+ $all_bookings_by_slots[$booking_time]['total_guest'] += intval( $booking->party );
302
 
303
  /**
304
  * Expanding bookings
318
  }
319
  $all_bookings_by_slots[$next]['overlapped'] = true;
320
  $all_bookings_by_slots[$next]['total_bookings']++;
321
+ $all_bookings_by_slots[$next]['total_guest'] += intval( $booking->party );
322
  $next += $interval;
323
  }
324
  }
406
  // consolidating timeslots to timeframes
407
  $timeframe = [];
408
  $available_slots_count = count( $available_slots );
409
+ if( 0 < $available_slots_count ) {
410
 
411
  $current_pair = [ 'from' => $available_slots[ 0 ] ];
412
 
537
  public function get_earliest_time( $open_time ) {
538
  global $rtb_controller;
539
 
 
 
 
 
 
 
 
540
  $interval = $rtb_controller->settings->get_setting( 'time-interval' ) * 60;
541
 
542
  $timezone = wp_timezone();
544
 
545
  // adjust open time with respect to the current time of the day for upcoming timeslots
546
  $current_time = time() + $offset;
547
+
548
+ // Only make adjustments for current day selections
549
+ if ( date( 'y-m-d', strtotime( "{$this->year}-{$this->month}-{$this->day}" ) ) !== date( 'y-m-d', $current_time) ) {
550
+ return $open_time;
551
+ }
552
+
553
+ $late_bookings = ( is_admin() && current_user_can( 'manage_bookings' ) ) ? '' : $rtb_controller->settings->get_setting( 'late-bookings' );
554
+
555
  if( $current_time > $open_time ) {
556
  while( $current_time > $open_time ) {
557
  $open_time += $interval;
830
  public function format_pickadate_time( $time ) {
831
  return array( date( 'G', $time ), date( 'i', $time ) );
832
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
833
  }
834
  }
includes/Booking.class.php CHANGED
@@ -23,6 +23,13 @@ class rtbBooking {
23
  */
24
  public $request_inserted = false;
25
 
 
 
 
 
 
 
 
26
  public function __construct() {}
27
 
28
  /**
@@ -86,7 +93,6 @@ class rtbBooking {
86
  'table' => array(),
87
  'payment_failure_message' => '',
88
  'receipt_id' => '',
89
- 'stripe_customer_id' => '',
90
  'reminder_sent' => false,
91
  'late_arrival_sent' => false,
92
  );
@@ -110,7 +116,6 @@ class rtbBooking {
110
  $this->table = $meta['table'];
111
  $this->payment_failure_message = $meta['payment_failure_message'];
112
  $this->receipt_id = $meta['receipt_id'];
113
- $this->stripe_customer_id = $meta['stripe_customer_id'];
114
  $this->late_arrival_sent = $meta['late_arrival_sent'];
115
  $this->reminder_sent = $meta['reminder_sent'];
116
  }
@@ -207,6 +212,39 @@ class rtbBooking {
207
 
208
  /**
209
  * Validate submission data. Expects to find data in $_POST.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
  * @since 0.0.1
211
  */
212
  public function validate_submission($action = null, $by_admin = false) {
@@ -214,6 +252,11 @@ class rtbBooking {
214
  global $rtb_controller;
215
 
216
  $this->validation_errors = array();
 
 
 
 
 
217
 
218
  // Date
219
  $date = empty( $_POST['rtb-date'] ) ? false : stripslashes_deep( $_POST['rtb-date'] );
@@ -267,8 +310,10 @@ class rtbBooking {
267
 
268
  $early_bookings = $rtb_controller->settings->get_setting( 'early-bookings' );
269
  if ( !empty( $early_bookings ) ) {
270
- $early_bookings_seconds = $early_bookings * 24 * 60 * 60; // Advanced bookings allowance in seconds
271
- if ( $request->format( 'U' ) > ( current_time( 'timestamp' ) + $early_bookings_seconds ) ) {
 
 
272
  $this->validation_errors[] = array(
273
  'field' => 'time',
274
  'error_msg' => 'Booking request too far in the future',
@@ -487,7 +532,7 @@ class rtbBooking {
487
  // Table
488
  $table = empty( $_POST['rtb-table'] ) ? array() : explode( ',', sanitize_text_field( stripslashes_deep( $_POST['rtb-table'] ) ) );
489
  $this->table = is_array( $table ) ? array_map( 'sanitize_text_field', $table ) : array();
490
-
491
  $table_required = $rtb_controller->settings->get_setting( 'require-table' );
492
  if ( $table_required && empty( $this->table ) ) {
493
  $this->validation_errors[] = array(
@@ -860,7 +905,7 @@ class rtbBooking {
860
  if ( isset( $this->ID ) and $booking->ID == $this->ID ) { continue; }
861
 
862
  $booking_time = strtotime( $booking->date );
863
- if ( isset( $times[$booking_time] ) ) { $times[$booking_time] += $booking->party; }
864
  else { $times[$booking_time] = (int) $booking->party; }
865
  }
866
 
@@ -1183,10 +1228,6 @@ class rtbBooking {
1183
  $meta['receipt_id'] = $this->receipt_id;
1184
  }
1185
 
1186
- if ( !empty( $this->stripe_customer_id ) ) {
1187
- $meta['stripe_customer_id'] = $this->stripe_customer_id;
1188
- }
1189
-
1190
  if ( !empty( $this->reminder_sent ) ) {
1191
  $meta['reminder_sent'] = $this->reminder_sent;
1192
  }
@@ -1200,5 +1241,26 @@ class rtbBooking {
1200
  return update_post_meta( $this->ID, 'rtb', $meta );
1201
  }
1202
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1203
  }
1204
  } // endif;
23
  */
24
  public $request_inserted = false;
25
 
26
+ /**
27
+ * Raw input, clone of $_POST
28
+ * @var array
29
+ * @since 2.3.0
30
+ */
31
+ public $raw_input = array();
32
+
33
  public function __construct() {}
34
 
35
  /**
93
  'table' => array(),
94
  'payment_failure_message' => '',
95
  'receipt_id' => '',
 
96
  'reminder_sent' => false,
97
  'late_arrival_sent' => false,
98
  );
116
  $this->table = $meta['table'];
117
  $this->payment_failure_message = $meta['payment_failure_message'];
118
  $this->receipt_id = $meta['receipt_id'];
 
119
  $this->late_arrival_sent = $meta['late_arrival_sent'];
120
  $this->reminder_sent = $meta['reminder_sent'];
121
  }
212
 
213
  /**
214
  * Validate submission data. Expects to find data in $_POST.
215
+ *
216
+ * ************************** NOTE **************************
217
+ * This function also create and assign all the required member variable with
218
+ * the acurate values which will be insreted in the DB. One special member,
219
+ * raw_input of type array holds the exact copy of $_POST
220
+ *
221
+ * Example:
222
+ * class a {
223
+ * public function a() {
224
+ * $this->name = 'John Doe';
225
+ * }
226
+ * public function b() {
227
+ * echo $this->name;
228
+ * }
229
+ * }
230
+ *
231
+ * $a = new a();
232
+ *
233
+ * var_dump($a);
234
+ * object(a)#1 (0) {
235
+ * }
236
+ *
237
+ * $a->a();
238
+ *
239
+ * var_dump($a);
240
+ * object(a)#1 (1) {
241
+ * ["name"]=>
242
+ * string(8) "John Doe"
243
+ * }
244
+ *
245
+ * $a->b();
246
+ * John Doe
247
+ *
248
  * @since 0.0.1
249
  */
250
  public function validate_submission($action = null, $by_admin = false) {
252
  global $rtb_controller;
253
 
254
  $this->validation_errors = array();
255
+ /**
256
+ * Raw, unprocessed value so that it can be used to preselect the form
257
+ * field values, eg. table
258
+ */
259
+ $this->raw_input = $_POST;
260
 
261
  // Date
262
  $date = empty( $_POST['rtb-date'] ) ? false : stripslashes_deep( $_POST['rtb-date'] );
310
 
311
  $early_bookings = $rtb_controller->settings->get_setting( 'early-bookings' );
312
  if ( !empty( $early_bookings ) ) {
313
+ $uppar_bound = ( new DateTime( 'now' ) )->setTime( 23, 59 );
314
+ $uppar_bound->add( new DateInterval( "P{$early_bookings}D" ) );
315
+
316
+ if ( $request > $uppar_bound ) {
317
  $this->validation_errors[] = array(
318
  'field' => 'time',
319
  'error_msg' => 'Booking request too far in the future',
532
  // Table
533
  $table = empty( $_POST['rtb-table'] ) ? array() : explode( ',', sanitize_text_field( stripslashes_deep( $_POST['rtb-table'] ) ) );
534
  $this->table = is_array( $table ) ? array_map( 'sanitize_text_field', $table ) : array();
535
+
536
  $table_required = $rtb_controller->settings->get_setting( 'require-table' );
537
  if ( $table_required && empty( $this->table ) ) {
538
  $this->validation_errors[] = array(
905
  if ( isset( $this->ID ) and $booking->ID == $this->ID ) { continue; }
906
 
907
  $booking_time = strtotime( $booking->date );
908
+ if ( isset( $times[$booking_time] ) ) { $times[$booking_time] += intval( $booking->party ); }
909
  else { $times[$booking_time] = (int) $booking->party; }
910
  }
911
 
1228
  $meta['receipt_id'] = $this->receipt_id;
1229
  }
1230
 
 
 
 
 
1231
  if ( !empty( $this->reminder_sent ) ) {
1232
  $meta['reminder_sent'] = $this->reminder_sent;
1233
  }
1241
  return update_post_meta( $this->ID, 'rtb', $meta );
1242
  }
1243
 
1244
+ public function payment_paid()
1245
+ {
1246
+ if( isset( $this->ID ) ) {
1247
+ $this->determine_status( true );
1248
+
1249
+ $this->insert_post_data();
1250
+
1251
+ do_action( 'rtb_booking_paid', $this );
1252
+ }
1253
+ }
1254
+
1255
+ public function payment_failed( $message = '' )
1256
+ {
1257
+ $this->post_status = 'payment_failed';
1258
+ $this->payment_failure_message = $message;
1259
+
1260
+ $this->insert_post_data();
1261
+
1262
+ do_action( 'rtb_booking_paid', $this );
1263
+ }
1264
+
1265
  }
1266
  } // endif;
includes/Cron.class.php CHANGED
@@ -155,11 +155,7 @@ class rtbCron {
155
  public function get_late_arrival_posts() {
156
  global $rtb_controller;
157
 
158
- $late_arrival_time = $rtb_controller->settings->get_setting( 'time-late-user' );
159
- $count = substr( $late_arrival_time, 0, strpos( $late_arrival_time, "_" ) );
160
- $unit = substr( $late_arrival_time, strpos( $late_arrival_time, "_" ) + 1 );
161
-
162
- $time_interval = $this->get_time_interval( $count, $unit );
163
 
164
  $after_datetime = new DateTime( 'now', wp_timezone() );
165
  $before_datetime = new DateTime( 'now', wp_timezone() );
@@ -192,11 +188,7 @@ class rtbCron {
192
  public function get_reminder_posts() {
193
  global $rtb_controller;
194
 
195
- $reminder_time = $rtb_controller->settings->get_setting( 'time-reminder-user' );
196
- $count = substr( $reminder_time, 0, strpos( $reminder_time, "_" ) );
197
- $unit = substr( $reminder_time, strpos( $reminder_time, "_" ) + 1 );
198
-
199
- $time_interval = $this->get_time_interval( $count, $unit );
200
 
201
  $after_datetime = new DateTime( 'now', wp_timezone() );
202
  $before_datetime = new DateTime( 'now', wp_timezone() );
@@ -227,7 +219,14 @@ class rtbCron {
227
  *
228
  * @since 2.0.0
229
  */
230
- public function get_time_interval( $count, $unit ) {
 
 
 
 
 
 
 
231
  switch ($unit) {
232
  case 'days':
233
  $multiplier = 24*3600;
155
  public function get_late_arrival_posts() {
156
  global $rtb_controller;
157
 
158
+ $time_interval = $this->get_time_interval( 'time-late-user' );
 
 
 
 
159
 
160
  $after_datetime = new DateTime( 'now', wp_timezone() );
161
  $before_datetime = new DateTime( 'now', wp_timezone() );
188
  public function get_reminder_posts() {
189
  global $rtb_controller;
190
 
191
+ $time_interval = $this->get_time_interval( 'time-reminder-user' );
 
 
 
 
192
 
193
  $after_datetime = new DateTime( 'now', wp_timezone() );
194
  $before_datetime = new DateTime( 'now', wp_timezone() );
219
  *
220
  * @since 2.0.0
221
  */
222
+ public function get_time_interval( $setting ) {
223
+ global $rtb_controller;
224
+
225
+ $late_arrival_time = $rtb_controller->settings->get_setting( $setting );
226
+
227
+ $count = intval( substr( $late_arrival_time, 0, strpos( $late_arrival_time, "_" ) ) );
228
+ $unit = substr( $late_arrival_time, strpos( $late_arrival_time, "_" ) + 1 );
229
+
230
  switch ($unit) {
231
  case 'days':
232
  $multiplier = 24*3600;
includes/CustomPostTypes.class.php CHANGED
@@ -379,13 +379,9 @@ class rtbCustomPostTypes {
379
  */
380
  public function show_pending_count() {
381
 
382
- $pending_count = get_option( 'rtb_pending_count' );
383
-
384
- if ( $pending_count === false ) {
385
- global $rtb_controller;
386
- $rtb_controller->cpts->update_pending_count();
387
- $pending_count = get_option( 'rtb_pending_count', 0 );
388
- }
389
 
390
  if ( !$pending_count ) {
391
  return;
@@ -420,7 +416,7 @@ class rtbCustomPostTypes {
420
  $current_date_time = date( 'Y-m-d H:i:s', current_time( 'timestamp' ) - HOUR_IN_SECONDS );
421
  $count = $wpdb->get_var(
422
  $wpdb->prepare(
423
- "SELECT COUNT(*) FROM {$wpdb->prefix}posts WHERE post_type=%s AND post_status='pending' AND post_date>=%s;",
424
  RTB_BOOKING_POST_TYPE,
425
  $current_date_time
426
  )
379
  */
380
  public function show_pending_count() {
381
 
382
+ global $rtb_controller;
383
+ $rtb_controller->cpts->update_pending_count();
384
+ $pending_count = get_option( 'rtb_pending_count', 0 );
 
 
 
 
385
 
386
  if ( !$pending_count ) {
387
  return;
416
  $current_date_time = date( 'Y-m-d H:i:s', current_time( 'timestamp' ) - HOUR_IN_SECONDS );
417
  $count = $wpdb->get_var(
418
  $wpdb->prepare(
419
+ "SELECT COUNT(ID) FROM {$wpdb->prefix}posts WHERE post_type=%s AND post_status='pending' AND post_date>=%s;",
420
  RTB_BOOKING_POST_TYPE,
421
  $current_date_time
422
  )
includes/Migration.class.php CHANGED
@@ -12,6 +12,10 @@ class rtbMigrationManager {
12
  public function __construct() {
13
 
14
  $this->convert_draft_status_to_payment_pending_status();
 
 
 
 
15
  }
16
 
17
 
@@ -40,6 +44,64 @@ class rtbMigrationManager {
40
  `post_status` = 'draft' AND `post_type` = 'rtb-booking'
41
  ");
42
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  }
44
 
45
  }
12
  public function __construct() {
13
 
14
  $this->convert_draft_status_to_payment_pending_status();
15
+
16
+ $this->convert_payment_gateway_setting();
17
+
18
+ $this->update_invalid_setting_values();
19
  }
20
 
21
 
44
  `post_status` = 'draft' AND `post_type` = 'rtb-booking'
45
  ");
46
  }
47
+
48
+ /**
49
+ * Update the rtb-payment-gateway setting from string to array
50
+ * Previously this setting was a radio, now it is a checkbox.
51
+ *
52
+ * @since 2.3.0
53
+ */
54
+ public function convert_payment_gateway_setting()
55
+ {
56
+ $settings_page = 'rtb-settings';
57
+ $options = get_option( $settings_page );
58
+
59
+ if( ! is_array( $options['rtb-payment-gateway'] ) && version_compare( RTB_VERSION, '2.2.11', '>' ) ) {
60
+ $options['rtb-payment-gateway'] = [ $options['rtb-payment-gateway'] ];
61
+
62
+ update_option( $settings_page, $options, true);
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Update setting of type count, which are 'time-reminder-user' and
68
+ * 'time-late-user'. When no value is being set in admin, it has underscore
69
+ * at least. Whereas, its expected to be empty
70
+ *
71
+ * @since 2.3.1
72
+ */
73
+ public function update_invalid_setting_values() {
74
+ $settings_page = 'rtb-settings';
75
+ $options = get_option( $settings_page );
76
+
77
+ if(
78
+ is_array( $options )
79
+ &&
80
+ isset( $options['time-reminder-user'] )
81
+ &&
82
+ '_' == $options['time-reminder-user']
83
+ &&
84
+ version_compare( RTB_VERSION, '2.2.11', '>' )
85
+ )
86
+ {
87
+ $options['time-reminder-user'] = '';
88
+ }
89
+
90
+ if(
91
+ is_array( $options )
92
+ &&
93
+ isset( $options['time-late-user'] )
94
+ &&
95
+ '_' == $options['time-late-user']
96
+ &&
97
+ version_compare( RTB_VERSION, '2.2.11', '>' )
98
+ )
99
+ {
100
+ $options['time-late-user'] = '';
101
+ }
102
+
103
+ update_option( $settings_page, $options, true);
104
+ }
105
  }
106
 
107
  }
includes/PaymentGateway.interface.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( !defined( 'ABSPATH' ) ) exit;
3
+
4
+ if ( !interface_exists( 'rtbPaymentGateway' ) ) {
5
+ /**
6
+ * Base interface to implement a Payment Gateway for Restaurant Reservations
7
+ *
8
+ * This class enforces the Payment Gateway base settings and their processing
9
+ * methods. This class should be implemented for each type of
10
+ * Payment Gateway. So, there would be a rtbPaymentStripe class or a
11
+ * rtbPaymentPayPal class.
12
+ *
13
+ * @since 2.3.0
14
+ */
15
+ interface rtbPaymentGateway {
16
+
17
+ /**
18
+ * Register the gateway.
19
+ *
20
+ * $gateway_list['stripe'] => [
21
+ * 'label' => __( 'Stripe', 'restaurant-reservations' ),
22
+ * 'instance' => $this
23
+ * ];
24
+ *
25
+ * @param array $gateway_list
26
+ * @return array $gateway_list
27
+ */
28
+ public static function register_gateway( array $gateway_list );
29
+
30
+ /**
31
+ * Print the payment form. The booking has been made and is on payment_pending
32
+ * status. Display the payment form/button here
33
+ *
34
+ * @param rtbBooking $booking booking for which the payment is required
35
+ * @return void Print the HTML
36
+ */
37
+ public function print_payment_form( $booking );
38
+
39
+ }
40
+
41
+ }
includes/PaymentGatewayPayPal.class.php ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( !defined( 'ABSPATH' ) ) exit;
3
+
4
+ if ( !class_exists( 'rtbPaymentGatewayPayPal' ) ) {
5
+ /**
6
+ * This class is responsible for payment processing via Paypal
7
+ *
8
+ * @since 2.3.0
9
+ */
10
+ class rtbPaymentGatewayPayPal implements rtbPaymentGateway {
11
+
12
+ private static $_instance;
13
+
14
+ private final function __construct() {
15
+
16
+ $this->register_hooks();
17
+
18
+ }
19
+
20
+ public static function register_gateway (array $gateway_list )
21
+ {
22
+ return array_merge(
23
+ $gateway_list,
24
+ [
25
+ 'paypal' => [
26
+ 'label' => __( 'PayPal', 'restaurant-reservations' ),
27
+ 'instance' => self::get_instance()
28
+ ]
29
+ ]
30
+ );
31
+ }
32
+
33
+ /**
34
+ * Get singleton instance of the class
35
+ *
36
+ * @return rtbPaymentGatewayPayPal instance
37
+ */
38
+ public static function get_instance()
39
+ {
40
+ if( ! isset( self::$_instance ) ) {
41
+ self::$_instance = new rtbPaymentGatewayPayPal();
42
+ }
43
+
44
+ return self::$_instance;
45
+ }
46
+
47
+ public function register_hooks() {
48
+ // If there's an IPN request, add our setup function to potentially handle it
49
+ if ( isset($_POST['ipn_track_id']) ) {
50
+ add_action( 'init', [$this, 'handle_ipn'], 11 );
51
+
52
+ // add an output buffer layer for the plugin
53
+ add_action( 'init', [$this, 'ob_start'] );
54
+ add_action( 'shutdown', [$this, 'flush_ob_end'] );
55
+ }
56
+ }
57
+
58
+ public function print_payment_form( $booking )
59
+ {
60
+ global $rtb_controller;
61
+
62
+ // Define the form's action parameter
63
+ $booking_page = $rtb_controller->settings->get_setting( 'booking-page' );
64
+ if ( !empty( $booking_page ) ) {
65
+ $booking_page = get_permalink( $booking_page );
66
+ }
67
+
68
+ $item_name = substr(get_bloginfo('name'), 0, 100) . 'Reservation Deposit';
69
+ $amount = $booking->calculate_deposit();
70
+ $business = $rtb_controller->settings->get_setting( 'rtb-paypal-email' );
71
+ $currency = $rtb_controller->settings->get_setting( 'rtb-currency' );
72
+ $notify_url = get_site_url();
73
+
74
+ echo "
75
+ <form action='https://www.paypal.com/cgi-bin/webscr' method='post' class='standard-form'>
76
+ <input type='hidden' name='item_name_1' value='{$item_name}' />
77
+ <input type='hidden' name='custom' value='booking_id={$booking->ID}' />
78
+ <input type='hidden' name='quantity_1' value='1' />
79
+ <input type='hidden' name='amount_1' value='{$amount}' />
80
+ <input type='hidden' name='cmd' value='_cart' />
81
+ <input type='hidden' name='upload' value='1' />
82
+ <input type='hidden' name='business' value='{$business}' />
83
+ <input type='hidden' name='currency_code' value='{$currency}' />
84
+ <input type='hidden' name='return' value='{$booking_page}' />
85
+ <input type='hidden' name='notify_url' value='{$notify_url}' />
86
+ <input type='submit' class='submit-button' value='Pay via PayPal' />
87
+ </form>
88
+ ";
89
+ }
90
+
91
+ /**
92
+ * Handle PayPal IPN requests
93
+ *
94
+ * @since 2.1.0
95
+ */
96
+ public function handle_ipn()
97
+ {
98
+ global $rtb_controller;
99
+
100
+ if ( ! $rtb_controller->settings->get_setting( 'require-deposit' ) ) {
101
+ return;
102
+ }
103
+
104
+ // CONFIG: Enable debug mode. This means we'll log requests into 'ipn.log' in the same directory.
105
+ // Especially useful if you encounter network errors or other intermittent problems with IPN (validation).
106
+ // Set this to 0 once you go live or don't require logging.
107
+ $debug = get_option( 'rtb_enable_payment_debugging' );
108
+
109
+ // Set to 0 once you're ready to go live
110
+ define("RTB_USE_SANDBOX", 0);
111
+ define("RTB_LOG_FILE", "ipn.log");
112
+
113
+ // Read POST data
114
+ // reading posted data directly from $_POST causes serialization
115
+ // issues with array data in POST. Reading raw POST data from input stream instead.
116
+ $raw_post_data = file_get_contents('php://input');
117
+ $raw_post_array = explode('&', $raw_post_data);
118
+ $myPost = array();
119
+ foreach ($raw_post_array as $keyval) {
120
+ $keyval = explode ('=', $keyval);
121
+ if (count($keyval) == 2)
122
+ $myPost[$keyval[0]] = urldecode($keyval[1]);
123
+ }
124
+
125
+ // read the post from PayPal system and add 'cmd'
126
+ $req = 'cmd=_notify-validate';
127
+ if(function_exists('get_magic_quotes_gpc')) {
128
+ $get_magic_quotes_exists = true;
129
+ }
130
+
131
+ foreach ($myPost as $key => $value) {
132
+ if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
133
+ $value = urlencode(stripslashes($value));
134
+ } else {
135
+ $value = urlencode($value);
136
+ }
137
+ $req .= "&$key=$value";
138
+ }
139
+
140
+ // Post IPN data back to PayPal to validate the IPN data is genuine
141
+ // Without this step anyone can fake IPN data
142
+ if(RTB_USE_SANDBOX == true) {
143
+ $paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr";
144
+ } else {
145
+ $paypal_url = "https://www.paypal.com/cgi-bin/webscr";
146
+ }
147
+
148
+ $response = wp_remote_post($paypal_url, array(
149
+ 'method' => 'POST',
150
+ 'body' => $req,
151
+ 'timeout' => 30
152
+ ));
153
+
154
+ // Inspect IPN validation result and act accordingly
155
+ // Split response headers and payload, a better way for strcmp
156
+ $tokens = explode("\r\n\r\n", trim($response['body']));
157
+ $res = trim(end($tokens));
158
+
159
+ if ( $debug ) {
160
+ update_option( 'rtb_debugging', get_option( 'rtb_debugging' ) . print_r( date('[Y-m-d H:i e] '). "IPN response: $res - $req ". PHP_EOL, true ) );
161
+ }
162
+
163
+ if (strcmp ($res, "VERIFIED") == 0) {
164
+
165
+ $paypal_receipt_number = $_POST['txn_id'];
166
+ $payment_amount = $_POST['mc_gross'];
167
+
168
+ parse_str($_POST['custom'], $custom_vars);
169
+ $booking_id = intval( $custom_vars['booking_id'] );
170
+
171
+ require_once( RTB_PLUGIN_DIR . '/includes/Booking.class.php' );
172
+
173
+ $booking = new rtbBooking();
174
+ $booking->load_post( $booking_id );
175
+
176
+ if ( ! $booking ) { return; }
177
+
178
+ $booking->deposit = sanitize_text_field( $payment_amount );
179
+ $booking->receipt_id = sanitize_text_field( $paypal_receipt_number );
180
+
181
+ $booking->payment_paid();
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Opens a buffer when handling PayPal IPN requests
187
+ *
188
+ * @since 2.1.0
189
+ */
190
+ public function ob_start()
191
+ {
192
+ ob_start();
193
+ }
194
+
195
+ /**
196
+ * Closes a buffer when handling PayPal IPN requests
197
+ *
198
+ * @since 2.1.0
199
+ */
200
+ public function flush_ob_end()
201
+ {
202
+ if ( ob_get_length() ) {
203
+ ob_end_clean();
204
+ }
205
+ }
206
+ }
207
+
208
+ }
209
+
210
+ /**
211
+ * Gateway has to register itself
212
+ */
213
+ add_filter(
214
+ 'rtb-payment-gateway-register',
215
+ ['rtbPaymentGatewayPayPal', 'register_gateway']
216
+ );
includes/PaymentGatewayStripe.class.php ADDED
@@ -0,0 +1,462 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( !defined( 'ABSPATH' ) ) exit;
3
+
4
+ if ( !class_exists( 'rtbPaymentGatewayStripe' ) ) {
5
+ /**
6
+ * This class is responsible for payment processing via Stripe
7
+ *
8
+ * @since 2.3.0
9
+ */
10
+ class rtbPaymentGatewayStripe implements rtbPaymentGateway {
11
+
12
+ private static $_instance;
13
+
14
+ private final function __construct() {
15
+
16
+ $this->register_hooks();
17
+
18
+ }
19
+
20
+ public static function register_gateway (array $gateway_list )
21
+ {
22
+ return array_merge(
23
+ $gateway_list,
24
+ [
25
+ 'stripe' => [
26
+ 'label' => __( 'Stripe', 'restaurant-reservations' ),
27
+ 'instance' => self::get_instance()
28
+ ]
29
+ ]
30
+ );
31
+ }
32
+
33
+ /**
34
+ * Get singleton instance of the class
35
+ *
36
+ * @return rtbPaymentGatewayStripe instance
37
+ */
38
+ public static function get_instance()
39
+ {
40
+ if( ! isset( self::$_instance ) ) {
41
+ self::$_instance = new rtbPaymentGatewayStripe();
42
+ }
43
+
44
+ return self::$_instance;
45
+ }
46
+
47
+ public function register_hooks()
48
+ {
49
+ add_action( 'rtb_booking_form_init', [$this, 'process_payment'] );
50
+
51
+ add_action( 'wp_ajax_rtb_stripe_get_intent', array( $this, 'create_stripe_pmtIntnt' ) );
52
+ add_action( 'wp_ajax_nopriv_rtb_stripe_get_intent', array( $this, 'create_stripe_pmtIntnt' ) );
53
+
54
+ add_action( 'wp_ajax_rtb_stripe_pmt_succeed', array( $this, 'stripe_sca_succeed' ) );
55
+ add_action( 'wp_ajax_nopriv_rtb_stripe_pmt_succeed', array( $this, 'stripe_sca_succeed' ) );
56
+
57
+ add_filter( 'rtb_booking_metadata_defaults', [$this, 'default_booking_stripe_info'], 30, 1 );
58
+ add_action( 'rtb_booking_load_post_data', [$this, 'populate_booking_stripe_info'], 30, 2 );
59
+ add_filter( 'rtb_insert_booking_metadata', [$this, 'save_booking_gateway_info'], 30, 2 );
60
+ }
61
+
62
+ public function print_payment_form( $booking )
63
+ {
64
+ global $rtb_controller;
65
+
66
+ // Function alias
67
+ $_gs = [$rtb_controller->settings, 'get_setting'];
68
+ $SCA = $_gs( 'rtb-stripe-sca' );
69
+
70
+ $btn_disabled = '';
71
+ $stripe_lib_version = 'v2';
72
+
73
+ if( $SCA )
74
+ {
75
+ $btn_disabled = "disabled='disabled'";
76
+ $stripe_lib_version = 'v3';
77
+ }
78
+
79
+ // Stripe Lib
80
+ wp_enqueue_script(
81
+ 'rtb-stripe',
82
+ "https://js.stripe.com/{$stripe_lib_version}/",
83
+ array( 'jquery' ),
84
+ RTB_VERSION,
85
+ true
86
+ );
87
+
88
+ // Stripe-JS processing logic
89
+ wp_enqueue_script(
90
+ 'rtb-stripe-payment',
91
+ RTB_PLUGIN_URL . '/assets/js/stripe-payment.js',
92
+ array( 'jquery', 'rtb-stripe' ),
93
+ RTB_VERSION,
94
+ true
95
+ );
96
+
97
+ wp_localize_script(
98
+ 'rtb-stripe-payment',
99
+ 'rtb_stripe_payment',
100
+ array(
101
+ 'stripe_mode' => $_gs( 'rtb-stripe-mode' ),
102
+ 'stripe_sca' => $SCA,
103
+ 'live_publishable_key' => $_gs( 'rtb-stripe-live-publishable' ),
104
+ 'test_publishable_key' => $_gs( 'rtb-stripe-test-publishable' ),
105
+ )
106
+ );
107
+
108
+ $payment_amount = $_gs( 'rtb-currency-symbol-location' ) == 'before'
109
+ ? $_gs( 'rtb-stripe-currency-symbol' ) . $booking->calculate_deposit()
110
+ : $booking->calculate_deposit() . $_gs( 'rtb-stripe-currency-symbol' );
111
+
112
+ $cc_exp_single_field = null != $_gs( 'rtb-expiration-field-single' )
113
+ ? "<input type='text' data-stripe='exp_month_year' class='single-masked'>"
114
+ : "<input type='text' size='2' data-stripe='exp_month'>
115
+ <span> / </span>
116
+ <input type='text' size='4' data-stripe='exp_year'>";
117
+ ?>
118
+
119
+ <h2>
120
+ <?php _e('Deposit Required: ', 'restaurant-reservations' ) . $payment_amount; ?>
121
+ </h2>
122
+
123
+ <div class='payment-errors'></div>
124
+
125
+ <form
126
+ action='#'
127
+ method='POST'
128
+ id='stripe-payment-form'
129
+ data-booking_id='<?php echo $booking->ID ;?>'>
130
+
131
+ <?php if( $SCA ) { ?>
132
+
133
+ <div class='form-row'>
134
+ <label><?php _e('Card Detail', 'restaurant-reservations'); ?></label>
135
+ <span id="cardElement"></span>
136
+ </div>
137
+
138
+ <?php } else { ?>
139
+
140
+ <div class='form-row'>
141
+ <label><?php _e('Card Number', 'restaurant-reservations'); ?></label>
142
+ <input type='text' size='20' autocomplete='off' data-stripe='card_number'/>
143
+ </div>
144
+ <div class='form-row'>
145
+ <label><?php _e('CVC', 'restaurant-reservations'); ?></label>
146
+ <input type='text' size='4' autocomplete='off' data-stripe='card_cvc'/>
147
+ </div>
148
+ <div class='form-row'>
149
+ <label><?php _e('Expiration (MM/YYYY)', 'restaurant-reservations'); ?></label>
150
+ <?php echo $cc_exp_single_field; ?>
151
+ </div>
152
+ <input type='hidden' name='action' value='rtb_stripe_booking_payment'/>
153
+ <input type='hidden' name='currency' value='<?php echo $_gs( 'rtb-currency' ); ?>' data-stripe='currency' />
154
+ <input type='hidden' name='payment_amount' value='<?php echo $booking->calculate_deposit(); ?>' />
155
+ <input type='hidden' name='booking_id' value='<?php echo $booking->ID; ?>' />
156
+
157
+ <?php } ?>
158
+
159
+ <p class="stripe-payment-help-text">
160
+ <?php _e( 'Please wait. Do not refresh until the button enables or the page reloads.', 'restaurant-reservations' ); ?>
161
+ </p>
162
+
163
+ <button type='submit' id='stripe-submit' <?php echo $btn_disabled; ?>>
164
+ <?php _e( 'Make Deposit', 'restaurant-reservations'); ?>
165
+ </button>
166
+
167
+ </form>
168
+ <?php
169
+ }
170
+
171
+ /**
172
+ * Maybe process payment, if coming from Stripe payment form
173
+ *
174
+ * @return void Redirect and exit or return
175
+ */
176
+ public function process_payment()
177
+ {
178
+ global $rtb_controller;
179
+
180
+ if ( ! isset( $_POST['stripeToken'] ) || ! isset( $_POST['booking_id'] ) ) {
181
+ return;
182
+ }
183
+
184
+ // Function alias
185
+ $_gs = [$rtb_controller->settings, 'get_setting'];
186
+ $booking_id = $_POST['booking_id'];
187
+
188
+ // Define the form's action parameter
189
+ $booking_page = $_gs( 'booking-page' );
190
+ if ( ! empty( $booking_page ) ) {
191
+ $booking_page = get_permalink( $booking_page );
192
+ }
193
+ else {
194
+ $booking_page = get_permalink();
195
+ }
196
+
197
+ // load the stripe libraries
198
+ require_once(RTB_PLUGIN_DIR . '/lib/stripe/init.php');
199
+
200
+ // retrieve the token generated by stripe.js
201
+ $token = $_POST['stripeToken'];
202
+
203
+ // JPY currency does not have any decimal palces
204
+ $is_JPY = "JPY" != $_gs( 'rtb-currency' );
205
+ $payment_amount = $is_JPY ? ( $_POST['payment_amount'] * 100 ) : $_POST['payment_amount'];
206
+
207
+ $stripe_secret = 'test' == $_gs( 'rtb-stripe-mode' )
208
+ ? $_gs( 'rtb-stripe-test-secret' )
209
+ : $_gs( 'rtb-stripe-live-secret' );
210
+
211
+ require_once( RTB_PLUGIN_DIR . '/includes/Booking.class.php' );
212
+ $booking = new rtbBooking();
213
+ $booking->load_post( $booking_id );
214
+
215
+ try {
216
+ \Stripe\Stripe::setApiKey( $stripe_secret );
217
+ $charge = \Stripe\Charge::create(array(
218
+ 'amount' => $payment_amount,
219
+ 'currency' => strtolower( $_gs( 'rtb-currency' ) ),
220
+ 'card' => $token
221
+ )
222
+ );
223
+
224
+ $booking->deposit = $is_JPY ? $payment_amount / 100 : $payment_amount;
225
+ $booking->receipt_id = $charge->id;
226
+
227
+ $booking->determine_status( true );
228
+
229
+ $booking->insert_post_data();
230
+
231
+ do_action( 'rtb_booking_paid', $booking );
232
+
233
+ // redirect on successful payment
234
+ $redirect = add_query_arg(
235
+ array(
236
+ 'payment' => 'paid',
237
+ 'booking_id' => $booking_id
238
+ ),
239
+ $booking_page
240
+ );
241
+
242
+ } catch (Exception $e) {
243
+
244
+ $booking->post_status = 'payment_failed';
245
+ $booking->payment_failure_message = $e->getDeclineCode();
246
+
247
+ $booking->insert_post_data();
248
+
249
+ // redirect on failed payment
250
+ $redirect = add_query_arg(
251
+ array(
252
+ 'payment' => 'failed',
253
+ 'booking_id' => $booking_id,
254
+ 'error_code' => urlencode( $e->getDeclineCode() )
255
+ ),
256
+ $booking_page
257
+ );
258
+ }
259
+
260
+ // redirect back to our previous page with the added query variable
261
+ wp_redirect($redirect); exit;
262
+ }
263
+
264
+ /**
265
+ * Create Stripe payment intent for reservation deposits
266
+ * Respond to AJAX/XHR request
267
+ *
268
+ * @since 2.2.8
269
+ */
270
+ public function create_stripe_pmtIntnt()
271
+ {
272
+ global $rtb_controller;
273
+
274
+ $response = function ($success, $msg, $data = []) {
275
+ echo json_encode(
276
+ array_merge(
277
+ [
278
+ 'success' => $success,
279
+ 'message' => $msg
280
+ ],
281
+ $data
282
+ )
283
+ );
284
+
285
+ exit(0);
286
+ };
287
+
288
+ if( ! isset( $_POST['booking_id'] ) ) {
289
+ $response(false, 'Invalid booking.');
290
+ }
291
+
292
+ require_once( RTB_PLUGIN_DIR . '/includes/Booking.class.php' );
293
+ $booking = new rtbBooking();
294
+ $booking->load_post( $_POST['booking_id'] );
295
+
296
+ $payment_amount = "JPY" != $rtb_controller->settings->get_setting( 'rtb-currency' )
297
+ ? $booking->calculate_deposit() * 100
298
+ : $booking->calculate_deposit();
299
+
300
+ // load the stripe libraries
301
+ require_once(RTB_PLUGIN_DIR . '/lib/stripe/init.php');
302
+
303
+ $stripe_secret = 'test' == $rtb_controller->settings->get_setting( 'rtb-stripe-mode' )
304
+ ? $rtb_controller->settings->get_setting( 'rtb-stripe-test-secret' )
305
+ : $rtb_controller->settings->get_setting( 'rtb-stripe-live-secret' );
306
+
307
+ try {
308
+ \Stripe\Stripe::setApiKey( $stripe_secret );
309
+
310
+ // $customer = \Stripe\Customer::create([
311
+ // 'email' => $booking->email,
312
+ // 'name' => $booking->name
313
+ // ]);
314
+
315
+ // $booking->stripe_customer_id = $customer->id;
316
+ // $booking->insert_post_data();
317
+
318
+ $metadata = array_filter([
319
+ 'Booking ID' => $booking->ID,
320
+ 'Email' => $booking->email,
321
+ 'Name' => $booking->name,
322
+ 'Date' => $booking->date,
323
+ 'Party' => $booking->party
324
+ ]);
325
+
326
+ if( is_array( $booking->table ) && ! empty( $booking->table ) ) {
327
+ $metadata['Table'] = implode('+', $booking->table);
328
+ }
329
+
330
+ $desc = implode(', ', $metadata );
331
+ $stmt_desc = substr( implode( ';', $metadata ), 0, 22 );
332
+
333
+ $intent = \Stripe\PaymentIntent::create([
334
+ 'amount' => $payment_amount,
335
+ 'currency' => $rtb_controller->settings->get_setting( 'rtb-currency' ),
336
+ 'payment_method_types' => ['card'],
337
+ 'receipt_email' => $booking->email,
338
+ 'description' => apply_filters( 'rtb-stripe-payment-desc', $desc ),
339
+ 'statement_descriptor' => apply_filters( 'rtb-stripe-payment-stmnt-desc', $stmt_desc ),
340
+ 'metadata' => $metadata
341
+ ]);
342
+
343
+ $response(
344
+ true,
345
+ 'Payment Intent generated succsssfully',
346
+ [
347
+ 'clientSecret' => $intent->client_secret,
348
+ 'name' => $booking->name,
349
+ 'email' => $booking->email,
350
+ ]
351
+ );
352
+ }
353
+ catch(Exception $ex) {
354
+ $response( false, 'Please try again.', ['error' => $ex->getError()] );
355
+ }
356
+ }
357
+
358
+ /**
359
+ * Stripe SCA payment's final status for reservation deposits
360
+ * Respond to AJAX/XHR request
361
+ *
362
+ * @since 2.2.8
363
+ */
364
+ public function stripe_sca_succeed()
365
+ {
366
+ global $rtb_controller;
367
+
368
+ $response = function ($success = false, $urlParams = '') {
369
+ echo json_encode([
370
+ 'success' => $success,
371
+ 'urlParams' => $urlParams
372
+ ]);
373
+
374
+ exit(0);
375
+ };
376
+
377
+ $success = false;
378
+ $urlParams = '';
379
+
380
+ if( ! isset( $_POST['booking_id'] ) ) {
381
+ $response();
382
+ }
383
+
384
+ require_once( RTB_PLUGIN_DIR . '/includes/Booking.class.php' );
385
+ $booking = new rtbBooking();
386
+ $booking->load_post( $_POST['booking_id'] );
387
+
388
+ if( isset( $_POST['success'] ) && 'false' != $_POST['success'] ) {
389
+
390
+ $booking->deposit = "JPY" != $rtb_controller->settings->get_setting( 'rtb-currency' )
391
+ ? $_POST['payment_amount'] / 100
392
+ : $_POST['payment_amount'];
393
+
394
+ $booking->receipt_id = $_POST['payment_id'];
395
+ $booking->payment_paid();
396
+
397
+ // urlParams on successful payment
398
+ $success = true;
399
+
400
+ $urlParams = array(
401
+ 'payment' => 'paid',
402
+ 'booking_id' => $booking->ID
403
+ );
404
+
405
+ }
406
+ else {
407
+ $payment_failure_message = ! empty( $_POST['message'] )
408
+ ? $_POST['message'] : '';
409
+
410
+ $booking->payment_failed( $payment_failure_message );
411
+ }
412
+
413
+ $response($success, $urlParams);
414
+ }
415
+
416
+ /**
417
+ * Repopulate $booking with stripe meta information
418
+ *
419
+ * @param rtbBooking $booking
420
+ * @param WP_Post $wp_post
421
+ */
422
+ public function populate_booking_stripe_info( rtbBooking $booking, $wp_post )
423
+ {
424
+ if ( is_array( $meta = get_post_meta( $booking->ID, 'rtb', true ) ) ) {
425
+ $booking->stripe_customer_id = isset( $meta['stripe_customer_id'] )
426
+ ? $meta['stripe_customer_id']
427
+ : '';
428
+ }
429
+ }
430
+
431
+ /**
432
+ * Set $booking's default stripe meta information
433
+ *
434
+ * @param rtbBooking $booking
435
+ * @param WP_Post $wp_post
436
+ */
437
+ public function default_booking_stripe_info( $info_list )
438
+ {
439
+ $info_list['stripe_customer_id'] = '';
440
+
441
+ return $info_list;
442
+ }
443
+
444
+ public function save_booking_gateway_info ( $meta, rtbBooking $booking )
445
+ {
446
+ if ( isset( $booking->stripe_customer_id ) && !empty( $booking->stripe_customer_id ) ) {
447
+ $meta['stripe_customer_id'] = $this->stripe_customer_id;
448
+ }
449
+
450
+ return $meta;
451
+ }
452
+ }
453
+
454
+ }
455
+
456
+ /**
457
+ * Gateway has to register itself
458
+ */
459
+ add_filter(
460
+ 'rtb-payment-gateway-register',
461
+ ['rtbPaymentGatewayStripe', 'register_gateway']
462
+ );
includes/PaymentManager.class.php ADDED
@@ -0,0 +1,710 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( !defined( 'ABSPATH' ) ) exit;
3
+
4
+ if ( !class_exists( 'rtbPaymentManager' ) ) {
5
+ /**
6
+ * This class to handle the Payment options for Restaurant Reservations
7
+ *
8
+ * This class sets up the payment options, register all the payment gateways and
9
+ * acts as a bridge between Rest of the plugin and payment gateways like
10
+ * rendering forms, processing payments, handling IPNs etc
11
+ *
12
+ * @since 2.3.0
13
+ */
14
+ class rtbPaymentManager {
15
+
16
+ /**
17
+ * Default values for Payment manager settings
18
+ */
19
+ public $defaults = array();
20
+
21
+ /**
22
+ * Should a premium setting be disabled or not
23
+ */
24
+ public $premium_permissions = array();
25
+
26
+ /**
27
+ * All the available payment processing gateway with their internal name,
28
+ * display name and the PHP Class
29
+ *
30
+ * @var array [
31
+ * 'paypal' => [
32
+ * 'name' => 'PayPal',
33
+ * 'instance' => 'new rtbPaymentGatewayPayPal()'
34
+ * ]
35
+ * ]
36
+ */
37
+ public $available_gateway_list = array();
38
+
39
+ /**
40
+ * List of enabled gateway list from admin
41
+ *
42
+ * @var array ['paypal']
43
+ */
44
+ public $enabled_gateway_list = array();
45
+
46
+ /**
47
+ * Gateway selected for the current booking
48
+ * @var string
49
+ */
50
+ public $in_use_gateway = '';
51
+
52
+ /**
53
+ * Booking object. ID property does not exist when no booking loaded
54
+ * @var rtbBooking
55
+ */
56
+ public $booking;
57
+
58
+ public $booking_form_field_slug = 'payment-gateway';
59
+
60
+ /**
61
+ * Currencies accepted for deposits
62
+ */
63
+ public $currency_options = array(
64
+ 'AUD' => 'Australian Dollar',
65
+ 'BRL' => 'Brazilian Real',
66
+ 'CAD' => 'Canadian Dollar',
67
+ 'CZK' => 'Czech Koruna',
68
+ 'DKK' => 'Danish Krone',
69
+ 'EUR' => 'Euro',
70
+ 'HKD' => 'Hong Kong Dollar',
71
+ 'HUF' => 'Hungarian Forint',
72
+ 'ILS' => 'Israeli New Sheqel',
73
+ 'JPY' => 'Japanese Yen',
74
+ 'MYR' => 'Malaysian Ringgit',
75
+ 'MXN' => 'Mexican Peso',
76
+ 'NOK' => 'Norwegian Krone',
77
+ 'NZD' => 'New Zealand Dollar',
78
+ 'PHP' => 'Philippine Peso',
79
+ 'PLN' => 'Polish Zloty',
80
+ 'GBP' => 'Pound Sterling',
81
+ 'RUB' => 'Russian Ruble',
82
+ 'SGD' => 'Singapore Dollar',
83
+ 'SEK' => 'Swedish Krona',
84
+ 'CHF' => 'Swiss Franc',
85
+ 'TWD' => 'Taiwan New Dollar',
86
+ 'THB' => 'Thai Baht',
87
+ 'TRY' => 'Turkish Lira',
88
+ 'USD' => 'U.S. Dollar'
89
+ );
90
+
91
+ /**
92
+ * Constructor
93
+ */
94
+ public function __construct()
95
+ {
96
+ $this->load_basics();
97
+
98
+ add_filter( 'rtb_settings_check_permissions', [$this, 'check_permissions'] );
99
+
100
+ add_filter( 'rtb_settings_defaults', [$this, 'set_defaults'] );
101
+
102
+ $this->currency_options = apply_filters( 'rtb_payments_currency_options', $this->currency_options );
103
+
104
+ add_filter( 'rtb_settings_page', [$this, 'load_payment_settings'] );
105
+
106
+ do_action( 'rtb_payment_manager_init' );
107
+ }
108
+
109
+ /**
110
+ * Pre-check the permissions to enable/disable Payment Manager's settings
111
+ * as per the current license type
112
+ *
113
+ * @param array checked permissions array from Main settings class
114
+ *
115
+ * @return array checked permissions array amended with payment related permissions
116
+ */
117
+ public function check_permissions( $premium_permissions )
118
+ {
119
+ global $rtb_controller;
120
+
121
+ $this->premium_permissions['payments'] = array();
122
+ if ( ! $rtb_controller->permissions->check_permission('payments') ) {
123
+ $this->premium_permissions['payments'] = array(
124
+ 'disabled' => true,
125
+ 'disabled_image' => 'https://www.etoilewebdesign.com/wp-content/uploads/2018/06/Logo-White-Filled40-px.png',
126
+ 'purchase_link' => 'https://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/',
127
+ 'ultimate_needed' => 'Yes'
128
+ );
129
+ }
130
+
131
+ $this->premium_permissions = array_merge( $premium_permissions, $this->premium_permissions );
132
+
133
+ return $this->premium_permissions;
134
+ }
135
+
136
+ /**
137
+ * Load the Payment Manager's default values in global default values
138
+ *
139
+ * @param array $defaults default values of Payment Gateway settings
140
+ *
141
+ * @return array $defaults
142
+ */
143
+ public function set_defaults( $defaults )
144
+ {
145
+ $this->defaults = array(
146
+ 'rtb-paypal-email' => get_option( 'admin_email' ),
147
+ 'rtb-stripe-mode' => 'test',
148
+ 'rtb-currency' => 'USD',
149
+ 'rtb-stripe-currency-symbol' => '$',
150
+ 'rtb-currency-symbol-location' => 'before'
151
+ );
152
+
153
+ return array_merge( $defaults, $this->defaults );
154
+ }
155
+
156
+ /**
157
+ * Add Payment Manager settings in global settings page
158
+ *
159
+ * @param sapLibrary_2_2_0 $settings_page An object of Simple Admin Pages page
160
+ *
161
+ * @return sapLibrary_2_2_0
162
+ */
163
+ public function load_payment_settings( $settings_page )
164
+ {
165
+ // Add Payment settings tab
166
+ $settings_page->add_section(
167
+ 'rtb-settings',
168
+ array(
169
+ 'id' => 'rtb-payments-tab',
170
+ 'title' => __( 'Payments', 'restaurant-reservations' ),
171
+ 'is_tab' => true,
172
+ 'rank' => 5
173
+ )
174
+ );
175
+
176
+ // Add settings group in Payment settings tab
177
+ $settings_page->add_section(
178
+ 'rtb-settings',
179
+ array_merge(
180
+ array(
181
+ 'id' => 'rtb-general-payment',
182
+ 'title' => __( 'General', 'restaurant-reservations' ),
183
+ 'tab' => 'rtb-payments-tab',
184
+ ),
185
+ $this->premium_permissions['payments']
186
+ )
187
+ );
188
+
189
+ // Add settings in General settings group
190
+ $settings_page->add_setting(
191
+ 'rtb-settings',
192
+ 'rtb-general-payment',
193
+ 'toggle',
194
+ array(
195
+ 'id' => 'require-deposit',
196
+ 'title' => __( 'Require Deposit', 'restaurant-reservations' ),
197
+ 'description' => __( 'Require guests to make a deposit when making a reservation.', 'restaurant-reservations' )
198
+ )
199
+ );
200
+ $settings_page->add_setting(
201
+ 'rtb-settings',
202
+ 'rtb-general-payment',
203
+ 'checkbox',
204
+ array(
205
+ 'id' => 'rtb-payment-gateway',
206
+ 'title' => __( 'Payment Gateway', 'restaurant-reservations' ),
207
+ 'description' => __( 'Which payment gateway should be used to accept deposits.', 'restaurant-reservations' ),
208
+ 'options' => $this->get_available_gateway_list()
209
+ )
210
+ );
211
+ $settings_page->add_setting(
212
+ 'rtb-settings',
213
+ 'rtb-general-payment',
214
+ 'radio',
215
+ array(
216
+ 'id' => 'rtb-deposit-type',
217
+ 'title' => __( 'Deposit Type', 'restaurant-reservations' ),
218
+ 'description' => __( 'What type of deposit should be required, per reservation or per guest?', 'restaurant-reservations' ),
219
+ 'options' => array(
220
+ 'reservation' => 'Per Reservation',
221
+ 'guest' => 'Per Guest'
222
+ )
223
+ )
224
+ );
225
+ $settings_page->add_setting(
226
+ 'rtb-settings',
227
+ 'rtb-general-payment',
228
+ 'text',
229
+ array(
230
+ 'id' => 'rtb-deposit-amount',
231
+ 'title' => __( 'Deposit Amount', 'restaurant-reservations' ),
232
+ 'description' => __( 'What deposit amount is required (either per reservation or per guest, depending on the setting above)? Minimum is $0.50 in most currencies.', 'restaurant-reservations' )
233
+ )
234
+ );
235
+ $settings_page->add_setting(
236
+ 'rtb-settings',
237
+ 'rtb-general-payment',
238
+ 'select',
239
+ array(
240
+ 'id' => 'rtb-currency',
241
+ 'title' => __( 'Currency', 'restaurant-reservations' ),
242
+ 'description' => __( 'Select the currency you accept for your deposits.', 'restaurant-reservations' ),
243
+ 'blank_option' => false,
244
+ 'options' => $this->currency_options
245
+ )
246
+ );
247
+
248
+ // Add settings group in Payment settings tab
249
+ $settings_page->add_section(
250
+ 'rtb-settings',
251
+ array_merge(
252
+ array(
253
+ 'id' => 'rtb-paypal-payment',
254
+ 'title' => __( 'PayPal', 'restaurant-reservations' ),
255
+ 'tab' => 'rtb-payments-tab',
256
+ ),
257
+ $this->premium_permissions['payments']
258
+ )
259
+ );
260
+
261
+ // Add settings in PayPal settings group
262
+ $settings_page->add_setting(
263
+ 'rtb-settings',
264
+ 'rtb-paypal-payment',
265
+ 'text',
266
+ array(
267
+ 'id' => 'rtb-paypal-email',
268
+ 'title' => __( 'PayPal Email Address', 'restaurant-reservations' ),
269
+ 'description' => __( 'The email address you\'ll be using to accept PayPal payments.', 'restaurant-reservations' ),
270
+ 'placeholder' =>$this->defaults['rtb-paypal-email']
271
+ )
272
+ );
273
+
274
+ // Add settings group in Payment settings tab
275
+ $settings_page->add_section(
276
+ 'rtb-settings',
277
+ array_merge(
278
+ array(
279
+ 'id' => 'rtb-stripe-payment',
280
+ 'title' => __( 'Stripe', 'restaurant-reservations' ),
281
+ 'tab' => 'rtb-payments-tab',
282
+ ),
283
+ $this->premium_permissions['payments']
284
+ )
285
+ );
286
+
287
+ // Add settings in Stripe settings group
288
+ $settings_page->add_setting(
289
+ 'rtb-settings',
290
+ 'rtb-stripe-payment',
291
+ 'toggle',
292
+ array(
293
+ 'id' => 'rtb-stripe-sca',
294
+ 'title' => __( 'Strong Customer Authorization (SCA)', 'restaurant-reservations' ),
295
+ 'description' => __( 'User will be redirected to Stripe and presented with 3D secure or bank redirect for payment authentication. (May be necessary for certain EU compliance.)', 'restaurant-reservations' )
296
+ )
297
+ );
298
+ $settings_page->add_setting(
299
+ 'rtb-settings',
300
+ 'rtb-stripe-payment',
301
+ 'text',
302
+ array(
303
+ 'id' => 'rtb-stripe-currency-symbol',
304
+ 'title' => __( 'Stripe Currency Symbol', 'restaurant-reservations' ),
305
+ 'description' => __( 'The currency symbol you\'d like displayed before or after the required deposit amount.', 'restaurant-reservations' ),
306
+ 'placeholder' => $this->defaults['rtb-stripe-currency-symbol']
307
+ )
308
+ );
309
+ $settings_page->add_setting(
310
+ 'rtb-settings',
311
+ 'rtb-stripe-payment',
312
+ 'toggle',
313
+ array(
314
+ 'id' => 'rtb-expiration-field-single',
315
+ 'title' => __( 'CC Expiration Single Field', 'restaurant-reservations' ),
316
+ 'description' => __( 'Should the field for card expiry details be a single field with a mask or two separate fields for month and year?', 'restaurant-reservations' )
317
+ )
318
+ );
319
+ $settings_page->add_setting(
320
+ 'rtb-settings',
321
+ 'rtb-stripe-payment',
322
+ 'radio',
323
+ array(
324
+ 'id' => 'rtb-currency-symbol-location',
325
+ 'title' => __( 'Currency Symbol Location', 'restaurant-reservations' ),
326
+ 'description' => __( 'Should the currency symbol be placed before or after the deposit amount?', 'restaurant-reservations' ),
327
+ 'options' => array(
328
+ 'before' => 'Before',
329
+ 'after' => 'After'
330
+ )
331
+ )
332
+ );
333
+ $settings_page->add_setting(
334
+ 'rtb-settings',
335
+ 'rtb-stripe-payment',
336
+ 'radio',
337
+ array(
338
+ 'id' => 'rtb-stripe-mode',
339
+ 'title' => __( 'Test/Live Mode', 'restaurant-reservations' ),
340
+ 'description' => __( 'Should the system use test or live mode? Test mode should only be used for testing, no deposits will actually be processed while turned on.', 'restaurant-reservations' ),
341
+ 'options' => array(
342
+ 'test' => 'Test',
343
+ 'live' => 'Live'
344
+ )
345
+ )
346
+ );
347
+ $settings_page->add_setting(
348
+ 'rtb-settings',
349
+ 'rtb-stripe-payment',
350
+ 'text',
351
+ array(
352
+ 'id' => 'rtb-stripe-live-secret',
353
+ 'title' => __( 'Stripe Live Secret', 'restaurant-reservations' ),
354
+ 'description' => __( 'The live secret that you have set up for your Stripe account.', 'restaurant-reservations' )
355
+ )
356
+ );
357
+ $settings_page->add_setting(
358
+ 'rtb-settings',
359
+ 'rtb-stripe-payment',
360
+ 'text',
361
+ array(
362
+ 'id' => 'rtb-stripe-live-publishable',
363
+ 'title' => __( 'Stripe Live Publishable', 'restaurant-reservations' ),
364
+ 'description' => __( 'The live publishable that you have set up for your Stripe account.', 'restaurant-reservations' )
365
+ )
366
+ );
367
+ $settings_page->add_setting(
368
+ 'rtb-settings',
369
+ 'rtb-stripe-payment',
370
+ 'text',
371
+ array(
372
+ 'id' => 'rtb-stripe-test-secret',
373
+ 'title' => __( 'Stripe Test Secret', 'restaurant-reservations' ),
374
+ 'description' => __( 'The test secret that you have set up for your Stripe account. Only needed for testing payments.', 'restaurant-reservations' )
375
+ )
376
+ );
377
+ $settings_page->add_setting(
378
+ 'rtb-settings',
379
+ 'rtb-stripe-payment',
380
+ 'text',
381
+ array(
382
+ 'id' => 'rtb-stripe-test-publishable',
383
+ 'title' => __( 'Stripe Test Publishable', 'restaurant-reservations' ),
384
+ 'description' => __( 'The test publishable that you have set up for your Stripe account. Only needed for testing payments.', 'restaurant-reservations' )
385
+ )
386
+ );
387
+
388
+ do_action( 'rtb_settings_payment_manager', $settings_page );
389
+
390
+ return $settings_page;
391
+ }
392
+
393
+ /**
394
+ * Acts like a constructor
395
+ */
396
+ public function load_basics()
397
+ {
398
+ global $rtb_controller;
399
+
400
+ require_once RTB_PLUGIN_DIR . "/includes/PaymentGateway.interface.php";
401
+ require_once RTB_PLUGIN_DIR . "/includes/PaymentGatewayPayPal.class.php";
402
+ require_once RTB_PLUGIN_DIR . "/includes/PaymentGatewayStripe.class.php";
403
+
404
+ do_action( 'rtb_payment_manager_load_gateways' );
405
+
406
+ $this->available_gateway_list = apply_filters(
407
+ 'rtb-payment-gateway-register',
408
+ $this->available_gateway_list
409
+ );
410
+
411
+ $this->strip_invalid_gateway();
412
+
413
+ $this->enabled_gateway_list = $rtb_controller->settings->get_setting( 'rtb-payment-gateway' );
414
+
415
+ $this->enabled_gateway_list = apply_filters(
416
+ 'rtb-payment-active-gateway',
417
+ $this->enabled_gateway_list,
418
+ $this->available_gateway_list
419
+ );
420
+
421
+ // if multiple gateways enabled, print list to ask for one gateway
422
+ if ( 1 < count( $this->enabled_gateway_list ) ) {
423
+ add_filter( 'rtb_booking_form_fields', [$this, 'add_field_booking_form_gateway'], 30, 3 );
424
+ }
425
+
426
+ // Determine $in_use_gateway
427
+ add_action( 'rtb_validate_booking_submission', [$this, 'validate_booking_form_gateway'] );
428
+
429
+ // Save gateway selected/used for booking as booking meta
430
+ add_filter( 'rtb_insert_booking_metadata', [$this, 'save_booking_gateway_used'], 30, 2 );
431
+
432
+ // Repopulate gateway information
433
+ add_action( 'rtb_booking_load_post_data', [$this, 'populate_booking_gateway_used'], 30, 2 );
434
+ }
435
+
436
+ /**
437
+ * Get available gateway list with gateway slug as key and label as value
438
+ *
439
+ * @return array
440
+ */
441
+ public function get_available_gateway_list()
442
+ {
443
+ $list = [];
444
+
445
+ foreach ($this->available_gateway_list as $key => $value) {
446
+ $list[$key] = $value['label'];
447
+ }
448
+
449
+ return $list;
450
+ }
451
+
452
+ /**
453
+ * Get enabled gateway list with gateway slug as key and label as value
454
+ *
455
+ * @return array
456
+ */
457
+ public function get_enabled_gateway_list()
458
+ {
459
+ $list = [];
460
+
461
+ foreach ($this->enabled_gateway_list as $key) {
462
+ $list[$key] = $this->available_gateway_list[$key]['label'];
463
+ }
464
+
465
+ return $list;
466
+ }
467
+
468
+ /**
469
+ * Is Payments functionality enabled?
470
+ *
471
+ * @return boolean
472
+ */
473
+ public function is_payment_enabled()
474
+ {
475
+ global $rtb_controller;
476
+
477
+ return (
478
+ $rtb_controller->settings->get_setting( 'require-deposit' )
479
+ &&
480
+ 0 < count( $this->get_enabled_gateway_list() )
481
+ );
482
+ }
483
+
484
+ /**
485
+ * Add the payment gateway selector field in the bookgin form
486
+ *
487
+ * @param array $fields Booking form field array. For more info, refer to
488
+ * rtbSettings::get_booking_form_fields()
489
+ * @param stdObject $request
490
+ * @param array $args
491
+ */
492
+ public function add_field_booking_form_gateway( $fields, $request, $args )
493
+ {
494
+ if ( ! $this->is_payment_enabled() ) {
495
+ return $fields;
496
+ }
497
+
498
+ /**
499
+ * This is different from admin setting, that is why, to reduce the confusion
500
+ * we use variabel instead of direct field name
501
+ *
502
+ * @var string rtb-payment-gateway
503
+ */
504
+ $prefixed_field_slug = "rtb-{$this->booking_form_field_slug}";
505
+
506
+ $payment_gateway_field = [
507
+ $this->booking_form_field_slug => [
508
+ // 'legend' => __( 'Payment', 'restaurant-reservations' ),
509
+ 'fields' => [
510
+ // Field names are prefixed with "rtb-" while rendering field's HTML
511
+ 'payment-gateway' => [
512
+ 'required' => true,
513
+ 'title' => __( 'Payment Gateway', 'restaurant-reservations' ),
514
+ 'callback' => 'rtb_print_form_select_field',
515
+ 'callback_args' => [
516
+ 'options' => $this->get_enabled_gateway_list(),
517
+ 'empty_option' => true
518
+ ],
519
+ 'request_input' => isset( $request->raw_input[$prefixed_field_slug] )
520
+ ? $request->raw_input[$prefixed_field_slug]
521
+ : (
522
+ property_exists($request, $this->booking_form_field_slug)
523
+ ? $request->{$this->booking_form_field_slug}
524
+ : ''
525
+ )
526
+ ]
527
+ ]
528
+ ]
529
+ ];
530
+
531
+ return array_merge( $fields, $payment_gateway_field );
532
+ }
533
+
534
+ /**
535
+ * Validate the payment gateway option
536
+ *
537
+ * $booking is not set yet
538
+ *
539
+ * @param stdObject $request
540
+ */
541
+ public function validate_booking_form_gateway( $request )
542
+ {
543
+ if ( ! $this->is_payment_enabled() ) {
544
+ return;
545
+ }
546
+
547
+ $prefixed_field_slug = "rtb-{$this->booking_form_field_slug}";
548
+
549
+ // Do not validate if only one gateway enabled
550
+ if ( 1 === count( $this->enabled_gateway_list ) ) {
551
+ $this->in_use_gateway = $this->enabled_gateway_list[0];
552
+ }
553
+ elseif (
554
+ array_key_exists( $prefixed_field_slug, $_POST )
555
+ &&
556
+ ! empty( $_POST[$prefixed_field_slug] )
557
+ &&
558
+ in_array( $_POST[$prefixed_field_slug], $this->enabled_gateway_list )
559
+ )
560
+ {
561
+ $this->in_use_gateway = $_POST[$prefixed_field_slug];
562
+ }
563
+ else {
564
+ $request->validation_errors[] = array(
565
+ 'field' => $prefixed_field_slug,
566
+ 'message' => __( 'Please select a valid payment gateway.', 'restaurant-reservations' )
567
+ );
568
+ }
569
+
570
+ if ( $this->isset_gateway_in_use() ) {
571
+ $request->{$this->booking_form_field_slug} = $this->in_use_gateway;
572
+ }
573
+ }
574
+
575
+ /**
576
+ * Attach payment gateway information with the booking
577
+ *
578
+ * @param array $meta
579
+ * @param rtbBooking $booking
580
+ *
581
+ * @return array
582
+ */
583
+ public function save_booking_gateway_used( $meta, rtbBooking $booking )
584
+ {
585
+ if ( isset( $booking->{$this->booking_form_field_slug} ) ) {
586
+ $meta[$this->booking_form_field_slug] = $booking->{$this->booking_form_field_slug};
587
+ }
588
+
589
+ return $meta;
590
+ }
591
+
592
+ /**
593
+ * Repopulate $booking with gateway information
594
+ *
595
+ * @param rtbBooking $booking
596
+ * @param WP_Post $wp_post
597
+ */
598
+ public function populate_booking_gateway_used( rtbBooking $booking, $wp_post )
599
+ {
600
+ if ( is_array( $meta = get_post_meta( $booking->ID, 'rtb', true ) ) ) {
601
+ $booking->{$this->booking_form_field_slug} = isset( $meta[$this->booking_form_field_slug] )
602
+ ? $meta[$this->booking_form_field_slug]
603
+ : '';
604
+ }
605
+ }
606
+
607
+ /**
608
+ * Print the payment form's HTML code, after a new booking has been inserted
609
+ * notices.
610
+ *
611
+ * $booking must be set before this.
612
+ */
613
+ public function print_payment_form()
614
+ {
615
+ global $rtb_controller;
616
+
617
+ require_once( RTB_PLUGIN_DIR . '/includes/Booking.class.php' );
618
+
619
+ if ( ! $this->isset_gateway_in_use() ) {
620
+ $this->set_gateway_in_use( $this->booking->{$this->booking_form_field_slug} );
621
+ }
622
+
623
+ if (
624
+ in_array( $this->in_use_gateway, $this->enabled_gateway_list )
625
+ &&
626
+ property_exists($this->booking, 'ID')
627
+ )
628
+ {
629
+ $gateway = $this->available_gateway_list[$this->in_use_gateway]['instance'];
630
+
631
+ $gateway->print_payment_form( $this->booking );
632
+ }
633
+ else {
634
+ $this->print_invalid_gateway();
635
+ }
636
+ }
637
+
638
+ public function print_invalid_gateway()
639
+ {
640
+ echo __(
641
+ 'Invalid gateweay selected. Please contact us for the confirmation.',
642
+ 'restaurant-reservations'
643
+ );
644
+ }
645
+
646
+ public function process_payment()
647
+ {
648
+ // code...
649
+ }
650
+
651
+ public function is_payment_processed()
652
+ {
653
+ // code...
654
+ }
655
+
656
+ public function payment_processing_status()
657
+ {
658
+ // code...
659
+ }
660
+
661
+ /**
662
+ * Set booking object
663
+ *
664
+ * @param rtbBooking $booking
665
+ */
666
+ public function set_booking(rtbBooking $booking)
667
+ {
668
+ $this->booking = $booking;
669
+
670
+ return $this;
671
+ }
672
+
673
+ public function set_gateway_in_use( $gateway )
674
+ {
675
+ $this->in_use_gateway = $gateway;
676
+ }
677
+
678
+ public function get_gateway_in_use()
679
+ {
680
+ if ( $this->isset_gateway_in_use() ) {
681
+ return $this->in_use_gateway;
682
+ }
683
+
684
+ return '';
685
+ }
686
+
687
+ public function isset_gateway_in_use()
688
+ {
689
+ return in_array( $this->in_use_gateway, $this->enabled_gateway_list );
690
+ }
691
+
692
+ /**
693
+ * Remove any class registered as payment gateway without implementing the
694
+ * payment gateway interface
695
+ */
696
+ public function strip_invalid_gateway()
697
+ {
698
+ $new_list = [];
699
+
700
+ foreach ( $this->available_gateway_list as $gateway => $data ) {
701
+ if ( $data['instance'] instanceof rtbPaymentGateway ) {
702
+ $new_list[$gateway] = $data;
703
+ }
704
+ }
705
+
706
+ $this->available_gateway_list = $new_list;
707
+ }
708
+ }
709
+
710
+ }
includes/Settings.class.php CHANGED
@@ -21,6 +21,12 @@ class rtbSettings {
21
  */
22
  public $settings = array();
23
 
 
 
 
 
 
 
24
  /**
25
  * Languages supported by the pickadate library
26
  */
@@ -70,37 +76,6 @@ class rtbSettings {
70
  'zh_TW' => 'zh_TW',
71
  );
72
 
73
- /**
74
- * Currencies accepted for deposits
75
- */
76
- public $currency_options = array(
77
- 'AUD' => 'Australian Dollar',
78
- 'BRL' => 'Brazilian Real',
79
- 'CAD' => 'Canadian Dollar',
80
- 'CZK' => 'Czech Koruna',
81
- 'DKK' => 'Danish Krone',
82
- 'EUR' => 'Euro',
83
- 'HKD' => 'Hong Kong Dollar',
84
- 'HUF' => 'Hungarian Forint',
85
- 'ILS' => 'Israeli New Sheqel',
86
- 'JPY' => 'Japanese Yen',
87
- 'MYR' => 'Malaysian Ringgit',
88
- 'MXN' => 'Mexican Peso',
89
- 'NOK' => 'Norwegian Krone',
90
- 'NZD' => 'New Zealand Dollar',
91
- 'PHP' => 'Philippine Peso',
92
- 'PLN' => 'Polish Zloty',
93
- 'GBP' => 'Pound Sterling',
94
- 'RUB' => 'Russian Ruble',
95
- 'SGD' => 'Singapore Dollar',
96
- 'SEK' => 'Swedish Krona',
97
- 'CHF' => 'Swiss Franc',
98
- 'TWD' => 'Taiwan New Dollar',
99
- 'THB' => 'Thai Baht',
100
- 'TRY' => 'Turkish Lira',
101
- 'USD' => 'U.S. Dollar',
102
- );
103
-
104
  public $country_phone_array = array(
105
  // 'AD' => array( 'name' => 'ANDORRA', 'code' => '376' ),
106
  // 'AE' => array( 'name' => 'UNITED ARAB EMIRATES', 'code' => '971' ),
@@ -336,15 +311,102 @@ class rtbSettings {
336
 
337
  public function __construct() {
338
 
339
- add_action( 'init', array( $this, 'set_defaults' ) );
 
 
340
 
341
- add_action( 'init', array( $this, 'load_settings_panel' ) );
342
 
343
  // Order schedule exceptions and remove past exceptions
344
  add_filter( 'sanitize_option_rtb-settings', array( $this, 'clean_schedule_exceptions' ), 100 );
345
 
346
  }
347
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
348
  /**
349
  * Load the plugin's default settings
350
  * @since 0.0.1
@@ -361,13 +423,6 @@ class rtbSettings {
361
  'time-format' => _x( 'h:i A', 'Default time format for display. Must match formatting rules at http://amsul.ca/pickadate.js/time/#formats', 'restaurant-reservations' ),
362
  'time-interval' => _x( '30', 'Default interval in minutes when selecting a time.', 'restaurant-reservations' ),
363
 
364
- // Payment defaults
365
- 'rtb-paypal-email' => get_option( 'admin_email' ),
366
- 'rtb-stripe-currency-symbol' => '$',
367
- 'rtb-currency-symbol-location' => 'before',
368
- 'rtb-currency' => 'USD',
369
- 'rtb-stripe-mode' => 'live',
370
-
371
  // Export defaults
372
  'ebfrtb-paper-size' => 'A4',
373
  'ebfrtb-pdf-lib' => 'mpdf',
@@ -561,7 +616,7 @@ If you were not the one to cancel this booking, please contact us.
561
  $this->defaults['i8n'] = $i8n;
562
  }
563
 
564
- $this->defaults = apply_filters( 'rtb_defaults', $this->defaults );
565
  }
566
 
567
  /**
@@ -1157,15 +1212,6 @@ If you were not the one to cancel this booking, please contact us.
1157
  )
1158
  );
1159
 
1160
- if ( ! $rtb_controller->permissions->check_permission('premium_view_bookings') ) {
1161
- $premium_view_bookings_permissions = array(
1162
- 'disabled' => true,
1163
- 'disabled_image'=> 'https://www.etoilewebdesign.com/wp-content/uploads/2018/06/Logo-White-Filled40-px.png',
1164
- 'purchase_link' => 'https://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/'
1165
- );
1166
- }
1167
- else { $premium_view_bookings_permissions = array(); }
1168
-
1169
  $sap->add_section(
1170
  'rtb-settings',
1171
  array(
@@ -1183,7 +1229,7 @@ If you were not the one to cancel this booking, please contact us.
1183
  'title' => __( 'View Bookings Form', 'restaurant-reservations' ),
1184
  'tab' => 'rtb-premium',
1185
  ),
1186
- $premium_view_bookings_permissions
1187
  )
1188
  );
1189
  $sap->add_setting(
@@ -1223,15 +1269,6 @@ If you were not the one to cancel this booking, please contact us.
1223
  )
1224
  );
1225
 
1226
- if ( ! $rtb_controller->permissions->check_permission('mailchimp') ) {
1227
- $mailchimp_permissions = array(
1228
- 'disabled' => true,
1229
- 'disabled_image'=> 'https://www.etoilewebdesign.com/wp-content/uploads/2018/06/Logo-White-Filled40-px.png',
1230
- 'purchase_link' => 'https://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/'
1231
- );
1232
- }
1233
- else { $mailchimp_permissions = array(); }
1234
-
1235
  $sap->add_section(
1236
  'rtb-settings',
1237
  array_merge(
@@ -1240,7 +1277,7 @@ If you were not the one to cancel this booking, please contact us.
1240
  'title' => __( 'MailChimp', 'restaurant-reservations' ),
1241
  'tab' => 'rtb-premium',
1242
  ),
1243
- $mailchimp_permissions
1244
  )
1245
  );
1246
 
@@ -1308,15 +1345,6 @@ If you were not the one to cancel this booking, please contact us.
1308
  );
1309
  }
1310
 
1311
- if ( ! $rtb_controller->permissions->check_permission('premium_seat_restrictions') ) {
1312
- $premium_seat_restrictions_permissions = array(
1313
- 'disabled' => true,
1314
- 'disabled_image'=> 'https://www.etoilewebdesign.com/wp-content/uploads/2018/06/Logo-White-Filled40-px.png',
1315
- 'purchase_link' => 'https://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/'
1316
- );
1317
- }
1318
- else { $premium_seat_restrictions_permissions = array(); }
1319
-
1320
  $sap->add_section(
1321
  'rtb-settings',
1322
  array_merge(
@@ -1325,7 +1353,7 @@ If you were not the one to cancel this booking, please contact us.
1325
  'title' => __( 'Seat Restrictions', 'restaurant-reservations' ),
1326
  'tab' => 'rtb-premium',
1327
  ),
1328
- $premium_seat_restrictions_permissions
1329
  )
1330
  );
1331
  $sap->add_setting(
@@ -1412,16 +1440,6 @@ If you were not the one to cancel this booking, please contact us.
1412
  )
1413
  );
1414
 
1415
- if ( ! $rtb_controller->permissions->check_permission('premium_table_restrictions') ) {
1416
- $premium_table_restrictions_permissions = array(
1417
- 'disabled' => true,
1418
- 'disabled_image'=> 'https://www.etoilewebdesign.com/wp-content/uploads/2018/06/Logo-White-Filled40-px.png',
1419
- 'purchase_link' => 'https://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/',
1420
- 'ultimate_needed' => 'Yes'
1421
- );
1422
- }
1423
- else { $premium_table_restrictions_permissions = array(); }
1424
-
1425
  $sap->add_section(
1426
  'rtb-settings',
1427
  array_merge(
@@ -1430,9 +1448,10 @@ If you were not the one to cancel this booking, please contact us.
1430
  'title' => __( 'Table Restrictions', 'restaurant-reservations' ),
1431
  'tab' => 'rtb-premium',
1432
  ),
1433
- $premium_table_restrictions_permissions
1434
  )
1435
  );
 
1436
  $sap->add_setting(
1437
  'rtb-settings',
1438
  'rtb-table-assignments',
@@ -1443,6 +1462,7 @@ If you were not the one to cancel this booking, please contact us.
1443
  'description' => __( 'Allow guests to select a table that they\'d like to sit at during their visit.', 'restaurant-reservations' )
1444
  )
1445
  );
 
1446
  $sap->add_setting(
1447
  'rtb-settings',
1448
  'rtb-table-assignments',
@@ -1453,6 +1473,7 @@ If you were not the one to cancel this booking, please contact us.
1453
  'description' => __( 'Don\'t allow a reservation to be made without a valid table selected, even if all other booking criteria are met (acceptable party size, below max reservations/seats).', 'restaurant-reservations' )
1454
  )
1455
  );
 
1456
  $sap->add_setting(
1457
  'rtb-settings',
1458
  'rtb-table-assignments',
@@ -1487,6 +1508,7 @@ If you were not the one to cancel this booking, please contact us.
1487
  )
1488
  )
1489
  );
 
1490
  $sap->add_setting(
1491
  'rtb-settings',
1492
  'rtb-table-assignments',
@@ -1527,15 +1549,6 @@ If you were not the one to cancel this booking, please contact us.
1527
  )
1528
  );
1529
 
1530
- if ( ! $rtb_controller->permissions->check_permission('designer') ) {
1531
- $designer_permissions = array(
1532
- 'disabled' => true,
1533
- 'disabled_image'=> 'https://www.etoilewebdesign.com/wp-content/uploads/2018/06/Logo-White-Filled40-px.png',
1534
- 'purchase_link' => 'https://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/'
1535
- );
1536
- }
1537
- else { $designer_permissions = array(); }
1538
-
1539
  $sap->add_section(
1540
  'rtb-settings',
1541
  array(
@@ -1553,7 +1566,7 @@ If you were not the one to cancel this booking, please contact us.
1553
  'title' => __( 'Email Templates', 'restaurant-reservations' ),
1554
  'tab' => 'rtb-notifications-tab',
1555
  ),
1556
- $designer_permissions
1557
  )
1558
  );
1559
 
@@ -1853,16 +1866,6 @@ If you were not the one to cancel this booking, please contact us.
1853
  )
1854
  );
1855
 
1856
- if ( ! $rtb_controller->permissions->check_permission('reminders') ) {
1857
- $reminders_permissions = array(
1858
- 'disabled' => true,
1859
- 'disabled_image' => 'https://www.etoilewebdesign.com/wp-content/uploads/2018/06/Logo-White-Filled40-px.png',
1860
- 'purchase_link' => 'https://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/',
1861
- 'ultimate_needed' => 'Yes'
1862
- );
1863
- }
1864
- else { $reminders_permissions = array(); }
1865
-
1866
  $sap->add_section(
1867
  'rtb-settings',
1868
  array_merge(
@@ -1872,7 +1875,7 @@ If you were not the one to cancel this booking, please contact us.
1872
  'tab' => 'rtb-notifications-tab',
1873
  'description' => __( 'Set up reservation and late arrival reminders.' ),
1874
  ),
1875
- $reminders_permissions
1876
  )
1877
  );
1878
 
@@ -1889,7 +1892,9 @@ If you were not the one to cancel this booking, please contact us.
1889
  );
1890
 
1891
  $country_phone_display_array = array();
1892
- foreach ( $this->country_phone_array as $country_code => $country_array ) { $country_phone_display_array[$country_code] = $country_array['name'] . ' (+' . $country_array['code'] . ')'; }
 
 
1893
 
1894
  $sap->add_setting(
1895
  'rtb-settings',
@@ -1935,23 +1940,23 @@ If you were not the one to cancel this booking, please contact us.
1935
  );
1936
 
1937
  $sap->add_setting(
1938
- 'rtb-settings',
1939
- 'rtb-reservation-reminders',
1940
- 'count',
1941
- array(
1942
- 'id' => 'time-reminder-user',
1943
- 'title' => __( 'Reservation Reminder Before Time', 'restaurant-reservations' ),
1944
- 'description' => __( 'How long before a reservation should a reminder email be sent? Leave blank to not send a reservation reminder.', 'restaurant-reservations' ),
1945
- 'min_value' => 1,
1946
- 'max_value' => 60,
1947
- 'increment' => 1,
1948
- 'units' => array(
1949
- 'minutes' => 'Minutes',
1950
- 'hours' => 'Hours',
1951
- 'days' => 'Days'
1952
- )
1953
- )
1954
- );
1955
 
1956
  $sap->add_setting(
1957
  'rtb-settings',
@@ -1982,15 +1987,15 @@ If you were not the one to cancel this booking, please contact us.
1982
  'rtb-reservation-reminders',
1983
  'count',
1984
  array(
1985
- 'id' => 'time-late-user',
1986
- 'title' => __( 'Late for Reservation Time', 'restaurant-reservations' ),
1987
- 'description' => __( 'How long after being late for a reservation should a late arrival email be sent? Leave blank to not send a late arrival email.', 'restaurant-reservations' ),
1988
- 'min_value' => 1,
1989
  'max_value' => 60,
1990
  'increment' => 1,
1991
- 'units' => array(
1992
- 'minutes' => 'Minutes',
1993
- 'hours' => 'Hours',
1994
  )
1995
  )
1996
  );
@@ -2051,240 +2056,6 @@ If you were not the one to cancel this booking, please contact us.
2051
  )
2052
  );
2053
 
2054
- if ( ! $rtb_controller->permissions->check_permission('payments') ) {
2055
- $payment_permissions = array(
2056
- 'disabled' => true,
2057
- 'disabled_image' => 'https://www.etoilewebdesign.com/wp-content/uploads/2018/06/Logo-White-Filled40-px.png',
2058
- 'purchase_link' => 'https://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/',
2059
- 'ultimate_needed' => 'Yes'
2060
- );
2061
- }
2062
- else { $payment_permissions = array(); }
2063
-
2064
- $sap->add_section(
2065
- 'rtb-settings',
2066
- array(
2067
- 'id' => 'rtb-payments-tab',
2068
- 'title' => __( 'Payments', 'restaurant-reservations' ),
2069
- 'is_tab' => true,
2070
- )
2071
- );
2072
-
2073
- $sap->add_section(
2074
- 'rtb-settings',
2075
- array_merge(
2076
- array(
2077
- 'id' => 'rtb-general-payment',
2078
- 'title' => __( 'General', 'restaurant-reservations' ),
2079
- 'tab' => 'rtb-payments-tab',
2080
- ),
2081
- $payment_permissions
2082
- )
2083
- );
2084
- $sap->add_setting(
2085
- 'rtb-settings',
2086
- 'rtb-general-payment',
2087
- 'toggle',
2088
- array(
2089
- 'id' => 'require-deposit',
2090
- 'title' => __( 'Require Deposit', 'restaurant-reservations' ),
2091
- 'description' => __( 'Require guests to make a deposit when making a reservation.', 'restaurant-reservations' )
2092
- )
2093
- );
2094
- $sap->add_setting(
2095
- 'rtb-settings',
2096
- 'rtb-general-payment',
2097
- 'radio',
2098
- array(
2099
- 'id' => 'rtb-payment-gateway',
2100
- 'title' => __( 'Payment Gateway', 'restaurant-reservations' ),
2101
- 'description' => __( 'Which payment gateway should be used to accept deposits.', 'restaurant-reservations' ),
2102
- 'options' => array(
2103
- 'paypal' => 'PayPal',
2104
- 'stripe' => 'Stripe'
2105
- )
2106
- )
2107
- );
2108
- $sap->add_setting(
2109
- 'rtb-settings',
2110
- 'rtb-general-payment',
2111
- 'radio',
2112
- array(
2113
- 'id' => 'rtb-deposit-type',
2114
- 'title' => __( 'Deposit Type', 'restaurant-reservations' ),
2115
- 'description' => __( 'What type of deposit should be required, per reservation or per guest?', 'restaurant-reservations' ),
2116
- 'options' => array(
2117
- 'reservation' => 'Per Reservation',
2118
- 'guest' => 'Per Guest'
2119
- )
2120
- )
2121
- );
2122
- $sap->add_setting(
2123
- 'rtb-settings',
2124
- 'rtb-general-payment',
2125
- 'text',
2126
- array(
2127
- 'id' => 'rtb-deposit-amount',
2128
- 'title' => __( 'Deposit Amount', 'restaurant-reservations' ),
2129
- 'description' => __( 'What deposit amount is required (either per reservation or per guest, depending on the setting above)? Minimum is $0.50 in most currencies.', 'restaurant-reservations' )
2130
- )
2131
- );
2132
- $sap->add_setting(
2133
- 'rtb-settings',
2134
- 'rtb-general-payment',
2135
- 'select',
2136
- array(
2137
- 'id' => 'rtb-currency',
2138
- 'title' => __( 'Currency', 'restaurant-reservations' ),
2139
- 'description' => __( 'Select the currency you accept for your deposits.', 'restaurant-reservations' ),
2140
- 'blank_option' => false,
2141
- 'options' => $this->currency_options
2142
- )
2143
- );
2144
-
2145
- $sap->add_section(
2146
- 'rtb-settings',
2147
- array_merge(
2148
- array(
2149
- 'id' => 'rtb-paypal-payment',
2150
- 'title' => __( 'PayPal', 'restaurant-reservations' ),
2151
- 'tab' => 'rtb-payments-tab',
2152
- ),
2153
- $payment_permissions
2154
- )
2155
- );
2156
- $sap->add_setting(
2157
- 'rtb-settings',
2158
- 'rtb-paypal-payment',
2159
- 'text',
2160
- array(
2161
- 'id' => 'rtb-paypal-email',
2162
- 'title' => __( 'PayPal Email Address', 'restaurant-reservations' ),
2163
- 'description' => __( 'The email address you\'ll be using to accept PayPal payments.', 'restaurant-reservations' ),
2164
- 'placeholder' =>$this->defaults['rtb-paypal-email']
2165
- )
2166
- );
2167
-
2168
- $sap->add_section(
2169
- 'rtb-settings',
2170
- array_merge(
2171
- array(
2172
- 'id' => 'rtb-stripe-payment',
2173
- 'title' => __( 'Stripe', 'restaurant-reservations' ),
2174
- 'tab' => 'rtb-payments-tab',
2175
- ),
2176
- $payment_permissions
2177
- )
2178
- );
2179
- $sap->add_setting(
2180
- 'rtb-settings',
2181
- 'rtb-stripe-payment',
2182
- 'toggle',
2183
- array(
2184
- 'id' => 'rtb-stripe-sca',
2185
- 'title' => __( 'Strong Customer Authorization (SCA)', 'restaurant-reservations' ),
2186
- 'description' => __( 'User will be redirected to Stripe and presented with 3D secure or bank redirect for payment authentication. (May be necessary for certain EU compliance.)', 'restaurant-reservations' )
2187
- )
2188
- );
2189
- $sap->add_setting(
2190
- 'rtb-settings',
2191
- 'rtb-stripe-payment',
2192
- 'text',
2193
- array(
2194
- 'id' => 'rtb-stripe-currency-symbol',
2195
- 'title' => __( 'Stripe Currency Symbol', 'restaurant-reservations' ),
2196
- 'description' => __( 'The currency symbol you\'d like displayed before or after the required deposit amount.', 'restaurant-reservations' ),
2197
- 'placeholder' => $this->defaults['rtb-stripe-currency-symbol']
2198
- )
2199
- );
2200
- $sap->add_setting(
2201
- 'rtb-settings',
2202
- 'rtb-stripe-payment',
2203
- 'toggle',
2204
- array(
2205
- 'id' => 'rtb-expiration-field-single',
2206
- 'title' => __( 'CC Expiration Single Field', 'restaurant-reservations' ),
2207
- 'description' => __( 'Should the field for card expiry details be a single field with a mask or two separate fields for month and year?', 'restaurant-reservations' )
2208
- )
2209
- );
2210
- $sap->add_setting(
2211
- 'rtb-settings',
2212
- 'rtb-stripe-payment',
2213
- 'radio',
2214
- array(
2215
- 'id' => 'rtb-currency-symbol-location',
2216
- 'title' => __( 'Currency Symbol Location', 'restaurant-reservations' ),
2217
- 'description' => __( 'Should the currency symbol be placed before or after the deposit amount?', 'restaurant-reservations' ),
2218
- 'options' => array(
2219
- 'before' => 'Before',
2220
- 'after' => 'After'
2221
- )
2222
- )
2223
- );
2224
- $sap->add_setting(
2225
- 'rtb-settings',
2226
- 'rtb-stripe-payment',
2227
- 'radio',
2228
- array(
2229
- 'id' => 'rtb-stripe-mode',
2230
- 'title' => __( 'Test/Live Mode', 'restaurant-reservations' ),
2231
- 'description' => __( 'Should the system use test or live mode? Test mode should only be used for testing, no deposits will actually be processed while turned on.', 'restaurant-reservations' ),
2232
- 'options' => array(
2233
- 'test' => 'Test',
2234
- 'live' => 'Live'
2235
- )
2236
- )
2237
- );
2238
- $sap->add_setting(
2239
- 'rtb-settings',
2240
- 'rtb-stripe-payment',
2241
- 'text',
2242
- array(
2243
- 'id' => 'rtb-stripe-live-secret',
2244
- 'title' => __( 'Stripe Live Secret', 'restaurant-reservations' ),
2245
- 'description' => __( 'The live secret that you have set up for your Stripe account.', 'restaurant-reservations' )
2246
- )
2247
- );
2248
- $sap->add_setting(
2249
- 'rtb-settings',
2250
- 'rtb-stripe-payment',
2251
- 'text',
2252
- array(
2253
- 'id' => 'rtb-stripe-live-publishable',
2254
- 'title' => __( 'Stripe Live Publishable', 'restaurant-reservations' ),
2255
- 'description' => __( 'The live publishable that you have set up for your Stripe account.', 'restaurant-reservations' )
2256
- )
2257
- );
2258
- $sap->add_setting(
2259
- 'rtb-settings',
2260
- 'rtb-stripe-payment',
2261
- 'text',
2262
- array(
2263
- 'id' => 'rtb-stripe-test-secret',
2264
- 'title' => __( 'Stripe Test Secret', 'restaurant-reservations' ),
2265
- 'description' => __( 'The test secret that you have set up for your Stripe account. Only needed for testing payments.', 'restaurant-reservations' )
2266
- )
2267
- );
2268
- $sap->add_setting(
2269
- 'rtb-settings',
2270
- 'rtb-stripe-payment',
2271
- 'text',
2272
- array(
2273
- 'id' => 'rtb-stripe-test-publishable',
2274
- 'title' => __( 'Stripe Test Publishable', 'restaurant-reservations' ),
2275
- 'description' => __( 'The test publishable that you have set up for your Stripe account. Only needed for testing payments.', 'restaurant-reservations' )
2276
- )
2277
- );
2278
-
2279
- if ( ! $rtb_controller->permissions->check_permission('export') ) {
2280
- $export_permissions = array(
2281
- 'disabled' => true,
2282
- 'disabled_image'=> 'https://www.etoilewebdesign.com/wp-content/uploads/2018/06/Logo-White-Filled40-px.png',
2283
- 'purchase_link' => 'https://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/'
2284
- );
2285
- }
2286
- else { $export_permissions = array(); }
2287
-
2288
  //Create a tab for export settings
2289
  $sap->add_section(
2290
  'rtb-settings',
@@ -2303,7 +2074,7 @@ If you were not the one to cancel this booking, please contact us.
2303
  'title' => __( 'Settings', 'restaurant-reservations' ),
2304
  'tab' => 'rtb-export-tab',
2305
  ),
2306
- $export_permissions
2307
  )
2308
  );
2309
 
@@ -2351,15 +2122,6 @@ If you were not the one to cancel this booking, please contact us.
2351
  )
2352
  );
2353
 
2354
- if ( ! $rtb_controller->permissions->check_permission('styling') ) {
2355
- $styling_permissions = array(
2356
- 'disabled' => true,
2357
- 'disabled_image'=> 'https://www.etoilewebdesign.com/wp-content/uploads/2018/06/Logo-White-Filled40-px.png',
2358
- 'purchase_link' => 'https://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/'
2359
- );
2360
- }
2361
- else { $styling_permissions = array(); }
2362
-
2363
  // Create a tab for styling settings
2364
  $sap->add_section(
2365
  'rtb-settings',
@@ -2378,7 +2140,7 @@ If you were not the one to cancel this booking, please contact us.
2378
  'title' => __( 'Reservation Form', 'restaurant-reservations' ),
2379
  'tab' => 'rtb-styling-settings-tab',
2380
  ),
2381
- $styling_permissions
2382
  )
2383
  );
2384
 
@@ -2914,10 +2676,18 @@ If you were not the one to cancel this booking, please contact us.
2914
  $require_table = $rtb_controller->settings->get_setting( 'require-table' );
2915
  if ( $enable_tables ) {
2916
 
2917
-
2918
  $fields['reservation']['fields']['table'] = array(
2919
  'title' => __( 'Table(s)', 'restaurant-reservations' ),
2920
- 'request_input' => empty( $request->table ) ? '' : $request->table,
 
 
 
 
 
 
 
 
 
2921
  'callback' => 'rtb_print_form_select_field',
2922
  'callback_args' => array(
2923
  'options' => $this->get_form_table_options(),
21
  */
22
  public $settings = array();
23
 
24
+ /**
25
+ * Should a premium setting be disabled or not
26
+ * @since 2.4.0
27
+ */
28
+ public $premium_permissions = array();
29
+
30
  /**
31
  * Languages supported by the pickadate library
32
  */
76
  'zh_TW' => 'zh_TW',
77
  );
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  public $country_phone_array = array(
80
  // 'AD' => array( 'name' => 'ANDORRA', 'code' => '376' ),
81
  // 'AE' => array( 'name' => 'UNITED ARAB EMIRATES', 'code' => '971' ),
311
 
312
  public function __construct() {
313
 
314
+ add_action( 'init', array( $this, 'check_permissions' ), 10 );
315
+
316
+ add_action( 'init', array( $this, 'set_defaults' ), 11 );
317
 
318
+ add_action( 'init', array( $this, 'load_settings_panel' ), 12 );
319
 
320
  // Order schedule exceptions and remove past exceptions
321
  add_filter( 'sanitize_option_rtb-settings', array( $this, 'clean_schedule_exceptions' ), 100 );
322
 
323
  }
324
 
325
+ /**
326
+ * Pre-check the permissions to enable/disable settings as per the
327
+ * current license type
328
+ * @return void
329
+ */
330
+ public function check_permissions() {
331
+ global $rtb_controller;
332
+
333
+ $this->premium_permissions['view_bookings'] = array();
334
+ if ( ! $rtb_controller->permissions->check_permission('premium_view_bookings') ) {
335
+ $this->premium_permissions['view_bookings'] = array(
336
+ 'disabled' => true,
337
+ 'disabled_image' => 'https://www.etoilewebdesign.com/wp-content/uploads/2018/06/Logo-White-Filled40-px.png',
338
+ 'purchase_link' => 'https://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/'
339
+ );
340
+ }
341
+
342
+ $this->premium_permissions['mailchimp'] = array();
343
+ if ( ! $rtb_controller->permissions->check_permission('mailchimp') ) {
344
+ $this->premium_permissions['mailchimp'] = array(
345
+ 'disabled' => true,
346
+ 'disabled_image' => 'https://www.etoilewebdesign.com/wp-content/uploads/2018/06/Logo-White-Filled40-px.png',
347
+ 'purchase_link' => 'https://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/'
348
+ );
349
+ }
350
+
351
+ $this->premium_permissions['seat_restrictions'] = array();
352
+ if ( ! $rtb_controller->permissions->check_permission('premium_seat_restrictions') ) {
353
+ $this->premium_permissions['seat_restrictions'] = array(
354
+ 'disabled' => true,
355
+ 'disabled_image' => 'https://www.etoilewebdesign.com/wp-content/uploads/2018/06/Logo-White-Filled40-px.png',
356
+ 'purchase_link' => 'https://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/'
357
+ );
358
+ }
359
+
360
+ $this->premium_permissions['table_restrictions'] = array();
361
+ if ( ! $rtb_controller->permissions->check_permission('premium_table_restrictions') ) {
362
+ $this->premium_permissions['table_restrictions'] = array(
363
+ 'disabled' => true,
364
+ 'disabled_image' => 'https://www.etoilewebdesign.com/wp-content/uploads/2018/06/Logo-White-Filled40-px.png',
365
+ 'purchase_link' => 'https://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/',
366
+ 'ultimate_needed' => 'Yes'
367
+ );
368
+ }
369
+
370
+ $this->premium_permissions['designer'] = array();
371
+ if ( ! $rtb_controller->permissions->check_permission('designer') ) {
372
+ $this->premium_permissions['designer'] = array(
373
+ 'disabled' => true,
374
+ 'disabled_image' => 'https://www.etoilewebdesign.com/wp-content/uploads/2018/06/Logo-White-Filled40-px.png',
375
+ 'purchase_link' => 'https://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/'
376
+ );
377
+ }
378
+
379
+ $this->premium_permissions['reminders'] = array();
380
+ if ( ! $rtb_controller->permissions->check_permission('reminders') ) {
381
+ $this->premium_permissions['reminders'] = array(
382
+ 'disabled' => true,
383
+ 'disabled_image' => 'https://www.etoilewebdesign.com/wp-content/uploads/2018/06/Logo-White-Filled40-px.png',
384
+ 'purchase_link' => 'https://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/',
385
+ 'ultimate_needed' => 'Yes'
386
+ );
387
+ }
388
+
389
+ $this->premium_permissions['export'] = array();
390
+ if ( ! $rtb_controller->permissions->check_permission('export') ) {
391
+ $this->premium_permissions['export'] = array(
392
+ 'disabled' => true,
393
+ 'disabled_image'=> 'https://www.etoilewebdesign.com/wp-content/uploads/2018/06/Logo-White-Filled40-px.png',
394
+ 'purchase_link' => 'https://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/'
395
+ );
396
+ }
397
+
398
+ $this->premium_permissions['styling'] = array();
399
+ if ( ! $rtb_controller->permissions->check_permission('styling') ) {
400
+ $this->premium_permissions['styling'] = array(
401
+ 'disabled' => true,
402
+ 'disabled_image'=> 'https://www.etoilewebdesign.com/wp-content/uploads/2018/06/Logo-White-Filled40-px.png',
403
+ 'purchase_link' => 'https://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/'
404
+ );
405
+ }
406
+
407
+ $this->premium_permissions = apply_filters( 'rtb_settings_check_permissions', $this->premium_permissions );
408
+ }
409
+
410
  /**
411
  * Load the plugin's default settings
412
  * @since 0.0.1
423
  'time-format' => _x( 'h:i A', 'Default time format for display. Must match formatting rules at http://amsul.ca/pickadate.js/time/#formats', 'restaurant-reservations' ),
424
  'time-interval' => _x( '30', 'Default interval in minutes when selecting a time.', 'restaurant-reservations' ),
425
 
 
 
 
 
 
 
 
426
  // Export defaults
427
  'ebfrtb-paper-size' => 'A4',
428
  'ebfrtb-pdf-lib' => 'mpdf',
616
  $this->defaults['i8n'] = $i8n;
617
  }
618
 
619
+ $this->defaults = apply_filters( 'rtb_settings_defaults', $this->defaults );
620
  }
621
 
622
  /**
1212
  )
1213
  );
1214
 
 
 
 
 
 
 
 
 
 
1215
  $sap->add_section(
1216
  'rtb-settings',
1217
  array(
1229
  'title' => __( 'View Bookings Form', 'restaurant-reservations' ),
1230
  'tab' => 'rtb-premium',
1231
  ),
1232
+ $this->premium_permissions['view_bookings']
1233
  )
1234
  );
1235
  $sap->add_setting(
1269
  )
1270
  );
1271
 
 
 
 
 
 
 
 
 
 
1272
  $sap->add_section(
1273
  'rtb-settings',
1274
  array_merge(
1277
  'title' => __( 'MailChimp', 'restaurant-reservations' ),
1278
  'tab' => 'rtb-premium',
1279
  ),
1280
+ $this->premium_permissions['mailchimp']
1281
  )
1282
  );
1283
 
1345
  );
1346
  }
1347
 
 
 
 
 
 
 
 
 
 
1348
  $sap->add_section(
1349
  'rtb-settings',
1350
  array_merge(
1353
  'title' => __( 'Seat Restrictions', 'restaurant-reservations' ),
1354
  'tab' => 'rtb-premium',
1355
  ),
1356
+ $this->premium_permissions['seat_restrictions']
1357
  )
1358
  );
1359
  $sap->add_setting(
1440
  )
1441
  );
1442
 
 
 
 
 
 
 
 
 
 
 
1443
  $sap->add_section(
1444
  'rtb-settings',
1445
  array_merge(
1448
  'title' => __( 'Table Restrictions', 'restaurant-reservations' ),
1449
  'tab' => 'rtb-premium',
1450
  ),
1451
+ $this->premium_permissions['table_restrictions']
1452
  )
1453
  );
1454
+
1455
  $sap->add_setting(
1456
  'rtb-settings',
1457
  'rtb-table-assignments',
1462
  'description' => __( 'Allow guests to select a table that they\'d like to sit at during their visit.', 'restaurant-reservations' )
1463
  )
1464
  );
1465
+
1466
  $sap->add_setting(
1467
  'rtb-settings',
1468
  'rtb-table-assignments',
1473
  'description' => __( 'Don\'t allow a reservation to be made without a valid table selected, even if all other booking criteria are met (acceptable party size, below max reservations/seats).', 'restaurant-reservations' )
1474
  )
1475
  );
1476
+
1477
  $sap->add_setting(
1478
  'rtb-settings',
1479
  'rtb-table-assignments',
1508
  )
1509
  )
1510
  );
1511
+
1512
  $sap->add_setting(
1513
  'rtb-settings',
1514
  'rtb-table-assignments',
1549
  )
1550
  );
1551
 
 
 
 
 
 
 
 
 
 
1552
  $sap->add_section(
1553
  'rtb-settings',
1554
  array(
1566
  'title' => __( 'Email Templates', 'restaurant-reservations' ),
1567
  'tab' => 'rtb-notifications-tab',
1568
  ),
1569
+ $this->premium_permissions['designer']
1570
  )
1571
  );
1572
 
1866
  )
1867
  );
1868
 
 
 
 
 
 
 
 
 
 
 
1869
  $sap->add_section(
1870
  'rtb-settings',
1871
  array_merge(
1875
  'tab' => 'rtb-notifications-tab',
1876
  'description' => __( 'Set up reservation and late arrival reminders.' ),
1877
  ),
1878
+ $this->premium_permissions['reminders']
1879
  )
1880
  );
1881
 
1892
  );
1893
 
1894
  $country_phone_display_array = array();
1895
+ foreach ( $this->country_phone_array as $country_code => $country_array ) {
1896
+ $country_phone_display_array[$country_code] = $country_array['name'] . ' (+' . $country_array['code'] . ')';
1897
+ }
1898
 
1899
  $sap->add_setting(
1900
  'rtb-settings',
1940
  );
1941
 
1942
  $sap->add_setting(
1943
+ 'rtb-settings',
1944
+ 'rtb-reservation-reminders',
1945
+ 'count',
1946
+ array(
1947
+ 'id' => 'time-reminder-user',
1948
+ 'title' => __( 'Reservation Reminder Before Time', 'restaurant-reservations' ),
1949
+ 'description' => __( 'How long before a reservation should a reminder email be sent? Leave blank to not send a reservation reminder.', 'restaurant-reservations' ),
1950
+ 'min_value' => 1,
1951
+ 'max_value' => 60,
1952
+ 'increment' => 1,
1953
+ 'units' => array(
1954
+ 'minutes' => 'Minutes',
1955
+ 'hours' => 'Hours',
1956
+ 'days' => 'Days'
1957
+ )
1958
+ )
1959
+ );
1960
 
1961
  $sap->add_setting(
1962
  'rtb-settings',
1987
  'rtb-reservation-reminders',
1988
  'count',
1989
  array(
1990
+ 'id' => 'time-late-user',
1991
+ 'title' => __( 'Late for Reservation Time', 'restaurant-reservations' ),
1992
+ 'description' => __( 'How long after being late for a reservation should a late arrival email be sent? Leave blank to not send a late arrival email.', 'restaurant-reservations' ),
1993
+ 'min_value' => 1,
1994
  'max_value' => 60,
1995
  'increment' => 1,
1996
+ 'units' => array(
1997
+ 'minutes' => 'Minutes',
1998
+ 'hours' => 'Hours',
1999
  )
2000
  )
2001
  );
2056
  )
2057
  );
2058
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2059
  //Create a tab for export settings
2060
  $sap->add_section(
2061
  'rtb-settings',
2074
  'title' => __( 'Settings', 'restaurant-reservations' ),
2075
  'tab' => 'rtb-export-tab',
2076
  ),
2077
+ $this->premium_permissions['export']
2078
  )
2079
  );
2080
 
2122
  )
2123
  );
2124
 
 
 
 
 
 
 
 
 
 
2125
  // Create a tab for styling settings
2126
  $sap->add_section(
2127
  'rtb-settings',
2140
  'title' => __( 'Reservation Form', 'restaurant-reservations' ),
2141
  'tab' => 'rtb-styling-settings-tab',
2142
  ),
2143
+ $this->premium_permissions['styling']
2144
  )
2145
  );
2146
 
2676
  $require_table = $rtb_controller->settings->get_setting( 'require-table' );
2677
  if ( $enable_tables ) {
2678
 
 
2679
  $fields['reservation']['fields']['table'] = array(
2680
  'title' => __( 'Table(s)', 'restaurant-reservations' ),
2681
+ /**
2682
+ * Raw, unprocessed value because processed value is an array
2683
+ */
2684
+ 'request_input' => empty( $request->table )
2685
+ ? ''
2686
+ : (
2687
+ array_key_exists( 'rtb-table', $request->raw_input )
2688
+ ? $request->raw_input['rtb-table']
2689
+ : ''
2690
+ ),
2691
  'callback' => 'rtb_print_form_select_field',
2692
  'callback_args' => array(
2693
  'options' => $this->get_form_table_options(),
includes/WP_List_Table.BookingsTable.class.php CHANGED
@@ -318,7 +318,6 @@ class rtbBookingsTable extends WP_List_Table {
318
  $views = array(
319
  'all' => sprintf( '<a href="%s"%s>%s</a>', esc_url( remove_query_arg( array( 'status', 'paged' ), $this->query_string ) ), $current === 'all' || $current == '' ? ' class="current"' : '', __( 'All', 'restaurant-reservations' ) . ' <span class="count">(' . $this->booking_counts['total'] . ')</span>' ),
320
  'pending' => sprintf( '<a href="%s"%s>%s</a>', esc_url( add_query_arg( array( 'status' => 'pending', 'paged' => FALSE ), $this->query_string ) ), $current === 'pending' ? ' class="current"' : '', __( 'Pending', 'restaurant-reservations' ) . ' <span class="count">(' . $this->booking_counts['pending'] . ')</span>' ),
321
- 'payment_pending' => sprintf( '<a href="%s"%s>%s</a>', esc_url( add_query_arg( array( 'status' => 'payment_pending', 'paged' => FALSE ), $this->query_string ) ), $current === 'payment_pending' ? ' class="current"' : '', __( 'Payment Pending', 'restaurant-reservations' ) . ' <span class="count">(' . $this->booking_counts['payment_pending'] . ')</span>' ),
322
  'confirmed' => sprintf( '<a href="%s"%s>%s</a>', esc_url( add_query_arg( array( 'status' => 'confirmed', 'paged' => FALSE ), $this->query_string ) ), $current === 'confirmed' ? ' class="current"' : '', __( 'Confirmed', 'restaurant-reservations' ) . ' <span class="count">(' . $this->booking_counts['confirmed'] . ')</span>' ),
323
  'closed' => sprintf( '<a href="%s"%s>%s</a>', esc_url( add_query_arg( array( 'status' => 'closed', 'paged' => FALSE ), $this->query_string ) ), $current === 'closed' ? ' class="current"' : '', __( 'Closed', 'restaurant-reservations' ) . ' <span class="count">(' . $this->booking_counts['closed'] . ')</span>' ),
324
  'trash' => sprintf( '<a href="%s"%s>%s</a>', esc_url( add_query_arg( array( 'status' => 'trash', 'paged' => FALSE ), $this->query_string ) ), $current === 'trash' ? ' class="current"' : '', __( 'Trash', 'restaurant-reservations' ) . ' <span class="count">(' . $this->booking_counts['trash'] . ')</span>' ),
@@ -328,6 +327,10 @@ class rtbBookingsTable extends WP_List_Table {
328
  array_splice($views, 3, 0, array( 'payment_failed' => sprintf( '<a href="%s"%s>%s</a>', esc_url( add_query_arg( array( 'status' => 'payment_failed', 'paged' => FALSE ), $this->query_string ) ), $current === 'payment_failed' ? ' class="current"' : '', __( 'Payment Failed', 'restaurant-reservations' ) . ' <span class="count">(' . $this->booking_counts['payment_failed'] . ')</span>' ), ) );
329
  }
330
 
 
 
 
 
331
  return apply_filters( 'rtb_bookings_table_views_status', $views );
332
  }
333
 
318
  $views = array(
319
  'all' => sprintf( '<a href="%s"%s>%s</a>', esc_url( remove_query_arg( array( 'status', 'paged' ), $this->query_string ) ), $current === 'all' || $current == '' ? ' class="current"' : '', __( 'All', 'restaurant-reservations' ) . ' <span class="count">(' . $this->booking_counts['total'] . ')</span>' ),
320
  'pending' => sprintf( '<a href="%s"%s>%s</a>', esc_url( add_query_arg( array( 'status' => 'pending', 'paged' => FALSE ), $this->query_string ) ), $current === 'pending' ? ' class="current"' : '', __( 'Pending', 'restaurant-reservations' ) . ' <span class="count">(' . $this->booking_counts['pending'] . ')</span>' ),
 
321
  'confirmed' => sprintf( '<a href="%s"%s>%s</a>', esc_url( add_query_arg( array( 'status' => 'confirmed', 'paged' => FALSE ), $this->query_string ) ), $current === 'confirmed' ? ' class="current"' : '', __( 'Confirmed', 'restaurant-reservations' ) . ' <span class="count">(' . $this->booking_counts['confirmed'] . ')</span>' ),
322
  'closed' => sprintf( '<a href="%s"%s>%s</a>', esc_url( add_query_arg( array( 'status' => 'closed', 'paged' => FALSE ), $this->query_string ) ), $current === 'closed' ? ' class="current"' : '', __( 'Closed', 'restaurant-reservations' ) . ' <span class="count">(' . $this->booking_counts['closed'] . ')</span>' ),
323
  'trash' => sprintf( '<a href="%s"%s>%s</a>', esc_url( add_query_arg( array( 'status' => 'trash', 'paged' => FALSE ), $this->query_string ) ), $current === 'trash' ? ' class="current"' : '', __( 'Trash', 'restaurant-reservations' ) . ' <span class="count">(' . $this->booking_counts['trash'] . ')</span>' ),
327
  array_splice($views, 3, 0, array( 'payment_failed' => sprintf( '<a href="%s"%s>%s</a>', esc_url( add_query_arg( array( 'status' => 'payment_failed', 'paged' => FALSE ), $this->query_string ) ), $current === 'payment_failed' ? ' class="current"' : '', __( 'Payment Failed', 'restaurant-reservations' ) . ' <span class="count">(' . $this->booking_counts['payment_failed'] . ')</span>' ), ) );
328
  }
329
 
330
+ if ( isset( $this->booking_counts['payment_pending'] ) and $this->booking_counts['payment_pending'] > 0 ) {
331
+ array_splice($views, 3, 0, array( 'payment_pending' => sprintf( '<a href="%s"%s>%s</a>', esc_url( add_query_arg( array( 'status' => 'payment_pending', 'paged' => FALSE ), $this->query_string ) ), $current === 'payment_pending' ? ' class="current"' : '', __( 'Payment Pending', 'restaurant-reservations' ) . ' <span class="count">(' . $this->booking_counts['payment_pending'] . ')</span>' ), ) );
332
+ }
333
+
334
  return apply_filters( 'rtb_bookings_table_views_status', $views );
335
  }
336
 
includes/load-customizer.php CHANGED
@@ -27,7 +27,9 @@ if ( ! function_exists('etfrtb_customize_init_blank_state') ) {
27
  function etfrtb_customize_init_blank_state( $components ) {
28
  global $rtb_controller;
29
 
30
- if ( ! $rtb_controller->permissions->check_permission( 'templates' ) ) { return; }
 
 
31
 
32
  // Reset the customize register actions
33
  add_action( 'wp_loaded', 'etfrtb_customize_reset_register', 1 );
27
  function etfrtb_customize_init_blank_state( $components ) {
28
  global $rtb_controller;
29
 
30
+ if ( ! $rtb_controller->permissions->check_permission( 'templates' ) ) {
31
+ return $components;
32
+ }
33
 
34
  // Reset the customize register actions
35
  add_action( 'wp_loaded', 'etfrtb_customize_reset_register', 1 );
includes/template-functions.php CHANGED
@@ -29,10 +29,12 @@ add_shortcode( 'booking-form', 'rtb_booking_form_shortcode' );
29
  * @since 0.0.1
30
  */
31
  if ( !function_exists( 'rtb_print_booking_form' ) ) {
32
- function rtb_print_booking_form( $args = array() ) {
33
-
34
  global $rtb_controller;
35
 
 
 
36
  // Only allow the form to be displayed once on a page
37
  if ( $rtb_controller->form_rendered === true ) {
38
  return;
@@ -141,18 +143,25 @@ function rtb_print_booking_form( $args = array() ) {
141
  <?php
142
  }
143
 
144
-
145
- elseif ( isset($_POST['stripeToken']) ) :
146
- rtb_process_stripe_payment();
147
-
148
  elseif ( $rtb_controller->request->request_inserted === true or isset($_GET['payment']) ) :
149
  if ( isset($_GET['payment']) && 'rtb-delayed-deposit' != $_GET['payment'] ) { ?>
150
  <div class="rtb-message">
151
  <p><?php printf( __( 'Your reservation deposit payment has failed with the following message "%s" Please contact the site administrator for assistance.', 'restaurant-reservations' ), isset( $_GET['error_code'] ) ? esc_html( urldecode( $_GET['error_code'] ) ) : ' unknown error.' ); ?></p>
152
  </div>
153
  <?php }
 
 
 
 
 
 
 
 
154
 
155
- rtb_print_payment_form();
 
 
 
156
 
157
  elseif ( isset($_GET['bookingCancelled']) and $_GET['bookingCancelled'] == 'success') : ?>
158
  <div class="rtb-message">
@@ -216,19 +225,26 @@ function rtb_print_booking_form( $args = array() ) {
216
 
217
  <?php do_action( 'rtb_booking_form_after_fields' ); ?>
218
 
219
- <div id='rtb_recaptcha'></div>
220
- <?php echo rtb_print_form_error( 'recaptcha' ); ?>
 
221
 
222
- <?php
223
- $button_text = $rtb_controller->settings->get_setting( 'require-deposit' ) ? __( 'Proceed to Deposit', 'restaurant-reservations' ) : __( 'Request Booking', 'restaurant-reservations' );
224
-
225
- $button = sprintf(
226
- '<button type="submit">%s</button>',
227
- apply_filters( 'rtb_booking_form_submit_label', $button_text )
228
- );
229
-
230
- echo apply_filters( 'rtb_booking_form_submit_button', $button );
231
- ?>
 
 
 
 
 
 
232
 
233
 
234
  </form>
@@ -245,327 +261,6 @@ function rtb_print_booking_form( $args = array() ) {
245
  }
246
  } // endif;
247
 
248
- /**
249
- * Print the payment form's HTML code, after a new booking has been inserted
250
- * notices.
251
- * @since 2.1.0
252
- */
253
- if ( !function_exists( 'rtb_print_payment_form' ) ) {
254
- function rtb_print_payment_form( $args = array() ) {
255
- global $rtb_controller;
256
-
257
- // Define the form's action parameter
258
- $booking_page = $rtb_controller->settings->get_setting( 'booking-page' );
259
- if ( !empty( $booking_page ) ) {
260
- $booking_page = get_permalink( $booking_page );
261
- }
262
-
263
- require_once( RTB_PLUGIN_DIR . '/includes/Booking.class.php' );
264
- $booking = new rtbBooking();
265
- $booking->load_post( isset( $_GET['booking_id'] ) ? intval( $_GET['booking_id'] ) : $rtb_controller->request->ID );
266
-
267
- if ( $rtb_controller->settings->get_setting( 'rtb-payment-gateway' ) == "paypal" ) { ?>
268
- <form action='https://www.paypal.com/cgi-bin/webscr' method='post' class='standard-form'>
269
- <input type='hidden' name='item_name_1' value='<?php echo substr(get_bloginfo('name'), 0, 100); ?> Reservation Deposit' />
270
- <input type='hidden' name='custom' value='booking_id=<?php echo $booking->ID; ?>' />
271
- <input type='hidden' name='quantity_1' value='1' />
272
- <input type='hidden' name='amount_1' value='<?php echo $booking->calculate_deposit(); ?>' />
273
- <input type='hidden' name='cmd' value='_cart' />
274
- <input type='hidden' name='upload' value='1' />
275
- <input type='hidden' name='business' value='<?php echo $rtb_controller->settings->get_setting( 'rtb-paypal-email' ); ?>' />
276
- <input type='hidden' name='currency_code' value='<?php echo $rtb_controller->settings->get_setting( 'rtb-currency' ); ?>' />
277
- <input type='hidden' name='return' value='<?php $booking_page; ?>' />
278
- <input type='hidden' name='notify_url' value='<?php echo get_site_url(); ?>' />
279
- <input type='submit' class='submit-button' value='Pay via PayPal' />
280
- </form>
281
- <?php
282
- }
283
- else {
284
- $btn_disabled = '';
285
- if( $rtb_controller->settings->get_setting( 'rtb-stripe-sca' ) ) {
286
- $btn_disabled = "disabled='disabled'";
287
- wp_enqueue_script( 'rtb-stripe', 'https://js.stripe.com/v3/', array( 'jquery' ), RTB_VERSION, true );
288
- }
289
- else {
290
- wp_enqueue_script( 'rtb-stripe', 'https://js.stripe.com/v2/', array( 'jquery' ), RTB_VERSION, true );
291
- }
292
-
293
- wp_enqueue_script( 'rtb-stripe-payment', RTB_PLUGIN_URL . '/assets/js/stripe-payment.js', array( 'jquery', 'rtb-stripe' ), RTB_VERSION, true );
294
-
295
- wp_localize_script(
296
- 'rtb-stripe-payment',
297
- 'rtb_stripe_payment',
298
- array(
299
- 'stripe_mode' => $rtb_controller->settings->get_setting( 'rtb-stripe-mode' ),
300
- 'stripe_sca' => $rtb_controller->settings->get_setting( 'rtb-stripe-sca' ),
301
- 'live_publishable_key' => $rtb_controller->settings->get_setting( 'rtb-stripe-live-publishable' ),
302
- 'test_publishable_key' => $rtb_controller->settings->get_setting( 'rtb-stripe-test-publishable' ),
303
- )
304
- );
305
-
306
- $payment_amount = $rtb_controller->settings->get_setting( 'rtb-currency-symbol-location' ) == 'before'
307
- ? $rtb_controller->settings->get_setting( 'rtb-stripe-currency-symbol' ) . $booking->calculate_deposit()
308
- : $booking->calculate_deposit() . $rtb_controller->settings->get_setting( 'rtb-stripe-currency-symbol' );
309
-
310
- $cc_exp_single_field = null != $rtb_controller->settings->get_setting( 'rtb-expiration-field-single' )
311
- ? "<input type='text' data-stripe='exp_month_year' class='single-masked'>"
312
- : "<input type='text' size='2' data-stripe='exp_month'>
313
- <span> / </span>
314
- <input type='text' size='4' data-stripe='exp_year'>";
315
- ?>
316
-
317
- <h2><?php echo __('Deposit Required: ', 'restaurant-reservations' ) . $payment_amount; ?></h2>
318
-
319
- <div class='payment-errors'></div>
320
-
321
- <form action='#' method='POST' id='stripe-payment-form' data-booking_id='<?php echo $booking->ID ;?>'>
322
-
323
- <?php if( $rtb_controller->settings->get_setting( 'rtb-stripe-sca' ) ) { ?>
324
- <div class='form-row'>
325
- <label><?php _e('Card Detail', 'restaurant-reservations'); ?></label>
326
- <span id="cardElement"></span>
327
- </div>
328
- <?php } else { ?>
329
- <div class='form-row'>
330
- <label><?php _e('Card Number', 'restaurant-reservations'); ?></label>
331
- <input type='text' size='20' autocomplete='off' data-stripe='card_number'/>
332
- </div>
333
- <div class='form-row'>
334
- <label><?php _e('CVC', 'restaurant-reservations'); ?></label>
335
- <input type='text' size='4' autocomplete='off' data-stripe='card_cvc'/>
336
- </div>
337
- <div class='form-row'>
338
- <label><?php _e('Expiration (MM/YYYY)', 'restaurant-reservations'); ?></label>
339
- <?php echo $cc_exp_single_field; ?>
340
- </div>
341
- <input type='hidden' name='action' value='rtb_stripe_booking_payment'/>
342
- <input type='hidden' name='currency' value='<?php echo $rtb_controller->settings->get_setting( 'rtb-currency' ); ?>' data-stripe='currency' />
343
- <input type='hidden' name='payment_amount' value='<?php echo $booking->calculate_deposit(); ?>' />
344
- <input type='hidden' name='booking_id' value='<?php echo $booking->ID; ?>' />
345
- <?php } ?>
346
- <p class="stripe-payment-help-text">
347
- <?php _e( 'Please wait. Do not refresh until the button enables or the page reloads.', 'restaurant-reservations' ); ?>
348
- </p>
349
- <button type='submit' id='stripe-submit' <?php echo $btn_disabled; ?>><?php _e( 'Make Deposit', 'restaurant-reservations'); ?></button>
350
- </form>
351
- <?php }
352
- }
353
- } // endif;
354
-
355
- /**
356
- * Process Stripe payments for reservation deposits
357
- * @since 2.1.0
358
- */
359
- if ( !function_exists( 'rtb_process_stripe_payment' ) ) {
360
- function rtb_process_stripe_payment() {
361
- global $rtb_controller;
362
-
363
- $booking_id = isset($_POST['booking_id']) ? absint( $_POST['booking_id'] ) : 0;
364
-
365
- if ( ! $booking_id ) { return; }
366
-
367
- // Define the form's action parameter
368
- $booking_page = $rtb_controller->settings->get_setting( 'booking-page' );
369
- if ( ! empty( $booking_page ) ) {
370
- $booking_page = get_permalink( $booking_page );
371
- }
372
- else { $booking_page = get_permalink(); }
373
-
374
-
375
- // load the stripe libraries
376
- require_once(RTB_PLUGIN_DIR . '/lib/stripe/init.php');
377
-
378
- // retrieve the token generated by stripe.js
379
- $token = $_POST['stripeToken'];
380
-
381
- $payment_amount = ( $rtb_controller->settings->get_setting( 'rtb-currency' ) != "JPY" ? $_POST['payment_amount'] * 100 : $_POST['payment_amount'] );
382
-
383
- $stripe_secret = $rtb_controller->settings->get_setting( 'rtb-stripe-mode' ) == 'test' ? $rtb_controller->settings->get_setting( 'rtb-stripe-test-secret' ) : $rtb_controller->settings->get_setting( 'rtb-stripe-live-secret' );
384
-
385
- require_once( RTB_PLUGIN_DIR . '/includes/Booking.class.php' );
386
- $booking = new rtbBooking();
387
- $booking->load_post( $booking_id );
388
-
389
- try {
390
- \Stripe\Stripe::setApiKey( $stripe_secret );
391
- $charge = \Stripe\Charge::create(array(
392
- 'amount' => $payment_amount,
393
- 'currency' => strtolower( $rtb_controller->settings->get_setting( 'rtb-currency' ) ),
394
- 'card' => $token
395
- )
396
- );
397
-
398
- $booking->deposit = ( $rtb_controller->settings->get_setting( 'rtb-currency' ) != "JPY" ? $payment_amount / 100 : $payment_amount );
399
- $booking->receipt_id = $charge->id;
400
-
401
- $booking->determine_status( true );
402
-
403
- $booking->insert_post_data();
404
-
405
- do_action( 'rtb_booking_paid', $booking );
406
-
407
- // redirect on successful payment
408
- $redirect = add_query_arg(
409
- array(
410
- 'payment' => 'paid',
411
- 'booking_id' => $booking_id
412
- ),
413
- $booking_page
414
- );
415
-
416
- } catch (Exception $e) {
417
-
418
- $booking->post_status = 'payment_failed';
419
- $booking->payment_failure_message = $e->getDeclineCode();
420
-
421
- $booking->insert_post_data();
422
-
423
- // redirect on failed payment
424
- $redirect = add_query_arg(
425
- array(
426
- 'payment' => 'failed',
427
- 'booking_id' => $booking_id,
428
- 'error_code' => urlencode( $e->getDeclineCode() )
429
- ),
430
- $booking_page
431
- );
432
- }
433
-
434
- // redirect back to our previous page with the added query variable
435
- wp_redirect($redirect); exit;
436
- }
437
- } // endif;
438
-
439
- // add an output buffer layer for the plugin
440
- add_action( 'init', 'rtb_add_ob_start' );
441
- add_action( 'shutdown', 'rtb_flush_ob_end' );
442
-
443
- // If there's an IPN request, add our setup function to potentially handle it
444
- if ( isset($_POST['ipn_track_id']) ) { add_action( 'init', 'rtb_setup_paypal_ipn', 11 ); }
445
-
446
- /**
447
- * Sets up the PayPal IPN process
448
- * @since 2.1.0
449
- */
450
- if ( !function_exists( 'rtb_handle_paypal_ipn' ) ) {
451
- function rtb_setup_paypal_ipn() {
452
- global $rtb_controller;
453
-
454
- if ( ! $rtb_controller->settings->get_setting( 'require-deposit' ) ) { return; }
455
-
456
- rtb_handle_paypal_ipn();
457
- }
458
- } // endif;
459
-
460
- /**
461
- * Handle PayPal IPN requests
462
- * @since 2.1.0
463
- */
464
- if ( !function_exists( 'rtb_handle_paypal_ipn' ) ) {
465
- function rtb_handle_paypal_ipn() {
466
-
467
- // CONFIG: Enable debug mode. This means we'll log requests into 'ipn.log' in the same directory.
468
- // Especially useful if you encounter network errors or other intermittent problems with IPN (validation).
469
- // Set this to 0 once you go live or don't require logging.
470
- $debug = get_option( 'rtb_enable_payment_debugging' );
471
-
472
- // Set to 0 once you're ready to go live
473
- define("RTB_USE_SANDBOX", 0);
474
- define("RTB_LOG_FILE", "ipn.log");
475
- // Read POST data
476
- // reading posted data directly from $_POST causes serialization
477
- // issues with array data in POST. Reading raw POST data from input stream instead.
478
- $raw_post_data = file_get_contents('php://input');
479
- $raw_post_array = explode('&', $raw_post_data);
480
- $myPost = array();
481
- foreach ($raw_post_array as $keyval) {
482
- $keyval = explode ('=', $keyval);
483
- if (count($keyval) == 2)
484
- $myPost[$keyval[0]] = urldecode($keyval[1]);
485
- }
486
- // read the post from PayPal system and add 'cmd'
487
- $req = 'cmd=_notify-validate';
488
- if(function_exists('get_magic_quotes_gpc')) {
489
- $get_magic_quotes_exists = true;
490
- }
491
- foreach ($myPost as $key => $value) {
492
- if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
493
- $value = urlencode(stripslashes($value));
494
- } else {
495
- $value = urlencode($value);
496
- }
497
- $req .= "&$key=$value";
498
- }
499
- // Post IPN data back to PayPal to validate the IPN data is genuine
500
- // Without this step anyone can fake IPN data
501
- if(RTB_USE_SANDBOX == true) {
502
- $paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr";
503
- } else {
504
- $paypal_url = "https://www.paypal.com/cgi-bin/webscr";
505
- }
506
-
507
- $response = wp_remote_post($paypal_url, array(
508
- 'method' => 'POST',
509
- 'body' => $req,
510
- 'timeout' => 30
511
- ));
512
-
513
- // Inspect IPN validation result and act accordingly
514
- // Split response headers and payload, a better way for strcmp
515
- $tokens = explode("\r\n\r\n", trim($response['body']));
516
- $res = trim(end($tokens));
517
-
518
- if ( $debug ) {
519
- update_option( 'rtb_debugging', get_option( 'rtb_debugging' ) . print_r( date('[Y-m-d H:i e] '). "IPN response: $res - $req ". PHP_EOL, true ) );
520
- }
521
-
522
- if (strcmp ($res, "VERIFIED") == 0) {
523
-
524
- $paypal_receipt_number = $_POST['txn_id'];
525
- $payment_amount = $_POST['mc_gross'];
526
-
527
- parse_str($_POST['custom'], $custom_vars);
528
- $booking_id = intval( $custom_vars['booking_id'] );
529
-
530
- require_once( RTB_PLUGIN_DIR . '/includes/Booking.class.php' );
531
-
532
- $booking = new rtbBooking();
533
- $booking->load_post( $booking_id );
534
-
535
- if ( ! $booking ) { return; }
536
-
537
- $booking->deposit = sanitize_text_field( $payment_amount );
538
- $booking->receipt_id = sanitize_text_field( $paypal_receipt_number );
539
-
540
- $booking->determine_status( true );
541
-
542
- $booking->insert_post_data();
543
-
544
- do_action( 'rtb_booking_paid', $booking );
545
- }
546
- }
547
- } // endif;
548
-
549
- /**
550
- * Opens a buffer when handling PayPal IPN requests
551
- * @since 2.1.0
552
- */
553
- if ( !function_exists( 'rtb_add_ob_start' ) ) {
554
- function rtb_add_ob_start() {
555
- ob_start();
556
- }
557
- } // endif;
558
-
559
- /**
560
- * Closes a buffer when handling PayPal IPN requests
561
- * @since 2.1.0
562
- */
563
- if ( !function_exists( 'rtb_flush_ob_end' ) ) {
564
- function rtb_flush_ob_end() {
565
- if ( ob_get_length() ) { ob_end_clean(); }
566
- }
567
- } // endif;
568
-
569
  /**
570
  * Create a shortcode to view and (optionally) sign in bookings
571
  * @since 2.0.0
@@ -936,7 +631,7 @@ if ( !function_exists( 'rtb_print_form_select_field' ) ) {
936
  function rtb_print_form_select_field( $slug, $title, $value, $args ) {
937
 
938
  $slug = esc_attr( $slug );
939
- $value = esc_attr( $value );
940
  $options = is_array( $args['options'] ) ? $args['options'] : array();
941
  $classes = isset( $args['classes'] ) ? $args['classes'] : array();
942
  $classes[] = 'rtb-select';
29
  * @since 0.0.1
30
  */
31
  if ( !function_exists( 'rtb_print_booking_form' ) ) {
32
+ function rtb_print_booking_form( $args = array() )
33
+ {
34
  global $rtb_controller;
35
 
36
+ do_action( 'rtb_booking_form_init' );
37
+
38
  // Only allow the form to be displayed once on a page
39
  if ( $rtb_controller->form_rendered === true ) {
40
  return;
143
  <?php
144
  }
145
 
 
 
 
 
146
  elseif ( $rtb_controller->request->request_inserted === true or isset($_GET['payment']) ) :
147
  if ( isset($_GET['payment']) && 'rtb-delayed-deposit' != $_GET['payment'] ) { ?>
148
  <div class="rtb-message">
149
  <p><?php printf( __( 'Your reservation deposit payment has failed with the following message "%s" Please contact the site administrator for assistance.', 'restaurant-reservations' ), isset( $_GET['error_code'] ) ? esc_html( urldecode( $_GET['error_code'] ) ) : ' unknown error.' ); ?></p>
150
  </div>
151
  <?php }
152
+
153
+ $booking_id = isset( $_GET['booking_id'] )
154
+ ? intval( $_GET['booking_id'] )
155
+ : $rtb_controller->request->ID;
156
+
157
+ require_once( RTB_PLUGIN_DIR . '/includes/Booking.class.php' );
158
+ $booking = new rtbBooking();
159
+ $booking->load_post( $booking_id );
160
 
161
+ $rtb_controller
162
+ ->payment_manager
163
+ ->set_booking( $booking )
164
+ ->print_payment_form();
165
 
166
  elseif ( isset($_GET['bookingCancelled']) and $_GET['bookingCancelled'] == 'success') : ?>
167
  <div class="rtb-message">
225
 
226
  <?php do_action( 'rtb_booking_form_after_fields' ); ?>
227
 
228
+ <fieldset class="rtb-form-footer">
229
+ <div id='rtb_recaptcha'></div>
230
+ <?php echo rtb_print_form_error( 'recaptcha' ); ?>
231
 
232
+ <?php
233
+ $button_text = $rtb_controller->settings->get_setting( 'require-deposit' )
234
+ ? __( 'Proceed to Deposit', 'restaurant-reservations' )
235
+ : __( 'Request Booking', 'restaurant-reservations' );
236
+
237
+ $button = sprintf(
238
+ '<button type="submit">%s</button>',
239
+ apply_filters( 'rtb_booking_form_submit_label', $button_text )
240
+ );
241
+
242
+ echo sprintf(
243
+ '<div class="rtb-form-submit">%s</div>',
244
+ apply_filters( 'rtb_booking_form_submit_button', $button )
245
+ );
246
+ ?>
247
+ </fieldset>
248
 
249
 
250
  </form>
261
  }
262
  } // endif;
263
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  /**
265
  * Create a shortcode to view and (optionally) sign in bookings
266
  * @since 2.0.0
631
  function rtb_print_form_select_field( $slug, $title, $value, $args ) {
632
 
633
  $slug = esc_attr( $slug );
634
+ $value = is_array( $value ) ? array_map( 'esc_attr', $value ) : esc_attr( $value );
635
  $options = is_array( $args['options'] ) ? $args['options'] : array();
636
  $classes = isset( $args['classes'] ) ? $args['classes'] : array();
637
  $classes[] = 'rtb-select';
lib/simple-admin-pages/classes/AdminPage.class.php CHANGED
@@ -175,6 +175,21 @@ class sapAdminPage_2_2_0 {
175
 
176
  $current_page = $this->get_current_page( $_GET );
177
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  ?>
179
 
180
  <div class="wrap">
@@ -184,22 +199,18 @@ class sapAdminPage_2_2_0 {
184
  <?php if ( isset( $this->default_tab ) ) : ?>
185
  <h2 class="nav-tab-wrapper">
186
  <?php
187
- foreach( $this->sections as $section ) {
188
-
189
- if ( isset( $section->is_tab ) && $section->is_tab === true ) {
190
-
191
- $tab_url = add_query_arg(
192
- array(
193
- 'settings-updated' => false,
194
- 'tab' => $section->id
195
- )
196
- );
197
-
198
- $active = $current_page == $section->id ? ' nav-tab-active' : '';
199
- echo '<a href="' . esc_url( $tab_url ) . '" title="' . esc_attr( $section->title ) . '" class="nav-tab' . $active . '">';
200
- echo esc_html( $section->title );
201
- echo '</a>';
202
- }
203
  }
204
  ?>
205
  </h2>
175
 
176
  $current_page = $this->get_current_page( $_GET );
177
 
178
+ // Fetch and Order sections/tabs
179
+ $tab_list = [];
180
+ foreach( $this->sections as $section ) {
181
+ if ( isset( $section->is_tab ) && $section->is_tab === true ) {
182
+ if( property_exists( $section, 'rank' ) ) {
183
+ // array start from 0, rank start from 1
184
+ array_splice($tab_list, ($section->rank - 1), 0, [$section]);
185
+ }
186
+ else {
187
+ $tab_list[] = $section;
188
+ }
189
+ }
190
+ }
191
+
192
+
193
  ?>
194
 
195
  <div class="wrap">
199
  <?php if ( isset( $this->default_tab ) ) : ?>
200
  <h2 class="nav-tab-wrapper">
201
  <?php
202
+ foreach( $tab_list as $section ) {
203
+ $tab_url = add_query_arg(
204
+ array(
205
+ 'settings-updated' => false,
206
+ 'tab' => $section->id
207
+ )
208
+ );
209
+
210
+ $active = $current_page == $section->id ? ' nav-tab-active' : '';
211
+ echo '<a href="' . esc_url( $tab_url ) . '" title="' . esc_attr( $section->title ) . '" class="nav-tab' . $active . '">';
212
+ echo esc_html( $section->title );
213
+ echo '</a>';
 
 
 
 
214
  }
215
  ?>
216
  </h2>
lib/simple-admin-pages/classes/AdminPageSetting.Checkbox.class.php CHANGED
@@ -21,8 +21,6 @@
21
 
22
  class sapAdminPageSettingCheckbox_2_2_0 extends sapAdminPageSetting_2_2_0 {
23
 
24
- //public $sanitize_callback = 'sanitize_text_field';
25
-
26
  /**
27
  * Display this setting
28
  * @since 2.0
@@ -49,4 +47,21 @@ class sapAdminPageSettingCheckbox_2_2_0 extends sapAdminPageSetting_2_2_0 {
49
 
50
  }
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  }
21
 
22
  class sapAdminPageSettingCheckbox_2_2_0 extends sapAdminPageSetting_2_2_0 {
23
 
 
 
24
  /**
25
  * Display this setting
26
  * @since 2.0
47
 
48
  }
49
 
50
+ public function sanitize_callback_wrapper( $values ) {
51
+ return is_array( $values ) ? array_map( $this->sanitize_callback, $values ) : array();
52
+ }
53
+
54
+ /**
55
+ * Escape the value to display it safely HTML textarea fields
56
+ * @since 2.0.a.5
57
+ */
58
+ public function esc_value( $val ) {
59
+
60
+ foreach ($val as $value) {
61
+ $escaped[] = esc_attr($value);
62
+ }
63
+
64
+ return $escaped;
65
+ }
66
+
67
  }
lib/simple-admin-pages/classes/Library.class.php CHANGED
@@ -301,6 +301,7 @@ class sapLibrary_2_2_0 {
301
  $this->pages[ $page ]->sections[ $section ]->add_setting( new $class( $args ) );
302
  }
303
 
 
304
  }
305
 
306
  /**
301
  $this->pages[ $page ]->sections[ $section ]->add_setting( new $class( $args ) );
302
  }
303
 
304
+ return $this;
305
  }
306
 
307
  /**
lib/simple-admin-pages/js/count.js CHANGED
@@ -4,7 +4,12 @@ jQuery(document).ready(function() {
4
 
5
  var count = jQuery('#' + id + '_count').val();
6
  var unit = jQuery('#' + id + '_unit').val();
7
-
8
- jQuery('#' + id).val(count + '_' + unit);
9
- })
10
- })
 
 
 
 
 
4
 
5
  var count = jQuery('#' + id + '_count').val();
6
  var unit = jQuery('#' + id + '_unit').val();
7
+
8
+ if( count && unit ) {
9
+ jQuery('#' + id).val(count + '_' + unit);
10
+ }
11
+ else {
12
+ jQuery('#' + id).val('');
13
+ }
14
+ });
15
+ });
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: FiveStarPlugins
3
  Requires at Least: 4.4
4
  Tested Up To: 5.8
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.2.12
7
  License: GPLv3
8
  License URI:http://www.gnu.org/licenses/gpl-3.0.html
9
  Donate Link: https://www.etoilewebdesign.com/plugin-donations/
@@ -197,6 +197,15 @@ Find answers to even more questions in the [FAQ](http://doc.fivestarplugins.com/
197
 
198
  == Changelog ==
199
 
 
 
 
 
 
 
 
 
 
200
  = 2.2.12 (2021-07-21) =
201
  - The plugin has been tested up to WordPress version 5.8.
202
 
3
  Requires at Least: 4.4
4
  Tested Up To: 5.8
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.3.0
7
  License: GPLv3
8
  License URI:http://www.gnu.org/licenses/gpl-3.0.html
9
  Donate Link: https://www.etoilewebdesign.com/plugin-donations/
197
 
198
  == Changelog ==
199
 
200
+ = 2.3.0 (2021-08-23) =
201
+ - Updated the payment gateway option, so you can now offer PayPal and Stripe at the same time (your customers can choose which to use).
202
+ - Fixed issue with Early Bookings feature were the X day option was calculating using hours instead of days.
203
+ - Fixed an issue in which, if there was only one valid time slot left, it would sometimes not display as available.
204
+ - Fixed an issue in which, if your set timezone was on a different day than UTC (e.g. near midnight), it would sometimes show the incorrect hours as available.
205
+ - Fixed an issue loading the customizer for the email templates.
206
+ - Fixed an issue causing the reservation reminder and late arrival notifications to still send if no time interval was specified.
207
+ - Fixed an issue in which the red badge would still show beside the Bookings WP admin menu item even if there were no pending bookings.
208
+
209
  = 2.2.12 (2021-07-21) =
210
  - The plugin has been tested up to WordPress version 5.8.
211
 
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.2.12
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.2.7' );
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__ ) );
@@ -51,8 +51,12 @@ class rtbInit {
51
 
52
  // Set up empty request object
53
  $this->request = new stdClass();
 
54
  $this->request->request_processed = false;
55
  $this->request->request_inserted = false;
 
 
 
56
 
57
  // Load query class
58
  require_once( RTB_PLUGIN_DIR . '/includes/Query.class.php' );
@@ -107,6 +111,10 @@ class rtbInit {
107
  require_once( RTB_PLUGIN_DIR . '/includes/Settings.class.php' );
108
  $this->settings = new rtbSettings();
109
 
 
 
 
 
110
  // Load plugin dashboard
111
  require_once( RTB_PLUGIN_DIR . '/includes/Dashboard.class.php' );
112
  new rtbDashboard();
@@ -490,3 +498,15 @@ class rtbInit {
490
  global $rtb_controller;
491
  $rtb_controller = new rtbInit();
492
 
 
 
 
 
 
 
 
 
 
 
 
 
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.3.0
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.3.0' );
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__ ) );
51
 
52
  // Set up empty request object
53
  $this->request = new stdClass();
54
+ $this->request->raw_input = array();
55
  $this->request->request_processed = false;
56
  $this->request->request_inserted = false;
57
+ }
58
+
59
+ public function boot() {
60
 
61
  // Load query class
62
  require_once( RTB_PLUGIN_DIR . '/includes/Query.class.php' );
111
  require_once( RTB_PLUGIN_DIR . '/includes/Settings.class.php' );
112
  $this->settings = new rtbSettings();
113
 
114
+ // Load Payment Manager
115
+ require_once( RTB_PLUGIN_DIR . '/includes/PaymentManager.class.php' );
116
+ $this->payment_manager = new rtbPaymentManager();
117
+
118
  // Load plugin dashboard
119
  require_once( RTB_PLUGIN_DIR . '/includes/Dashboard.class.php' );
120
  new rtbDashboard();
498
  global $rtb_controller;
499
  $rtb_controller = new rtbInit();
500
 
501
+ /**
502
+ * Because we refer $rtb_controller in many other modules during their object
503
+ * construction, separating the object construction from its uses. Please refer
504
+ * to the link after the constructor's official PHP definition.
505
+ *
506
+ * "Classes which have a constructor method call this method on each newly-
507
+ * created object, so it is suitable for any initialization that the object
508
+ * may need before it is used."
509
+ *
510
+ * https://www.php.net/manual/en/language.oop5.decon.php
511
+ */
512
+ $rtb_controller->boot();