Restaurant Reservations - Version 2.2.0

Version Description

(2020-10-21) = - This is a relatively big update with several new features, corrections, styling, etc., so please take caution and test before updating on a live site (or wait a few days before updating in case some minor corrective updates need to be released). - Added in a new filtering option in the admin to display bookings from a specific date and/or time frame. - Added in the ability to send a mass email to multiple bookings. - (The above two new additions could, for example, be used as a way of contact tracing.) - Table numbers are now included in the export (both PDF and Excel/CSV). - Added in a redirect URL option for the cancellation form. - Made the admin booking table sortable by the status column. - Added an option to disable the capture of the IP address when a booking is made. - Updated the interaction between the "automatically confirm below party size" and "automatically confirm below seats number" settings, to allow them to work in an OR capacity, so they can be used together. - Corrected an issue where sometimes the "automatically confirm below party size" feature would, even if set to 1, still confirm for a party size of 1. - Corrected an issue where the validation that prevents an exact duplicate booking would still throw an error if the old matching booking was in the trash. - Corrected an issue where the styling of some admin pages was not being applied when WordPress was set to certain specific non-English languages. - Small updates to class names that might have been too common and could potentially allow for a styling conflict with other plugins/themes. - Added in several filters for developers to be able to modify/extend plugin behaviour (e.g. in your theme's functions.php file). See http://doc.fivestarplugins.com/plugins/restaurant-reservations/developer/ for more info.

Download this release

Release Info

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

Code changes from version 2.1.24 to 2.2.0

assets/css/admin.css CHANGED
@@ -42,8 +42,9 @@
42
  top: -9999px;
43
  left: -9999px;
44
  display: inline-block;
45
- padding: 1em;
46
- background: #fff;
 
47
  -webkit-box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
48
  box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
49
  }
@@ -51,7 +52,8 @@
51
  #rtb-filters.date-filters-visible .date-filters {
52
  position: relative;
53
  top: auto;
54
- left: 0;
 
55
  }
56
 
57
  #rtb-filters .date-filters .datepicker {
@@ -766,10 +768,10 @@ NEW DASHBOARD
766
 
767
  /*** WRAP ***/
768
 
769
- .bookings_page_rtb-dashboard #wpcontent {
770
  padding-left: 0;
771
  }
772
- .bookings_page_rtb-dashboard .wrap {
773
  margin: 10px 0 0;
774
  }
775
 
@@ -957,9 +959,9 @@ NEW DASHBOARD
957
  float: left;
958
  width: 100%;
959
  }
960
- body.bookings_page_rtb-settings .rtb-admin-header-menu,
961
- body.bookings_page_cffrtb-editor .rtb-admin-header-menu,
962
- body.toplevel_page_rtb-bookings .rtb-admin-header-menu {
963
  margin-left: -20px;
964
  width: calc(100% + 20px);
965
  }
@@ -1804,7 +1806,7 @@ body.toplevel_page_rtb-bookings .rtb-admin-header-menu {
1804
  /************************/
1805
 
1806
  /* Side Menu */
1807
- .bookings_page_rtb-settings .wrap h2.nav-tab-wrapper {
1808
  position: relative;
1809
  float: left;
1810
  border: none;
@@ -1814,7 +1816,7 @@ body.toplevel_page_rtb-bookings .rtb-admin-header-menu {
1814
  padding-top: 0;
1815
  margin-top: 20px;
1816
  }
1817
- .bookings_page_rtb-settings .wrap h2.nav-tab-wrapper a {
1818
  clear: both;
1819
  display: block;
1820
  position: relative;
@@ -1832,29 +1834,29 @@ body.toplevel_page_rtb-bookings .rtb-admin-header-menu {
1832
  line-height: 34px;
1833
  font-size: 13px;
1834
  }
1835
- .bookings_page_rtb-settings .wrap h2.nav-tab-wrapper a:last-of-type {
1836
  border-bottom: none;
1837
  }
1838
- .bookings_page_rtb-settings .wrap h2.nav-tab-wrapper a.nav-tab-active {
1839
  box-shadow: none;
1840
  background-color: #fff !important;
1841
  color: #1b335f;
1842
  border-left: 4px solid #1b335f;
1843
  }
1844
- .bookings_page_rtb-settings .wrap h2.nav-tab-wrapper a:hover {
1845
  color: #29324e;
1846
  background-color: rgba(199,199,199, 0.5);
1847
  box-shadow: none;
1848
  border-left: 4px solid #29324e;
1849
  }
1850
- .bookings_page_rtb-settings .wrap h2.nav-tab-wrapper a.nav-tab-active:hover {
1851
  color: #1b335f;
1852
  background-color: #fff;
1853
  border-left: 4px solid #1b335f;
1854
  }
1855
 
1856
  /* Right side */
1857
- .bookings_page_rtb-settings .wrap form {
1858
  display: block;
1859
  position: relative;
1860
  float: left;
@@ -1867,13 +1869,13 @@ body.toplevel_page_rtb-bookings .rtb-admin-header-menu {
1867
  border: none;
1868
  }
1869
 
1870
- .bookings_page_rtb-settings .wrap form h2:first-of-type {
1871
  font-size: 18px;
1872
  color: #1b335f;
1873
  margin: 0 0 32px !important;
1874
  }
1875
 
1876
- .bookings_page_rtb-settings .wrap form h2:nth-of-type(1n+2) {
1877
  position: relative;
1878
  float: left;
1879
  background: #1b335f;
@@ -1886,7 +1888,7 @@ body.toplevel_page_rtb-bookings .rtb-admin-header-menu {
1886
  text-transform: uppercase;
1887
  z-index: 2;
1888
  }
1889
- .bookings_page_rtb-settings .wrap form .form-table {
1890
  width: 100%;
1891
  box-sizing: border-box;
1892
  margin: 0 auto 16px;
@@ -1895,13 +1897,13 @@ body.toplevel_page_rtb-bookings .rtb-admin-header-menu {
1895
  padding: 11px 5%;
1896
  }
1897
 
1898
- .bookings_page_rtb-settings .wrap form p.description {
1899
  display: none;
1900
  }
1901
- .bookings_page_rtb-settings .wrap form .form-table p.description {
1902
  display: block;
1903
  }
1904
- .bookings_page_rtb-settings .wrap form .form-table p.description.disabled {
1905
  color: #b5b5b5;
1906
  }
1907
 
@@ -1983,7 +1985,7 @@ input:checked + .rtb-admin-switch-slider:before {
1983
 
1984
 
1985
  /* RADIO BUTTON AND CHECKBOX */
1986
- .bookings_page_rtb-settings .wrap form .form-table fieldset label {
1987
  line-height: 1.4em;
1988
  margin: .25em 0 .5em;
1989
  display: inline-block;
@@ -2069,23 +2071,23 @@ input:checked + .rtb-admin-switch-slider:before {
2069
  }
2070
 
2071
  /* Textbox and Text Area and Select boxes */
2072
- .bookings_page_rtb-settings .wrap form .form-table input[type=text],
2073
- .bookings_page_rtb-settings .wrap form .form-table input[type=search],
2074
- .bookings_page_rtb-settings .wrap form .form-table input[type=tel],
2075
- .bookings_page_rtb-settings .wrap form .form-table input[type=url],
2076
- .bookings_page_rtb-settings .wrap form .form-table input[type=week],
2077
- .bookings_page_rtb-settings .wrap form .form-table input[type=password],
2078
- .bookings_page_rtb-settings .wrap form .form-table input[type=color],
2079
- .bookings_page_rtb-settings .wrap form .form-table input[type=email],
2080
- .bookings_page_rtb-settings .wrap form .form-table input[type=number],
2081
- .bookings_page_rtb-settings .wrap form .form-table textarea,
2082
- .bookings_page_rtb-settings .wrap form .form-table select {
2083
  border: 2px solid #ccc;
2084
  border-radius: 5px;
2085
  box-shadow: none;
2086
  }
2087
- .bookings_page_rtb-settings .wrap form .form-table select,
2088
- .bookings_page_rtb-settings .wrap form .form-table textarea {
2089
  width: auto !important;
2090
  min-width: 50%;
2091
  max-width: 100% !important;
@@ -2095,11 +2097,11 @@ input:checked + .rtb-admin-switch-slider:before {
2095
  min-width: 0;
2096
  }
2097
 
2098
- .bookings_page_rtb-settings .wrap form .form-table textarea {
2099
  min-width: 300px;
2100
  min-height: 200px;
2101
  }
2102
- .bookings_page_rtb-settings .wrap form .form-table .wp-editor-wrap textarea {
2103
  border: none;
2104
  border-radius: 0;
2105
  min-width: 0;
@@ -2177,43 +2179,43 @@ OTHER OPTION PAGE STYLING
2177
  RESPONSIVE
2178
  *************/
2179
  @media screen and (max-width: 1099px) {
2180
- .bookings_page_rtb-settings .wrap h2.nav-tab-wrapper {
2181
  clear: both;
2182
  width: 100%;
2183
  }
2184
- .bookings_page_rtb-settings .wrap form {
2185
  clear: both;
2186
  width: calc(100% - 96px);
2187
  }
2188
  }
2189
  @media screen and (max-width: 782px) {
2190
- .bookings_page_rtb-settings .wrap h2.nav-tab-wrapper {
2191
  margin: 0 0 20px 0;
2192
  }
2193
- .bookings_page_rtb-settings .wrap form {
2194
  width: calc(100% - 96px);
2195
  }
2196
  .rtb-admin-section-heading {
2197
  text-align: center;
2198
  }
2199
- .bookings_page_rtb-settings .wrap form .form-table,
2200
  .ufaq-styling-set .form-table {
2201
  box-shadow: none;
2202
  }
2203
- .bookings_page_rtb-settings .wrap form .form-table,
2204
  .ufaq-styling-set .form-table,
2205
- .bookings_page_rtb-settings .wrap form .form-table tbody,
2206
- .bookings_page_rtb-settings .wrap form .form-table tr,
2207
- .bookings_page_rtb-settings .wrap form .form-table th,
2208
- .bookings_page_rtb-settings .wrap form .form-table td {
2209
  clear: both;
2210
  float: left;
2211
  width: 100%;
2212
  }
2213
- .bookings_page_rtb-settings .wrap form .form-table {
2214
  padding: 11px 0;
2215
  }
2216
- .bookings_page_rtb-settings .wrap form .form-table th {
2217
  padding: 20px 5% 8px;
2218
  width: 90%;
2219
  height: auto;
@@ -2224,26 +2226,26 @@ RESPONSIVE
2224
  background-repeat: no-repeat;
2225
  cursor: pointer;
2226
  }
2227
- .bookings_page_rtb-settings .wrap form .form-table td {
2228
  padding-top: 4px;
2229
  }
2230
- .bookings_page_rtb-settings .wrap form .form-table td fieldset {
2231
  position: relative;
2232
  }
2233
- .bookings_page_rtb-settings .wrap form .form-table td label {
2234
  position: relative;
2235
  clear: both;
2236
  float: left;
2237
  width: 90%;
2238
  margin-left: 5% !important;
2239
  }
2240
- .bookings_page_rtb-settings .wrap form .form-table td label.rtb-admin-switch {
2241
  position: absolute;
2242
  width: 40px;
2243
  top: -35px;
2244
  right: 5%;
2245
  }
2246
- .bookings_page_rtb-settings .wrap form .form-table td p {
2247
  display: none;
2248
  position: relative;
2249
  float: left;
@@ -2253,7 +2255,7 @@ RESPONSIVE
2253
  border-bottom: 1px solid #ccc;
2254
  font-size: 13px;
2255
  }
2256
- .bookings_page_rtb-settings .wrap form .form-table td input[type="button"] {
2257
  display: block;
2258
  margin: 10px auto 4px;
2259
  }
@@ -2509,8 +2511,8 @@ RESPONSIVE
2509
  margin: 0.5em 2px;
2510
  }
2511
 
2512
- .bookings_page_rtb-settings .description,
2513
- .bookings_page_rtb-settings .form-table th {
2514
  margin-left: 2px;
2515
  }
2516
 
@@ -2596,8 +2598,8 @@ NEW STYLING FOR ADD/DELETE AREAS LIKE CUSTOM FIELDS
2596
  cursor: pointer;
2597
  }
2598
 
2599
- .bookings_page_rtb-settings .wrap form .form-table .sap-infinite-table input[type="number"],
2600
- .bookings_page_rtb-settings .wrap form .form-table .sap-infinite-table input[type="text"] {
2601
  width: 64px;
2602
  }
2603
 
@@ -2641,4 +2643,40 @@ NEW STYLING FOR ADD/DELETE AREAS LIKE CUSTOM FIELDS
2641
  }
2642
  .rtb-trial-version-select-modal-submit:hover {
2643
  background: #91B5CE;
2644
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  top: -9999px;
43
  left: -9999px;
44
  display: inline-block;
45
+ padding: 12px;
46
+ background: #fff;
47
+ box-sizing: border-box;
48
  -webkit-box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
49
  box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
50
  }
52
  #rtb-filters.date-filters-visible .date-filters {
53
  position: relative;
54
  top: auto;
55
+ left: 0;
56
+ width: 300px;
57
  }
58
 
59
  #rtb-filters .date-filters .datepicker {
768
 
769
  /*** WRAP ***/
770
 
771
+ body[class*="_rtb-dashboard"] #wpcontent {
772
  padding-left: 0;
773
  }
774
+ body[class*="_rtb-dashboard"] .wrap {
775
  margin: 10px 0 0;
776
  }
777
 
959
  float: left;
960
  width: 100%;
961
  }
962
+ body[class*="_rtb-settings"] .rtb-admin-header-menu,
963
+ body[class*="_cffrtb-editor"] .rtb-admin-header-menu,
964
+ body[class*="_rtb-bookings"] .rtb-admin-header-menu {
965
  margin-left: -20px;
966
  width: calc(100% + 20px);
967
  }
1806
  /************************/
1807
 
1808
  /* Side Menu */
1809
+ body[class*="_rtb-settings"] .wrap h2.nav-tab-wrapper {
1810
  position: relative;
1811
  float: left;
1812
  border: none;
1816
  padding-top: 0;
1817
  margin-top: 20px;
1818
  }
1819
+ body[class*="_rtb-settings"] .wrap h2.nav-tab-wrapper a {
1820
  clear: both;
1821
  display: block;
1822
  position: relative;
1834
  line-height: 34px;
1835
  font-size: 13px;
1836
  }
1837
+ body[class*="_rtb-settings"] .wrap h2.nav-tab-wrapper a:last-of-type {
1838
  border-bottom: none;
1839
  }
1840
+ body[class*="_rtb-settings"] .wrap h2.nav-tab-wrapper a.nav-tab-active {
1841
  box-shadow: none;
1842
  background-color: #fff !important;
1843
  color: #1b335f;
1844
  border-left: 4px solid #1b335f;
1845
  }
1846
+ body[class*="_rtb-settings"] .wrap h2.nav-tab-wrapper a:hover {
1847
  color: #29324e;
1848
  background-color: rgba(199,199,199, 0.5);
1849
  box-shadow: none;
1850
  border-left: 4px solid #29324e;
1851
  }
1852
+ body[class*="_rtb-settings"] .wrap h2.nav-tab-wrapper a.nav-tab-active:hover {
1853
  color: #1b335f;
1854
  background-color: #fff;
1855
  border-left: 4px solid #1b335f;
1856
  }
1857
 
1858
  /* Right side */
1859
+ body[class*="_rtb-settings"] .wrap form {
1860
  display: block;
1861
  position: relative;
1862
  float: left;
1869
  border: none;
1870
  }
1871
 
1872
+ body[class*="_rtb-settings"] .wrap form h2:first-of-type {
1873
  font-size: 18px;
1874
  color: #1b335f;
1875
  margin: 0 0 32px !important;
1876
  }
1877
 
1878
+ body[class*="_rtb-settings"] .wrap form h2:nth-of-type(1n+2) {
1879
  position: relative;
1880
  float: left;
1881
  background: #1b335f;
1888
  text-transform: uppercase;
1889
  z-index: 2;
1890
  }
1891
+ body[class*="_rtb-settings"] .wrap form .form-table {
1892
  width: 100%;
1893
  box-sizing: border-box;
1894
  margin: 0 auto 16px;
1897
  padding: 11px 5%;
1898
  }
1899
 
1900
+ body[class*="_rtb-settings"] .wrap form p.description {
1901
  display: none;
1902
  }
1903
+ body[class*="_rtb-settings"] .wrap form .form-table p.description {
1904
  display: block;
1905
  }
1906
+ body[class*="_rtb-settings"] .wrap form .form-table p.description.disabled {
1907
  color: #b5b5b5;
1908
  }
1909
 
1985
 
1986
 
1987
  /* RADIO BUTTON AND CHECKBOX */
1988
+ body[class*="_rtb-settings"] .wrap form .form-table fieldset label {
1989
  line-height: 1.4em;
1990
  margin: .25em 0 .5em;
1991
  display: inline-block;
2071
  }
2072
 
2073
  /* Textbox and Text Area and Select boxes */
2074
+ body[class*="_rtb-settings"] .wrap form .form-table input[type=text],
2075
+ body[class*="_rtb-settings"] .wrap form .form-table input[type=search],
2076
+ body[class*="_rtb-settings"] .wrap form .form-table input[type=tel],
2077
+ body[class*="_rtb-settings"] .wrap form .form-table input[type=url],
2078
+ body[class*="_rtb-settings"] .wrap form .form-table input[type=week],
2079
+ body[class*="_rtb-settings"] .wrap form .form-table input[type=password],
2080
+ body[class*="_rtb-settings"] .wrap form .form-table input[type=color],
2081
+ body[class*="_rtb-settings"] .wrap form .form-table input[type=email],
2082
+ body[class*="_rtb-settings"] .wrap form .form-table input[type=number],
2083
+ body[class*="_rtb-settings"] .wrap form .form-table textarea,
2084
+ body[class*="_rtb-settings"] .wrap form .form-table select {
2085
  border: 2px solid #ccc;
2086
  border-radius: 5px;
2087
  box-shadow: none;
2088
  }
2089
+ body[class*="_rtb-settings"] .wrap form .form-table select,
2090
+ body[class*="_rtb-settings"] .wrap form .form-table textarea {
2091
  width: auto !important;
2092
  min-width: 50%;
2093
  max-width: 100% !important;
2097
  min-width: 0;
2098
  }
2099
 
2100
+ body[class*="_rtb-settings"] .wrap form .form-table textarea {
2101
  min-width: 300px;
2102
  min-height: 200px;
2103
  }
2104
+ body[class*="_rtb-settings"] .wrap form .form-table .wp-editor-wrap textarea {
2105
  border: none;
2106
  border-radius: 0;
2107
  min-width: 0;
2179
  RESPONSIVE
2180
  *************/
2181
  @media screen and (max-width: 1099px) {
2182
+ body[class*="_rtb-settings"] .wrap h2.nav-tab-wrapper {
2183
  clear: both;
2184
  width: 100%;
2185
  }
2186
+ body[class*="_rtb-settings"] .wrap form {
2187
  clear: both;
2188
  width: calc(100% - 96px);
2189
  }
2190
  }
2191
  @media screen and (max-width: 782px) {
2192
+ body[class*="_rtb-settings"] .wrap h2.nav-tab-wrapper {
2193
  margin: 0 0 20px 0;
2194
  }
2195
+ body[class*="_rtb-settings"] .wrap form {
2196
  width: calc(100% - 96px);
2197
  }
2198
  .rtb-admin-section-heading {
2199
  text-align: center;
2200
  }
2201
+ body[class*="_rtb-settings"] .wrap form .form-table,
2202
  .ufaq-styling-set .form-table {
2203
  box-shadow: none;
2204
  }
2205
+ body[class*="_rtb-settings"] .wrap form .form-table,
2206
  .ufaq-styling-set .form-table,
2207
+ body[class*="_rtb-settings"] .wrap form .form-table tbody,
2208
+ body[class*="_rtb-settings"] .wrap form .form-table tr,
2209
+ body[class*="_rtb-settings"] .wrap form .form-table th,
2210
+ body[class*="_rtb-settings"] .wrap form .form-table td {
2211
  clear: both;
2212
  float: left;
2213
  width: 100%;
2214
  }
2215
+ body[class*="_rtb-settings"] .wrap form .form-table {
2216
  padding: 11px 0;
2217
  }
2218
+ body[class*="_rtb-settings"] .wrap form .form-table th {
2219
  padding: 20px 5% 8px;
2220
  width: 90%;
2221
  height: auto;
2226
  background-repeat: no-repeat;
2227
  cursor: pointer;
2228
  }
2229
+ body[class*="_rtb-settings"] .wrap form .form-table td {
2230
  padding-top: 4px;
2231
  }
2232
+ body[class*="_rtb-settings"] .wrap form .form-table td fieldset {
2233
  position: relative;
2234
  }
2235
+ body[class*="_rtb-settings"] .wrap form .form-table td label {
2236
  position: relative;
2237
  clear: both;
2238
  float: left;
2239
  width: 90%;
2240
  margin-left: 5% !important;
2241
  }
2242
+ body[class*="_rtb-settings"] .wrap form .form-table td label.rtb-admin-switch {
2243
  position: absolute;
2244
  width: 40px;
2245
  top: -35px;
2246
  right: 5%;
2247
  }
2248
+ body[class*="_rtb-settings"] .wrap form .form-table td p {
2249
  display: none;
2250
  position: relative;
2251
  float: left;
2255
  border-bottom: 1px solid #ccc;
2256
  font-size: 13px;
2257
  }
2258
+ body[class*="_rtb-settings"] .wrap form .form-table td input[type="button"] {
2259
  display: block;
2260
  margin: 10px auto 4px;
2261
  }
2511
  margin: 0.5em 2px;
2512
  }
2513
 
2514
+ body[class*="_rtb-settings"] .description,
2515
+ body[class*="_rtb-settings"] .form-table th {
2516
  margin-left: 2px;
2517
  }
2518
 
2598
  cursor: pointer;
2599
  }
2600
 
2601
+ body[class*="_rtb-settings"] .wrap form .form-table .sap-infinite-table input[type="number"],
2602
+ body[class*="_rtb-settings"] .wrap form .form-table .sap-infinite-table input[type="text"] {
2603
  width: 64px;
2604
  }
2605
 
2643
  }
2644
  .rtb-trial-version-select-modal-submit:hover {
2645
  background: #91B5CE;
2646
+ }
2647
+
2648
+
2649
+ /*********************************
2650
+ CUSTOM FIELDS
2651
+ *********************************/
2652
+ #cffrtb-field-editor.rtb-admin-modal .button {
2653
+ margin-top: 0;
2654
+ }
2655
+
2656
+
2657
+ /*********************************
2658
+ NEW DATE SELETION FILTERS
2659
+ *********************************/
2660
+ .rtb-admin-bookings-filters-start,
2661
+ .rtb-admin-bookings-filters-end {
2662
+ position: relative;
2663
+ float: left;
2664
+ width: 100%;
2665
+ margin: 0 0 4px;
2666
+ }
2667
+ .rtb-admin-bookings-filters-start input,
2668
+ .rtb-admin-bookings-filters-end input {
2669
+ position: relative;
2670
+ float: left;
2671
+ width: calc(50% - 4px);
2672
+ margin: 0 2px 4px;
2673
+ border: 1px solid #ddd;
2674
+ background: #f5f5f5;
2675
+ color: #555;
2676
+ border-radius: 2px;
2677
+ }
2678
+ .rtb-admin-bookings-filters-start input::placeholder,
2679
+ .rtb-admin-bookings-filters-end input::placeholder {
2680
+ color: #555;
2681
+ }
2682
+
assets/css/booking-form.css CHANGED
@@ -6,6 +6,13 @@
6
  .rtb-hidden {
7
  display: none;
8
  }
 
 
 
 
 
 
 
9
  .rtb-booking-form fieldset {
10
  padding-bottom: 1em;
11
  margin-bottom: 1em;
@@ -206,37 +213,49 @@ label[for="rtb-cancellation-email"] {
206
  cursor: pointer;
207
  }
208
 
209
- .rtb-bookings-results,
210
- .rtb-cancel-booking-div {
211
  position: relative;
212
  float: left;
213
  width: 100%;
214
  margin-top: 16px;
215
  }
216
  .rtb-cancel-booking-div {
217
- position: relative;
218
- float: left;
219
- width: calc(100% - 2px);
220
  border: 1px solid #ddd;
 
 
 
 
 
 
 
 
221
  }
222
  .rtb-cancel-booking {
223
- position: relative;
224
- float: left;
225
  width: 200px;
226
  text-align: center;
227
  padding: 10px 0;
228
  background: #fe4e4e;
229
  color: #fff;
230
  cursor: pointer;
 
231
  }
232
  .rtb-cancel-booking:hover {
233
  background: #ff6b6b;
234
  color: #fff;
235
  }
 
 
 
236
  .rtb-booking-information {
237
- position: relative;
238
- float: left;
239
  margin-left: 32px;
240
  width: calc(100% - 232px);
241
  padding: 10px 0;
 
 
 
 
 
 
 
 
242
  }
6
  .rtb-hidden {
7
  display: none;
8
  }
9
+ .rtb-booking-form {
10
+ position: relative;
11
+ /*float: left;*/
12
+ width: 100%;
13
+ clear: both;
14
+ margin-bottom: 48px;
15
+ }
16
  .rtb-booking-form fieldset {
17
  padding-bottom: 1em;
18
  margin-bottom: 1em;
213
  cursor: pointer;
214
  }
215
 
216
+ .rtb-bookings-results {
 
217
  position: relative;
218
  float: left;
219
  width: 100%;
220
  margin-top: 16px;
221
  }
222
  .rtb-cancel-booking-div {
 
 
 
223
  border: 1px solid #ddd;
224
+ margin-bottom: 8px;
225
+ }
226
+ .rtb-cancel-booking-div + .alert {
227
+ margin: 0;
228
+ }
229
+ .rtb-cancel-booking-div + .alert.error {
230
+ color: #f24a4d;
231
+ background: #f24a4d47;
232
  }
233
  .rtb-cancel-booking {
 
 
234
  width: 200px;
235
  text-align: center;
236
  padding: 10px 0;
237
  background: #fe4e4e;
238
  color: #fff;
239
  cursor: pointer;
240
+ display: inline-block;
241
  }
242
  .rtb-cancel-booking:hover {
243
  background: #ff6b6b;
244
  color: #fff;
245
  }
246
+ .rtb-cancel-booking.cancelled {
247
+ background: #24b124;
248
+ }
249
  .rtb-booking-information {
 
 
250
  margin-left: 32px;
251
  width: calc(100% - 232px);
252
  padding: 10px 0;
253
+ display: inline-block;
254
+ }
255
+
256
+ #rtb_recaptcha {
257
+ position: relative;
258
+ float: left;
259
+ width: 100%;
260
+ margin: 16px 0;
261
  }
assets/css/contemporary.css CHANGED
@@ -130,24 +130,24 @@
130
  }
131
 
132
 
133
- .rtb-booking-form fieldset.contact {
134
  margin-bottom: 60px;
135
  }
136
- .rtb-booking-form fieldset.contact label {
137
  margin-left: 21px;
138
  color: #666;
139
  font-weight: bold;
140
  }
141
- .rtb-booking-form fieldset.contact .rtb-text {
142
  position: relative;
143
  float: left;
144
  display: block;
145
  width: 300px;
146
  }
147
 
148
- .rtb-booking-form form fieldset.contact select,
149
- .rtb-booking-form form fieldset.contact textarea,
150
- .rtb-booking-form form fieldset.contact input {
151
  width: 300px;
152
  }
153
 
130
  }
131
 
132
 
133
+ .rtb-booking-form fieldset.rtb-contact {
134
  margin-bottom: 60px;
135
  }
136
+ .rtb-booking-form fieldset.rtb-contact label {
137
  margin-left: 21px;
138
  color: #666;
139
  font-weight: bold;
140
  }
141
+ .rtb-booking-form fieldset.rtb-contact .rtb-text {
142
  position: relative;
143
  float: left;
144
  display: block;
145
  width: 300px;
146
  }
147
 
148
+ .rtb-booking-form form fieldset.rtb-contact select,
149
+ .rtb-booking-form form fieldset.rtb-contact textarea,
150
+ .rtb-booking-form form fieldset.rtb-contact input {
151
  width: 300px;
152
  }
153
 
assets/js/admin.js CHANGED
@@ -26,6 +26,32 @@ jQuery(document).ready(function ($) {
26
  });
27
  });
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  // Show or hide extra booking details in the bookings table
30
  $( '.rtb-show-details' ).click( function (e) {
31
  e.preventDefault();
@@ -67,6 +93,26 @@ jQuery(document).ready(function ($) {
67
  e.preventDefault();
68
  });
69
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  // Show booking form modal
71
  $( '.add-booking' ).click( function( e ) {
72
  e.preventDefault();
26
  });
27
  });
28
 
29
+ // Add a time picker for filtering in admin
30
+ $ ( '#start-time, #end-time' ).each( function() {
31
+ var $time_input = $( this );
32
+
33
+ $time_input.pickatime({
34
+ format: rtb_pickadate.time_format,
35
+ formatSubmit: 'h:i A',
36
+ hiddenName: true,
37
+ interval: parseInt( rtb_pickadate.time_interval, 10 ),
38
+ container: 'body',
39
+
40
+ // Select the value when loaded if a value has been set
41
+ onStart: function() {
42
+ if ( $time_input.val() !== '' ) {
43
+ var today = new Date();
44
+ var today_date = today.getFullYear() + '/' + ( today.getMonth() + 1 ) + '/' + today.getDate();
45
+ var time = new Date( today_date + ' ' + $time_input.val() );
46
+ if ( Object.prototype.toString.call( time ) === "[object Date]" ) {
47
+ this.set( 'select', time );
48
+ }
49
+
50
+ }
51
+ }
52
+ });
53
+ });
54
+
55
  // Show or hide extra booking details in the bookings table
56
  $( '.rtb-show-details' ).click( function (e) {
57
  e.preventDefault();
93
  e.preventDefault();
94
  });
95
 
96
+ // Register clicks on the 'Send Email' bulk action
97
+ $( '#rtb-bookings-table .bulkactions #doaction' ).on( 'click', function(e) {
98
+
99
+ var target = $( e.target );
100
+ var select = target.parent().find( 'select' ).first();
101
+
102
+ if ( select.val() != 'send-email' ) { return; }
103
+
104
+ e.stopPropagation();
105
+ e.preventDefault();
106
+
107
+ var booking_ids = [];
108
+
109
+ $( 'input[name="bookings[]"]:checked' ).each( function() {
110
+ booking_ids.push( $( this ).val() );
111
+ });
112
+
113
+ rtb_toggle_email_modal( true, booking_ids.join(','), 'multiple-emails', 'Multiple Bookings' );
114
+ });
115
+
116
  // Show booking form modal
117
  $( '.add-booking' ).click( function( e ) {
118
  e.preventDefault();
assets/js/booking-form.js CHANGED
@@ -599,10 +599,10 @@ jQuery(document).ready(function() {
599
  jQuery('.rtb-cancellation-form, .rtb-booking-form-form').toggleClass('rtb-hidden');
600
 
601
  if (jQuery('.rtb-cancellation-form').hasClass('rtb-hidden')) {
602
- jQuery('.rtb-cancellation-toggle').html('Want to cancel your reservation?');
603
  }
604
  else {
605
- jQuery('.rtb-cancellation-toggle').html('Make a reservation');
606
  }
607
  });
608
 
@@ -617,8 +617,8 @@ jQuery(document).ready(function() {
617
 
618
  jQuery(response.data.bookings).each(function( index, val) {
619
  booking_html += '<div class="rtb-cancel-booking-div">';
620
- booking_html += '<div class="rtb-cancel-booking" data-bookingid="' + val.ID + '" data-bookingemail="' + val.email + '">Cancel</div>';
621
- booking_html += '<div class="rtb-booking-information">' + val.datetime + ' - ' + val.party + ' guest' + (val.party > 1 ? 's' : '') + '</div>'
622
  booking_html += '</div>';
623
  });
624
 
@@ -632,15 +632,41 @@ jQuery(document).ready(function() {
632
  });
633
 
634
  function cancellationHandler() {
635
- jQuery('.rtb-cancel-booking').off('click');
636
- jQuery('.rtb-cancel-booking').on('click', function() {
637
- var booking_id = jQuery(this).data('bookingid');
638
- var booking_email = jQuery(this).data('bookingemail');
639
 
640
- var data = 'booking_id=' + booking_id + '&booking_email=' + booking_email + '&action=rtb_cancel_reservations'; console.log(data);
641
- jQuery.post(ajaxurl, data, function(response) { console.log(response);
642
- if (response.success) {window.location.href = replaceUrlParam(window.location.href, 'bookingCancelled', 'success');}
643
- else {jQuery('.rtb-bookings-results').html(response.data.msg);}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
644
  });
645
  });
646
  }
599
  jQuery('.rtb-cancellation-form, .rtb-booking-form-form').toggleClass('rtb-hidden');
600
 
601
  if (jQuery('.rtb-cancellation-form').hasClass('rtb-hidden')) {
602
+ jQuery('.rtb-cancellation-toggle').html(rtb_booking_form_js_localize.want_to_cancel);
603
  }
604
  else {
605
+ jQuery('.rtb-cancellation-toggle').html(rtb_booking_form_js_localize.make);
606
  }
607
  });
608
 
617
 
618
  jQuery(response.data.bookings).each(function( index, val) {
619
  booking_html += '<div class="rtb-cancel-booking-div">';
620
+ booking_html += '<div class="rtb-cancel-booking" data-bookingid="' + val.ID + '" data-bookingemail="' + val.email + '">' + rtb_booking_form_js_localize.cancel + '</div>';
621
+ booking_html += '<div class="rtb-booking-information">' + val.datetime + ' - ' + val.party + ' ' + (val.party > 1 ? rtb_booking_form_js_localize.guests : rtb_booking_form_js_localize.guest) + '</div>'
622
  booking_html += '</div>';
623
  });
624
 
632
  });
633
 
634
  function cancellationHandler() {
635
+ jQuery('.rtb-cancel-booking:not(.cancelled)').off('click');
636
+ jQuery('.rtb-cancel-booking:not(.cancelled)').on('click', function() {
637
+ var btn = jQuery(this);
 
638
 
639
+ if(btn.hasClass('processing')) {
640
+ return;
641
+ }
642
+
643
+ btn.addClass('processing');
644
+
645
+ var booking_id = btn.data('bookingid');
646
+ var booking_email = btn.data('bookingemail');
647
+
648
+ var data = {
649
+ 'booking_id': booking_id,
650
+ 'booking_email': booking_email,
651
+ 'action': 'rtb_cancel_reservations'
652
+ };
653
+
654
+ jQuery.post(ajaxurl, data, function(response) {
655
+ if (response.success) {
656
+ if (response.data.hasOwnProperty('cancelled_redirect')) {
657
+ window.location.href = response.data.cancelled_redirect;
658
+ }
659
+ else {
660
+ btn.off('click');
661
+ btn.addClass('cancelled');
662
+ btn.text('Cancelled');
663
+ }
664
+ }
665
+ else {
666
+ btn.parent().after(`<p class="alert error">${response.data.msg}</p>`);
667
+ }
668
+
669
+ btn.removeClass('processing');
670
  });
671
  });
672
  }
includes/AdminBookings.class.php CHANGED
@@ -651,9 +651,7 @@ class rtbAdminBookings {
651
  $_POST[ $field['name'] ] = $field['value'];
652
  }
653
 
654
- $id = (int) $_POST['ID'];
655
- $name = sanitize_text_field( $_POST['name'] );
656
- $email = sanitize_text_field( $_POST['email'] );
657
  $subject = stripcslashes( sanitize_text_field( $_POST['rtb-email-subject'] ) );
658
  $message = stripcslashes( wp_kses_post( $_POST['rtb-email-message'] ) );
659
 
@@ -666,7 +664,7 @@ class rtbAdminBookings {
666
  );
667
  }
668
 
669
- if ( empty( $id ) || empty( $name ) || empty( $email ) ) {
670
  wp_send_json_error(
671
  array(
672
  'error' => 'email_missing_data',
@@ -676,31 +674,27 @@ class rtbAdminBookings {
676
  }
677
 
678
  require_once( RTB_PLUGIN_DIR . '/includes/Booking.class.php' );
679
- $booking = new rtbBooking();
680
-
681
- if ( !$booking->load_post( $id ) ) {
682
- wp_send_json_error(
683
- array(
684
- 'error' => 'email_missing_booking',
685
- 'msg' => __( 'There was an error loading the booking and the email was not sent.', 'restaurant-reservations' ),
686
- )
687
- );
688
- }
 
 
 
 
 
689
 
690
- $email = new rtbNotificationEmail( 'admin_email_notice', 'user' );
691
- $email->subject = empty( $subject ) ? $rtb_controller->settings->get_setting( 'subject-admin-notice' ) : $subject;
692
- $email->message = $message;
693
- $email->set_booking( $booking );
694
- if ( $email->prepare_notification() ) {
695
- do_action( 'rtb_send_notification_before', $email );
696
- $email->send_notification();
697
- do_action( 'rtb_send_notification_after', $email );
698
  }
699
 
700
- // Store email in postmeta for log
701
- $booking->add_log( 'email', $email->subject, $email->message );
702
- $booking->insert_post_data();
703
-
704
  wp_send_json_success();
705
  }
706
 
651
  $_POST[ $field['name'] ] = $field['value'];
652
  }
653
 
654
+ $ids = ( isset( $_POST['ID'] ) and $_POST['ID'] != '' ) ? explode( ',', $_POST['ID'] ) : array();
 
 
655
  $subject = stripcslashes( sanitize_text_field( $_POST['rtb-email-subject'] ) );
656
  $message = stripcslashes( wp_kses_post( $_POST['rtb-email-message'] ) );
657
 
664
  );
665
  }
666
 
667
+ if ( empty( $ids ) ) {
668
  wp_send_json_error(
669
  array(
670
  'error' => 'email_missing_data',
674
  }
675
 
676
  require_once( RTB_PLUGIN_DIR . '/includes/Booking.class.php' );
677
+
678
+ foreach ( $ids as $id ) {
679
+
680
+ $booking = new rtbBooking();
681
+ $booking->load_post( $id );
682
+
683
+ $email = new rtbNotificationEmail( 'admin_email_notice', 'user' );
684
+ $email->subject = empty( $subject ) ? $rtb_controller->settings->get_setting( 'subject-admin-notice' ) : $subject;
685
+ $email->message = $message;
686
+ $email->set_booking( $booking );
687
+ if ( $email->prepare_notification() ) {
688
+ do_action( 'rtb_send_notification_before', $email );
689
+ $email->send_notification();
690
+ do_action( 'rtb_send_notification_after', $email );
691
+ }
692
 
693
+ // Store email in postmeta for log
694
+ $booking->add_log( 'email', $email->subject, $email->message );
695
+ $booking->insert_post_data();
 
 
 
 
 
696
  }
697
 
 
 
 
 
698
  wp_send_json_success();
699
  }
700
 
includes/Ajax.class.php CHANGED
@@ -121,6 +121,8 @@ if ( !class_exists( 'rtbAJAX' ) ) {
121
  public function cancel_reservation( $ajax = true ) {
122
  global $rtb_controller;
123
 
 
 
124
  $booking_id = isset($_REQUEST['booking_id']) ? absint( $_REQUEST['booking_id'] ) : '';
125
  $booking_email = isset($_REQUEST['booking_email']) ? sanitize_email( $_REQUEST['booking_email'] ) : '';
126
 
@@ -155,27 +157,44 @@ if ( !class_exists( 'rtbAJAX' ) ) {
155
 
156
  if ( $ajax ) {
157
  if ( $success ) {
158
- wp_send_json_success(
 
 
 
 
 
 
 
 
 
 
159
  array(
160
- 'booking_id' => $booking_id
 
161
  )
162
  );
163
  }
164
  }
165
- elseif ( $success ) {
166
- $booking_page_id = $rtb_controller->settings->get_setting( 'booking-page' );
167
- $booking_page_url = get_permalink( $booking_page_id );
168
 
169
- $cancelled_url = add_query_arg(
170
- array(
171
- 'bookingCancelled' => 'success'
172
- ),
173
- $booking_page_url
174
- );
175
 
176
- header( 'location:' . $cancelled_url );
177
- }
 
 
 
 
 
178
 
 
 
179
  }
180
 
181
  /**
121
  public function cancel_reservation( $ajax = true ) {
122
  global $rtb_controller;
123
 
124
+ $cancelled_redirect = $rtb_controller->settings->get_setting( 'cancelled-redirect-page' );
125
+
126
  $booking_id = isset($_REQUEST['booking_id']) ? absint( $_REQUEST['booking_id'] ) : '';
127
  $booking_email = isset($_REQUEST['booking_email']) ? sanitize_email( $_REQUEST['booking_email'] ) : '';
128
 
157
 
158
  if ( $ajax ) {
159
  if ( $success ) {
160
+
161
+ $response = array( 'booking_id' => $booking_id );
162
+
163
+ if( '' != $cancelled_redirect ) {
164
+ $response['cancelled_redirect'] = $cancelled_redirect;
165
+ }
166
+
167
+ wp_send_json_success( $response );
168
+ }
169
+ else {
170
+ wp_send_json_error(
171
  array(
172
+ 'error' => 'unknown',
173
+ 'msg' => __( 'Unkown error. Please try again', 'restaurant-reservations' ),
174
  )
175
  );
176
  }
177
  }
178
+ else {
179
+ $redirect_url = '';
 
180
 
181
+ if( '' != $cancelled_redirect && $success ) {
182
+ $redirect_url = $cancelled_redirect;
183
+ }
184
+ else {
185
+ $booking_page_id = $rtb_controller->settings->get_setting( 'booking-page' );
186
+ $booking_page_url = get_permalink( $booking_page_id );
187
 
188
+ $redirect_url = add_query_arg(
189
+ array(
190
+ 'bookingCancelled' => $success ? 'success' : 'fail'
191
+ ),
192
+ $booking_page_url
193
+ );
194
+ }
195
 
196
+ header( 'location:' . $redirect_url );
197
+ }
198
  }
199
 
200
  /**
includes/Booking.class.php CHANGED
@@ -569,10 +569,10 @@ class rtbBooking {
569
  'post_variable' => $ip,
570
  'message' => __( 'Your booking has been rejected. Please call us if you would like to make a booking.', 'restaurant-reservations' ),
571
  );
572
- } elseif ( empty( $this->ip ) ) {
573
  $this->ip = sanitize_text_field( $ip );
574
  }
575
- } elseif ( empty( $this->ip ) ) {
576
  $this->ip = sanitize_text_field( $_SERVER['REMOTE_ADDR'] );
577
  }
578
 
@@ -595,7 +595,7 @@ class rtbBooking {
595
  }
596
 
597
  // Check if there is a booking already made with the exact same information, to prevent double bookings on refresh
598
- if ( $this->is_duplicate_booking() ){
599
  $this->validation_errors[] = array(
600
  'field' => 'date',
601
  'error_msg' => 'duplicate booking',
@@ -873,15 +873,37 @@ class rtbBooking {
873
  * @since 2.1.20
874
  */
875
  public function is_duplicate_booking() {
876
- global $wpdb;
 
 
 
 
 
 
 
 
 
877
 
878
- $sql = "SELECT ID FROM $wpdb->posts WHERE post_type=%s AND post_date=%s AND post_title=%s";
879
- $args = array(
880
- RTB_BOOKING_POST_TYPE,
881
- $this->date,
882
- $this->name
 
 
 
 
 
 
 
 
 
883
  );
884
 
 
 
 
 
885
  if ( isset( $this->ID ) ) {
886
  $sql .= ' AND ID!=%d';
887
  $args[] = $this->ID;
@@ -890,7 +912,6 @@ class rtbBooking {
890
  $booking_result = $wpdb->get_row( $wpdb->prepare( $sql, $args ) );
891
 
892
  if ( $booking_result ) {
893
-
894
  $meta = get_post_meta( $booking_result->ID, 'rtb', true );
895
  $meta = is_array( $meta ) ? $meta : array();
896
 
@@ -969,7 +990,7 @@ class rtbBooking {
969
  $max_seats_setting = $rtb_controller->settings->get_setting( 'auto-confirm-max-seats' );
970
  $max_seats = substr( $max_seats_setting, 0, strpos( $max_seats_setting, '_' ) );
971
 
972
- if ( $max_seats == 'undefined' or $max_seats <= 1 or $this->party >= $max_seats ) { return false; }
973
 
974
  $dining_block_setting = $rtb_controller->settings->get_setting( 'rtb-dining-block-length' );
975
  $dining_block = substr( $dining_block_setting, 0, strpos( $dining_block_setting, '_' ) );
@@ -1008,7 +1029,8 @@ class rtbBooking {
1008
  if ( key ( $current_seats ) < $time - $dining_block_seconds ) { array_shift( $current_seats ); }
1009
 
1010
  // Check if adding the current party puts us at or above the max confirmation number
1011
- if ( array_sum( $current_seats ) + $this->party >= $max_seats ) { $auto_confirm = false; break; }
 
1012
  }
1013
 
1014
  return $auto_confirm;
569
  'post_variable' => $ip,
570
  'message' => __( 'Your booking has been rejected. Please call us if you would like to make a booking.', 'restaurant-reservations' ),
571
  );
572
+ } elseif ( empty( $this->ip ) and ! $rtb_controller->settings->get_setting( 'disable-ip-capture' ) ) {
573
  $this->ip = sanitize_text_field( $ip );
574
  }
575
+ } elseif ( empty( $this->ip ) and ! $rtb_controller->settings->get_setting( 'disable-ip-capture' ) ) {
576
  $this->ip = sanitize_text_field( $_SERVER['REMOTE_ADDR'] );
577
  }
578
 
595
  }
596
 
597
  // Check if there is a booking already made with the exact same information, to prevent double bookings on refresh
598
+ if ( $this->is_duplicate_booking() ) {
599
  $this->validation_errors[] = array(
600
  'field' => 'date',
601
  'error_msg' => 'duplicate booking',
873
  * @since 2.1.20
874
  */
875
  public function is_duplicate_booking() {
876
+ global $wpdb, $rtb_controller;
877
+
878
+ if( 0 < count($this->validation_errors) ) {
879
+ /**
880
+ * Do not run this check if there is an error already
881
+ * There could abe a moment when someminfo could be missing, which is required
882
+ * for this qurey to function.
883
+ */
884
+ return null;
885
+ }
886
 
887
+ $valid_status = ['confirmed', 'pending'];
888
+
889
+ // This is an intermediate status when payment is pending
890
+ if ( $rtb_controller->settings->get_setting( 'require-deposit' ) ) {
891
+ $valid_status = array_merge($valid_status, ['draft']);
892
+ }
893
+
894
+ $args = array_merge(
895
+ array(
896
+ RTB_BOOKING_POST_TYPE,
897
+ $this->date,
898
+ $this->name
899
+ ),
900
+ $valid_status
901
  );
902
 
903
+ $status_placeholder = implode( ',', array_fill( 0, count( $valid_status ), '%s' ) );
904
+
905
+ $sql = "SELECT ID FROM {$wpdb->posts} WHERE post_type=%s AND post_date=%s AND post_title=%s AND post_status IN ({$status_placeholder})";
906
+
907
  if ( isset( $this->ID ) ) {
908
  $sql .= ' AND ID!=%d';
909
  $args[] = $this->ID;
912
  $booking_result = $wpdb->get_row( $wpdb->prepare( $sql, $args ) );
913
 
914
  if ( $booking_result ) {
 
915
  $meta = get_post_meta( $booking_result->ID, 'rtb', true );
916
  $meta = is_array( $meta ) ? $meta : array();
917
 
990
  $max_seats_setting = $rtb_controller->settings->get_setting( 'auto-confirm-max-seats' );
991
  $max_seats = substr( $max_seats_setting, 0, strpos( $max_seats_setting, '_' ) );
992
 
993
+ if ( $max_seats == 'undefined' or $max_seats < 2 or $this->party >= $max_seats ) { return false; }
994
 
995
  $dining_block_setting = $rtb_controller->settings->get_setting( 'rtb-dining-block-length' );
996
  $dining_block = substr( $dining_block_setting, 0, strpos( $dining_block_setting, '_' ) );
1029
  if ( key ( $current_seats ) < $time - $dining_block_seconds ) { array_shift( $current_seats ); }
1030
 
1031
  // Check if adding the current party puts us at or above the max confirmation number
1032
+ var_dump($current_seats, array_sum( $current_seats ), $this->party, $max_seats);
1033
+ if ( array_sum( $current_seats ) + $this->party >= $max_seats ) { $auto_confirm = false; break; }
1034
  }
1035
 
1036
  return $auto_confirm;
includes/Dashboard.class.php CHANGED
@@ -134,7 +134,7 @@ class rtbDashboard {
134
  </div>
135
 
136
  <div class="rtb-dashboard-new-widget-box ewd-widget-box-full" id="rtb-dashboard-optional-table">
137
- <div class="rtb-dashboard-new-widget-box-top">Bookings Summary<span id="rtb-dash-optional-table-down-caret">&nbsp;&nbsp;&#9660;</span><span id="rtb-dash-optional-table-up-caret">&nbsp;&nbsp;&#9650;</span></div>
138
  <div class="rtb-dashboard-new-widget-box-bottom">
139
  <table class='rtb-overview-table wp-list-table widefat fixed striped posts'>
140
  <thead>
134
  </div>
135
 
136
  <div class="rtb-dashboard-new-widget-box ewd-widget-box-full" id="rtb-dashboard-optional-table">
137
+ <div class="rtb-dashboard-new-widget-box-top"><?php _e('Bookings Summary', 'restaurant-reservations'); ?><span id="rtb-dash-optional-table-down-caret">&nbsp;&nbsp;&#9660;</span><span id="rtb-dash-optional-table-up-caret">&nbsp;&nbsp;&#9650;</span></div>
138
  <div class="rtb-dashboard-new-widget-box-bottom">
139
  <table class='rtb-overview-table wp-list-table widefat fixed striped posts'>
140
  <thead>
includes/Export.CSV.class.php CHANGED
@@ -42,12 +42,16 @@ class ebfrtbExportCSV extends ebfrtbExport {
42
  }
43
 
44
  // Privacy consent
45
- $require_consent = $rtb_controller->settings->get_setting( 'require-consent' );
46
- if ( !empty( $require_consent ) ) {
47
  add_filter( 'ebfrtb_export_csv_booking_headers', array( $this, 'add_privacy_header' ) );
48
  add_filter( 'ebfrtb_export_csv_booking', array( $this, 'add_privacy' ), 10, 2 );
49
  }
50
 
 
 
 
 
 
51
  add_filter( 'ebfrtb_export_csv_booking_headers', array( $this, 'add_custom_fields_header' ) );
52
  add_filter( 'ebfrtb_export_csv_booking', array( $this, 'add_custom_fields' ), 10, 2 );
53
  }
@@ -207,6 +211,40 @@ class ebfrtbExportCSV extends ebfrtbExport {
207
  return $arr;
208
  }
209
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
  /**
211
  * Add custom fields to CSV headers
212
  *
42
  }
43
 
44
  // Privacy consent
45
+ if ( $rtb_controller->settings->get_setting( 'require-consent' ) ) {
 
46
  add_filter( 'ebfrtb_export_csv_booking_headers', array( $this, 'add_privacy_header' ) );
47
  add_filter( 'ebfrtb_export_csv_booking', array( $this, 'add_privacy' ), 10, 2 );
48
  }
49
 
50
+ if ( $rtb_controller->settings->get_setting( 'enable-tables' ) ) {
51
+ add_filter( 'ebfrtb_export_csv_booking_headers', array( $this, 'add_table_header' ), 9 );
52
+ add_filter( 'ebfrtb_export_csv_booking', array( $this, 'add_table' ), 9, 2 );
53
+ }
54
+
55
  add_filter( 'ebfrtb_export_csv_booking_headers', array( $this, 'add_custom_fields_header' ) );
56
  add_filter( 'ebfrtb_export_csv_booking', array( $this, 'add_custom_fields' ), 10, 2 );
57
  }
211
  return $arr;
212
  }
213
 
214
+ /**
215
+ * Add a header for the table(s) feature if it's active
216
+ *
217
+ * @param array $headers Key/value of spreadsheet header rows id/label
218
+ * @since 2.2.0
219
+ */
220
+ public function add_table_header( $headers ) {
221
+
222
+ $headers[0] = array_merge(
223
+ $headers[0],
224
+ array( 'table' => __( 'Table(s)', 'restaurant-reservations' ) )
225
+ );
226
+
227
+ return $headers;
228
+ }
229
+
230
+ /**
231
+ * Add the selected table(s) to the array for conversion to csv
232
+ *
233
+ * @param array $arr Assoc array of booking data compiled for conversion to
234
+ * csv
235
+ * @param rtbBooking $booking Original booking object
236
+ * @since 2.2.0
237
+ */
238
+ public function add_table( $arr, $booking ) {
239
+
240
+ $arr = array_merge(
241
+ $arr,
242
+ array( 'consent_acquired' => implode( ',', $booking->table ) )
243
+ );
244
+
245
+ return $arr;
246
+ }
247
+
248
  /**
249
  * Add custom fields to CSV headers
250
  *
includes/Export.PDF.class.php CHANGED
@@ -64,7 +64,11 @@ class ebfrtbExportPDF extends ebfrtbExport {
64
  $this->query_args = $args['query_args'];
65
  }
66
 
67
- //Add custom field hooks
 
 
 
 
68
  add_filter( 'ebfrtb_mpdf_after_details', array($this, 'add_custom_fields_to_mpdf' ) );
69
  add_filter( 'ebfrtb_tcpdf_after_details', array($this, 'add_custom_fields_to_tcpdf' ) );
70
  }
@@ -205,6 +209,24 @@ class ebfrtbExportPDF extends ebfrtbExport {
205
  return $this->export;
206
  }
207
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  /**
209
  * Add custom fields to TCPDF output
210
  *
64
  $this->query_args = $args['query_args'];
65
  }
66
 
67
+ // Maybe add table hooks
68
+ add_filter( 'ebfrtb_mpdf_after_details', array($this, 'add_booking_table_to_pdf' ) );
69
+ add_filter( 'ebfrtb_tcpdf_after_details', array($this, 'add_booking_table_to_pdf' ) );
70
+
71
+ // Add custom field hooks
72
  add_filter( 'ebfrtb_mpdf_after_details', array($this, 'add_custom_fields_to_mpdf' ) );
73
  add_filter( 'ebfrtb_tcpdf_after_details', array($this, 'add_custom_fields_to_tcpdf' ) );
74
  }
209
  return $this->export;
210
  }
211
 
212
+ /**
213
+ *Maybe add the table for a booking to PDF output
214
+ *
215
+ * @since 2.2
216
+ */
217
+ public function add_booking_table_to_pdf( $booking ) {
218
+ global $rtb_controller;
219
+
220
+ if ( $rtb_controller->settings->get_setting( 'enable-tables' ) ) { ?>
221
+
222
+ <p class="booking-table">
223
+ <span class="label"><?php echo __( 'Table(s)' ) . esc_html_x( ': ', 'Appears after table label in PDF exports', 'custom-fields-for-rtb' ); ?></span>
224
+ <?php echo implode( ',', $booking->table ); ?>
225
+ </p>
226
+
227
+ <?php }
228
+ }
229
+
230
  /**
231
  * Add custom fields to TCPDF output
232
  *
includes/Query.class.php CHANGED
@@ -103,11 +103,11 @@ class rtbQuery {
103
  $date_query = array( 'inclusive' => true );
104
 
105
  if ( !empty( $args['start_date'] ) ) {
106
- $date_query['after'] = sanitize_text_field( $args['start_date'] );
107
  }
108
 
109
  if ( !empty( $args['end_date'] ) ) {
110
- $date_query['before'] = sanitize_text_field( $args['end_date'] ) . ' 23:59'; // end of day
111
  }
112
 
113
  if ( count( $date_query ) ) {
@@ -185,6 +185,7 @@ class rtbQuery {
185
  if ( !empty( $_REQUEST['orderby'] ) ) {
186
  $args['orderby'] = sanitize_key( $_REQUEST['orderby'] );
187
  if ( $args['orderby'] === 'id' ) { $args['orderby'] = 'ID'; }
 
188
  }
189
 
190
  if ( !empty( $_REQUEST['order'] ) && $_REQUEST['order'] === 'desc' ) {
@@ -243,5 +244,10 @@ class rtbQuery {
243
  return $this->bookings;
244
  }
245
 
 
 
 
 
 
246
  }
247
  } // endif
103
  $date_query = array( 'inclusive' => true );
104
 
105
  if ( !empty( $args['start_date'] ) ) {
106
+ $date_query['after'] = sanitize_text_field( $args['start_date'] ) . ( ( isset( $args['start_time'] ) and $args['start_time'] ) ? $args['start_time'] : '' );
107
  }
108
 
109
  if ( !empty( $args['end_date'] ) ) {
110
+ $date_query['before'] = sanitize_text_field( $args['end_date'] ) . ( ( isset( $args['end_time'] ) and $args['end_time'] ) ? $args['end_time'] : ' 23:59' );
111
  }
112
 
113
  if ( count( $date_query ) ) {
185
  if ( !empty( $_REQUEST['orderby'] ) ) {
186
  $args['orderby'] = sanitize_key( $_REQUEST['orderby'] );
187
  if ( $args['orderby'] === 'id' ) { $args['orderby'] = 'ID'; }
188
+ if ( $args['orderby'] === 'status' ) { add_filter( 'posts_orderby', array( $this, 'orderby_status' ) ); }
189
  }
190
 
191
  if ( !empty( $_REQUEST['order'] ) && $_REQUEST['order'] === 'desc' ) {
244
  return $this->bookings;
245
  }
246
 
247
+ public function orderby_status() {
248
+
249
+ return 'post_status ' . ( ( isset( $_REQUEST['order'] ) and $_REQUEST['order'] == 'desc' ) ? 'DESC' : 'ASC' );
250
+ }
251
+
252
  }
253
  } // endif
includes/Settings.class.php CHANGED
@@ -965,6 +965,17 @@ If you were not the one to cancel this booking, please contact us.
965
  )
966
  );
967
 
 
 
 
 
 
 
 
 
 
 
 
968
  $sap->add_section(
969
  'rtb-settings',
970
  array(
@@ -1091,7 +1102,18 @@ If you were not the one to cancel this booking, please contact us.
1091
  array(
1092
  'id' => 'rtb-privacy',
1093
  'title' => __( 'Privacy', 'restaurant-reservations' ),
1094
- 'tab' => 'rtb-basic',
 
 
 
 
 
 
 
 
 
 
 
1095
  )
1096
  );
1097
 
@@ -1102,7 +1124,7 @@ If you were not the one to cancel this booking, please contact us.
1102
  array(
1103
  'id' => 'require-consent',
1104
  'title' => __( 'Require Consent', 'restaurant-reservations' ),
1105
- 'description' => __( 'Require customers to consent to the collection of their details when making a booking. This may be required to comply with privacy laws in your country.', 'restaurant-reservations' )
1106
  )
1107
  );
1108
 
@@ -1342,7 +1364,7 @@ If you were not the one to cancel this booking, please contact us.
1342
  'title' => __( 'Max Reservations', 'restaurant-reservations' ),
1343
  'description' => __( 'How many reservations, if enabled above, should be allowed at the same time? Set dining block length setting above to change how long a meal typically lasts.', 'restaurant-reservations' ),
1344
  'min_value' => 1,
1345
- 'max_value' => 100,
1346
  'increment' => 1
1347
  )
1348
  );
@@ -1356,7 +1378,7 @@ If you were not the one to cancel this booking, please contact us.
1356
  'title' => __( 'Max People', 'restaurant-reservations' ),
1357
  'description' => __( 'How many people, if enabled above, should be allowed to be present in the restaurant at the same time? Set dining block length setting above to change how long a meal typically lasts. May not work correctly if max reservations is set.', 'restaurant-reservations' ),
1358
  'min_value' => 1,
1359
- 'max_value' => 100,
1360
  'increment' => 1
1361
  )
1362
  );
@@ -1370,7 +1392,7 @@ If you were not the one to cancel this booking, please contact us.
1370
  'title' => __( 'Automatically Confirm Below Reservation Number', 'restaurant-reservations' ),
1371
  'description' => __( 'Set a maximum number of reservations at one time below which all bookings will be automatically confirmed.', 'restaurant-reservations' ),
1372
  'min_value' => 1,
1373
- 'max_value' => 100,
1374
  'increment' => 1
1375
  )
1376
  );
@@ -1384,7 +1406,7 @@ If you were not the one to cancel this booking, please contact us.
1384
  'title' => __( 'Automatically Confirm Below Seats Number', 'restaurant-reservations' ),
1385
  'description' => __( 'Set a maximum number of seats at one time below which all bookings will be automatically confirmed.', 'restaurant-reservations' ),
1386
  'min_value' => 1,
1387
- 'max_value' => 400,
1388
  'increment' => 1
1389
  )
1390
  );
@@ -2804,7 +2826,7 @@ If you were not the one to cancel this booking, please contact us.
2804
  ),
2805
 
2806
  // Contact details fieldset
2807
- 'contact' => array(
2808
  'legend' => __( 'Contact Details', 'restaurant-reservations' ),
2809
  'fields' => array(
2810
  'name' => array(
@@ -2884,6 +2906,8 @@ If you were not the one to cancel this booking, please contact us.
2884
  'required' => $require_table,
2885
  'order' => 999
2886
  );
 
 
2887
  }
2888
 
2889
  return apply_filters( 'rtb_booking_form_fields', $fields, $request, $args );
@@ -2936,6 +2960,7 @@ If you were not the one to cancel this booking, please contact us.
2936
  '{site_name}' => __( 'The name of this website', 'restaurant-reservations' ),
2937
  '{site_link}' => __( 'A link to this website', 'restaurant-reservations' ),
2938
  '{current_time}' => __( 'Current date and time', 'restaurant-reservations' ),
 
2939
  )
2940
  );
2941
 
965
  )
966
  );
967
 
968
+ $sap->add_setting(
969
+ 'rtb-settings',
970
+ 'rtb-general',
971
+ 'text',
972
+ array(
973
+ 'id' => 'cancelled-redirect-page',
974
+ 'title' => __( 'Cancellation Redirect Page', 'restaurant-reservations' ),
975
+ 'description' => __( 'Input the URL of the page you want the cancellation form to redirect to when someone cancels their reservation. Only applicable if the "Allow Cancellations" option above is enabled. If left blank, it will display a success message instead of redirecting.', 'restaurant-reservations' ),
976
+ )
977
+ );
978
+
979
  $sap->add_section(
980
  'rtb-settings',
981
  array(
1102
  array(
1103
  'id' => 'rtb-privacy',
1104
  'title' => __( 'Privacy', 'restaurant-reservations' ),
1105
+ 'tab' => 'rtb-basic',
1106
+ )
1107
+ );
1108
+
1109
+ $sap->add_setting(
1110
+ 'rtb-settings',
1111
+ 'rtb-privacy',
1112
+ 'toggle',
1113
+ array(
1114
+ 'id' => 'disable-ip-capture',
1115
+ 'title' => __( 'Disable IP Capture', 'restaurant-reservations' ),
1116
+ 'description' => __( 'This turns off the feature that captures the IP address of the device making the booking.', 'restaurant-reservations' )
1117
  )
1118
  );
1119
 
1124
  array(
1125
  'id' => 'require-consent',
1126
  'title' => __( 'Require Consent', 'restaurant-reservations' ),
1127
+ 'description' => __( 'Require customers to consent to the collection of their details when making a booking. This may be required to comply with privacy laws in your country.', 'restaurant-reservations' )
1128
  )
1129
  );
1130
 
1364
  'title' => __( 'Max Reservations', 'restaurant-reservations' ),
1365
  'description' => __( 'How many reservations, if enabled above, should be allowed at the same time? Set dining block length setting above to change how long a meal typically lasts.', 'restaurant-reservations' ),
1366
  'min_value' => 1,
1367
+ 'max_value' => apply_filters( 'rtb-max-reservations-upper-limit', 100 ),
1368
  'increment' => 1
1369
  )
1370
  );
1378
  'title' => __( 'Max People', 'restaurant-reservations' ),
1379
  'description' => __( 'How many people, if enabled above, should be allowed to be present in the restaurant at the same time? Set dining block length setting above to change how long a meal typically lasts. May not work correctly if max reservations is set.', 'restaurant-reservations' ),
1380
  'min_value' => 1,
1381
+ 'max_value' => apply_filters( 'rtb-max-people-upper-limit', 100 ),
1382
  'increment' => 1
1383
  )
1384
  );
1392
  'title' => __( 'Automatically Confirm Below Reservation Number', 'restaurant-reservations' ),
1393
  'description' => __( 'Set a maximum number of reservations at one time below which all bookings will be automatically confirmed.', 'restaurant-reservations' ),
1394
  'min_value' => 1,
1395
+ 'max_value' => apply_filters( 'rtb-auto-confirm-reservations-upper-limit', 100 ),
1396
  'increment' => 1
1397
  )
1398
  );
1406
  'title' => __( 'Automatically Confirm Below Seats Number', 'restaurant-reservations' ),
1407
  'description' => __( 'Set a maximum number of seats at one time below which all bookings will be automatically confirmed.', 'restaurant-reservations' ),
1408
  'min_value' => 1,
1409
+ 'max_value' => apply_filters( 'rtb-auto-confirm-seats-upper-limit', 400 ),
1410
  'increment' => 1
1411
  )
1412
  );
2826
  ),
2827
 
2828
  // Contact details fieldset
2829
+ 'rtb-contact' => array(
2830
  'legend' => __( 'Contact Details', 'restaurant-reservations' ),
2831
  'fields' => array(
2832
  'name' => array(
2906
  'required' => $require_table,
2907
  'order' => 999
2908
  );
2909
+ } elseif ( array_key_exists( 'table', $fields['reservation']['fields'] ) ) {
2910
+ unset( $fields['reservation']['fields']['table'] );
2911
  }
2912
 
2913
  return apply_filters( 'rtb_booking_form_fields', $fields, $request, $args );
2960
  '{site_name}' => __( 'The name of this website', 'restaurant-reservations' ),
2961
  '{site_link}' => __( 'A link to this website', 'restaurant-reservations' ),
2962
  '{current_time}' => __( 'Current date and time', 'restaurant-reservations' ),
2963
+ '{table}' => __( 'The table(s) for the booking', 'restaurant-reservations' ),
2964
  )
2965
  );
2966
 
includes/WP_List_Table.BookingsTable.class.php CHANGED
@@ -58,6 +58,15 @@ class rtbBookingsTable extends WP_List_Table {
58
  public $filter_start_date = null;
59
  public $filter_end_date = null;
60
 
 
 
 
 
 
 
 
 
 
61
  /**
62
  * Current location filter
63
  *
@@ -146,15 +155,19 @@ class rtbBookingsTable extends WP_List_Table {
146
  *
147
  * @since 0.0.1
148
  */
149
- public function set_date_filter( $start_date = null, $end_date = null) {
150
 
151
  if ( !empty( $_GET['action'] ) && $_GET['action'] == 'clear_date_filters' ) {
152
- $this->filter_start_date = null;
153
- $this->filter_end_date = null;
 
 
154
  }
155
 
156
- $this->filter_start_date = $start_date;
157
- $this->filter_end_date = $end_date;
 
 
158
 
159
  if ( $start_date === null ) {
160
  $this->filter_start_date = !empty( $_GET['start_date'] ) ? sanitize_text_field( $_GET['start_date'] ) : null;
@@ -165,6 +178,16 @@ class rtbBookingsTable extends WP_List_Table {
165
  $this->filter_end_date = !empty( $_GET['end_date'] ) ? sanitize_text_field( $_GET['end_date'] ) : null;
166
  $this->filter_end_date = !empty( $_POST['end_date'] ) ? sanitize_text_field( $_POST['end_date'] ) : $this->filter_end_date;
167
  }
 
 
 
 
 
 
 
 
 
 
168
  }
169
 
170
  /**
@@ -199,6 +222,14 @@ class rtbBookingsTable extends WP_List_Table {
199
  $this->query_string = add_query_arg( array( 'end_date' => $this->filter_end_date ), $this->query_string );
200
  }
201
 
 
 
 
 
 
 
 
 
202
  $this->filter_location = ! isset( $_GET['location'] ) ? 0 : intval( $_GET['location'] );
203
  $this->filter_location = ! isset( $_POST['location'] ) ? $this->filter_location : intval( $_POST['location'] );
204
  $this->query_string = remove_query_arg( 'location', $this->query_string );
@@ -240,7 +271,7 @@ class rtbBookingsTable extends WP_List_Table {
240
  $views['date'] = '<span class="date-filter-range current">' . $this->get_current_date_range() . '</span>';
241
  $views['date'] .= '<a id="rtb-date-filter-link" href="#"><span class="dashicons dashicons-calendar"></span> <span class="rtb-date-filter-label">Change date range</span></a>';
242
  } else {
243
- $views['date'] = '<a id="rtb-date-filter-link" href="#">' . esc_html__( 'Between dates', 'restaurant-reservations' ) . '</a>';
244
  }
245
 
246
  $views = apply_filters( 'rtb_bookings_table_views_date_range', $views );
@@ -252,12 +283,18 @@ class rtbBookingsTable extends WP_List_Table {
252
  </ul>
253
 
254
  <div class="date-filters">
255
- <label for="start-date" class="screen-reader-text"><?php _e( 'Start Date:', 'restaurant-reservations' ); ?></label>
256
- <input type="text" id="start-date" name="start_date" class="datepicker" value="<?php echo esc_attr( $this->filter_start_date ); ?>" placeholder="<?php _e( 'Start Date', 'restaurant-reservations' ); ?>" />
257
- <label for="end-date" class="screen-reader-text"><?php _e( 'End Date:', 'restaurant-reservations' ); ?></label>
258
- <input type="text" id="end-date" name="end_date" class="datepicker" value="<?php echo esc_attr( $this->filter_end_date ); ?>" placeholder="<?php _e( 'End Date', 'restaurant-reservations' ); ?>" />
 
 
 
 
 
 
259
  <input type="submit" class="button button-secondary" value="<?php _e( 'Apply', 'restaurant-reservations' ); ?>"/>
260
- <?php if( !empty( $this->filter_start_date ) || !empty( $this->filter_end_date ) ) : ?>
261
  <a href="<?php echo esc_url( add_query_arg( array( 'action' => 'clear_date_filters' ) ) ); ?>" class="button button-secondary"><?php _e( 'Clear Filter', 'restaurant-reservations' ); ?></a>
262
  <?php endif; ?>
263
  </div>
@@ -402,7 +439,8 @@ class rtbBookingsTable extends WP_List_Table {
402
  $columns = array(
403
  'id' => array( 'ID', true ),
404
  'date' => array( 'date', true ),
405
- 'name' => array( 'title', true )
 
406
  );
407
  return apply_filters( 'rtb_bookings_table_sortable_columns', $columns );
408
  }
@@ -582,10 +620,11 @@ class rtbBookingsTable extends WP_List_Table {
582
  */
583
  public function get_bulk_actions() {
584
  $actions = array(
585
- 'delete' => __( 'Delete', 'restaurant-reservations' ),
586
- 'set-status-confirmed' => __( 'Set To Confirmed', 'restaurant-reservations' ),
587
- 'set-status-pending' => __( 'Set To Pending Review', 'restaurant-reservations' ),
588
- 'set-status-closed' => __( 'Set To Closed', 'restaurant-reservations' )
 
589
  );
590
 
591
  return apply_filters( 'rtb_bookings_table_bulk_actions', $actions );
@@ -758,7 +797,7 @@ class rtbBookingsTable extends WP_List_Table {
758
  ?>
759
 
760
  <div class="tablenav top rtb-top-actions-wrapper">
761
- <?php wp_nonce_field( 'bulk-' . $this->args['plural'] ); ?>
762
  <?php $this->extra_tablenav( $which ); ?>
763
  </div>
764
 
@@ -881,12 +920,12 @@ class rtbBookingsTable extends WP_List_Table {
881
  if ( $this->filter_start_date !== null || $this->filter_end_date !== null ) {
882
 
883
  if ( $this->filter_start_date !== null ) {
884
- $start_date = new DateTime( $this->filter_start_date );
885
  $where .= " AND p.post_date >= '" . $start_date->format( 'Y-m-d H:i:s' ) . "'";
886
  }
887
 
888
  if ( $this->filter_end_date !== null ) {
889
- $end_date = new DateTime( $this->filter_end_date );
890
  $where .= " AND p.post_date <= '" . $end_date->format( 'Y-m-d H:i:s' ) . "'";
891
  }
892
 
@@ -941,10 +980,12 @@ class rtbBookingsTable extends WP_List_Table {
941
 
942
  if ( !empty( $this->filter_start_date ) ) {
943
  $args['start_date'] = $this->filter_start_date;
 
944
  }
945
 
946
  if ( !empty( $this->filter_end_date ) ) {
947
  $args['end_date'] = $this->filter_end_date;
 
948
  }
949
 
950
  $query = new rtbQuery( $args, 'bookings-table' );
58
  public $filter_start_date = null;
59
  public $filter_end_date = null;
60
 
61
+ /**
62
+ * Current time filters
63
+ *
64
+ * @var string
65
+ * @since 2.2.0
66
+ */
67
+ public $filter_start_time = null;
68
+ public $filter_end_time = null;
69
+
70
  /**
71
  * Current location filter
72
  *
155
  *
156
  * @since 0.0.1
157
  */
158
+ public function set_date_filter( $start_date = null, $end_date = null, $start_time = null, $end_time = null ) {
159
 
160
  if ( !empty( $_GET['action'] ) && $_GET['action'] == 'clear_date_filters' ) {
161
+ $this->filter_start_date = null;
162
+ $this->filter_end_date = null;
163
+ $this->filter_start_time = null;
164
+ $this->filter_end_time = null;
165
  }
166
 
167
+ $this->filter_start_date = $start_date;
168
+ $this->filter_end_date = $end_date;
169
+ $this->filter_start_time = $start_time;
170
+ $this->filter_end_time = $end_time;
171
 
172
  if ( $start_date === null ) {
173
  $this->filter_start_date = !empty( $_GET['start_date'] ) ? sanitize_text_field( $_GET['start_date'] ) : null;
178
  $this->filter_end_date = !empty( $_GET['end_date'] ) ? sanitize_text_field( $_GET['end_date'] ) : null;
179
  $this->filter_end_date = !empty( $_POST['end_date'] ) ? sanitize_text_field( $_POST['end_date'] ) : $this->filter_end_date;
180
  }
181
+
182
+ if ( $start_time === null ) {
183
+ $this->filter_start_time = !empty( $_GET['start_time'] ) ? sanitize_text_field( $_GET['start_time'] ) : null;
184
+ $this->filter_start_time = !empty( $_POST['start_time'] ) ? sanitize_text_field( $_POST['start_time'] ) : $this->filter_start_time;
185
+ }
186
+
187
+ if ( $end_time === null ) {
188
+ $this->filter_end_time = !empty( $_GET['end_time'] ) ? sanitize_text_field( $_GET['end_time'] ) : null;
189
+ $this->filter_end_time = !empty( $_POST['end_time'] ) ? sanitize_text_field( $_POST['end_time'] ) : $this->filter_end_time;
190
+ }
191
  }
192
 
193
  /**
222
  $this->query_string = add_query_arg( array( 'end_date' => $this->filter_end_date ), $this->query_string );
223
  }
224
 
225
+ if ( $this->filter_start_time !== null ) {
226
+ $this->query_string = add_query_arg( array( 'start_time' => $this->filter_start_time ), $this->query_string );
227
+ }
228
+
229
+ if ( $this->filter_end_time !== null ) {
230
+ $this->query_string = add_query_arg( array( 'end_time' => $this->filter_end_time ), $this->query_string );
231
+ }
232
+
233
  $this->filter_location = ! isset( $_GET['location'] ) ? 0 : intval( $_GET['location'] );
234
  $this->filter_location = ! isset( $_POST['location'] ) ? $this->filter_location : intval( $_POST['location'] );
235
  $this->query_string = remove_query_arg( 'location', $this->query_string );
271
  $views['date'] = '<span class="date-filter-range current">' . $this->get_current_date_range() . '</span>';
272
  $views['date'] .= '<a id="rtb-date-filter-link" href="#"><span class="dashicons dashicons-calendar"></span> <span class="rtb-date-filter-label">Change date range</span></a>';
273
  } else {
274
+ $views['date'] = '<a id="rtb-date-filter-link" href="#">' . esc_html__( 'Specific Date(s)/Time', 'restaurant-reservations' ) . '</a>';
275
  }
276
 
277
  $views = apply_filters( 'rtb_bookings_table_views_date_range', $views );
283
  </ul>
284
 
285
  <div class="date-filters">
286
+ <div class="rtb-admin-bookings-filters-start">
287
+ <label for="start-date" class="screen-reader-text"><?php _e( 'Start Date:', 'restaurant-reservations' ); ?></label>
288
+ <input type="text" id="start-date" name="start_date" class="datepicker" value="<?php echo esc_attr( $this->filter_start_date ); ?>" placeholder="<?php _e( 'Start Date', 'restaurant-reservations' ); ?>" />
289
+ <input type="text" id="start-time" name="start_time" class="timepicker" value="<?php echo esc_attr( $this->filter_start_time ); ?>" placeholder="<?php _e( 'Start Time', 'restaurant-reservations' ); ?>" />
290
+ </div>
291
+ <div class="rtb-admin-bookings-filters-end">
292
+ <label for="end-date" class="screen-reader-text"><?php _e( 'End Date:', 'restaurant-reservations' ); ?></label>
293
+ <input type="text" id="end-date" name="end_date" class="datepicker" value="<?php echo esc_attr( $this->filter_end_date ); ?>" placeholder="<?php _e( 'End Date', 'restaurant-reservations' ); ?>" />
294
+ <input type="text" id="end-time" name="end_time" class="timepicker" value="<?php echo esc_attr( $this->filter_end_time ); ?>" placeholder="<?php _e( 'End Time', 'restaurant-reservations' ); ?>" />
295
+ </div>
296
  <input type="submit" class="button button-secondary" value="<?php _e( 'Apply', 'restaurant-reservations' ); ?>"/>
297
+ <?php if( !empty( $this->filter_start_date ) || !empty( $this->filter_end_date ) || !empty( $this->filter_start_time ) || !empty( $this->filter_end_time ) ) : ?>
298
  <a href="<?php echo esc_url( add_query_arg( array( 'action' => 'clear_date_filters' ) ) ); ?>" class="button button-secondary"><?php _e( 'Clear Filter', 'restaurant-reservations' ); ?></a>
299
  <?php endif; ?>
300
  </div>
439
  $columns = array(
440
  'id' => array( 'ID', true ),
441
  'date' => array( 'date', true ),
442
+ 'name' => array( 'title', true ),
443
+ 'status' => array( 'status', true ),
444
  );
445
  return apply_filters( 'rtb_bookings_table_sortable_columns', $columns );
446
  }
620
  */
621
  public function get_bulk_actions() {
622
  $actions = array(
623
+ 'delete' => __( 'Delete', 'restaurant-reservations' ),
624
+ 'set-status-confirmed' => __( 'Set To Confirmed', 'restaurant-reservations' ),
625
+ 'set-status-pending' => __( 'Set To Pending Review', 'restaurant-reservations' ),
626
+ 'set-status-closed' => __( 'Set To Closed', 'restaurant-reservations' ),
627
+ 'send-email' => __( 'Send Email', 'restaurant-reservations' )
628
  );
629
 
630
  return apply_filters( 'rtb_bookings_table_bulk_actions', $actions );
797
  ?>
798
 
799
  <div class="tablenav top rtb-top-actions-wrapper">
800
+ <?php wp_nonce_field( 'bulk-' . $this->_args['plural'] ); ?>
801
  <?php $this->extra_tablenav( $which ); ?>
802
  </div>
803
 
920
  if ( $this->filter_start_date !== null || $this->filter_end_date !== null ) {
921
 
922
  if ( $this->filter_start_date !== null ) {
923
+ $start_date = new DateTime( $this->filter_start_date . ' ' . $this->filter_start_time );
924
  $where .= " AND p.post_date >= '" . $start_date->format( 'Y-m-d H:i:s' ) . "'";
925
  }
926
 
927
  if ( $this->filter_end_date !== null ) {
928
+ $end_date = new DateTime( $this->filter_end_date . ' ' . $this->filter_end_time );
929
  $where .= " AND p.post_date <= '" . $end_date->format( 'Y-m-d H:i:s' ) . "'";
930
  }
931
 
980
 
981
  if ( !empty( $this->filter_start_date ) ) {
982
  $args['start_date'] = $this->filter_start_date;
983
+ $args['start_time'] = $this->filter_start_time;
984
  }
985
 
986
  if ( !empty( $this->filter_end_date ) ) {
987
  $args['end_date'] = $this->filter_end_date;
988
+ $args['end_time'] = $this->filter_end_time;
989
  }
990
 
991
  $query = new rtbQuery( $args, 'bookings-table' );
includes/template-functions.php CHANGED
@@ -102,42 +102,59 @@ function rtb_print_booking_form( $args = array() ) {
102
  <?php $post_status = isset( $_GET['booking_id'] ) ? get_post_status( intval( $_GET['booking_id'] ) ) : $rtb_controller->request->post_status; ?>
103
 
104
  <?php
105
- if ( $post_status == 'confirmed' ) {
106
- if( $rtb_controller->settings->get_setting('confirmed-redirect-page') != '' ){
107
- header( 'Location:' . $rtb_controller->settings->get_setting('confirmed-redirect-page') );
 
 
 
 
108
  }
109
- else{
110
- ?>
111
- <div class="rtb-message">
112
- <p><?php echo $rtb_controller->settings->get_setting('confirmed-message'); ?></p>
113
- </div>
114
- <?php
115
  }
116
  }
117
  else {
118
- if( $rtb_controller->settings->get_setting('pending-redirect-page') != '' ) {
119
- header( 'Location:' . $rtb_controller->settings->get_setting('pending-redirect-page') );
120
  }
121
- else{
122
- ?>
123
- <div class="rtb-message">
124
- <p><?php echo $rtb_controller->settings->get_setting('success-message'); ?></p>
125
- </div>
126
- <?php
127
  }
128
  }
129
- ?>
130
 
131
- <?php elseif ( isset($_POST['stripeToken']) ) : ?>
132
- <?php rtb_process_stripe_payment(); ?>
133
- <?php elseif ( $rtb_controller->request->request_inserted === true or isset($_GET['payment']) ) : ?>
134
- <?php if ( isset($_GET['payment']) ) { ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  <div class="rtb-message">
136
  <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>
137
  </div>
138
- <?php } ?>
139
- <?php rtb_print_payment_form(); ?>
140
- <?php elseif ( isset($_GET['bookingCancelled']) and $_GET['bookingCancelled'] == 'success') : ?>
 
 
141
  <div class="rtb-message">
142
  <p><?php _e( 'Your reservation has been successfully cancelled.', 'restaurant-reservations' ) ?></p>
143
  </div>
102
  <?php $post_status = isset( $_GET['booking_id'] ) ? get_post_status( intval( $_GET['booking_id'] ) ) : $rtb_controller->request->post_status; ?>
103
 
104
  <?php
105
+
106
+ $success_redirect_location = '';
107
+ $success_message = '';
108
+
109
+ if ( 'confirmed' == $post_status ) {
110
+ if( '' != $rtb_controller->settings->get_setting('confirmed-redirect-page') ) {
111
+ $success_redirect_location = $rtb_controller->settings->get_setting('confirmed-redirect-page');
112
  }
113
+ else {
114
+ $success_message = $rtb_controller->settings->get_setting('confirmed-message');
 
 
 
 
115
  }
116
  }
117
  else {
118
+ if( '' != $rtb_controller->settings->get_setting('pending-redirect-page') ) {
119
+ $success_redirect_location = $rtb_controller->settings->get_setting('pending-redirect-page');
120
  }
121
+ else {
122
+ $success_message = $rtb_controller->settings->get_setting('success-message');
 
 
 
 
123
  }
124
  }
 
125
 
126
+ if( ! empty($success_redirect_location) ) {
127
+ $success_redirect_location = apply_filters(
128
+ 'rtb_booking_submit_success_redirect',
129
+ $success_redirect_location,
130
+ $post_status,
131
+ $rtb_controller->request
132
+ );
133
+
134
+ header( 'Location:' . $success_redirect_location );
135
+ }
136
+ else {
137
+ ?>
138
+ <div class="rtb-message">
139
+ <p><?php echo $success_message; ?></p>
140
+ </div>
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']) ) { ?>
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">
159
  <p><?php _e( 'Your reservation has been successfully cancelled.', 'restaurant-reservations' ) ?></p>
160
  </div>
readme.txt CHANGED
@@ -3,6 +3,7 @@ Contributors: FiveStarPlugins
3
  Requires at Least: 4.4
4
  Tested Up To: 5.5
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
  License: GPLv3
7
  License URI:http://www.gnu.org/licenses/gpl-3.0.html
8
  Donate Link: https://www.etoilewebdesign.com/plugin-donations/
@@ -196,6 +197,22 @@ Find answers to even more questions in the [FAQ](http://doc.fivestarplugins.com/
196
 
197
  == Changelog ==
198
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  = 2.1.24 (2020-10-13) =
200
  - Corrects issue with time clearing from previous update that sometimes caused the time to clear on the edit booking screen in the admin even when the date had not been changed.
201
  - Updating picker.js library.
3
  Requires at Least: 4.4
4
  Tested Up To: 5.5
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.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.2.0 (2020-10-21) =
201
+ - <strong>This is a relatively big update with several new features, corrections, styling, etc., so please take caution and test before updating on a live site (or wait a few days before updating in case some minor corrective updates need to be released).</strong>
202
+ - Added in a new filtering option in the admin to display bookings from a specific date and/or time frame.
203
+ - Added in the ability to send a mass email to multiple bookings.
204
+ - (The above two new additions could, for example, be used as a way of contact tracing.)
205
+ - Table numbers are now included in the export (both PDF and Excel/CSV).
206
+ - Added in a redirect URL option for the cancellation form.
207
+ - Made the admin booking table sortable by the status column.
208
+ - Added an option to disable the capture of the IP address when a booking is made.
209
+ - Updated the interaction between the "automatically confirm below party size" and "automatically confirm below seats number" settings, to allow them to work in an OR capacity, so they can be used together.
210
+ - Corrected an issue where sometimes the "automatically confirm below party size" feature would, even if set to 1, still confirm for a party size of 1.
211
+ - Corrected an issue where the validation that prevents an exact duplicate booking would still throw an error if the old matching booking was in the trash.
212
+ - Corrected an issue where the styling of some admin pages was not being applied when WordPress was set to certain specific non-English languages.
213
+ - Small updates to class names that might have been too common and could potentially allow for a styling conflict with other plugins/themes.
214
+ - Added in several filters for developers to be able to modify/extend plugin behaviour (e.g. in your theme's functions.php file). See [http://doc.fivestarplugins.com/plugins/restaurant-reservations/developer/](http://doc.fivestarplugins.com/plugins/restaurant-reservations/developer/) for more info.
215
+
216
  = 2.1.24 (2020-10-13) =
217
  - Corrects issue with time clearing from previous update that sometimes caused the time to clear on the edit booking screen in the admin even when the date had not been changed.
218
  - Updating picker.js library.
restaurant-reservations.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Five Star Restaurant Reservations - WordPress Booking Plugin
4
  * Plugin URI: http://www.fivestarplugins.com/plugins/five-star-restaurant-reservations/
5
  * Description: Restaurant reservations made easy. Accept bookings online. Quickly confirm or reject reservations, send email notifications, set booking times and more.
6
- * Version: 2.1.24
7
  * Author: FiveStarPlugins
8
  * Author URI: https://profiles.wordpress.org/fivestarplugins/
9
  * Text Domain: restaurant-reservations
@@ -328,7 +328,7 @@ class rtbInit {
328
  return;
329
  }
330
 
331
- if ( $screen->base == 'toplevel_page_rtb-bookings' || $screen->base == $admin_page_hooks['rtb-bookings'] . '_page_rtb-settings' || $screen->base == $admin_page_hooks['rtb-bookings'] . '_page_rtb-addons' ) {
332
  wp_enqueue_style( 'rtb-admin-css', RTB_PLUGIN_URL . '/assets/css/admin.css', array(), RTB_VERSION );
333
  wp_enqueue_script( 'rtb-admin-js', RTB_PLUGIN_URL . '/assets/js/admin.js', array( 'jquery' ), '', true );
334
  wp_enqueue_style( 'rtb-spectrum-css', RTB_PLUGIN_URL . '/assets/css/spectrum.css' );
@@ -388,6 +388,17 @@ class rtbInit {
388
 
389
  wp_register_style( 'rtb-booking-form', RTB_PLUGIN_URL . '/assets/css/booking-form.css' );
390
  wp_register_script( 'rtb-booking-form', RTB_PLUGIN_URL . '/assets/js/booking-form.js', array( 'jquery' ) );
 
 
 
 
 
 
 
 
 
 
 
391
  }
392
 
393
  /**
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.0
7
  * Author: FiveStarPlugins
8
  * Author URI: https://profiles.wordpress.org/fivestarplugins/
9
  * Text Domain: restaurant-reservations
328
  return;
329
  }
330
 
331
+ if ( $screen->base == 'toplevel_page_rtb-bookings' || $screen->base == $admin_page_hooks['rtb-bookings'] . '_page_rtb-settings' || $screen->base == $admin_page_hooks['rtb-bookings'] . '_page_rtb-addons' || $screen->base == $admin_page_hooks['rtb-bookings'] . '_page_cffrtb-editor' ) {
332
  wp_enqueue_style( 'rtb-admin-css', RTB_PLUGIN_URL . '/assets/css/admin.css', array(), RTB_VERSION );
333
  wp_enqueue_script( 'rtb-admin-js', RTB_PLUGIN_URL . '/assets/js/admin.js', array( 'jquery' ), '', true );
334
  wp_enqueue_style( 'rtb-spectrum-css', RTB_PLUGIN_URL . '/assets/css/spectrum.css' );
388
 
389
  wp_register_style( 'rtb-booking-form', RTB_PLUGIN_URL . '/assets/css/booking-form.css' );
390
  wp_register_script( 'rtb-booking-form', RTB_PLUGIN_URL . '/assets/js/booking-form.js', array( 'jquery' ) );
391
+ wp_localize_script(
392
+ 'rtb-booking-form',
393
+ 'rtb_booking_form_js_localize',
394
+ array(
395
+ 'want_to_cancel' => __( 'Want to cancel your reservation?', 'restaurant-reservations' ),
396
+ 'make' => __( 'Make a reservation', 'restaurant-reservations' ),
397
+ 'guest' => __( 'guest', 'restaurant-reservations' ),
398
+ 'guests' => __( 'guests', 'restaurant-reservations' ),
399
+ 'cancel' => __( 'Cancel', 'restaurant-reservations' )
400
+ )
401
+ );
402
  }
403
 
404
  /**